[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\ntab_width = 4\nindent_size = 4\nend_of_line = crlf\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.{yml,yaml}]\nindent_style = space\nindent_size = 2\n\n[*.cs]\ndotnet_hide_advanced_members = true\ndotnet_member_insertion_location = with_other_members_of_the_same_kind\ndotnet_property_generation_behavior = prefer_throwing_properties\ndotnet_search_reference_assemblies = true\ndotnet_separate_import_directive_groups = false:warning\ndotnet_sort_system_directives_first = true:warning\nfile_header_template = unset\n\ndotnet_style_qualification_for_event = false:warning\ndotnet_style_qualification_for_field = false:warning\ndotnet_style_qualification_for_method = false:warning\ndotnet_style_qualification_for_property = false:warning\ndotnet_style_predefined_type_for_locals_parameters_members = true:warning\ndotnet_style_predefined_type_for_member_access = true:warning\ndotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning\ndotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning\ndotnet_style_parentheses_in_other_operators = always_for_clarity:warning\ndotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning\ndotnet_style_require_accessibility_modifiers = always:warning\ndotnet_prefer_system_hash_code = true:warning\ndotnet_style_coalesce_expression = true:warning\ndotnet_style_collection_initializer = false:warning\ndotnet_style_explicit_tuple_names = true:warning\ndotnet_style_namespace_match_folder = true:warning\ndotnet_style_null_propagation = true:warning\ndotnet_style_object_initializer = true:warning\ndotnet_style_operator_placement_when_wrapping = beginning_of_line\ndotnet_style_prefer_auto_properties = true:warning\ndotnet_style_prefer_collection_expression = false:warning\ndotnet_style_prefer_compound_assignment = true:warning\ndotnet_style_prefer_conditional_expression_over_assignment = false:warning\ndotnet_style_prefer_conditional_expression_over_return = false:warning\ndotnet_style_prefer_foreach_explicit_cast_in_source = always:warning\ndotnet_style_prefer_inferred_anonymous_type_member_names = true:warning\ndotnet_style_prefer_inferred_tuple_names = true:warning\ndotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning\ndotnet_style_prefer_simplified_boolean_expressions = true:warning\ndotnet_style_prefer_simplified_interpolation = true:warning\ndotnet_style_readonly_field = true:warning\ndotnet_code_quality_unused_parameters = all:warning\ndotnet_remove_unnecessary_suppression_exclusions = none\ndotnet_style_allow_multiple_blank_lines_experimental = false:warning\ndotnet_style_allow_statement_immediately_after_block_experimental = true:warning\n\ncsharp_style_var_elsewhere = true:warning\ncsharp_style_var_for_built_in_types = true:warning\ncsharp_style_var_when_type_is_apparent = true:warning\ncsharp_style_expression_bodied_accessors = when_on_single_line:warning\ncsharp_style_expression_bodied_constructors = false:warning\ncsharp_style_expression_bodied_indexers = when_on_single_line:warning\ncsharp_style_expression_bodied_lambdas = when_on_single_line:warning\ncsharp_style_expression_bodied_local_functions = false:warning\ncsharp_style_expression_bodied_methods = false:warning\ncsharp_style_expression_bodied_operators = false:warning\ncsharp_style_expression_bodied_properties = when_on_single_line:warning\ncsharp_style_pattern_matching_over_as_with_null_check = true:warning\ncsharp_style_pattern_matching_over_is_with_cast_check = true:warning\ncsharp_style_prefer_extended_property_pattern = true:warning\ncsharp_style_prefer_not_pattern = true:warning\ncsharp_style_prefer_pattern_matching = true:warning\ncsharp_style_prefer_switch_expression = false:warning\ncsharp_style_conditional_delegate_call = true:warning\ncsharp_prefer_static_anonymous_function = true:warning\ncsharp_prefer_static_local_function = true:warning\ncsharp_preferred_modifier_order = public,internal,private,protected,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:warning\ncsharp_style_prefer_readonly_struct = true:warning\ncsharp_style_prefer_readonly_struct_member = true:warning\ncsharp_prefer_braces = true:warning\ncsharp_prefer_simple_using_statement = true:warning\ncsharp_prefer_system_threading_lock = true:warning\ncsharp_style_namespace_declarations = file_scoped:warning\ncsharp_style_prefer_method_group_conversion = true:warning\ncsharp_style_prefer_primary_constructors = true:warning\ncsharp_style_prefer_top_level_statements = false:warning\ncsharp_prefer_simple_default_expression = true:warning\ncsharp_style_deconstructed_variable_declaration = true:warning\ncsharp_style_implicit_object_creation_when_type_is_apparent = true:warning\ncsharp_style_inlined_variable_declaration = true:warning\ncsharp_style_prefer_index_operator = false:warning\ncsharp_style_prefer_local_over_anonymous_function = true:warning\ncsharp_style_prefer_null_check_over_type_check = true:warning\ncsharp_style_prefer_range_operator = false:warning\ncsharp_style_prefer_tuple_swap = true:warning\ncsharp_style_prefer_utf8_string_literals = true:warning\ncsharp_style_throw_expression = true:warning\ncsharp_style_unused_value_assignment_preference = discard_variable:warning\ncsharp_style_unused_value_expression_statement_preference = discard_variable:warning\ncsharp_using_directive_placement = outside_namespace:warning\ncsharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true:warning\ncsharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true:warning\ncsharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = false:warning\ncsharp_style_allow_blank_lines_between_consecutive_braces_experimental = false:warning\ncsharp_style_allow_embedded_statements_on_same_line_experimental = false:warning\n\ncsharp_new_line_before_catch = true\ncsharp_new_line_before_else = true\ncsharp_new_line_before_finally = true\ncsharp_new_line_before_members_in_anonymous_types = true\ncsharp_new_line_before_members_in_object_initializers = true\ncsharp_new_line_before_open_brace = all\ncsharp_new_line_between_query_expression_clauses = true\ncsharp_indent_block_contents = true\ncsharp_indent_braces = false\ncsharp_indent_case_contents = true\ncsharp_indent_case_contents_when_block = true\ncsharp_indent_labels = no_change\ncsharp_indent_switch_labels = true\ncsharp_space_after_cast = false\ncsharp_space_after_colon_in_inheritance_clause = true\ncsharp_space_after_comma = true\ncsharp_space_after_dot = false\ncsharp_space_after_keywords_in_control_flow_statements = true\ncsharp_space_after_semicolon_in_for_statement = true\ncsharp_space_around_binary_operators = before_and_after\ncsharp_space_around_declaration_statements = false:warning\ncsharp_space_before_colon_in_inheritance_clause = true\ncsharp_space_before_comma = false\ncsharp_space_before_dot = false\ncsharp_space_before_open_square_brackets = false\ncsharp_space_before_semicolon_in_for_statement = false\ncsharp_space_between_empty_square_brackets = false\ncsharp_space_between_method_call_empty_parameter_list_parentheses = false\ncsharp_space_between_method_call_name_and_opening_parenthesis = false\ncsharp_space_between_method_call_parameter_list_parentheses = false\ncsharp_space_between_method_declaration_empty_parameter_list_parentheses = false\ncsharp_space_between_method_declaration_name_and_open_parenthesis = false\ncsharp_space_between_method_declaration_parameter_list_parentheses = false\ncsharp_space_between_parentheses = false\ncsharp_space_between_square_brackets = false\ncsharp_preserve_single_line_blocks = true\ncsharp_preserve_single_line_statements = false\n\ndotnet_naming_rule.interface_should_be_pascal.severity = warning\ndotnet_naming_rule.interface_should_be_pascal.symbols = interface\ndotnet_naming_rule.interface_should_be_pascal.style = pascal\ndotnet_naming_rule.types_should_be_pascal.severity = warning\ndotnet_naming_rule.types_should_be_pascal.symbols = types\ndotnet_naming_rule.types_should_be_pascal.style = pascal\ndotnet_naming_rule.non_field_members_should_be_pascal.severity = warning\ndotnet_naming_rule.non_field_members_should_be_pascal.symbols = non_field_members\ndotnet_naming_rule.non_field_members_should_be_pascal.style = pascal\ndotnet_naming_symbols.interface.applicable_kinds = interface\ndotnet_naming_symbols.interface.applicable_accessibilities = *\ndotnet_naming_symbols.interface.required_modifiers = \ndotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum\ndotnet_naming_symbols.types.applicable_accessibilities = *\ndotnet_naming_symbols.types.required_modifiers = \ndotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method\ndotnet_naming_symbols.non_field_members.applicable_accessibilities = *\ndotnet_naming_symbols.non_field_members.required_modifiers = \ndotnet_naming_style.pascal.required_prefix = \ndotnet_naming_style.pascal.required_suffix = \ndotnet_naming_style.pascal.word_separator = \ndotnet_naming_style.pascal.capitalization = pascal_case"
  },
  {
    "path": ".gitattributes",
    "content": "###############################################################################\n# Set default behavior to automatically normalize line endings.\n###############################################################################\n* text=auto\n\n###############################################################################\n# Set default behavior for command prompt diff.\n#\n# This is need for earlier builds of msysgit that does not have it on by\n# default for csharp files.\n# Note: This is only used by command line\n###############################################################################\n#*.cs     diff=csharp\n\n###############################################################################\n# Set the merge driver for project and solution files\n#\n# Merging from the command prompt will add diff markers to the files if there\n# are conflicts (Merging from VS is not affected by the settings below, in VS\n# the diff markers are never inserted). Diff markers may cause the following \n# file extensions to fail to load in VS. An alternative would be to treat\n# these files as binary and thus will always conflict and require user\n# intervention with every merge. To do so, just uncomment the entries below\n###############################################################################\n#*.sln       merge=binary\n#*.csproj    merge=binary\n#*.vbproj    merge=binary\n#*.vcxproj   merge=binary\n#*.vcproj    merge=binary\n#*.dbproj    merge=binary\n#*.fsproj    merge=binary\n#*.lsproj    merge=binary\n#*.wixproj   merge=binary\n#*.modelproj merge=binary\n#*.sqlproj   merge=binary\n#*.wwaproj   merge=binary\n\n###############################################################################\n# behavior for image files\n#\n# image files are treated as binary by default.\n###############################################################################\n#*.jpg   binary\n#*.png   binary\n#*.gif   binary\n\n###############################################################################\n# diff behavior for common document formats\n# \n# Convert binary document formats to text before diffing them. This feature\n# is only available from the command line. Turn it on by uncommenting the \n# entries below.\n###############################################################################\n#*.doc   diff=astextplain\n#*.DOC   diff=astextplain\n#*.docx  diff=astextplain\n#*.DOCX  diff=astextplain\n#*.dot   diff=astextplain\n#*.DOT   diff=astextplain\n#*.pdf   diff=astextplain\n#*.PDF   diff=astextplain\n#*.rtf   diff=astextplain\n#*.RTF   diff=astextplain\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/01_bug_report.yml",
    "content": "name: Bug 报告\ndescription: 在提出问题前请先自行排除服务器端问题和升级到最新客户端，同时也请通过搜索确认是否有人提出过相同问题。\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        ### 报告 Bug 前请务必确认以下事项：\n        > ** **\n        > **✓ 已自行排除服务器端问题。**\n        > **✓ 已升级到最新客户端版本。**\n        > **✓ 已通过搜索确认没有人提出过相同问题。**\n        > **✓ 已确认自己的电脑系统环境是受支持的。**\n\n        ---\n\n  - type: input\n    id: \"os-version\"\n    attributes:\n      label: \"操作系统和版本\"\n      description: \"操作系统和版本\"\n    validations:\n      required: true\n\n  - type: input\n    id: \"expectation\"\n    attributes:\n      label: \"预期情况\"\n      description: \"描述你认为应该发生什么\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: \"describe-the-bug\"\n    attributes:\n      label: \"实际情况\"\n      description: \"描述实际发生了什么\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: \"reproduction-method\"\n    attributes:\n      label: \"复现方法\"\n      description: \"在BUG出现前执行了哪些操作\"\n      placeholder: \"标序号\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: \"gui-log\"\n    attributes:\n      label: \"软件日志\"\n      description: \"位置在软件当前目录下的guiLogs\"\n      placeholder: \"在日志开始和结束位置粘贴冒号后的内容到这：\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: \"core-log\"\n    attributes:\n      label: \"内核日志\"\n      description: \"位置在软件主界面的信息框内\"\n      placeholder: \"在信息框内鼠标右键复制全部信息粘贴在这：\"\n    validations:\n      required: true\n\n  - type: textarea\n    id: \"more\"\n    attributes:\n      label: \"额外信息\"\n      description: \"可选\"\n    validations:\n      required: false\n\n  - type: checkboxes\n    id: \"latest-version\"\n    attributes:\n      label: \"我确认已更新至最新版本\"\n      description: \"否则请更新后尝试\"\n      options:\n        - label: 是\n          required: true\n\n  - type: checkboxes\n    id: \"issues\"\n    attributes:\n      label: \"我确认已查询历史issues\"\n      description: \"否则请查询后提出\"\n      options:\n        - label: 是\n          required: true\n\n  - type: checkboxes\n    id: \"system-version\"\n    attributes:\n      label: \"我确认系统版本是受支持的\"\n      description: \"否则请切换后尝试\"\n      options:\n        - label: 是\n          required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/02_feature_request.yml",
    "content": "name: Feature 请求\ndescription: \"为这个项目提出一个建议\"\ntitle: \"[Feature request]: \"\nlabels: ['enhancement']\nbody: \n- type: input\n  id: problem\n  attributes:\n    label: 相关问题\n    description: \"清楚而简洁地描述问题是什么。\"\n    placeholder: \"当我想要……时，软件不能……\"\n  validations:\n    required: true\n- type: input\n  id: way-to-solve\n  attributes:\n    label: 描述你希望的解决方案\n    description: \"你希望发生什么\"\n  validations:\n    required: true\n- type: input\n  id: instead\n  attributes:\n    label: 描述你所考虑的替代方案\n  validations:\n    required: false\n- type: checkboxes\n  id: \"issues\"\n  attributes:\n    label: \"我确认已查询历史issues\"\n    description: \"否则请查询后提出\"\n    options:\n      - label: 是\n        required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\n\ncontact_links:\n  - name: Discussions / 讨论区\n    url: https://github.com/2dust/v2rayN/discussions\n    about: 使用问题或需要帮助请前往 Discussions。\n  - name: Wiki / 使用说明\n    url: https://github.com/2dust/v2rayN/wiki\n    about: 查看常见问题和使用文档。\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n\n  - package-ecosystem: \"nuget\"\n    directory: \"/\"\n    schedule:\n      interval: \"daily\"\n"
  },
  {
    "path": ".github/workflows/build-all.yml",
    "content": "name: release all platforms\n\non:\n  workflow_dispatch:\n    inputs:\n      release_tag:\n        required: false\n        type: string\n\njobs:\n  update:\n    runs-on: ubuntu-latest\n    steps:\n\n      - name: Trigger build windows\n        if: github.event.inputs.release_tag != ''\n        run: |\n          curl -X POST \\\n            -H \"Accept: application/vnd.github.v3+json\" \\\n            -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n            https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-windows.yml/dispatches \\\n            -d \"{\n              \\\"ref\\\": \\\"master\\\",\n              \\\"inputs\\\": {\n                \\\"release_tag\\\": \\\"${{ github.event.inputs.release_tag }}\\\"\n              }\n            }\"\n\n      - name: Trigger build linux\n        if: github.event.inputs.release_tag != ''\n        run: |\n          curl -X POST \\\n            -H \"Accept: application/vnd.github.v3+json\" \\\n            -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n            https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-linux.yml/dispatches \\\n            -d \"{\n              \\\"ref\\\": \\\"master\\\",\n              \\\"inputs\\\": {\n                \\\"release_tag\\\": \\\"${{ github.event.inputs.release_tag }}\\\"\n              }\n            }\"\n\n      - name: Trigger build osx\n        if: github.event.inputs.release_tag != ''\n        run: |\n          curl -X POST \\\n            -H \"Accept: application/vnd.github.v3+json\" \\\n            -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n            https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-osx.yml/dispatches \\\n            -d \"{\n              \\\"ref\\\": \\\"master\\\",\n              \\\"inputs\\\": {\n                \\\"release_tag\\\": \\\"${{ github.event.inputs.release_tag }}\\\"\n              }\n            }\"\n\n      - name: Trigger build windows desktop\n        if: github.event.inputs.release_tag != ''\n        run: |\n          curl -X POST \\\n            -H \"Accept: application/vnd.github.v3+json\" \\\n            -H \"Authorization: token ${{ secrets.GITHUB_TOKEN }}\" \\\n            https://api.github.com/repos/${{ github.repository }}/actions/workflows/build-windows-desktop.yml/dispatches \\\n            -d \"{\n              \\\"ref\\\": \\\"master\\\",\n              \\\"inputs\\\": {\n                \\\"release_tag\\\": \\\"${{ github.event.inputs.release_tag }}\\\"\n              }\n            }\""
  },
  {
    "path": ".github/workflows/build-linux.yml",
    "content": "name: release Linux\n\non:\n  workflow_dispatch:\n    inputs:\n      release_tag:\n        required: false\n        type: string\n  push:\n    branches:\n      - master\n    tags:\n      - 'v*'\n      - 'V*'\n\npermissions:\n  contents: write\n\nenv:\n  OutputArch: \"linux-64\"\n  OutputArchArm: \"linux-arm64\"\n  OutputPath64:  \"${{ github.workspace }}/v2rayN/Release/linux-64\"\n  OutputPathArm64:  \"${{ github.workspace }}/v2rayN/Release/linux-arm64\"\n\njobs:\n  build:\n    strategy:\n      matrix:\n        configuration: [Release]\n    runs-on: ubuntu-24.04\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6.0.2\n      with:\n        submodules: 'recursive'\n        fetch-depth: '0'\n\n    - name: Setup .NET\n      uses: actions/setup-dotnet@v5.2.0\n      with:\n        dotnet-version: '8.0.x'\n\n    - name: Build\n      run: |\n        cd v2rayN\n        dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-x64   -p:SelfContained=true -o \"$OutputPath64\"\n        dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r linux-arm64 -p:SelfContained=true -o \"$OutputPathArm64\"\n        dotnet publish ./AmazTool/AmazTool.csproj             -c Release -r linux-x64   -p:SelfContained=true -p:PublishTrimmed=true -o \"$OutputPath64\"\n        dotnet publish ./AmazTool/AmazTool.csproj             -c Release -r linux-arm64 -p:SelfContained=true -p:PublishTrimmed=true -o \"$OutputPathArm64\"\n\n    - name: Upload build artifacts\n      uses: actions/upload-artifact@v7.0.0\n      with:\n        name: v2rayN-linux\n        path: |\n          ${{ github.workspace }}/v2rayN/Release/linux*\n\n    # release debian package\n    - name: Package debian\n      if: github.event.inputs.release_tag != ''\n      run: |\n        chmod 755 package-debian.sh\n        ./package-debian.sh \"$OutputArch\" \"$OutputPath64\" \"${{ github.event.inputs.release_tag }}\"\n        ./package-debian.sh \"$OutputArchArm\" \"$OutputPathArm64\" \"${{ github.event.inputs.release_tag }}\"\n\n    - name: Upload deb to release\n      uses: svenstaro/upload-release-action@v2\n      if: github.event.inputs.release_tag != ''\n      with:\n        file: ${{ github.workspace }}/v2rayN*.deb\n        tag: ${{ github.event.inputs.release_tag }}\n        file_glob: true\n        prerelease: true\n\n    # release zip archive\n    - name: Package release zip archive\n      if: github.event.inputs.release_tag != ''\n      run: |\n        chmod 755 package-release-zip.sh\n        ./package-release-zip.sh \"$OutputArch\" \"$OutputPath64\"\n        ./package-release-zip.sh \"$OutputArchArm\" \"$OutputPathArm64\"\n    \n    - name: Upload zip archive to release\n      uses: svenstaro/upload-release-action@v2\n      if: github.event.inputs.release_tag != ''\n      with:\n        file: ${{ github.workspace }}/v2rayN*.zip\n        tag: ${{ github.event.inputs.release_tag }}\n        file_glob: true\n        prerelease: true\n\n  rpm:\n    needs: build\n    if: |\n      (github.event_name == 'workflow_dispatch' && github.event.inputs.release_tag != '') ||\n      (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/'))\n    runs-on: ubuntu-24.04\n    container:\n      image: registry.access.redhat.com/ubi10/ubi\n    env:\n      RELEASE_TAG: ${{ github.event.inputs.release_tag != '' && github.event.inputs.release_tag || github.ref_name }}\n\n    steps:\n    - name: Prepare tools (Red Hat)\n      shell: bash\n      run: |\n        set -euo pipefail\n\n        . /etc/os-release\n        EL_MAJOR=\"${VERSION_ID%%.*}\"\n        echo \"EL_MAJOR=${EL_MAJOR}\"\n\n        dnf -y makecache || true\n        command -v curl >/dev/null || dnf -y install curl ca-certificates\n\n        ARCH=\"$(uname -m)\"\n        case \"$ARCH\" in x86_64|aarch64) ;; *) echo \"Unsupported arch: $ARCH\"; exit 1 ;; esac\n\n        install_epel_from_dir() {\n          local base=\"$1\" rpm\n          echo \"Try: $base\"\n\n          rpm=\"$(\n            {\n              curl -fsSL \"$base/Packages/\"   2>/dev/null\n              curl -fsSL \"$base/Packages/e/\" 2>/dev/null | sed 's|href=\"|href=\"e/|'\n            } |\n            sed -n 's/.*href=\"\\([^\"]*epel-release-[^\"]*\\.noarch\\.rpm\\)\".*/\\1/p' |\n            sort -V | tail -n1\n          )\" || true\n\n          if [[ -n \"$rpm\" ]]; then\n            dnf -y install \"$base/Packages/$rpm\"\n            return 0\n          fi\n          return 1\n        }\n\n        FEDORA=\"https://dl.fedoraproject.org/pub/epel/epel-release-latest-${EL_MAJOR}.noarch.rpm\"\n        echo \"Try Fedora: $FEDORA\"\n\n        if curl -fsSLI \"$FEDORA\" >/dev/null; then\n          dnf -y install \"$FEDORA\"\n        else\n          ROCKY=\"https://dl.rockylinux.org/pub/rocky/${EL_MAJOR}/extras/${ARCH}/os\"\n          if install_epel_from_dir \"$ROCKY\"; then\n            :\n          else\n            ALMA=\"https://repo.almalinux.org/almalinux/${EL_MAJOR}/extras/${ARCH}/os\"\n            if install_epel_from_dir \"$ALMA\"; then\n              :\n            else\n              echo \"EPEL bootstrap failed (Fedora/Rocky/Alma)\"\n              exit 1\n            fi\n          fi\n        fi\n\n        dnf -y install sudo git rpm-build rpmdevtools dnf-plugins-core \\\n                       rsync findutils tar gzip unzip which\n\n        dnf repolist | grep -i epel || true\n\n    - name: Checkout repo (for scripts)\n      uses: actions/checkout@v6.0.2\n      with:\n        submodules: 'recursive'\n        fetch-depth: '0'\n\n    - name: Restore build artifacts\n      uses: actions/download-artifact@v8\n      with:\n        name: v2rayN-linux\n        path: ${{ github.workspace }}/v2rayN/Release\n\n    - name: Ensure script permissions\n      run: chmod 755 package-rhel.sh\n\n    - name: Package RPM (RHEL-family)\n      run: ./package-rhel.sh \"${RELEASE_TAG}\" --arch all\n\n    - name: Collect RPMs into workspace\n      run: |\n        mkdir -p \"$GITHUB_WORKSPACE/dist/rpm\"\n        rsync -av \"$HOME/rpmbuild/RPMS/\" \"$GITHUB_WORKSPACE/dist/rpm/\" || true\n        find \"$GITHUB_WORKSPACE/dist/rpm\" -name \"v2rayN-*-1*.x86_64.rpm\"  -exec mv {} \"$GITHUB_WORKSPACE/dist/rpm/v2rayN-linux-rhel-64.rpm\" \\;  || true\n        find \"$GITHUB_WORKSPACE/dist/rpm\" -name \"v2rayN-*-1*.aarch64.rpm\" -exec mv {} \"$GITHUB_WORKSPACE/dist/rpm/v2rayN-linux-rhel-arm64.rpm\" \\; || true\n        echo \"==== Dist tree ====\"\n        ls -R \"$GITHUB_WORKSPACE/dist/rpm\" || true\n\n    - name: Upload RPM artifacts\n      uses: actions/upload-artifact@v7.0.0\n      with:\n        name: v2rayN-rpm\n        path: dist/rpm/**/*.rpm\n\n    - name: Upload RPMs to release\n      uses: svenstaro/upload-release-action@v2\n      with:\n        file: dist/rpm/**/*.rpm\n        tag: ${{ env.RELEASE_TAG }}\n        file_glob: true\n        prerelease: true\n"
  },
  {
    "path": ".github/workflows/build-osx.yml",
    "content": "name: release macOS\n\non:\n  workflow_dispatch:\n    inputs:\n      release_tag:\n        required: false\n        type: string\n  push:\n    branches:\n      - master\n\nenv:\n  OutputArch: \"macos-64\"\n  OutputArchArm: \"macos-arm64\"\n  OutputPath64:  \"${{ github.workspace }}/v2rayN/Release/macos-64\"\n  OutputPathArm64:  \"${{ github.workspace }}/v2rayN/Release/macos-arm64\"\n\njobs:\n  build:\n    strategy:\n      matrix:\n        configuration: [Release]\n\n    runs-on: macos-latest\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6.0.2\n      with:\n        submodules: 'recursive'\n        fetch-depth: '0'\n\n    - name: Setup\n      uses: actions/setup-dotnet@v5.2.0\n      with:\n        dotnet-version: '8.0.x'\n\n    - name: Build\n      run: |\n        cd v2rayN \n        dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-x64   -p:SelfContained=true -o $OutputPath64\n        dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r osx-arm64 -p:SelfContained=true -o $OutputPathArm64\n        dotnet publish ./AmazTool/AmazTool.csproj             -c Release -r osx-x64   -p:SelfContained=true -p:PublishTrimmed=true -o $OutputPath64\n        dotnet publish ./AmazTool/AmazTool.csproj             -c Release -r osx-arm64 -p:SelfContained=true -p:PublishTrimmed=true -o $OutputPathArm64\n\n    - name: Upload build artifacts\n      uses: actions/upload-artifact@v7.0.0\n      with:\n        name: v2rayN-macos\n        path: |\n          ${{ github.workspace }}/v2rayN/Release/macos*\n    \n    # release osx package\n    - name: Package osx\n      if: github.event.inputs.release_tag != ''\n      run: |\n        brew install create-dmg\n        chmod 755 package-osx.sh\n        ./package-osx.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }}\n        ./package-osx.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}\n    \n    - name: Upload dmg to release\n      uses: svenstaro/upload-release-action@v2\n      if: github.event.inputs.release_tag != ''\n      with:\n        file: ${{ github.workspace }}/v2rayN*.dmg\n        tag: ${{ github.event.inputs.release_tag }}\n        file_glob: true\n        prerelease: true\n\n    # release zip archive\n    - name: Package release zip archive\n      if: github.event.inputs.release_tag != ''\n      run: |\n        chmod 755 package-release-zip.sh\n        ./package-release-zip.sh $OutputArch $OutputPath64\n        ./package-release-zip.sh $OutputArchArm $OutputPathArm64\n    \n    - name: Upload zip archive to release\n      uses: svenstaro/upload-release-action@v2\n      if: github.event.inputs.release_tag != ''\n      with:\n        file: ${{ github.workspace }}/v2rayN*.zip\n        tag: ${{ github.event.inputs.release_tag }}\n        file_glob: true\n        prerelease: true"
  },
  {
    "path": ".github/workflows/build-windows-desktop.yml",
    "content": "name: release Windows desktop (Avalonia UI)\n\non:\n  workflow_dispatch:\n    inputs:\n      release_tag:\n        required: false\n        type: string\n  push:\n    branches:\n      - master\n\nenv:\n  OutputArch: \"windows-64\"\n  OutputArchArm: \"windows-arm64\"\n  OutputPath64:  \"${{ github.workspace }}/v2rayN/Release/windows-64\"\n  OutputPathArm64:  \"${{ github.workspace }}/v2rayN/Release/windows-arm64\"\n\njobs:\n  build:\n    strategy:\n      matrix:\n        configuration: [Release]\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6.0.2\n      with:\n        submodules: 'recursive'\n        fetch-depth: '0'\n\n    - name: Setup\n      uses: actions/setup-dotnet@v5.2.0\n      with:\n        dotnet-version: '8.0.x'\n\n    - name: Build\n      run: |\n        cd v2rayN \n        dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-x64   -p:SelfContained=true -p:EnableWindowsTargeting=true -o $OutputPath64\n        dotnet publish ./v2rayN.Desktop/v2rayN.Desktop.csproj -c Release -r win-arm64 -p:SelfContained=true -p:EnableWindowsTargeting=true -o $OutputPathArm64\n        dotnet publish ./AmazTool/AmazTool.csproj             -c Release -r win-x64   -p:SelfContained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64\n        dotnet publish ./AmazTool/AmazTool.csproj             -c Release -r win-arm64 -p:SelfContained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64\n\n    - name: Upload build artifacts\n      uses: actions/upload-artifact@v7.0.0\n      with:\n        name: v2rayN-windows-desktop\n        path: |\n          ${{ github.workspace }}/v2rayN/Release/windows*\n\n    # release zip archive\n    - name: Package release zip archive\n      if: github.event.inputs.release_tag != ''\n      run: |\n        chmod 755 package-release-zip.sh\n        ./package-release-zip.sh $OutputArch $OutputPath64\n        mv \"v2rayN-${OutputArch}.zip\" \"v2rayN-${OutputArch}-desktop.zip\"\n        ./package-release-zip.sh $OutputArchArm $OutputPathArm64\n        mv \"v2rayN-${OutputArchArm}.zip\" \"v2rayN-${OutputArchArm}-desktop.zip\"\n\n    - name: Upload zip archive to release\n      uses: svenstaro/upload-release-action@v2\n      if: github.event.inputs.release_tag != ''\n      with:\n        file: ${{ github.workspace }}/v2rayN*.zip\n        tag: ${{ github.event.inputs.release_tag }}\n        file_glob: true\n        prerelease: true\n"
  },
  {
    "path": ".github/workflows/build-windows.yml",
    "content": "name: release Windows\n\non:\n  workflow_dispatch:\n    inputs:\n      release_tag:\n        required: false\n        type: string\n  push:\n    branches:\n      - master\n\nenv:\n  OutputArch: \"windows-64\"\n  OutputArchArm: \"windows-arm64\"\n  OutputPath64:  \"${{ github.workspace }}/v2rayN/Release/windows-64\"\n  OutputPathArm64:  \"${{ github.workspace }}/v2rayN/Release/windows-arm64\"\n\njobs:\n  build:\n    strategy:\n      matrix:\n        configuration: [Release]\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - name: Checkout\n      uses: actions/checkout@v6.0.2\n\n    - name: Setup\n      uses: actions/setup-dotnet@v5.2.0\n      with:\n        dotnet-version: '8.0.x'\n\n    - name: Build\n      run: |\n        cd v2rayN \n        dotnet publish ./v2rayN/v2rayN.csproj     -c Release -r win-x64   -p:SelfContained=true -p:EnableWindowsTargeting=true -o $OutputPath64\n        dotnet publish ./v2rayN/v2rayN.csproj     -c Release -r win-arm64 -p:SelfContained=true -p:EnableWindowsTargeting=true -o $OutputPathArm64\n        dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-x64   -p:SelfContained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPath64\n        dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 -p:SelfContained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64\n  \n    - name: Upload build artifacts\n      uses: actions/upload-artifact@v7.0.0\n      with:\n        name: v2rayN-windows\n        path: |\n          ${{ github.workspace }}/v2rayN/Release/windows*\n    \n    # release zip archive\n    - name: Package release zip archive\n      if: github.event.inputs.release_tag != ''\n      run: |\n        chmod 755 package-release-zip.sh\n        ./package-release-zip.sh $OutputArch $OutputPath64\n        ./package-release-zip.sh $OutputArchArm $OutputPathArm64\n    \n    - name: Upload zip archive to release\n      uses: svenstaro/upload-release-action@v2\n      if: github.event.inputs.release_tag != ''\n      with:\n        file: ${{ github.workspace }}/v2rayN*.zip\n        tag: ${{ github.event.inputs.release_tag }}\n        file_glob: true\n        prerelease: true\n"
  },
  {
    "path": ".github/workflows/winget-publish.yml",
    "content": "name: WinGet submission on release\n# based off of https://github.com/nushell/nushell/blob/main/.github/workflows/winget-submission.yml\n# inspired by https://github.com/microsoft/PowerToys/blob/main/.github/workflows/package-submissions.yml\n# Modified by @MerrickZ https://github.com/anpho\n\non:\n  workflow_dispatch:\n  release:\n    types: [released]\n\njobs:\n  winget:\n    name: Publish winget package\n    runs-on: windows-latest\n    steps:\n      - name: Submit v2ray package to Windows Package Manager Community Repository\n        run: |\n\n          $wingetPackage = \"2dust.v2rayN\"\n          $gitToken = \"${{ secrets.PT_WINGET }}\"\n\n          $github = Invoke-RestMethod -uri \"https://api.github.com/repos/2dust/v2rayN/releases\" \n\n          $targetRelease = $github | Where-Object -Property prerelease -match 'False' | Select -First 1\n          \n          $x64InstallerUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'v2rayN-windows-64\\.zip' | Select -ExpandProperty browser_download_url\n          $arm64InstallerUrl = $targetRelease | Select -ExpandProperty assets -First 1 | Where-Object -Property name -match 'v2rayN-windows-arm64\\.zip' | Select -ExpandProperty browser_download_url\n          \n          $ver = $targetRelease.tag_name\n\n          # getting latest wingetcreate file\n          iwr https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe\n          \n          Write-Host \"Updating with both x64 and arm64 installers\"\n          Write-Host \"Version: $ver\"\n          Write-Host \"x64 URL: $x64InstallerUrl\"\n          Write-Host \"arm64 URL: $arm64InstallerUrl\"\n          \n          .\\wingetcreate.exe update $wingetPackage -s -v $ver -u \"$x64InstallerUrl|x64\" \"$arm64InstallerUrl|arm64\" -t $gitToken\n"
  },
  {
    "path": ".gitignore",
    "content": "﻿## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore\n\n# User-specific files\n*.rsuser\n*.suo\n*.user\n*.userosscache\n*.sln.docstates\n\n# User-specific files (MonoDevelop/Xamarin Studio)\n*.userprefs\n\n# Mono auto generated files\nmono_crash.*\n\n# Build results\n[Dd]ebug/\n[Dd]ebugPublic/\n[Rr]elease/\n[Rr]eleases/\nx64/\nx86/\n[Ww][Ii][Nn]32/\n[Aa][Rr][Mm]/\n[Aa][Rr][Mm]64/\nbld/\n[Bb]in/\n[Oo]bj/\n[Ll]og/\n[Ll]ogs/\n\n# Visual Studio 2015/2017 cache/options directory\n.vs/\n# Uncomment if you have tasks that create the project's static files in wwwroot\n#wwwroot/\n\n# Visual Studio 2017 auto generated files\nGenerated\\ Files/\n\n# MSTest test Results\n[Tt]est[Rr]esult*/\n[Bb]uild[Ll]og.*\n\n# NUnit\n*.VisualState.xml\nTestResult.xml\nnunit-*.xml\n\n# Build Results of an ATL Project\n[Dd]ebugPS/\n[Rr]eleasePS/\ndlldata.c\n\n# Benchmark Results\nBenchmarkDotNet.Artifacts/\n\n# .NET Core\nproject.lock.json\nproject.fragment.lock.json\nartifacts/\n\n# ASP.NET Scaffolding\nScaffoldingReadMe.txt\n\n# StyleCop\nStyleCopReport.xml\n\n# Files built by Visual Studio\n*_i.c\n*_p.c\n*_h.h\n*.ilk\n*.meta\n*.obj\n*.iobj\n*.pch\n*.pdb\n*.ipdb\n*.pgc\n*.pgd\n*.rsp\n# but not Directory.Build.rsp, as it configures directory-level build defaults\n!Directory.Build.rsp\n*.sbr\n*.tlb\n*.tli\n*.tlh\n*.tmp\n*.tmp_proj\n*_wpftmp.csproj\n*.log\n*.tlog\n*.vspscc\n*.vssscc\n.builds\n*.pidb\n*.svclog\n*.scc\n\n# Chutzpah Test files\n_Chutzpah*\n\n# Visual C++ cache files\nipch/\n*.aps\n*.ncb\n*.opendb\n*.opensdf\n*.sdf\n*.cachefile\n*.VC.db\n*.VC.VC.opendb\n\n# Visual Studio profiler\n*.psess\n*.vsp\n*.vspx\n*.sap\n\n# Visual Studio Trace Files\n*.e2e\n\n# TFS 2012 Local Workspace\n$tf/\n\n# Guidance Automation Toolkit\n*.gpState\n\n# ReSharper is a .NET coding add-in\n_ReSharper*/\n*.[Rr]e[Ss]harper\n*.DotSettings.user\n\n# TeamCity is a build add-in\n_TeamCity*\n\n# DotCover is a Code Coverage Tool\n*.dotCover\n\n# AxoCover is a Code Coverage Tool\n.axoCover/*\n!.axoCover/settings.json\n\n# Coverlet is a free, cross platform Code Coverage Tool\ncoverage*.json\ncoverage*.xml\ncoverage*.info\n\n# Visual Studio code coverage results\n*.coverage\n*.coveragexml\n\n# NCrunch\n_NCrunch_*\n.*crunch*.local.xml\nnCrunchTemp_*\n\n# MightyMoose\n*.mm.*\nAutoTest.Net/\n\n# Web workbench (sass)\n.sass-cache/\n\n# Installshield output folder\n[Ee]xpress/\n\n# DocProject is a documentation generator add-in\nDocProject/buildhelp/\nDocProject/Help/*.HxT\nDocProject/Help/*.HxC\nDocProject/Help/*.hhc\nDocProject/Help/*.hhk\nDocProject/Help/*.hhp\nDocProject/Help/Html2\nDocProject/Help/html\n\n# Click-Once directory\npublish/\n\n# Publish Web Output\n*.[Pp]ublish.xml\n*.azurePubxml\n# Note: Comment the next line if you want to checkin your web deploy settings,\n# but database connection strings (with potential passwords) will be unencrypted\n*.pubxml\n*.publishproj\n\n# Microsoft Azure Web App publish settings. Comment the next line if you want to\n# checkin your Azure Web App publish settings, but sensitive information contained\n# in these scripts will be unencrypted\nPublishScripts/\n\n# NuGet Packages\n*.nupkg\n# NuGet Symbol Packages\n*.snupkg\n# The packages folder can be ignored because of Package Restore\n**/[Pp]ackages/*\n# except build/, which is used as an MSBuild target.\n!**/[Pp]ackages/build/\n# Uncomment if necessary however generally it will be regenerated when needed\n#!**/[Pp]ackages/repositories.config\n# NuGet v3's project.json files produces more ignorable files\n*.nuget.props\n*.nuget.targets\n\n# Microsoft Azure Build Output\ncsx/\n*.build.csdef\n\n# Microsoft Azure Emulator\necf/\nrcf/\n\n# Windows Store app package directories and files\nAppPackages/\nBundleArtifacts/\nPackage.StoreAssociation.xml\n_pkginfo.txt\n*.appx\n*.appxbundle\n*.appxupload\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\n# Others\nClientBin/\n~$*\n*~\n*.dbmdl\n*.dbproj.schemaview\n*.jfm\n*.pfx\n*.publishsettings\norleans.codegen.cs\n\n# Including strong name files can present a security risk\n# (https://github.com/github/gitignore/pull/2483#issue-259490424)\n#*.snk\n\n# Since there are multiple workflows, uncomment next line to ignore bower_components\n# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)\n#bower_components/\n\n# RIA/Silverlight projects\nGenerated_Code/\n\n# Backup & report files from converting an old project file\n# to a newer Visual Studio version. Backup files are not needed,\n# because we have git ;-)\n_UpgradeReport_Files/\nBackup*/\nUpgradeLog*.XML\nUpgradeLog*.htm\nServiceFabricBackup/\n*.rptproj.bak\n\n# SQL Server files\n*.mdf\n*.ldf\n*.ndf\n\n# Business Intelligence projects\n*.rdl.data\n*.bim.layout\n*.bim_*.settings\n*.rptproj.rsuser\n*- [Bb]ackup.rdl\n*- [Bb]ackup ([0-9]).rdl\n*- [Bb]ackup ([0-9][0-9]).rdl\n\n# Microsoft Fakes\nFakesAssemblies/\n\n# GhostDoc plugin setting file\n*.GhostDoc.xml\n\n# Node.js Tools for Visual Studio\n.ntvs_analysis.dat\nnode_modules/\n\n# Visual Studio 6 build log\n*.plg\n\n# Visual Studio 6 workspace options file\n*.opt\n\n# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)\n*.vbw\n\n# Visual Studio 6 auto-generated project file (contains which files were open etc.)\n*.vbp\n\n# Visual Studio 6 workspace and project file (working project files containing files to include in project)\n*.dsw\n*.dsp\n\n# Visual Studio 6 technical files\n*.ncb\n*.aps\n\n# Visual Studio LightSwitch build output\n**/*.HTMLClient/GeneratedArtifacts\n**/*.DesktopClient/GeneratedArtifacts\n**/*.DesktopClient/ModelManifest.xml\n**/*.Server/GeneratedArtifacts\n**/*.Server/ModelManifest.xml\n_Pvt_Extensions\n\n# Paket dependency manager\n.paket/paket.exe\npaket-files/\n\n# FAKE - F# Make\n.fake/\n\n# CodeRush personal settings\n.cr/personal\n\n# Python Tools for Visual Studio (PTVS)\n__pycache__/\n*.pyc\n\n# Cake - Uncomment if you are using it\n# tools/**\n# !tools/packages.config\n\n# Tabs Studio\n*.tss\n\n# Telerik's JustMock configuration file\n*.jmconfig\n\n# BizTalk build output\n*.btp.cs\n*.btm.cs\n*.odx.cs\n*.xsd.cs\n\n# OpenCover UI analysis results\nOpenCover/\n\n# Azure Stream Analytics local run output\nASALocalRun/\n\n# MSBuild Binary and Structured Log\n*.binlog\n\n# NVidia Nsight GPU debugger configuration file\n*.nvuser\n\n# MFractors (Xamarin productivity tool) working folder\n.mfractor/\n\n# Local History for Visual Studio\n.localhistory/\n\n# Visual Studio History (VSHistory) files\n.vshistory/\n\n# BeatPulse healthcheck temp database\nhealthchecksdb\n\n# Backup folder for Package Reference Convert tool in Visual Studio 2017\nMigrationBackup/\n\n# Ionide (cross platform F# VS Code tools) working folder\n.ionide/\n\n# Fody - auto-generated XML schema\nFodyWeavers.xsd\n\n# VS Code files for those working on multiple tools\n.vscode/*\n!.vscode/settings.json\n!.vscode/tasks.json\n!.vscode/launch.json\n!.vscode/extensions.json\n*.code-workspace\n\n# Local History for Visual Studio Code\n.history/\n\n# Windows Installer files from build outputs\n*.cab\n*.msi\n*.msix\n*.msm\n*.msp\n\n# JetBrains Rider\n.idea/\n*.sln.iml\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"v2rayN/GlobalHotKeys\"]\n\tpath = v2rayN/GlobalHotKeys\n\turl = https://github.com/2dust/GlobalHotKeys\n"
  },
  {
    "path": "LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification 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\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe 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\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, 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\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, 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.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy 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\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where 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) 2019-Present  2dust\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\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    v2rayN  Copyright (C) 2019-Present  2dust\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\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.md",
    "content": "# v2rayN\n\nA GUI client for Windows, Linux and macOS, support [Xray](https://github.com/XTLS/Xray-core)\nand [sing-box](https://github.com/SagerNet/sing-box)\nand [others](https://github.com/2dust/v2rayN/wiki/List-of-supported-cores)\n\n[![GitHub commit activity](https://img.shields.io/github/commit-activity/m/2dust/v2rayN)](https://github.com/2dust/v2rayN/commits/master)\n[![CodeFactor](https://www.codefactor.io/repository/github/2dust/v2rayn/badge)](https://www.codefactor.io/repository/github/2dust/v2rayn)\n[![GitHub Releases](https://img.shields.io/github/downloads/2dust/v2rayN/latest/total?logo=github)](https://github.com/2dust/v2rayN/releases)\n[![Chat on Telegram](https://img.shields.io/badge/Chat%20on-Telegram-brightgreen.svg)](https://t.me/v2rayn)\n\n## How to use\n\nRead the [Wiki](https://github.com/2dust/v2rayN/wiki) for details.\n\n## Telegram Channel\n\n[github_2dust](https://t.me/github_2dust)\n"
  },
  {
    "path": "package-debian.sh",
    "content": "#!/bin/bash\n\nArch=\"$1\"\nOutputPath=\"$2\"\nVersion=\"$3\"\n\nFileName=\"v2rayN-${Arch}.zip\"\nwget -nv -O $FileName \"https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName\"\n7z x $FileName\ncp -rf v2rayN-${Arch}/* $OutputPath\n\nPackagePath=\"v2rayN-Package-${Arch}\"\nmkdir -p \"${PackagePath}/DEBIAN\"\nmkdir -p \"${PackagePath}/opt\"\ncp -rf $OutputPath \"${PackagePath}/opt/v2rayN\"\necho \"When this file exists, app will not store configs under this folder\" > \"${PackagePath}/opt/v2rayN/NotStoreConfigHere.txt\"\n\nif [ $Arch = \"linux-64\" ]; then\n    Arch2=\"amd64\"\nelse\n    Arch2=\"arm64\"\nfi\necho $Arch2\n\n# basic\ncat >\"${PackagePath}/DEBIAN/control\" <<-EOF\nPackage: v2rayN\nVersion: $Version\nArchitecture: $Arch2\nMaintainer: https://github.com/2dust/v2rayN\nDepends: libc6 (>= 2.34), fontconfig (>= 2.13.1), desktop-file-utils (>= 0.26), xdg-utils (>= 1.1.3), coreutils (>= 8.32), bash (>= 5.1), libfreetype6 (>= 2.11)\nDescription: A GUI client for Windows and Linux, support Xray core and sing-box-core and others\nEOF\n\nmkdir -p \"${PackagePath}/usr/share/applications\"\ncat >\"${PackagePath}/usr/share/applications/v2rayN.desktop\" <<-EOF\n[Desktop Entry]\nName=v2rayN\nComment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others\nExec=/opt/v2rayN/v2rayN\nIcon=/opt/v2rayN/v2rayN.png\nTerminal=false\nType=Application\nCategories=Network;Application;\nEOF\n\ncat >\"${PackagePath}/DEBIAN/postinst\" <<-'EOF'\nset -e\nupdate-desktop-database || true\nexit 0\nEOF\n\nsudo chmod 0755 \"${PackagePath}/DEBIAN/postinst\"\nsudo chmod 0755 \"${PackagePath}/opt/v2rayN/v2rayN\"\nsudo chmod 0755 \"${PackagePath}/opt/v2rayN/AmazTool\"\n\n# Patch\n# set owner to root:root\nsudo chown -R root:root \"${PackagePath}\"\n# set all directories to 755 (readable & traversable by all users)\nsudo find \"${PackagePath}/opt/v2rayN\" -type d -exec chmod 755 {} +\n# set all regular files to 644 (readable by all users)\nsudo find \"${PackagePath}/opt/v2rayN\" -type f -exec chmod 644 {} +\n# ensure main binaries are 755 (executable by all users)\nsudo chmod 755 \"${PackagePath}/opt/v2rayN/v2rayN\" 2>/dev/null || true\nsudo chmod 755 \"${PackagePath}/opt/v2rayN/AmazTool\" 2>/dev/null || true\n\n# build deb package\nsudo dpkg-deb -Zxz --build $PackagePath\nsudo mv \"${PackagePath}.deb\" \"v2rayN-${Arch}.deb\"\n"
  },
  {
    "path": "package-osx.sh",
    "content": "#!/bin/bash\n\nArch=\"$1\"\nOutputPath=\"$2\"\nVersion=\"$3\"\n\nFileName=\"v2rayN-${Arch}.zip\"\nwget -nv -O $FileName \"https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName\"\n7z x $FileName\ncp -rf v2rayN-${Arch}/* $OutputPath\n\nPackagePath=\"v2rayN-Package-${Arch}\"\nmkdir -p \"$PackagePath/v2rayN.app/Contents/Resources\"\ncp -rf \"$OutputPath\" \"$PackagePath/v2rayN.app/Contents/MacOS\"\ncp -f \"$PackagePath/v2rayN.app/Contents/MacOS/v2rayN.icns\" \"$PackagePath/v2rayN.app/Contents/Resources/AppIcon.icns\"\necho \"When this file exists, app will not store configs under this folder\" > \"$PackagePath/v2rayN.app/Contents/MacOS/NotStoreConfigHere.txt\"\nchmod +x \"$PackagePath/v2rayN.app/Contents/MacOS/v2rayN\"\n\ncat >\"$PackagePath/v2rayN.app/Contents/Info.plist\" <<-EOF\n<?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>English</string>\n  <key>CFBundleDisplayName</key>\n  <string>v2rayN</string>\n  <key>CFBundleExecutable</key>\n  <string>v2rayN</string>\n  <key>CFBundleIconFile</key>\n  <string>AppIcon</string>\n  <key>CFBundleIconName</key>\n  <string>AppIcon</string>\n  <key>CFBundleIdentifier</key>\n  <string>2dust.v2rayN</string>\n  <key>CFBundleName</key>\n  <string>v2rayN</string>\n  <key>CFBundlePackageType</key>\n  <string>APPL</string>\n  <key>CFBundleShortVersionString</key>\n  <string>${Version}</string>\n  <key>CSResourcesFileMapped</key>\n  <true/>\n  <key>NSHighResolutionCapable</key>\n  <true/>\n  <key>LSMinimumSystemVersion</key>\n  <string>12.7</string>\n</dict>\n</plist>\nEOF\n\ncreate-dmg \\\n    --volname \"v2rayN Installer\" \\\n    --window-size 700 420 \\\n    --icon-size 100 \\\n    --icon \"v2rayN.app\" 160 185 \\\n    --hide-extension \"v2rayN.app\" \\\n    --app-drop-link 500 185 \\\n    \"v2rayN-${Arch}.dmg\" \\\n    \"$PackagePath/v2rayN.app\"\n"
  },
  {
    "path": "package-release-zip.sh",
    "content": "#!/bin/bash\n\nArch=\"$1\"\nOutputPath=\"$2\"\n\nOutputArch=\"v2rayN-${Arch}\"\nFileName=\"v2rayN-${Arch}.zip\"\n\nwget -nv -O $FileName \"https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName\"\n\nZipPath64=\"./$OutputArch\"\nmkdir $ZipPath64\n\ncp -rf $OutputPath \"$ZipPath64/$OutputArch\"\n7z a -tZip $FileName \"$ZipPath64/$OutputArch\" -mx1"
  },
  {
    "path": "package-rhel.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\n# Require Red Hat base branch\n. /etc/os-release\n\ncase \"${ID:-}\" in\n  rhel|rocky|almalinux|fedora|centos)\n    echo \"Detected supported system: ${NAME:-$ID} ${VERSION_ID:-}\"\n    ;;\n  *)\n    echo \"Unsupported system: ${NAME:-unknown} (${ID:-unknown}).\"\n    echo \"This script only supports: RHEL / Rocky / AlmaLinux / Fedora / CentOS.\"\n    exit 1\n    ;;\nesac\n\n# Kernel version\nMIN_KERNEL=\"6.11\"\nCURRENT_KERNEL=\"$(uname -r)\"\n\nlowest=\"$(printf '%s\\n%s\\n' \"$MIN_KERNEL\" \"$CURRENT_KERNEL\" | sort -V | head -n1)\"\n\nif [[ \"$lowest\" != \"$MIN_KERNEL\" ]]; then\n    echo \"Kernel $CURRENT_KERNEL is below $MIN_KERNEL\"\n    exit 1\nfi\n\necho \"[OK] Kernel $CURRENT_KERNEL verified.\"\n\n# Config & Parse arguments\nVERSION_ARG=\"${1:-}\"     # Pass version number like 7.13.8, or leave empty\nWITH_CORE=\"both\"         # Default: bundle both xray+sing-box\nFORCE_NETCORE=0          # --netcore => skip archive bundle, use separate downloads\nARCH_OVERRIDE=\"\"         # --arch x64|arm64|all (optional compile target)\nBUILD_FROM=\"\"            # --buildfrom 1|2|3 to select channel non-interactively\n\n# If the first argument starts with --, do not treat it as a version number\nif [[ \"${VERSION_ARG:-}\" == --* ]]; then\n  VERSION_ARG=\"\"\nfi\n# Take the first non --* argument as version, discard it\nif [[ -n \"${VERSION_ARG:-}\" ]]; then shift || true; fi\n\n# Parse remaining optional arguments\nwhile [[ $# -gt 0 ]]; do\n  case \"$1\" in\n    --with-core)     WITH_CORE=\"${2:-both}\"; shift 2;;\n    --xray-ver)      XRAY_VER=\"${2:-}\"; shift 2;;\n    --singbox-ver)   SING_VER=\"${2:-}\"; shift 2;;\n    --netcore)       FORCE_NETCORE=1; shift;;\n    --arch)          ARCH_OVERRIDE=\"${2:-}\"; shift 2;;\n    --buildfrom)     BUILD_FROM=\"${2:-}\"; shift 2;;\n    *)\n      if [[ -z \"${VERSION_ARG:-}\" ]]; then VERSION_ARG=\"$1\"; fi\n      shift;;\n  esac\ndone\n\n# Conflict: version number AND --buildfrom cannot be used together\nif [[ -n \"${VERSION_ARG:-}\" && -n \"${BUILD_FROM:-}\" ]]; then\n  echo \"You cannot specify both an explicit version and --buildfrom at the same time.\"\n  echo \"        Provide either a version (e.g. 7.14.0) OR --buildfrom 1|2|3.\"\n  exit 1\nfi\n\n# Check and install dependencies\nhost_arch=\"$(uname -m)\"\n[[ \"$host_arch\" == \"aarch64\" || \"$host_arch\" == \"x86_64\" ]] || { echo \"Only supports aarch64 / x86_64\"; exit 1; }\n\ninstall_ok=0\n\nif command -v dnf >/dev/null 2>&1; then\n  sudo dnf -y install rpm-build rpmdevtools curl unzip tar jq rsync dotnet-sdk-8.0 \\\n    && install_ok=1\nfi\n\nif [[ \"$install_ok\" -ne 1 ]]; then\n  echo \"Could not auto-install dependencies for '$ID'. Make sure these are available:\"\n  echo \"dotnet-sdk 8.x, curl, unzip, tar, rsync, rpm, rpmdevtools, rpm-build (on Red Hat branch)\"\nfi\n\n# Root directory\nSCRIPT_DIR=\"$(cd -- \"$(dirname -- \"${BASH_SOURCE[0]}\")\" && pwd)\"\ncd \"$SCRIPT_DIR\"\n\n# Git submodules (best effort)\nif [[ -f .gitmodules ]]; then\n  git submodule sync --recursive || true\n  git submodule update --init --recursive || true\nfi\n\n# Locate project\nPROJECT=\"v2rayN.Desktop/v2rayN.Desktop.csproj\"\nif [[ ! -f \"$PROJECT\" ]]; then\n  PROJECT=\"$(find . -maxdepth 3 -name 'v2rayN.Desktop.csproj' | head -n1 || true)\"\nfi\n[[ -f \"$PROJECT\" ]] || { echo \"v2rayN.Desktop.csproj not found\"; exit 1; }\n\nchoose_channel() {\n  # If --buildfrom provided, map it directly and skip interaction.\n  if [[ -n \"${BUILD_FROM:-}\" ]]; then\n    case \"$BUILD_FROM\" in\n      1) echo \"latest\"; return 0;;\n      2) echo \"prerelease\"; return 0;;\n      3) echo \"keep\"; return 0;;\n      *) echo \"[ERROR] Invalid --buildfrom value: ${BUILD_FROM}. Use 1|2|3.\" >&2; exit 1;;\n    esac\n  fi\n\n  # Print menu to stderr and read from /dev/tty so stdout only carries the token.\n  local ch=\"latest\" sel=\"\"\n\n  if [[ -t 0 ]]; then\n    echo \"[?] Choose v2rayN release channel:\" >&2\n    echo \"    1) Latest (stable)  [default]\" >&2\n    echo \"    2) Pre-release (preview)\" >&2\n    echo \"    3) Keep current (do nothing)\" >&2\n    printf \"Enter 1, 2 or 3 [default 1]: \" >&2\n\n    if read -r sel </dev/tty; then\n      case \"${sel:-}\" in\n        2) ch=\"prerelease\" ;;\n        3) ch=\"keep\" ;;\n      esac\n    fi\n  fi\n\n  echo \"$ch\"\n}\n\nget_latest_tag_latest() {\n  curl -fsSL \"https://api.github.com/repos/2dust/v2rayN/releases/latest\" \\\n    | jq -re '.tag_name' \\\n    | sed 's/^v//'\n}\n\nget_latest_tag_prerelease() {\n  curl -fsSL \"https://api.github.com/repos/2dust/v2rayN/releases?per_page=20\" \\\n    | jq -re 'first(.[] | select(.prerelease == true) | .tag_name)' \\\n    | sed 's/^v//'\n}\n\ngit_try_checkout() {\n  # Try a series of refs and checkout when found.\n  local want=\"$1\" ref=\"\"\n  if git rev-parse --git-dir >/dev/null 2>&1; then\n    git fetch --tags --force --prune --depth=1 || true\n    if git rev-parse \"refs/tags/${want}\" >/dev/null 2>&1; then\n      ref=\"${want}\"\n    fi\n    if [[ -n \"$ref\" ]]; then\n      echo \"[OK] Found ref '${ref}', checking out...\"\n      git checkout -f \"${ref}\"\n      if [[ -f .gitmodules ]]; then\n        git submodule sync --recursive || true\n        git submodule update --init --recursive || true\n      fi\n      return 0\n    fi\n  fi\n  return 1\n}\n\napply_channel_or_keep() {\n  local ch=\"$1\" tag\n\n  if [[ \"$ch\" == \"keep\" ]]; then\n    echo \"[*] Keep current repository state (no checkout).\"\n    VERSION=\"$(git describe --tags --abbrev=0 2>/dev/null || echo '0.0.0+git')\"\n    VERSION=\"${VERSION#v}\"\n    return 0\n  fi\n\n  echo \"[*] Resolving ${ch} tag from GitHub releases...\"\n  if [[ \"$ch\" == \"prerelease\" ]]; then\n    tag=\"$(get_latest_tag_prerelease || true)\"\n  else\n    tag=\"$(get_latest_tag_latest || true)\"\n  fi\n\n  [[ -n \"$tag\" ]] || { echo \"Failed to resolve latest tag for channel '${ch}'.\"; exit 1; }\n  echo \"[*] Latest tag for '${ch}': ${tag}\"\n  git_try_checkout \"$tag\" || { echo \"Failed to checkout '${tag}'.\"; exit 1; }\n  VERSION=\"${tag#v}\"\n}\n\nif git rev-parse --git-dir >/dev/null 2>&1; then\n  if [[ -n \"${VERSION_ARG:-}\" ]]; then\n    clean_ver=\"${VERSION_ARG#v}\"\n    if git_try_checkout \"$clean_ver\"; then\n      VERSION=\"$clean_ver\"\n    else\n      echo \"[WARN] Tag '${VERSION_ARG}' not found.\"\n      ch=\"$(choose_channel)\"\n      apply_channel_or_keep \"$ch\"\n    fi\n  else\n    ch=\"$(choose_channel)\"\n    apply_channel_or_keep \"$ch\"\n  fi\nelse\n  echo \"Current directory is not a git repo; proceeding on current tree.\"\n  VERSION=\"${VERSION_ARG:-0.0.0}\"\nfi\n\nVERSION=\"${VERSION#v}\"\necho \"[*] GUI version resolved as: ${VERSION}\"\n\n# Helpers for core\ndownload_xray() {\n  # Download Xray core\n  local outdir=\"$1\" ver=\"${XRAY_VER:-}\" url tmp zipname=\"xray.zip\"\n  mkdir -p \"$outdir\"\n  if [[ -z \"$ver\" ]]; then\n    ver=\"$(curl -fsSL https://api.github.com/repos/XTLS/Xray-core/releases/latest \\\n        | grep -Eo '\"tag_name\":\\s*\"v[^\"]+\"' | sed -E 's/.*\"v([^\"]+)\".*/\\1/' | head -n1)\" || true\n  fi\n  [[ -n \"$ver\" ]] || { echo \"[xray] Failed to get version\"; return 1; }\n  if [[ \"$RID_DIR\" == \"linux-arm64\" ]]; then\n    url=\"https://github.com/XTLS/Xray-core/releases/download/v${ver}/Xray-linux-arm64-v8a.zip\"\n  else\n    url=\"https://github.com/XTLS/Xray-core/releases/download/v${ver}/Xray-linux-64.zip\"\n  fi\n  echo \"[+] Download xray: $url\"\n  tmp=\"$(mktemp -d)\"; trap '[[ -n \"${tmp:-}\" ]] && rm -rf \"$tmp\"' RETURN\n  curl -fL \"$url\" -o \"$tmp/$zipname\"\n  unzip -q \"$tmp/$zipname\" -d \"$tmp\"\n  install -Dm755 \"$tmp/xray\" \"$outdir/xray\"\n}\n\ndownload_singbox() {\n  # Download sing-box\n  local outdir=\"$1\" ver=\"${SING_VER:-}\" url tmp tarname=\"singbox.tar.gz\" bin\n  mkdir -p \"$outdir\"\n  if [[ -z \"$ver\" ]]; then\n    ver=\"$(curl -fsSL https://api.github.com/repos/SagerNet/sing-box/releases/latest \\\n        | grep -Eo '\"tag_name\":\\s*\"v[^\"]+\"' | sed -E 's/.*\"v([^\"]+)\".*/\\1/' | head -n1)\" || true\n  fi\n  [[ -n \"$ver\" ]] || { echo \"[sing-box] Failed to get version\"; return 1; }\n  if [[ \"$RID_DIR\" == \"linux-arm64\" ]]; then\n    url=\"https://github.com/SagerNet/sing-box/releases/download/v${ver}/sing-box-${ver}-linux-arm64.tar.gz\"\n  else\n    url=\"https://github.com/SagerNet/sing-box/releases/download/v${ver}/sing-box-${ver}-linux-amd64.tar.gz\"\n  fi\n  echo \"[+] Download sing-box: $url\"\n  tmp=\"$(mktemp -d)\"; trap '[[ -n \"${tmp:-}\" ]] && rm -rf \"$tmp\"' RETURN\n  curl -fL \"$url\" -o \"$tmp/$tarname\"\n  tar -C \"$tmp\" -xzf \"$tmp/$tarname\"\n  bin=\"$(find \"$tmp\" -type f -name 'sing-box' | head -n1 || true)\"\n  [[ -n \"$bin\" ]] || { echo \"[!] sing-box unpack failed\"; return 1; }\n  install -Dm755 \"$bin\" \"$outdir/sing-box\"\n}\n\n# Move geo files to outroot/bin\nunify_geo_layout() {\n  local outroot=\"$1\"\n  mkdir -p \"$outroot/bin\"\n  local names=( \\\n    \"geosite.dat\" \\\n    \"geoip.dat\" \\\n    \"geoip-only-cn-private.dat\" \\\n    \"Country.mmdb\" \\\n    \"geoip.metadb\" \\\n  )\n  for n in \"${names[@]}\"; do\n    if [[ -f \"$outroot/bin/xray/$n\" ]]; then\n      mv -f \"$outroot/bin/xray/$n\" \"$outroot/bin/$n\"\n    fi\n  done\n}\n\n# Download geo/rule assets\ndownload_geo_assets() {\n  local outroot=\"$1\"\n  local bin_dir=\"$outroot/bin\"\n  local srss_dir=\"$bin_dir/srss\"\n  mkdir -p \"$bin_dir\" \"$srss_dir\"\n\n  echo \"[+] Download Xray Geo to ${bin_dir}\"\n  curl -fsSL -o \"$bin_dir/geosite.dat\" \\\n    \"https://github.com/Loyalsoldier/V2ray-rules-dat/releases/latest/download/geosite.dat\"\n  curl -fsSL -o \"$bin_dir/geoip.dat\" \\\n    \"https://github.com/Loyalsoldier/V2ray-rules-dat/releases/latest/download/geoip.dat\"\n  curl -fsSL -o \"$bin_dir/geoip-only-cn-private.dat\" \\\n    \"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/geoip-only-cn-private.dat\"\n  curl -fsSL -o \"$bin_dir/Country.mmdb\" \\\n    \"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb\"\n\n  echo \"[+] Download sing-box rule DB & rule-sets\"\n  curl -fsSL -o \"$bin_dir/geoip.metadb\" \\\n    \"https://github.com/MetaCubeX/meta-rules-dat/releases/latest/download/geoip.metadb\" || true\n\n  for f in \\\n    geoip-private.srs geoip-cn.srs geoip-facebook.srs geoip-fastly.srs \\\n    geoip-google.srs geoip-netflix.srs geoip-telegram.srs geoip-twitter.srs; do\n    curl -fsSL -o \"$srss_dir/$f\" \\\n      \"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geoip/$f\" || true\n  done\n  for f in \\\n    geosite-cn.srs geosite-gfw.srs geosite-google.srs geosite-greatfire.srs \\\n    geosite-geolocation-cn.srs geosite-category-ads-all.srs geosite-private.srs; do\n    curl -fsSL -o \"$srss_dir/$f\" \\\n      \"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-geosite/$f\" || true\n  done\n\n  # Unify to bin\n  unify_geo_layout \"$outroot\"\n}\n\n# Prefer the prebuilt v2rayN core bundle; then unify geo layout\ndownload_v2rayn_bundle() {\n  local outroot=\"$1\"\n  local url=\"\"\n  if [[ \"$RID_DIR\" == \"linux-arm64\" ]]; then\n    url=\"https://raw.githubusercontent.com/2dust/v2rayN-core-bin/refs/heads/master/v2rayN-linux-arm64.zip\"\n  else\n    url=\"https://raw.githubusercontent.com/2dust/v2rayN-core-bin/refs/heads/master/v2rayN-linux-64.zip\"\n  fi\n  echo \"[+] Try v2rayN bundle archive: $url\"\n  local tmp zipname\n  tmp=\"$(mktemp -d)\"; zipname=\"$tmp/v2rayn.zip\"\n  curl -fL \"$url\" -o \"$zipname\" || { echo \"[!] Bundle download failed\"; return 1; }\n  unzip -q \"$zipname\" -d \"$tmp\" || { echo \"[!] Bundle unzip failed\"; return 1; }\n\n  if [[ -d \"$tmp/bin\" ]]; then\n    mkdir -p \"$outroot/bin\"\n    rsync -a \"$tmp/bin/\" \"$outroot/bin/\"\n  else\n    rsync -a \"$tmp/\" \"$outroot/\"\n  fi\n\n  rm -f \"$outroot/v2rayn.zip\" 2>/dev/null || true\n  find \"$outroot\" -type d -name \"mihomo\" -prune -exec rm -rf {} + 2>/dev/null || true\n\n  local nested_dir\n  nested_dir=\"$(find \"$outroot\" -maxdepth 1 -type d -name 'v2rayN-linux-*' | head -n1 || true)\"\n  if [[ -n \"$nested_dir\" && -d \"$nested_dir/bin\" ]]; then\n    mkdir -p \"$outroot/bin\"\n    rsync -a \"$nested_dir/bin/\" \"$outroot/bin/\"\n    rm -rf \"$nested_dir\"\n  fi\n\n  # Unify to bin/\n  unify_geo_layout \"$outroot\"\n\n  echo \"[+] Bundle extracted to $outroot\"\n}\n\n# ===== Build results collection for --arch all ========================================\nBUILT_RPMS=()     # Will collect absolute paths of built RPMs\nBUILT_ALL=0       # Flag to know if we should print the final summary\n\n# ===== Build (single-arch) function ====================================================\nbuild_for_arch() {\n  # $1: target short arch: x64 | arm64\n  local short=\"$1\"\n  local rid rpm_target archdir\n  case \"$short\" in\n    x64)   rid=\"linux-x64\";   rpm_target=\"x86_64\"; archdir=\"x86_64\" ;;\n    arm64) rid=\"linux-arm64\"; rpm_target=\"aarch64\"; archdir=\"aarch64\" ;;\n    *) echo \"Unknown arch '$short' (use x64|arm64)\"; return 1;;\n  esac\n\n  echo \"[*] Building for target: $short  (RID=$rid, RPM --target $rpm_target)\"\n\n  # .NET publish (self-contained) for this RID\n  dotnet clean \"$PROJECT\" -c Release\n  rm -rf \"$(dirname \"$PROJECT\")/bin/Release/net8.0\" || true\n\n  dotnet restore \"$PROJECT\"\n  dotnet publish \"$PROJECT\" \\\n    -c Release -r \"$rid\" \\\n    -p:PublishSingleFile=false \\\n    -p:SelfContained=true\n\n  # Per-arch variables (scoped)\n  local RID_DIR=\"$rid\"\n  local PUBDIR\n  PUBDIR=\"$(dirname \"$PROJECT\")/bin/Release/net8.0/${RID_DIR}/publish\"\n  [[ -d \"$PUBDIR\" ]]\n\n  # Make RID_DIR visible to download helpers (they read this var)\n  export RID_DIR\n\n  # Per-arch working area\n  local PKGROOT=\"v2rayN-publish\"\n  local WORKDIR\n  WORKDIR=\"$(mktemp -d)\"\n  trap '[[ -n \"${WORKDIR:-}\" ]] && rm -rf \"$WORKDIR\"' RETURN\n\n  # rpmbuild topdir selection\n  local TOPDIR SPECDIR SOURCEDIR\n  rpmdev-setuptree\n  TOPDIR=\"${HOME}/rpmbuild\"\n  SPECDIR=\"${TOPDIR}/SPECS\"\n  SOURCEDIR=\"${TOPDIR}/SOURCES\"\n\n  # Stage publish content\n  mkdir -p \"$WORKDIR/$PKGROOT\"\n  cp -a \"$PUBDIR/.\" \"$WORKDIR/$PKGROOT/\"\n\n  # Optional icon\n  local ICON_CANDIDATE\n  ICON_CANDIDATE=\"$(dirname \"$PROJECT\")/../v2rayN.Desktop/v2rayN.png\"\n  [[ -f \"$ICON_CANDIDATE\" ]] && cp \"$ICON_CANDIDATE\" \"$WORKDIR/$PKGROOT/v2rayn.png\" || true\n\n  # Prepare bin structure\n  mkdir -p \"$WORKDIR/$PKGROOT/bin/xray\" \"$WORKDIR/$PKGROOT/bin/sing_box\"\n\n  # Bundle / cores per-arch\n  fetch_separate_cores_and_rules() {\n    local outroot=\"$1\"\n\n    if [[ \"$WITH_CORE\" == \"xray\" || \"$WITH_CORE\" == \"both\" ]]; then\n      download_xray \"$outroot/bin/xray\" || echo \"[!] xray download failed (skipped)\"\n    fi\n    if [[ \"$WITH_CORE\" == \"sing-box\" || \"$WITH_CORE\" == \"both\" ]]; then\n      download_singbox \"$outroot/bin/sing_box\" || echo \"[!] sing-box download failed (skipped)\"\n    fi\n    download_geo_assets \"$outroot\" || echo \"[!] Geo rules download failed (skipped)\"\n  }\n\n  if [[ \"$FORCE_NETCORE\" -eq 0 ]]; then\n    if download_v2rayn_bundle \"$WORKDIR/$PKGROOT\"; then\n      echo \"[*] Using v2rayN bundle archive.\"\n    else\n      echo \"[*] Bundle failed, fallback to separate core + rules.\"\n      fetch_separate_cores_and_rules \"$WORKDIR/$PKGROOT\"\n    fi\n  else\n    echo \"[*] --netcore specified: use separate core + rules.\"\n    fetch_separate_cores_and_rules \"$WORKDIR/$PKGROOT\"\n  fi\n\n  # Tarball\n  mkdir -p \"$SOURCEDIR\"\n  tar -C \"$WORKDIR\" -czf \"$SOURCEDIR/$PKGROOT.tar.gz\" \"$PKGROOT\"\n\n  # SPEC\n  local SPECFILE=\"$SPECDIR/v2rayN.spec\"\n  mkdir -p \"$SPECDIR\"\n  cat > \"$SPECFILE\" <<'SPEC'\n%global debug_package %{nil}\n%undefine _debuginfo_subpackages\n%undefine _debugsource_packages\n# Ignore outdated LTTng dependencies incorrectly reported by the .NET runtime (to avoid installation failures)\n%global __requires_exclude ^liblttng-ust\\.so\\..*$\n\nName:           v2rayN\nVersion:        __VERSION__\nRelease:        1%{?dist}\nSummary:        v2rayN (Avalonia) GUI client for Linux (x86_64/aarch64)\nLicense:        GPL-3.0-only\nURL:            https://github.com/2dust/v2rayN\nBugURL:         https://github.com/2dust/v2rayN/issues\nExclusiveArch:  aarch64 x86_64\nSource0:        __PKGROOT__.tar.gz\n\n# Runtime dependencies (Avalonia / X11 / Fonts / GL)\nRequires:       cairo, pango, openssl, mesa-libEGL, mesa-libGL\nRequires:       glibc >= 2.34\nRequires:       fontconfig >= 2.13.1\nRequires:       desktop-file-utils >= 0.26\nRequires:       xdg-utils >= 1.1.3\nRequires:       coreutils >= 8.32\nRequires:       bash >= 5.1\nRequires:       freetype >= 2.10\n\n%description\nv2rayN Linux for Red Hat Enterprise Linux\nSupport vless / vmess / Trojan / http / socks / Anytls / Hysteria2 / Shadowsocks / tuic / WireGuard\nSupport Red Hat Enterprise Linux / Fedora Linux / Rocky Linux / AlmaLinux / CentOS\nFor more information, Please visit our website\nhttps://github.com/2dust/v2rayN\n\n%prep\n%setup -q -n __PKGROOT__\n\n%build\n# no build\n\n%install\ninstall -dm0755 %{buildroot}/opt/v2rayN\ncp -a * %{buildroot}/opt/v2rayN/\n\n# Launcher (prefer native ELF first, then DLL fallback)\ninstall -dm0755 %{buildroot}%{_bindir}\ncat > %{buildroot}%{_bindir}/v2rayn << 'EOF'\n#!/usr/bin/bash\nset -euo pipefail\nDIR=\"/opt/v2rayN\"\n\n# Prefer native apphost\nif [[ -x \"$DIR/v2rayN\" ]]; then exec \"$DIR/v2rayN\" \"$@\"; fi\n\n# DLL fallback\nfor dll in v2rayN.Desktop.dll v2rayN.dll; do\n  if [[ -f \"$DIR/$dll\" ]]; then exec /usr/bin/dotnet \"$DIR/$dll\" \"$@\"; fi\ndone\n\necho \"v2rayN launcher: no executable found in $DIR\" >&2\nls -l \"$DIR\" >&2 || true\nexit 1\nEOF\nchmod 0755 %{buildroot}%{_bindir}/v2rayn\n\n# Desktop file\ninstall -dm0755 %{buildroot}%{_datadir}/applications\ncat > %{buildroot}%{_datadir}/applications/v2rayn.desktop << 'EOF'\n[Desktop Entry]\nType=Application\nName=v2rayN\nComment=v2rayN for Red Hat Enterprise Linux\nExec=v2rayn\nIcon=v2rayn\nTerminal=false\nCategories=Network;\nEOF\n\n# Icon\nif [ -f \"%{_builddir}/__PKGROOT__/v2rayn.png\" ]; then\n  install -dm0755 %{buildroot}%{_datadir}/icons/hicolor/256x256/apps\n  install -m0644 %{_builddir}/__PKGROOT__/v2rayn.png %{buildroot}%{_datadir}/icons/hicolor/256x256/apps/v2rayn.png\nfi\n\n%post\n/usr/bin/update-desktop-database %{_datadir}/applications >/dev/null 2>&1 || true\n/usr/bin/gtk-update-icon-cache -f %{_datadir}/icons/hicolor >/dev/null 2>&1 || true\n\n%postun\n/usr/bin/update-desktop-database %{_datadir}/applications >/dev/null 2>&1 || true\n/usr/bin/gtk-update-icon-cache -f %{_datadir}/icons/hicolor >/dev/null 2>&1 || true\n\n%files\n%{_bindir}/v2rayn\n/opt/v2rayN\n%{_datadir}/applications/v2rayn.desktop\n%{_datadir}/icons/hicolor/256x256/apps/v2rayn.png\nSPEC\n\n  # Replace placeholders\n  sed -i \"s/__VERSION__/${VERSION}/g\" \"$SPECFILE\"\n  sed -i \"s/__PKGROOT__/${PKGROOT}/g\" \"$SPECFILE\"\n\n  # Build RPM for this arch\n  rpmbuild -ba \"$SPECFILE\" --target \"$rpm_target\"\n\n  echo \"Build done for $short. RPM at:\"\n  local f\n  for f in \"${TOPDIR}/RPMS/${archdir}/v2rayN-${VERSION}-1\"*.rpm; do\n    [[ -e \"$f\" ]] || continue\n    echo \"  $f\"\n    BUILT_RPMS+=(\"$f\")\n  done\n}\n\n# ===== Arch selection and build orchestration =========================================\ncase \"${ARCH_OVERRIDE:-}\" in\n  all)           targets=(x64 arm64); BUILT_ALL=1 ;;\n  x64|amd64)     targets=(x64) ;;\n  arm64|aarch64) targets=(arm64) ;;\n  \"\")            targets=($([[ \"$host_arch\" == \"aarch64\" ]] && echo arm64 || echo x64)) ;;\n  *)             echo \"Unknown --arch '${ARCH_OVERRIDE}'. Use x64|arm64|all.\"; exit 1 ;;\nesac\n\nfor arch in \"${targets[@]}\"; do\n  build_for_arch \"$arch\"\ndone\n\n# Print Both arches information\nif [[ \"$BUILT_ALL\" -eq 1 ]]; then\n  echo \"\"\n  echo \"================ Build Summary (both architectures) ================\"\n  if [[ \"${#BUILT_RPMS[@]}\" -gt 0 ]]; then\n    for rp in \"${BUILT_RPMS[@]}\"; do\n      echo \"$rp\"\n    done\n  else\n    echo \"No RPMs detected in summary (check build logs above).\"\n  fi\n  echo \"====================================================================\"\nfi\n"
  },
  {
    "path": "v2rayN/AmazTool/AmazTool.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>Exe</OutputType>\n\t</PropertyGroup>\n\n\t<ItemGroup>\n\t\t<EmbeddedResource Update=\"Resx\\Resource.resx\">\n\t\t\t<Generator>ResXFileCodeGenerator</Generator>\n\t\t\t<LastGenOutput>Resource.Designer.cs</LastGenOutput>\n\t\t</EmbeddedResource>\n\n\t\t<Compile Update=\"Resx\\Resource.Designer.cs\">\n\t\t\t<DesignTime>True</DesignTime>\n\t\t\t<AutoGen>True</AutoGen>\n\t\t\t<DependentUpon>Resource.resx</DependentUpon>\n\t\t</Compile>\n\t</ItemGroup>\n\n</Project>"
  },
  {
    "path": "v2rayN/AmazTool/Program.cs",
    "content": "namespace AmazTool;\n\ninternal static class Program\n{\n    [STAThread]\n    private static void Main(string[] args)\n    {\n        try\n        {\n            // If no arguments are provided, display usage guidelines and exit\n            if (args.Length == 0)\n            {\n                ShowHelp();\n                return;\n            }\n\n            // Log all arguments for debugging purposes\n            foreach (var arg in args)\n            {\n                Console.WriteLine(arg);\n            }\n\n            // Parse command based on first argument\n            switch (args[0].ToLowerInvariant())\n            {\n                case \"rebootas\":\n                    // Handle application restart\n                    HandleRebootAsync();\n                    break;\n\n                case \"help\":\n                case \"--help\":\n                case \"-h\":\n                case \"/?\":\n                    // Display help information\n                    ShowHelp();\n                    break;\n\n                default:\n                    // Default behavior: handle as upgrade data\n                    // Maintain backward compatibility with existing usage pattern\n                    var argData = Uri.UnescapeDataString(string.Join(\" \", args));\n                    HandleUpgrade(argData);\n                    break;\n            }\n        }\n        catch (Exception ex)\n        {\n            // Global exception handling\n            Console.WriteLine($\"An error occurred: {ex.Message}\");\n            Console.WriteLine(\"Press any key to exit...\");\n            Console.ReadKey();\n        }\n    }\n\n    /// <summary>\n    /// Display help information and usage guidelines\n    /// </summary>\n    private static void ShowHelp()\n    {\n        Console.WriteLine(Resx.Resource.Guidelines);\n        Console.WriteLine(\"Available commands:\");\n        Console.WriteLine(\"  rebootas             - Restart the application\");\n        Console.WriteLine(\"  help                 - Display this help information\");\n        Thread.Sleep(5000);\n    }\n\n    /// <summary>\n    /// Handle application restart\n    /// </summary>\n    private static void HandleRebootAsync()\n    {\n        Console.WriteLine(\"Restarting application...\");\n        Thread.Sleep(1000);\n        Utils.StartV2RayN();\n    }\n\n    /// <summary>\n    /// Handle application upgrade with the provided data\n    /// </summary>\n    /// <param name=\"upgradeData\">Data for the upgrade process</param>\n    private static void HandleUpgrade(string upgradeData)\n    {\n        Console.WriteLine(\"Upgrading application...\");\n        UpgradeApp.Upgrade(upgradeData);\n    }\n}\n"
  },
  {
    "path": "v2rayN/AmazTool/Resx/Resource.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace AmazTool.Resx {\n    using System;\n    \n    \n    /// <summary>\n    ///   一个强类型的资源类，用于查找本地化的字符串等。\n    /// </summary>\n    // 此类是由 StronglyTypedResourceBuilder\n    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。\n    // 若要添加或移除成员，请编辑 .ResX 文件，然后重新运行 ResGen\n    // (以 /str 作为命令选项)，或重新生成 VS 项目。\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"17.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class Resource {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal Resource() {\n        }\n        \n        /// <summary>\n        ///   返回此类使用的缓存的 ResourceManager 实例。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"AmazTool.Resx.Resource\", typeof(Resource).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   重写当前线程的 CurrentUICulture 属性，对\n        ///   使用此强类型资源类的所有资源查找执行重写。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to terminate the v2rayN. Close it manually, or the upgrade may fail. 的本地化字符串。\n        /// </summary>\n        internal static string FailedTerminateProcess {\n            get {\n                return ResourceManager.GetString(\"FailedTerminateProcess\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to extract the update package. 的本地化字符串。\n        /// </summary>\n        internal static string FailedUnzipping {\n            get {\n                return ResourceManager.GetString(\"FailedUnzipping\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Upgrade failed. 的本地化字符串。\n        /// </summary>\n        internal static string FailedUpgrade {\n            get {\n                return ResourceManager.GetString(\"FailedUpgrade\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please run it from the main application. 的本地化字符串。\n        /// </summary>\n        internal static string Guidelines {\n            get {\n                return ResourceManager.GetString(\"Guidelines\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Information 的本地化字符串。\n        /// </summary>\n        internal static string Information {\n            get {\n                return ResourceManager.GetString(\"Information\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 In progress, please wait... 的本地化字符串。\n        /// </summary>\n        internal static string InProgress {\n            get {\n                return ResourceManager.GetString(\"InProgress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Start v2rayN, please wait... 的本地化字符串。\n        /// </summary>\n        internal static string Restartv2rayN {\n            get {\n                return ResourceManager.GetString(\"Restartv2rayN\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Start extracting the update package... 的本地化字符串。\n        /// </summary>\n        internal static string StartUnzipping {\n            get {\n                return ResourceManager.GetString(\"StartUnzipping\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Successfully extracted the update package. 的本地化字符串。\n        /// </summary>\n        internal static string SuccessUnzipping {\n            get {\n                return ResourceManager.GetString(\"SuccessUnzipping\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Upgrade success. 的本地化字符串。\n        /// </summary>\n        internal static string SuccessUpgrade {\n            get {\n                return ResourceManager.GetString(\"SuccessUpgrade\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Try to terminate the v2rayN process... 的本地化字符串。\n        /// </summary>\n        internal static string TryTerminateProcess {\n            get {\n                return ResourceManager.GetString(\"TryTerminateProcess\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Upgrade failed, file not found. 的本地化字符串。\n        /// </summary>\n        internal static string UpgradeFileNotFound {\n            get {\n                return ResourceManager.GetString(\"UpgradeFileNotFound\", resourceCulture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/AmazTool/Resx/Resource.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Restartv2rayN\" xml:space=\"preserve\">\n    <value>Start v2rayN, please wait...</value>\n  </data>\n  <data name=\"Guidelines\" xml:space=\"preserve\">\n    <value>Please run it from the main application.</value>\n  </data>\n  <data name=\"UpgradeFileNotFound\" xml:space=\"preserve\">\n    <value>Upgrade failed, file not found.</value>\n  </data>\n  <data name=\"InProgress\" xml:space=\"preserve\">\n    <value>In progress, please wait...</value>\n  </data>\n  <data name=\"TryTerminateProcess\" xml:space=\"preserve\">\n    <value>Try to terminate the v2rayN process...</value>\n  </data>\n  <data name=\"FailedTerminateProcess\" xml:space=\"preserve\">\n    <value>Failed to terminate the v2rayN. Close it manually, or the upgrade may fail.</value>\n  </data>\n  <data name=\"StartUnzipping\" xml:space=\"preserve\">\n    <value>Start extracting the update package...</value>\n  </data>\n  <data name=\"SuccessUnzipping\" xml:space=\"preserve\">\n    <value>Successfully extracted the update package.</value>\n  </data>\n  <data name=\"FailedUnzipping\" xml:space=\"preserve\">\n    <value>Failed to extract the update package.</value>\n  </data>\n  <data name=\"FailedUpgrade\" xml:space=\"preserve\">\n    <value>Upgrade failed.</value>\n  </data>\n  <data name=\"SuccessUpgrade\" xml:space=\"preserve\">\n    <value>Upgrade success.</value>\n  </data>\n  <data name=\"Information\" xml:space=\"preserve\">\n    <value>Information</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/AmazTool/Resx/Resource.zh-Hans.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Restartv2rayN\" xml:space=\"preserve\">\n    <value>正在重启，请等待...</value>\n  </data>\n  <data name=\"Guidelines\" xml:space=\"preserve\">\n    <value>请从主应用运行。</value>\n  </data>\n  <data name=\"UpgradeFileNotFound\" xml:space=\"preserve\">\n    <value>升级失败，文件不存在。</value>\n  </data>\n  <data name=\"InProgress\" xml:space=\"preserve\">\n    <value>正在进行中，请等待...</value>\n  </data>\n  <data name=\"TryTerminateProcess\" xml:space=\"preserve\">\n    <value>尝试结束 v2rayN 进程...</value>\n  </data>\n  <data name=\"FailedTerminateProcess\" xml:space=\"preserve\">\n    <value>请手动关闭正在运行的 v2rayN，否则可能升级失败。</value>\n  </data>\n  <data name=\"StartUnzipping\" xml:space=\"preserve\">\n    <value>开始解压缩更新包...</value>\n  </data>\n  <data name=\"SuccessUnzipping\" xml:space=\"preserve\">\n    <value>解压缩更新包成功。</value>\n  </data>\n  <data name=\"FailedUnzipping\" xml:space=\"preserve\">\n    <value>解压缩更新包失败。</value>\n  </data>\n  <data name=\"FailedUpgrade\" xml:space=\"preserve\">\n    <value>升级失败。</value>\n  </data>\n  <data name=\"SuccessUpgrade\" xml:space=\"preserve\">\n    <value>升级成功。</value>\n  </data>\n  <data name=\"Information\" xml:space=\"preserve\">\n    <value>提示</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/AmazTool/Resx/Resource.zh-Hant.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"Restartv2rayN\" xml:space=\"preserve\">\n    <value>正在重啟，請等待...</value>\n  </data>\n  <data name=\"Guidelines\" xml:space=\"preserve\">\n    <value>請從主應用程式運行。</value>\n  </data>\n  <data name=\"UpgradeFileNotFound\" xml:space=\"preserve\">\n    <value>升級失敗，檔案不存在。</value>\n  </data>\n  <data name=\"InProgress\" xml:space=\"preserve\">\n    <value>正在進行中，請等待...</value>\n  </data>\n  <data name=\"TryTerminateProcess\" xml:space=\"preserve\">\n    <value>嘗試結束 v2rayN 進程...</value>\n  </data>\n  <data name=\"FailedTerminateProcess\" xml:space=\"preserve\">\n    <value>請手動關閉正在執行的 v2rayN，否則可能會升級失敗。</value>\n  </data>\n  <data name=\"StartUnzipping\" xml:space=\"preserve\">\n    <value>開始解壓縮更新包...</value>\n  </data>\n  <data name=\"SuccessUnzipping\" xml:space=\"preserve\">\n    <value>解壓縮更新包成功。</value>\n  </data>\n  <data name=\"FailedUnzipping\" xml:space=\"preserve\">\n    <value>解壓縮更新包失敗。</value>\n  </data>\n  <data name=\"FailedUpgrade\" xml:space=\"preserve\">\n    <value>升級失敗。</value>\n  </data>\n  <data name=\"SuccessUpgrade\" xml:space=\"preserve\">\n    <value>升級成功。</value>\n  </data>\n  <data name=\"Information\" xml:space=\"preserve\">\n    <value>提示</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/AmazTool/UpgradeApp.cs",
    "content": "using System.Diagnostics;\nusing System.IO.Compression;\nusing System.Text;\n\nnamespace AmazTool;\n\ninternal class UpgradeApp\n{\n    public static void Upgrade(string fileName)\n    {\n        Console.WriteLine($\"{Resx.Resource.StartUnzipping}\\n{fileName}\");\n\n        Utils.Waiting(5);\n\n        if (!File.Exists(fileName))\n        {\n            Console.WriteLine(Resx.Resource.UpgradeFileNotFound);\n            return;\n        }\n\n        Console.WriteLine(Resx.Resource.TryTerminateProcess);\n        try\n        {\n            var existing = Process.GetProcessesByName(Utils.V2rayN);\n            foreach (var pp in existing)\n            {\n                var path = pp.MainModule?.FileName ?? \"\";\n                if (path.StartsWith(Utils.GetPath(Utils.V2rayN)))\n                {\n                    pp?.Kill();\n                    pp?.WaitForExit(1000);\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            // Access may be denied without admin right. The user may not be an administrator.\n            Console.WriteLine(Resx.Resource.FailedTerminateProcess + ex.StackTrace);\n        }\n\n        Console.WriteLine(Resx.Resource.StartUnzipping);\n        StringBuilder sb = new();\n        try\n        {\n            var thisAppOldFile = $\"{Utils.GetExePath()}.tmp\";\n            File.Delete(thisAppOldFile);\n            var splitKey = \"/\";\n\n            using var archive = ZipFile.OpenRead(fileName);\n            foreach (var entry in archive.Entries)\n            {\n                try\n                {\n                    if (entry.Length == 0)\n                    {\n                        continue;\n                    }\n\n                    Console.WriteLine(entry.FullName);\n\n                    var lst = entry.FullName.Split(splitKey);\n                    if (lst.Length == 1)\n                    {\n                        continue;\n                    }\n\n                    var fullName = string.Join(splitKey, lst[1..lst.Length]);\n\n                    if (string.Equals(Utils.GetExePath(), Utils.GetPath(fullName), StringComparison.OrdinalIgnoreCase))\n                    {\n                        File.Move(Utils.GetExePath(), thisAppOldFile);\n                    }\n\n                    var entryOutputPath = Utils.GetPath(fullName);\n                    Directory.CreateDirectory(Path.GetDirectoryName(entryOutputPath)!);\n                    //In the bin folder, if the file already exists, it will be skipped\n                    if (fullName.StartsWith(\"bin\") && File.Exists(entryOutputPath))\n                    {\n                        continue;\n                    }\n\n                    TryExtractToFile(entry, entryOutputPath);\n\n                    Console.WriteLine(entryOutputPath);\n                }\n                catch (Exception ex)\n                {\n                    sb.Append(ex.StackTrace);\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Console.WriteLine(Resx.Resource.FailedUpgrade + ex.StackTrace);\n            //return;\n        }\n        if (sb.Length > 0)\n        {\n            Console.WriteLine(Resx.Resource.FailedUpgrade + sb.ToString());\n            //return;\n        }\n\n        Console.WriteLine(Resx.Resource.Restartv2rayN);\n        Utils.Waiting(2);\n\n        Utils.StartV2RayN();\n    }\n\n    private static bool TryExtractToFile(ZipArchiveEntry entry, string outputPath)\n    {\n        var retryCount = 5;\n        var delayMs = 1000;\n\n        for (var i = 1; i <= retryCount; i++)\n        {\n            try\n            {\n                entry.ExtractToFile(outputPath, true);\n                return true;\n            }\n            catch\n            {\n                Thread.Sleep(delayMs * i);\n            }\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "v2rayN/AmazTool/Utils.cs",
    "content": "using System.Diagnostics;\n\nnamespace AmazTool;\n\ninternal class Utils\n{\n    public static string GetExePath()\n    {\n        return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;\n    }\n\n    public static string StartupPath()\n    {\n        return AppDomain.CurrentDomain.BaseDirectory;\n    }\n\n    public static string GetPath(string fileName)\n    {\n        var startupPath = StartupPath();\n        if (string.IsNullOrEmpty(fileName))\n        {\n            return startupPath;\n        }\n        return Path.Combine(startupPath, fileName);\n    }\n\n    public static string V2rayN => \"v2rayN\";\n\n    public static void StartV2RayN()\n    {\n        Process process = new()\n        {\n            StartInfo = new()\n            {\n                UseShellExecute = true,\n                FileName = V2rayN,\n                WorkingDirectory = StartupPath()\n            }\n        };\n        process.Start();\n    }\n\n    public static void Waiting(int second)\n    {\n        for (var i = second; i > 0; i--)\n        {\n            Console.WriteLine(i);\n            Thread.Sleep(1000);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/Directory.Build.props",
    "content": "<Project>\n\n    <PropertyGroup>\n        <Version>7.19.4</Version>\n    </PropertyGroup>\n\n    <PropertyGroup>\n        <TargetFramework>net8.0</TargetFramework>\n        <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>\n        <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>\n        <NoWarn>CA1031;CS1591;NU1507;CA1416;IDE0058;IDE0053;IDE0200</NoWarn>\n        <Nullable>annotations</Nullable>\n        <ImplicitUsings>enable</ImplicitUsings>\n        <Authors>2dust</Authors>\n        <PackageLicenseExpression>GPL-3.0</PackageLicenseExpression>\n        <Copyright>Copyright © 2017-$([System.DateTime]::UtcNow.Year) $(Authors)</Copyright>\n        <InvariantGlobalization>false</InvariantGlobalization>\n    </PropertyGroup>\n\n    <PropertyGroup Condition=\"'$(Configuration)' == 'Release'\">\n        <DebugType>embedded</DebugType>\n        <EventSourceSupport>false</EventSourceSupport>\n        <StackTraceSupport>false</StackTraceSupport>\n        <MetricsSupport>false</MetricsSupport>\n        <MetadataUpdaterSupport>false</MetadataUpdaterSupport>\n        <EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>\n        <EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>\n\n        <UseSystemResourceKeys>true</UseSystemResourceKeys>\n        <PublishSingleFile>true</PublishSingleFile>\n        <PublishReadyToRun>false</PublishReadyToRun>\n    </PropertyGroup>\n</Project>\n"
  },
  {
    "path": "v2rayN/Directory.Packages.props",
    "content": "<Project>\n  <PropertyGroup>\n    <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>\n    <CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>\n    <CentralPackageVersionOverrideEnabled>false</CentralPackageVersionOverrideEnabled>\n  </PropertyGroup>\n  <ItemGroup>\n    <PackageVersion Include=\"Avalonia.AvaloniaEdit\" Version=\"11.4.1\" />\n    <PackageVersion Include=\"Avalonia.Controls.DataGrid\" Version=\"11.3.12\" />\n    <PackageVersion Include=\"Avalonia.Desktop\" Version=\"11.3.12\" />\n    <PackageVersion Include=\"Avalonia.Diagnostics\" Version=\"11.3.12\" />\n    <PackageVersion Include=\"ReactiveUI.Avalonia\" Version=\"11.4.12\" />\n    <PackageVersion Include=\"CliWrap\" Version=\"3.10.0\" />\n    <PackageVersion Include=\"Downloader\" Version=\"5.1.0\" />\n    <PackageVersion Include=\"H.NotifyIcon.Wpf\" Version=\"2.4.1\" />\n    <PackageVersion Include=\"MaterialDesignThemes\" Version=\"5.3.0\" />\n    <PackageVersion Include=\"MessageBox.Avalonia\" Version=\"3.3.1.1\" />\n    <PackageVersion Include=\"QRCoder\" Version=\"1.7.0\" />\n    <PackageVersion Include=\"ReactiveUI\" Version=\"23.1.8\" />\n    <PackageVersion Include=\"ReactiveUI.Fody\" Version=\"19.5.41\" />\n    <PackageVersion Include=\"ReactiveUI.WPF\" Version=\"23.1.8\" />\n    <PackageVersion Include=\"Semi.Avalonia\" Version=\"11.3.7.3\" />\n    <PackageVersion Include=\"Semi.Avalonia.AvaloniaEdit\" Version=\"11.2.0.2\" />\n    <PackageVersion Include=\"Semi.Avalonia.DataGrid\" Version=\"11.3.7.3\" />\n    <PackageVersion Include=\"NLog\" Version=\"6.1.1\" />\n    <PackageVersion Include=\"sqlite-net-pcl\" Version=\"1.9.172\" />\n    <PackageVersion Include=\"TaskScheduler\" Version=\"2.12.2\" />\n    <PackageVersion Include=\"WebDav.Client\" Version=\"2.9.0\" />\n    <PackageVersion Include=\"YamlDotNet\" Version=\"16.3.0\" />\n    <PackageVersion Include=\"ZXing.Net.Bindings.SkiaSharp\" Version=\"0.16.14\" />\n  </ItemGroup>\n</Project>"
  },
  {
    "path": "v2rayN/ServiceLib/Base/MyReactiveObject.cs",
    "content": "namespace ServiceLib.Base;\n\npublic class MyReactiveObject : ReactiveObject\n{\n    protected static Config? _config;\n    protected Func<EViewAction, object?, Task<bool>>? _updateView;\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/EmbedUtils.cs",
    "content": "namespace ServiceLib.Common;\n\npublic static class EmbedUtils\n{\n    private static readonly string _tag = \"EmbedUtils\";\n    private static readonly ConcurrentDictionary<string, string> _dicEmbedCache = new();\n\n    /// <summary>\n    /// Get embedded text resources\n    /// </summary>\n    /// <param name=\"res\"></param>\n    /// <returns></returns>\n    public static string GetEmbedText(string res)\n    {\n        if (_dicEmbedCache.TryGetValue(res, out var value))\n        {\n            return value;\n        }\n        var result = string.Empty;\n\n        try\n        {\n            var assembly = Assembly.GetExecutingAssembly();\n            using var stream = assembly.GetManifestResourceStream(res);\n            ArgumentNullException.ThrowIfNull(stream);\n            using StreamReader reader = new(stream);\n            result = reader.ReadToEnd();\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        _dicEmbedCache.TryAdd(res, result);\n        return result;\n    }\n\n    /// <summary>\n    /// Get local storage resources\n    /// </summary>\n    /// <returns></returns>\n    public static string? LoadResource(string? res)\n    {\n        try\n        {\n            if (File.Exists(res))\n            {\n                return File.ReadAllText(res);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/Extension.cs",
    "content": "using System.Diagnostics.CodeAnalysis;\n\nnamespace ServiceLib.Common;\n\npublic static class Extension\n{\n    public static bool IsNullOrEmpty([NotNullWhen(false)] this string? value)\n    {\n        return string.IsNullOrWhiteSpace(value) || string.IsNullOrEmpty(value);\n    }\n\n    public static bool IsNotEmpty([NotNullWhen(false)] this string? value)\n    {\n        return !string.IsNullOrWhiteSpace(value);\n    }\n\n    public static string? NullIfEmpty(this string? value)\n    {\n        return string.IsNullOrWhiteSpace(value) ? null : value;\n    }\n\n    public static bool BeginWithAny(this string s, IEnumerable<char> chars)\n    {\n        if (s.IsNullOrEmpty())\n        {\n            return false;\n        }\n        return chars.Contains(s.First());\n    }\n\n    private static bool IsWhiteSpace(this string value)\n    {\n        return value.All(char.IsWhiteSpace);\n    }\n\n    public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)\n    {\n        while (reader.ReadLine() is { } line)\n        {\n            if (line.IsWhiteSpace())\n            {\n                continue;\n            }\n            yield return line;\n        }\n    }\n\n    public static string TrimEx(this string? value)\n    {\n        return value == null ? string.Empty : value.Trim();\n    }\n\n    public static string RemovePrefix(this string value, char prefix)\n    {\n        return value.StartsWith(prefix) ? value[1..] : value;\n    }\n\n    public static string RemovePrefix(this string value, string prefix)\n    {\n        return value.StartsWith(prefix) ? value[prefix.Length..] : value;\n    }\n\n    public static string UpperFirstChar(this string value)\n    {\n        if (string.IsNullOrEmpty(value))\n        {\n            return string.Empty;\n        }\n\n        return char.ToUpper(value.First()) + value[1..];\n    }\n\n    public static string AppendQuotes(this string value)\n    {\n        return string.IsNullOrEmpty(value) ? string.Empty : $\"\\\"{value}\\\"\";\n    }\n\n    public static int ToInt(this string? value, int defaultValue = 0)\n    {\n        return int.TryParse(value, out var result) ? result : defaultValue;\n    }\n\n    public static List<string> AppendEmpty(this IEnumerable<string> source)\n    {\n        return source.Concat(new[] { string.Empty }).ToList();\n    }\n\n    public static bool IsGroupType(this EConfigType configType)\n    {\n        return configType is EConfigType.PolicyGroup or EConfigType.ProxyChain;\n    }\n\n    public static bool IsComplexType(this EConfigType configType)\n    {\n        return configType is EConfigType.Custom or EConfigType.PolicyGroup or EConfigType.ProxyChain;\n    }\n\n    /// <summary>\n    /// Safely adds elements from a collection to the list. Does nothing if the source is null.\n    /// </summary>\n    public static void AddRangeSafe<T>(this ICollection<T> destination, IEnumerable<T>? source)\n    {\n        ArgumentNullException.ThrowIfNull(destination);\n\n        if (source is null)\n        {\n            return;\n        }\n\n        if (destination is List<T> list)\n        {\n            list.AddRange(source);\n            return;\n        }\n\n        foreach (var item in source)\n        {\n            destination.Add(item);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/FileUtils.cs",
    "content": "using System.Formats.Tar;\nusing System.IO.Compression;\n\nnamespace ServiceLib.Common;\n\npublic static class FileUtils\n{\n    private static readonly string _tag = \"FileManager\";\n\n    public static bool ByteArrayToFile(string fileName, byte[] content)\n    {\n        try\n        {\n            File.WriteAllBytes(fileName, content);\n            return true;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        return false;\n    }\n\n    public static void DecompressFile(string fileName, byte[] content)\n    {\n        try\n        {\n            using var fs = File.Create(fileName);\n            using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false);\n            input.CopyTo(fs);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public static void DecompressFile(string fileName, string toPath, string? toName)\n    {\n        try\n        {\n            FileInfo fileInfo = new(fileName);\n            using var originalFileStream = fileInfo.OpenRead();\n            using var decompressedFileStream = File.Create(toName != null ? Path.Combine(toPath, toName) : toPath);\n            using GZipStream decompressionStream = new(originalFileStream, CompressionMode.Decompress);\n            decompressionStream.CopyTo(decompressedFileStream);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public static void DecompressTarFile(string fileName, string toPath)\n    {\n        try\n        {\n            using var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);\n            using var gz = new GZipStream(fs, CompressionMode.Decompress, leaveOpen: true);\n            TarFile.ExtractToDirectory(gz, toPath, overwriteFiles: true);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public static string NonExclusiveReadAllText(string path)\n    {\n        return NonExclusiveReadAllText(path, Encoding.Default);\n    }\n\n    private static string NonExclusiveReadAllText(string path, Encoding encoding)\n    {\n        try\n        {\n            using FileStream fs = new(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);\n            using StreamReader sr = new(fs, encoding);\n            return sr.ReadToEnd();\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            throw;\n        }\n    }\n\n    public static bool ZipExtractToFile(string fileName, string toPath, string ignoredName)\n    {\n        try\n        {\n            using var archive = ZipFile.OpenRead(fileName);\n            foreach (var entry in archive.Entries)\n            {\n                if (entry.Length == 0)\n                {\n                    continue;\n                }\n                try\n                {\n                    if (ignoredName.IsNotEmpty() && entry.Name.Contains(ignoredName))\n                    {\n                        continue;\n                    }\n                    entry.ExtractToFile(Path.Combine(toPath, entry.Name), true);\n                }\n                catch (IOException ex)\n                {\n                    Logging.SaveLog(_tag, ex);\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return false;\n        }\n        return true;\n    }\n\n    public static List<string>? GetFilesFromZip(string fileName)\n    {\n        if (!File.Exists(fileName))\n        {\n            return null;\n        }\n        try\n        {\n            using var archive = ZipFile.OpenRead(fileName);\n            return archive.Entries.Select(entry => entry.FullName).ToList();\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return null;\n        }\n    }\n\n    public static bool CreateFromDirectory(string sourceDirectoryName, string destinationArchiveFileName)\n    {\n        try\n        {\n            if (File.Exists(destinationArchiveFileName))\n            {\n                File.Delete(destinationArchiveFileName);\n            }\n\n            ZipFile.CreateFromDirectory(sourceDirectoryName, destinationArchiveFileName, CompressionLevel.SmallestSize, true);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return false;\n        }\n        return true;\n    }\n\n    public static void CopyDirectory(string sourceDir, string destinationDir, bool recursive, bool overwrite, string? ignoredName = null)\n    {\n        // Get information about the source directory\n        var dir = new DirectoryInfo(sourceDir);\n\n        // Check if the source directory exists\n        if (!dir.Exists)\n        {\n            throw new DirectoryNotFoundException($\"Source directory not found: {dir.FullName}\");\n        }\n\n        // Cache directories before we start copying\n        var dirs = dir.GetDirectories();\n\n        // Create the destination directory\n        _ = Directory.CreateDirectory(destinationDir);\n\n        // Get the files in the source directory and copy to the destination directory\n        foreach (var file in dir.GetFiles())\n        {\n            if (ignoredName.IsNotEmpty() && file.Name.Contains(ignoredName))\n            {\n                continue;\n            }\n            if (file.Extension == file.Name)\n            {\n                continue;\n            }\n            var targetFilePath = Path.Combine(destinationDir, file.Name);\n            if (!overwrite && File.Exists(targetFilePath))\n            {\n                continue;\n            }\n            _ = file.CopyTo(targetFilePath, overwrite);\n        }\n\n        // If recursive and copying subdirectories, recursively call this method\n        if (recursive)\n        {\n            foreach (var subDir in dirs)\n            {\n                var newDestinationDir = Path.Combine(destinationDir, subDir.Name);\n                CopyDirectory(subDir.FullName, newDestinationDir, true, overwrite, ignoredName);\n            }\n        }\n    }\n\n    public static void DeleteExpiredFiles(string sourceDir, DateTime dtLine)\n    {\n        try\n        {\n            var files = Directory.GetFiles(sourceDir, \"*.*\");\n            foreach (var filePath in files)\n            {\n                var file = new FileInfo(filePath);\n                if (file.CreationTime >= dtLine)\n                {\n                    continue;\n                }\n                file.Delete();\n            }\n        }\n        catch\n        {\n            // ignored\n        }\n    }\n\n    /// <summary>\n    /// Creates a Linux shell file with the specified contents.\n    /// </summary>\n    /// <param name=\"fileName\"></param>\n    /// <param name=\"contents\"></param>\n    /// <param name=\"overwrite\"></param>\n    /// <returns></returns>\n    public static async Task<string> CreateLinuxShellFile(string fileName, string contents, bool overwrite)\n    {\n        var shFilePath = Utils.GetBinConfigPath(fileName);\n\n        // Check if the file already exists and if we should overwrite it\n        if (!overwrite && File.Exists(shFilePath))\n        {\n            return shFilePath;\n        }\n\n        File.Delete(shFilePath);\n        await File.WriteAllTextAsync(shFilePath, contents);\n        await Utils.SetLinuxChmod(shFilePath);\n\n        return shFilePath;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/JsonUtils.cs",
    "content": "namespace ServiceLib.Common;\n\npublic class JsonUtils\n{\n    private static readonly string _tag = \"JsonUtils\";\n\n    private static readonly JsonSerializerOptions _defaultDeserializeOptions = new()\n    {\n        PropertyNameCaseInsensitive = true,\n        ReadCommentHandling = JsonCommentHandling.Skip\n    };\n\n    private static readonly JsonSerializerOptions _defaultSerializeOptions = new()\n    {\n        WriteIndented = true,\n        DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,\n        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n    };\n\n    private static readonly JsonSerializerOptions _nullValueSerializeOptions = new()\n    {\n        WriteIndented = true,\n        DefaultIgnoreCondition = JsonIgnoreCondition.Never,\n        Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n    };\n\n    private static readonly JsonDocumentOptions _defaultDocumentOptions = new()\n    {\n        CommentHandling = JsonCommentHandling.Skip\n    };\n\n    /// <summary>\n    /// DeepCopy\n    /// </summary>\n    /// <typeparam name=\"T\"></typeparam>\n    /// <param name=\"obj\"></param>\n    /// <returns></returns>\n    public static T? DeepCopy<T>(T? obj)\n    {\n        if (obj is null)\n        {\n            return default;\n        }\n        return Deserialize<T>(Serialize(obj, false));\n    }\n\n    /// <summary>\n    /// Deserialize to object\n    /// </summary>\n    /// <typeparam name=\"T\"></typeparam>\n    /// <param name=\"strJson\"></param>\n    /// <returns></returns>\n    public static T? Deserialize<T>(string? strJson)\n    {\n        try\n        {\n            if (string.IsNullOrWhiteSpace(strJson))\n            {\n                return default;\n            }\n            return JsonSerializer.Deserialize<T>(strJson, _defaultDeserializeOptions);\n        }\n        catch\n        {\n            return default;\n        }\n    }\n\n    /// <summary>\n    /// parse\n    /// </summary>\n    /// <param name=\"strJson\"></param>\n    /// <returns></returns>\n    public static JsonNode? ParseJson(string? strJson)\n    {\n        try\n        {\n            if (string.IsNullOrWhiteSpace(strJson))\n            {\n                return null;\n            }\n            return JsonNode.Parse(strJson, nodeOptions: null, _defaultDocumentOptions);\n        }\n        catch\n        {\n            //SaveLog(ex.Message, ex);\n            return null;\n        }\n    }\n\n    /// <summary>\n    /// Serialize Object to Json string\n    /// </summary>\n    /// <param name=\"obj\"></param>\n    /// <param name=\"indented\"></param>\n    /// <param name=\"nullValue\"></param>\n    /// <returns></returns>\n    public static string Serialize(object? obj, bool indented = true, bool nullValue = false)\n    {\n        var result = string.Empty;\n        try\n        {\n            if (obj == null)\n            {\n                return result;\n            }\n            var options = nullValue ? _nullValueSerializeOptions : _defaultSerializeOptions;\n            result = JsonSerializer.Serialize(obj, options);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        return result;\n    }\n\n    /// <summary>\n    /// Serialize Object to Json string\n    /// </summary>\n    /// <param name=\"obj\"></param>\n    /// <param name=\"options\"></param>\n    /// <returns></returns>\n    public static string Serialize(object? obj, JsonSerializerOptions? options)\n    {\n        var result = string.Empty;\n        try\n        {\n            if (obj == null)\n            {\n                return result;\n            }\n            result = JsonSerializer.Serialize(obj, options ?? _defaultSerializeOptions);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        return result;\n    }\n\n    /// <summary>\n    /// SerializeToNode\n    /// </summary>\n    /// <param name=\"obj\"></param>\n    /// <returns></returns>\n    public static JsonNode? SerializeToNode(object? obj, JsonSerializerOptions? options = null)\n    {\n        return JsonSerializer.SerializeToNode(obj, options);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/Logging.cs",
    "content": "using NLog;\nusing NLog.Config;\nusing NLog.Targets;\n\nnamespace ServiceLib.Common;\n\npublic class Logging\n{\n    private static readonly Logger _logger1 = LogManager.GetLogger(\"Log1\");\n    private static readonly Logger _logger2 = LogManager.GetLogger(\"Log2\");\n\n    public static void Setup()\n    {\n        LoggingConfiguration config = new();\n        FileTarget fileTarget = new();\n        config.AddTarget(\"file\", fileTarget);\n        fileTarget.Layout = \"${longdate}-${level:uppercase=true} ${message}\";\n        fileTarget.FileName = Utils.GetLogPath(\"${shortdate}.txt\");\n        config.LoggingRules.Add(new LoggingRule(\"*\", LogLevel.Debug, fileTarget));\n        LogManager.Configuration = config;\n    }\n\n    public static void LoggingEnabled(bool enable)\n    {\n        if (!enable)\n        {\n            LogManager.SuspendLogging();\n        }\n    }\n\n    public static void SaveLog(string strContent)\n    {\n        if (!LogManager.IsLoggingEnabled())\n        {\n            return;\n        }\n\n        _logger1.Info(strContent);\n    }\n\n    public static void SaveLog(string strTitle, Exception ex)\n    {\n        if (!LogManager.IsLoggingEnabled())\n        {\n            return;\n        }\n\n        _logger2.Debug($\"{strTitle},{ex.Message}\");\n        _logger2.Debug(ex.StackTrace);\n        if (ex?.InnerException != null)\n        {\n            _logger2.Error(ex.InnerException);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/ProcUtils.cs",
    "content": "namespace ServiceLib.Common;\n\npublic static class ProcUtils\n{\n    private static readonly string _tag = \"ProcUtils\";\n\n    public static void ProcessStart(string? fileName, string arguments = \"\")\n    {\n        _ = ProcessStart(fileName, arguments, null);\n    }\n\n    public static int? ProcessStart(string? fileName, string arguments, string? dir)\n    {\n        if (fileName.IsNullOrEmpty())\n        {\n            return null;\n        }\n        try\n        {\n            if (fileName.Contains(' '))\n            {\n                fileName = fileName.AppendQuotes();\n            }\n            if (arguments.Contains(' '))\n            {\n                arguments = arguments.AppendQuotes();\n            }\n\n            Process proc = new()\n            {\n                StartInfo = new ProcessStartInfo\n                {\n                    UseShellExecute = true,\n                    FileName = fileName,\n                    Arguments = arguments,\n                    WorkingDirectory = dir ?? string.Empty\n                }\n            };\n            _ = proc.Start();\n            return dir is null ? null : proc.Id;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        return null;\n    }\n\n    public static void RebootAsAdmin(bool blAdmin = true)\n    {\n        try\n        {\n            ProcessStartInfo startInfo = new()\n            {\n                UseShellExecute = true,\n                Arguments = Global.RebootAs,\n                WorkingDirectory = Utils.StartupPath(),\n                FileName = Utils.GetExePath().AppendQuotes(),\n                Verb = blAdmin ? \"runas\" : null,\n            };\n            _ = Process.Start(startInfo);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/QRCodeUtils.cs",
    "content": "using QRCoder;\nusing QRCoder.Exceptions;\nusing SkiaSharp;\nusing ZXing.SkiaSharp;\n\nnamespace ServiceLib.Common;\n\npublic class QRCodeUtils\n{\n    public static byte[]? GenQRCode(string? url)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return null;\n        }\n        using QRCodeGenerator qrGenerator = new();\n        DataTooLongException? lastDtle = null;\n\n        var levels = new[]\n        {\n            QRCodeGenerator.ECCLevel.H,\n            QRCodeGenerator.ECCLevel.Q,\n            QRCodeGenerator.ECCLevel.M,\n            QRCodeGenerator.ECCLevel.L\n        };\n        foreach (var level in levels)\n        {\n            try\n            {\n                using var qrCodeData = qrGenerator.CreateQrCode(url, level);\n                using PngByteQRCode qrCode = new(qrCodeData);\n                return qrCode.GetGraphic(20);\n            }\n            catch (DataTooLongException ex)\n            {\n                lastDtle = ex;\n                continue;\n            }\n            catch\n            {\n                throw;\n            }\n        }\n\n        if (lastDtle != null)\n        {\n            throw lastDtle;\n        }\n\n        return null;\n    }\n\n    public static string? ParseBarcode(string? fileName)\n    {\n        if (fileName == null || !File.Exists(fileName))\n        {\n            return null;\n        }\n\n        try\n        {\n            var image = SKImage.FromEncodedData(fileName);\n            var bitmap = SKBitmap.FromImage(image);\n\n            return ReaderBarcode(bitmap);\n        }\n        catch\n        {\n            // ignored\n        }\n\n        return null;\n    }\n\n    public static string? ParseBarcode(byte[]? bytes)\n    {\n        try\n        {\n            var bitmap = SKBitmap.Decode(bytes);\n            //using var stream = new FileStream(\"test2.png\", FileMode.Create, FileAccess.Write);\n            //using var image = SKImage.FromBitmap(bitmap);\n            //using var encodedImage = image.Encode();\n            //encodedImage.SaveTo(stream);\n            return ReaderBarcode(bitmap);\n        }\n        catch\n        {\n            // ignored\n        }\n\n        return null;\n    }\n\n    private static string? ReaderBarcode(SKBitmap? bitmap)\n    {\n        var reader = new BarcodeReader();\n        var result = reader.Decode(bitmap);\n\n        if (result != null && result.Text.IsNotEmpty())\n        {\n            return result.Text;\n        }\n\n        //FlipBitmap\n        var result2 = reader.Decode(FlipBitmap(bitmap));\n        return result2?.Text;\n    }\n\n    private static SKBitmap FlipBitmap(SKBitmap bmp)\n    {\n        // Create a bitmap (to return)\n        var flipped = new SKBitmap(bmp.Width, bmp.Height, bmp.Info.ColorType, bmp.Info.AlphaType);\n\n        // Create a canvas to draw into the bitmap\n        using var canvas = new SKCanvas(flipped);\n\n        // Set a transform matrix which moves the bitmap to the right,\n        // and then \"scales\" it by -1, which just flips the pixels\n        // horizontally\n        canvas.Translate(bmp.Width, 0);\n        canvas.Scale(-1, 1);\n        canvas.DrawBitmap(bmp, 0, 0);\n        return flipped;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/Utils.cs",
    "content": "using System.Collections.Specialized;\nusing System.Security.Principal;\nusing CliWrap;\nusing CliWrap.Buffered;\n\nnamespace ServiceLib.Common;\n\npublic class Utils\n{\n    private static readonly string _tag = \"Utils\";\n\n    #region Conversion Functions\n\n    /// <summary>\n    /// Convert to comma-separated string\n    /// </summary>\n    /// <param name=\"lst\"></param>\n    /// <param name=\"wrap\"></param>\n    /// <returns></returns>\n    public static string List2String(List<string>? lst, bool wrap = false)\n    {\n        if (lst == null || lst.Count == 0)\n        {\n            return string.Empty;\n        }\n\n        var separator = wrap ? \",\" + Environment.NewLine : \",\";\n\n        try\n        {\n            return string.Join(separator, lst);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return string.Empty;\n        }\n    }\n\n    /// <summary>\n    /// Comma-separated string\n    /// </summary>\n    /// <param name=\"str\"></param>\n    /// <returns></returns>\n    public static List<string>? String2List(string? str)\n    {\n        if (string.IsNullOrWhiteSpace(str))\n        {\n            return null;\n        }\n\n        try\n        {\n            str = str.Replace(Environment.NewLine, string.Empty);\n            return new List<string>(str.Split(',', StringSplitOptions.RemoveEmptyEntries));\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return null;\n        }\n    }\n\n    /// <summary>\n    /// Comma-separated string, sorted and then converted to List\n    /// </summary>\n    /// <param name=\"str\"></param>\n    /// <returns></returns>\n    public static List<string>? String2ListSorted(string str)\n    {\n        var lst = String2List(str);\n        lst?.Sort();\n        return lst;\n    }\n\n    /// <summary>\n    /// Base64 Encode\n    /// </summary>\n    /// <param name=\"plainText\"></param>\n    /// <param name=\"removePadding\"></param>\n    /// <returns></returns>\n    public static string Base64Encode(string plainText, bool removePadding = false)\n    {\n        try\n        {\n            var plainTextBytes = Encoding.UTF8.GetBytes(plainText);\n            var base64 = Convert.ToBase64String(plainTextBytes);\n            if (removePadding)\n            {\n                base64 = base64.TrimEnd('=');\n            }\n            return base64;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return string.Empty;\n    }\n\n    /// <summary>\n    /// Base64 Decode\n    /// </summary>\n    /// <param name=\"plainText\"></param>\n    /// <returns></returns>\n    public static string Base64Decode(string? plainText)\n    {\n        try\n        {\n            if (plainText.IsNullOrEmpty())\n            {\n                return string.Empty;\n            }\n\n            plainText = plainText.Trim()\n                .Replace(Environment.NewLine, \"\")\n                .Replace(\"\\n\", \"\")\n                .Replace(\"\\r\", \"\")\n                .Replace('_', '/')\n                .Replace('-', '+')\n                .Replace(\" \", \"\");\n\n            if (plainText.Length % 4 > 0)\n            {\n                plainText = plainText.PadRight(plainText.Length + 4 - (plainText.Length % 4), '=');\n            }\n\n            var data = Convert.FromBase64String(plainText);\n            return Encoding.UTF8.GetString(data);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return string.Empty;\n    }\n\n    public static bool ToBool(object obj)\n    {\n        try\n        {\n            return Convert.ToBoolean(obj);\n        }\n        catch\n        {\n            return false;\n        }\n    }\n\n    public static string ToString(object? obj)\n    {\n        try\n        {\n            return obj?.ToString() ?? string.Empty;\n        }\n        catch\n        {\n            return string.Empty;\n        }\n    }\n\n    public static string HumanFy(long amount)\n    {\n        if (amount <= 0)\n        {\n            return $\"{amount:f1} B\";\n        }\n\n        string[] units = [\"KB\", \"MB\", \"GB\", \"TB\", \"PB\"];\n        var unitIndex = 0;\n        double size = amount;\n\n        // Loop and divide by 1024 until a suitable unit is found\n        while (size >= 1024 && unitIndex < units.Length - 1)\n        {\n            size /= 1024;\n            unitIndex++;\n        }\n\n        return $\"{size:f1} {units[unitIndex]}\";\n    }\n\n    public static string UrlEncode(string url)\n    {\n        return Uri.EscapeDataString(url);\n    }\n\n    public static string UrlDecode(string url)\n    {\n        return Uri.UnescapeDataString(url);\n    }\n\n    public static NameValueCollection ParseQueryString(string query)\n    {\n        var result = new NameValueCollection(StringComparer.OrdinalIgnoreCase);\n        if (query.IsNullOrEmpty())\n        {\n            return result;\n        }\n\n        var parts = query[1..].Split('&', StringSplitOptions.RemoveEmptyEntries);\n        foreach (var part in parts)\n        {\n            var keyValue = part.Split('=');\n            if (keyValue.Length != 2)\n            {\n                continue;\n            }\n\n            var key = Uri.UnescapeDataString(keyValue.First());\n            var val = Uri.UnescapeDataString(keyValue.Last());\n\n            if (result[key] is null)\n            {\n                result.Add(key, val);\n            }\n        }\n\n        return result;\n    }\n\n    public static string GetMd5(string str)\n    {\n        if (string.IsNullOrEmpty(str))\n        {\n            return string.Empty;\n        }\n\n        try\n        {\n            var byteOld = Encoding.UTF8.GetBytes(str);\n            var byteNew = MD5.HashData(byteOld);\n            StringBuilder sb = new(32);\n            foreach (var b in byteNew)\n            {\n                sb.Append(b.ToString(\"x2\"));\n            }\n\n            return sb.ToString();\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return string.Empty;\n        }\n    }\n\n    public static string GetFileHash(string filePath)\n    {\n        if (string.IsNullOrEmpty(filePath))\n        {\n            return string.Empty;\n        }\n\n        if (!File.Exists(filePath))\n        {\n            return string.Empty;\n        }\n\n        try\n        {\n            using var md5 = MD5.Create();\n            using var stream = File.OpenRead(filePath);\n            var hash = md5.ComputeHash(stream);\n            return BitConverter.ToString(hash).Replace(\"-\", \"\").ToLowerInvariant();\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return string.Empty;\n        }\n    }\n\n    /// <summary>\n    /// idn to idc\n    /// </summary>\n    /// <param name=\"url\"></param>\n    /// <returns></returns>\n    public static string GetPunycode(string url)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return url;\n        }\n\n        try\n        {\n            Uri uri = new(url);\n            if (uri.Host == uri.IdnHost || uri.Host == $\"[{uri.IdnHost}]\")\n            {\n                return url;\n            }\n            else\n            {\n                return url.Replace(uri.Host, uri.IdnHost);\n            }\n        }\n        catch\n        {\n            return url;\n        }\n    }\n\n    public static bool IsBase64String(string? plainText)\n    {\n        if (plainText.IsNullOrEmpty())\n        {\n            return false;\n        }\n\n        var buffer = new Span<byte>(new byte[plainText.Length]);\n        return Convert.TryFromBase64String(plainText, buffer, out var _);\n    }\n\n    public static string Convert2Comma(string text)\n    {\n        if (text.IsNullOrEmpty())\n        {\n            return text;\n        }\n\n        return text.Replace(\"，\", \",\").Replace(Environment.NewLine, \",\");\n    }\n\n    public static List<string> GetEnumNames<TEnum>() where TEnum : Enum\n    {\n        return Enum.GetValues(typeof(TEnum))\n            .Cast<TEnum>()\n            .Select(e => e.ToString())\n            .ToList();\n    }\n\n    public static Dictionary<string, List<string>> ParseHostsToDictionary(string? hostsContent)\n    {\n        if (hostsContent.IsNullOrEmpty())\n        {\n            return new();\n        }\n        var userHostsMap = hostsContent\n            .Split(new[] { '\\r', '\\n' }, StringSplitOptions.RemoveEmptyEntries)\n            .Select(line => line.Trim())\n            // skip full-line comments\n            .Where(line => !string.IsNullOrWhiteSpace(line) && !line.StartsWith('#'))\n            // ensure line still contains valid parts\n            .Where(line => !string.IsNullOrWhiteSpace(line) && line.Contains(' '))\n            .Select(line => line.Split(new[] { ' ', '\\t' }, StringSplitOptions.RemoveEmptyEntries))\n            .Where(parts => parts.Length >= 2)\n            .GroupBy(parts => parts[0])\n            .ToDictionary(\n                group => group.Key,\n                group => group.SelectMany(parts => parts.Skip(1)).ToList()\n            );\n\n        return userHostsMap;\n    }\n\n    /// <summary>\n    /// Parse a possibly non-standard URL into scheme, domain, port, and path.\n    /// If parsing fails, the entire input is returned as domain, and others are empty or zero.\n    /// </summary>\n    /// <param name=\"url\">Input URL or string</param>\n    /// <returns>(domain, scheme, port, path)</returns>\n    public static (string domain, string scheme, int port, string path) ParseUrl(string url)\n    {\n        if (string.IsNullOrWhiteSpace(url))\n        {\n            return (\"\", \"\", 0, \"\");\n        }\n\n        // 1. First, try to parse using the standard Uri class.\n        if (Uri.TryCreate(url, UriKind.Absolute, out var uri) && !string.IsNullOrEmpty(uri.Host))\n        {\n            var scheme = uri.Scheme;\n            var domain = uri.Host;\n            var port = uri.IsDefaultPort ? 0 : uri.Port;\n            var path = uri.PathAndQuery;\n            return (domain, scheme, port, path);\n        }\n\n        // 2. Try to handle more general cases with a regular expression, including non-standard schemes.\n        // This regex captures the scheme (optional), authority (host+port), and path (optional).\n        var match = Regex.Match(url, @\"^(?:([a-zA-Z][a-zA-Z0-9+.-]*):/{2,})?([^/?#]+)([^?#]*)?.*$\");\n\n        if (match.Success)\n        {\n            var scheme = match.Groups[1].Value;\n            var authority = match.Groups[2].Value;\n            var path = match.Groups[3].Value;\n\n            // Remove userinfo from the authority part.\n            var atIndex = authority.LastIndexOf('@');\n            if (atIndex > 0)\n            {\n                authority = authority.Substring(atIndex + 1);\n            }\n\n            var (domain, port) = ParseAuthority(authority);\n\n            // If the parsed domain is empty, it means the authority part is malformed, so trigger the fallback.\n            if (!string.IsNullOrEmpty(domain))\n            {\n                return (domain, scheme, port, path);\n            }\n        }\n\n        // 3. If all of the above fails, execute the final fallback strategy.\n        return (url, \"\", 0, \"\");\n    }\n\n    /// <summary>\n    /// Helper function to parse domain and port from the authority part, with correct handling for IPv6.\n    /// </summary>\n    private static (string domain, int port) ParseAuthority(string authority)\n    {\n        if (string.IsNullOrEmpty(authority))\n        {\n            return (\"\", 0);\n        }\n\n        var port = 0;\n        var domain = authority;\n\n        // Handle IPv6 addresses, e.g., \"[2001:db8::1]:443\"\n        if (authority.StartsWith('[') && authority.Contains(']'))\n        {\n            var closingBracketIndex = authority.LastIndexOf(']');\n            if (closingBracketIndex < authority.Length - 1 && authority[closingBracketIndex + 1] == ':')\n            {\n                // Port exists\n                var portStr = authority.Substring(closingBracketIndex + 2);\n                if (int.TryParse(portStr, out var portNum))\n                {\n                    port = portNum;\n                }\n                domain = authority.Substring(0, closingBracketIndex + 1);\n            }\n            else\n            {\n                // No port\n                domain = authority;\n            }\n        }\n        else // Handle IPv4 or domain names\n        {\n            var lastColonIndex = authority.LastIndexOf(':');\n            // Ensure there are digits after the colon and that this colon is not part of an IPv6 address.\n            if (lastColonIndex > 0 && lastColonIndex < authority.Length - 1 && authority.Substring(lastColonIndex + 1).All(char.IsDigit))\n            {\n                var portStr = authority.Substring(lastColonIndex + 1);\n                if (int.TryParse(portStr, out var portNum))\n                {\n                    port = portNum;\n                    domain = authority.Substring(0, lastColonIndex);\n                }\n            }\n        }\n\n        return (domain, port);\n    }\n\n    public static string? DomainStrategy4Sbox(string? strategy)\n    {\n        return strategy switch\n        {\n            not null when strategy.StartsWith(\"UseIPv4\") => \"prefer_ipv4\",\n            not null when strategy.StartsWith(\"UseIPv6\") => \"prefer_ipv6\",\n            not null when strategy.StartsWith(\"ForceIPv4\") => \"ipv4_only\",\n            not null when strategy.StartsWith(\"ForceIPv6\") => \"ipv6_only\",\n            _ => null\n        };\n    }\n\n    #endregion Conversion Functions\n\n    #region Data Checks\n\n    /// <summary>\n    /// Determine if the input is a number\n    /// </summary>\n    /// <param name=\"oText\"></param>\n    /// <returns></returns>\n    public static bool IsNumeric(string oText)\n    {\n        return oText.All(char.IsNumber);\n    }\n\n    /// <summary>\n    /// Validate if the domain address is valid\n    /// </summary>\n    /// <param name=\"domain\"></param>\n    public static bool IsDomain(string? domain)\n    {\n        if (domain.IsNullOrEmpty())\n        {\n            return false;\n        }\n\n        var ext = Path.GetExtension(domain);\n        if (ext.IsNotEmpty()\n            && ext[1..].ToLowerInvariant() is \"json\" or \"txt\" or \"xml\" or \"cfg\" or \"ini\" or \"log\" or \"yaml\" or \"yml\" or \"toml\")\n        {\n            return false;\n        }\n\n        return Uri.CheckHostName(domain) == UriHostNameType.Dns;\n    }\n\n    public static bool IsIpv6(string ip)\n    {\n        if (IPAddress.TryParse(ip, out var address))\n        {\n            return address.AddressFamily switch\n            {\n                AddressFamily.InterNetwork => false,\n                AddressFamily.InterNetworkV6 => true,\n                _ => false,\n            };\n        }\n\n        return false;\n    }\n\n    public static bool IsIpAddress(string? ip)\n    {\n        if (ip.IsNullOrEmpty())\n        {\n            return false;\n        }\n\n        ip = ip.Trim();\n\n        // First, validate using built-in parser\n        if (!IPAddress.TryParse(ip, out var address))\n        {\n            return false;\n        }\n\n        // For IPv4: ensure it has exactly 3 dots (meaning 4 parts)\n        if (address.AddressFamily == AddressFamily.InterNetwork)\n        {\n            return ip.Count(c => c == '.') == 3;\n        }\n\n        // For IPv6: TryParse is already strict enough\n        return address.AddressFamily == AddressFamily.InterNetworkV6;\n    }\n\n    public static Uri? TryUri(string url)\n    {\n        try\n        {\n            return new Uri(url);\n        }\n        catch (UriFormatException)\n        {\n            return null;\n        }\n    }\n\n    public static bool IsPrivateNetwork(string ip)\n    {\n        if (IPAddress.TryParse(ip, out var address))\n        {\n            // Loopback address check (127.0.0.1 for IPv4, ::1 for IPv6)\n            if (IPAddress.IsLoopback(address))\n            {\n                return true;\n            }\n\n            var ipBytes = address.GetAddressBytes();\n            if (address.AddressFamily == AddressFamily.InterNetwork)\n            {\n                // IPv4 private address check\n                if (ipBytes[0] == 10)\n                {\n                    return true;\n                }\n\n                if (ipBytes[0] == 172 && ipBytes[1] >= 16 && ipBytes[1] <= 31)\n                {\n                    return true;\n                }\n\n                if (ipBytes[0] == 192 && ipBytes[1] == 168)\n                {\n                    return true;\n                }\n            }\n            else if (address.AddressFamily == AddressFamily.InterNetworkV6)\n            {\n                // IPv6 private address check\n                // Link-local address fe80::/10\n                if (ipBytes[0] == 0xfe && (ipBytes[1] & 0xc0) == 0x80)\n                {\n                    return true;\n                }\n\n                // Unique local address fc00::/7 (typically fd00::/8)\n                if ((ipBytes[0] & 0xfe) == 0xfc)\n                {\n                    return true;\n                }\n\n                // Private portion in IPv4-mapped addresses ::ffff:0:0/96\n                if (address.IsIPv4MappedToIPv6)\n                {\n                    var ipv4Bytes = ipBytes.Skip(12).ToArray();\n                    if (ipv4Bytes[0] == 10)\n                    {\n                        return true;\n                    }\n\n                    if (ipv4Bytes[0] == 172 && ipv4Bytes[1] >= 16 && ipv4Bytes[1] <= 31)\n                    {\n                        return true;\n                    }\n\n                    if (ipv4Bytes[0] == 192 && ipv4Bytes[1] == 168)\n                    {\n                        return true;\n                    }\n                }\n            }\n        }\n\n        return false;\n    }\n\n    #endregion Data Checks\n\n    #region Speed Test\n\n    private static bool PortInUse(int port)\n    {\n        try\n        {\n            var (lstIpEndPoints, lstTcpConns) = GetActiveNetworkInfo();\n\n            if (lstIpEndPoints?.FindIndex(it => it.Port == port) >= 0)\n            {\n                return true;\n            }\n\n            if (lstTcpConns?.FindIndex(it => it.LocalEndPoint.Port == port) >= 0)\n            {\n                return true;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return false;\n    }\n\n    public static int GetFreePort(int defaultPort = 0)\n    {\n        try\n        {\n            if (!(defaultPort == 0 || Utils.PortInUse(defaultPort)))\n            {\n                return defaultPort;\n            }\n\n            TcpListener l = new(IPAddress.Loopback, 0);\n            l.Start();\n            var port = ((IPEndPoint)l.LocalEndpoint).Port;\n            l.Stop();\n            return port;\n        }\n        catch\n        {\n        }\n\n        return 59090;\n    }\n\n    public static (List<IPEndPoint> endpoints, List<TcpConnectionInformation> connections) GetActiveNetworkInfo()\n    {\n        var endpoints = new List<IPEndPoint>();\n        var connections = new List<TcpConnectionInformation>();\n\n        try\n        {\n            var ipGlobalProperties = IPGlobalProperties.GetIPGlobalProperties();\n\n            endpoints.AddRange(ipGlobalProperties.GetActiveTcpListeners());\n            endpoints.AddRange(ipGlobalProperties.GetActiveUdpListeners());\n            connections.AddRange(ipGlobalProperties.GetActiveTcpConnections());\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return (endpoints, connections);\n    }\n\n    #endregion Speed Test\n\n    #region Miscellaneous\n\n    public static bool UpgradeAppExists(out string upgradeFileName)\n    {\n        upgradeFileName = Path.Combine(GetBaseDirectory(), GetExeName(\"AmazTool\"));\n        return File.Exists(upgradeFileName);\n    }\n\n    /// <summary>\n    /// Get version\n    /// </summary>\n    /// <returns></returns>\n    public static string GetVersion(bool blFull = true)\n    {\n        try\n        {\n            return blFull\n                ? $\"{Global.AppName} - V{GetVersionInfo()} - {RuntimeInformation.ProcessArchitecture}\"\n                : $\"{Global.AppName}/{GetVersionInfo()}\";\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return Global.AppName;\n    }\n\n    public static string GetVersionInfo()\n    {\n        try\n        {\n            return Assembly.GetExecutingAssembly()?.GetName()?.Version?.ToString(3) ?? \"0.0\";\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return \"0.0\";\n        }\n    }\n\n    public static string GetRuntimeInfo()\n    {\n        return $\"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}\";\n    }\n\n    /// <summary>\n    /// GUID\n    /// </summary>\n    /// <returns></returns>\n    public static string GetGuid(bool full = true)\n    {\n        try\n        {\n            if (full)\n            {\n                return Guid.NewGuid().ToString(\"D\");\n            }\n            else\n            {\n                return BitConverter.ToInt64(Guid.NewGuid().ToByteArray(), 0).ToString();\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return string.Empty;\n    }\n\n    public static bool IsGuidByParse(string strSrc)\n    {\n        return Guid.TryParse(strSrc, out _);\n    }\n\n    private static Dictionary<string, string> GetSystemHosts(string hostFile)\n    {\n        var systemHosts = new Dictionary<string, string>();\n        try\n        {\n            if (!File.Exists(hostFile))\n            {\n                return systemHosts;\n            }\n            var hosts = File.ReadAllText(hostFile).Replace(\"\\r\", \"\");\n            var hostsList = hosts.Split(new[] { '\\n' }, StringSplitOptions.RemoveEmptyEntries);\n\n            foreach (var host in hostsList)\n            {\n                // Trim whitespace\n                var line = host.Trim();\n\n                // Skip comments and empty lines\n                if (line.IsNullOrEmpty() || line.StartsWith(\"#\"))\n                {\n                    continue;\n                }\n\n                // Strip inline comments\n                var commentIndex = line.IndexOf('#');\n                if (commentIndex >= 0)\n                {\n                    line = line.Substring(0, commentIndex).Trim();\n                }\n                if (line.IsNullOrEmpty())\n                {\n                    continue;\n                }\n\n                var hostItem = line.Split(new[] { ' ', '\\t' }, StringSplitOptions.RemoveEmptyEntries);\n                if (hostItem.Length < 2)\n                {\n                    continue;\n                }\n\n                var ipAddress = hostItem[0];\n                var domain = hostItem[1];\n\n                // Validate IP address\n                if (!IsIpAddress(ipAddress))\n                {\n                    continue;\n                }\n\n                // Validate domain name\n                if (domain.IsNullOrEmpty() || domain.Length > 255)\n                {\n                    continue;\n                }\n\n                systemHosts[domain] = ipAddress;\n            }\n\n            return systemHosts;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return systemHosts;\n    }\n\n    public static Dictionary<string, string> GetSystemHosts()\n    {\n        var hosts = GetSystemHosts(@\"C:\\Windows\\System32\\drivers\\etc\\hosts\");\n        var hostsIcs = GetSystemHosts(@\"C:\\Windows\\System32\\drivers\\etc\\hosts.ics\");\n\n        foreach (var (key, value) in hostsIcs)\n        {\n            hosts[key] = value;\n        }\n\n        return hosts;\n    }\n\n    public static async Task<string?> GetCliWrapOutput(string filePath, string? arg)\n    {\n        return await GetCliWrapOutput(filePath, arg != null ? new List<string>() { arg } : null);\n    }\n\n    public static async Task<string?> GetCliWrapOutput(string filePath, IEnumerable<string>? args)\n    {\n        try\n        {\n            var cmd = Cli.Wrap(filePath);\n            if (args != null)\n            {\n                if (args.Count() == 1)\n                {\n                    cmd = cmd.WithArguments(args.First());\n                }\n                else\n                {\n                    cmd = cmd.WithArguments(args);\n                }\n            }\n\n            var result = await cmd.ExecuteBufferedAsync();\n            if (result.IsSuccess)\n            {\n                return result.StandardOutput ?? \"\";\n            }\n\n            Logging.SaveLog(result.ToString() ?? \"\");\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"GetCliWrapOutput\", ex);\n        }\n\n        return null;\n    }\n\n    #endregion Miscellaneous\n\n    #region TempPath\n\n    public static bool HasWritePermission()\n    {\n        try\n        {\n            var basePath = GetBaseDirectory();\n            //When this file exists, it is equivalent to having no permission to read and write\n            if (File.Exists(Path.Combine(basePath, \"NotStoreConfigHere.txt\")))\n            {\n                return false;\n            }\n\n            //Check if it is installed by Windows WinGet\n            if (IsWindows() && basePath.Contains(\"Users\") && basePath.Contains(\"WinGet\"))\n            {\n                return false;\n            }\n\n            var tempPath = Path.Combine(basePath, \"guiTemps\");\n            if (!Directory.Exists(tempPath))\n            {\n                Directory.CreateDirectory(tempPath);\n            }\n            var fileName = Path.Combine(tempPath, GetGuid());\n            File.Create(fileName).Close();\n            File.Delete(fileName);\n        }\n        catch (Exception)\n        {\n            return false;\n        }\n\n        return true;\n    }\n\n    public static string GetPath(string fileName)\n    {\n        var startupPath = StartupPath();\n        if (fileName.IsNullOrEmpty())\n        {\n            return startupPath;\n        }\n\n        return Path.Combine(startupPath, fileName);\n    }\n\n    public static string GetBaseDirectory(string fileName = \"\")\n    {\n        return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);\n    }\n\n    public static string GetExePath()\n    {\n        return Environment.ProcessPath ?? Process.GetCurrentProcess().MainModule?.FileName ?? string.Empty;\n    }\n\n    public static string StartupPath()\n    {\n        if (Environment.GetEnvironmentVariable(Global.LocalAppData) == \"1\")\n        {\n            return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), \"v2rayN\");\n        }\n\n        return GetBaseDirectory();\n    }\n\n    public static string GetTempPath(string filename = \"\")\n    {\n        var tempPath = Path.Combine(StartupPath(), \"guiTemps\");\n        if (!Directory.Exists(tempPath))\n        {\n            Directory.CreateDirectory(tempPath);\n        }\n\n        if (filename.IsNullOrEmpty())\n        {\n            return tempPath;\n        }\n        else\n        {\n            return Path.Combine(tempPath, filename);\n        }\n    }\n\n    public static string GetBackupPath(string filename)\n    {\n        var tempPath = Path.Combine(StartupPath(), \"guiBackups\");\n        if (!Directory.Exists(tempPath))\n        {\n            Directory.CreateDirectory(tempPath);\n        }\n\n        return Path.Combine(tempPath, filename);\n    }\n\n    public static string GetConfigPath(string filename = \"\")\n    {\n        var tempPath = Path.Combine(StartupPath(), \"guiConfigs\");\n        if (!Directory.Exists(tempPath))\n        {\n            Directory.CreateDirectory(tempPath);\n        }\n\n        if (filename.IsNullOrEmpty())\n        {\n            return tempPath;\n        }\n        else\n        {\n            return Path.Combine(tempPath, filename);\n        }\n    }\n\n    public static string GetBinPath(string filename, string? coreType = null)\n    {\n        var tempPath = Path.Combine(StartupPath(), \"bin\");\n        if (!Directory.Exists(tempPath))\n        {\n            Directory.CreateDirectory(tempPath);\n        }\n\n        if (coreType != null)\n        {\n            tempPath = Path.Combine(tempPath, coreType.ToLower().ToString());\n            if (!Directory.Exists(tempPath))\n            {\n                Directory.CreateDirectory(tempPath);\n            }\n        }\n\n        if (filename.IsNullOrEmpty())\n        {\n            return tempPath;\n        }\n        else\n        {\n            return Path.Combine(tempPath, filename);\n        }\n    }\n\n    public static string GetLogPath(string filename = \"\")\n    {\n        var tempPath = Path.Combine(StartupPath(), \"guiLogs\");\n        if (!Directory.Exists(tempPath))\n        {\n            Directory.CreateDirectory(tempPath);\n        }\n\n        if (filename.IsNullOrEmpty())\n        {\n            return tempPath;\n        }\n        else\n        {\n            return Path.Combine(tempPath, filename);\n        }\n    }\n\n    public static string GetFontsPath(string filename = \"\")\n    {\n        var tempPath = Path.Combine(StartupPath(), \"guiFonts\");\n        if (!Directory.Exists(tempPath))\n        {\n            Directory.CreateDirectory(tempPath);\n        }\n\n        if (filename.IsNullOrEmpty())\n        {\n            return tempPath;\n        }\n        else\n        {\n            return Path.Combine(tempPath, filename);\n        }\n    }\n\n    public static string GetBinConfigPath(string filename = \"\")\n    {\n        var tempPath = Path.Combine(StartupPath(), \"binConfigs\");\n        if (!Directory.Exists(tempPath))\n        {\n            Directory.CreateDirectory(tempPath);\n        }\n\n        if (filename.IsNullOrEmpty())\n        {\n            return tempPath;\n        }\n        else\n        {\n            return Path.Combine(tempPath, filename);\n        }\n    }\n\n    #endregion TempPath\n\n    #region Platform\n\n    public static bool IsWindows() => OperatingSystem.IsWindows();\n\n    public static bool IsLinux() => OperatingSystem.IsLinux();\n\n    public static bool IsMacOS() => OperatingSystem.IsMacOS();\n\n    public static bool IsNonWindows() => !OperatingSystem.IsWindows();\n\n    public static string GetExeName(string name)\n    {\n        if (name.IsNullOrEmpty() || IsNonWindows())\n        {\n            return name;\n        }\n\n        if (name.EndsWith(\".exe\", StringComparison.OrdinalIgnoreCase))\n        {\n            return name;\n        }\n        else\n        {\n            return $\"{name}.exe\";\n        }\n    }\n\n    public static bool IsAdministrator()\n    {\n        if (IsWindows())\n        {\n            return new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);\n        }\n        return false;\n    }\n\n    public static bool IsPackagedInstall()\n    {\n        try\n        {\n            if (IsWindows() || IsMacOS())\n            {\n                return false;\n            }\n\n            var exePath = GetExePath();\n            var baseDir = string.IsNullOrEmpty(exePath) ? StartupPath() : Path.GetDirectoryName(exePath) ?? \"\";\n            var p = baseDir.Replace('\\\\', '/');\n\n            if (string.IsNullOrEmpty(p))\n            {\n                return false;\n            }\n\n            if (p.StartsWith(\"/opt/v2rayN\", StringComparison.OrdinalIgnoreCase))\n            {\n                return true;\n            }\n\n            if (p.StartsWith(\"/usr/lib/v2rayN\", StringComparison.OrdinalIgnoreCase))\n            {\n                return true;\n            }\n\n            if (p.StartsWith(\"/usr/share/v2rayN\", StringComparison.OrdinalIgnoreCase))\n            {\n                return true;\n            }\n        }\n        catch\n        {\n        }\n        return false;\n    }\n\n    private static async Task<string?> GetLinuxUserId()\n    {\n        var arg = new List<string>() { \"-c\", \"id -u\" };\n        return await GetCliWrapOutput(Global.LinuxBash, arg);\n    }\n\n    public static async Task<string?> SetLinuxChmod(string? fileName)\n    {\n        if (fileName.IsNullOrEmpty())\n        {\n            return null;\n        }\n        if (SetUnixFileMode(fileName))\n        {\n            Logging.SaveLog($\"Successfully set the file execution permission, {fileName}\");\n            return string.Empty;\n        }\n\n        if (fileName.Contains(' '))\n        {\n            fileName = fileName.AppendQuotes();\n        }\n        var arg = new List<string>() { \"-c\", $\"chmod +x {fileName}\" };\n        return await GetCliWrapOutput(Global.LinuxBash, arg);\n    }\n\n    public static bool SetUnixFileMode(string? fileName)\n    {\n        try\n        {\n            if (fileName.IsNullOrEmpty())\n            {\n                return false;\n            }\n\n            if (File.Exists(fileName))\n            {\n                var currentMode = File.GetUnixFileMode(fileName);\n                File.SetUnixFileMode(fileName, currentMode | UnixFileMode.UserExecute | UnixFileMode.GroupExecute | UnixFileMode.OtherExecute);\n                return true;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"SetUnixFileMode\", ex);\n        }\n        return false;\n    }\n\n    public static async Task<string?> GetLinuxFontFamily(string lang)\n    {\n        // var arg = new List<string>() { \"-c\", $\"fc-list :lang={lang} family\" };\n        var arg = new List<string>() { \"-c\", $\"fc-list : family\" };\n        return await GetCliWrapOutput(Global.LinuxBash, arg);\n    }\n\n    public static string? GetHomePath()\n    {\n        return IsWindows()\n            ? Environment.ExpandEnvironmentVariables(\"%HOMEDRIVE%%HOMEPATH%\")\n            : Environment.GetEnvironmentVariable(\"HOME\");\n    }\n\n    #endregion Platform\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/WindowsUtils.cs",
    "content": "using Microsoft.Win32;\n\nnamespace ServiceLib.Common;\n\ninternal static class WindowsUtils\n{\n    private static readonly string _tag = \"WindowsUtils\";\n\n    public static string? RegReadValue(string path, string name, string def)\n    {\n        RegistryKey? regKey = null;\n        try\n        {\n            regKey = Registry.CurrentUser.OpenSubKey(path, false);\n            var value = regKey?.GetValue(name) as string;\n            return value.IsNullOrEmpty() ? def : value;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        finally\n        {\n            regKey?.Close();\n        }\n        return def;\n    }\n\n    public static void RegWriteValue(string path, string name, object value)\n    {\n        RegistryKey? regKey = null;\n        try\n        {\n            regKey = Registry.CurrentUser.CreateSubKey(path);\n            if (value.ToString().IsNullOrEmpty())\n            {\n                regKey?.DeleteValue(name, false);\n            }\n            else\n            {\n                regKey?.SetValue(name, value);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        finally\n        {\n            regKey?.Close();\n        }\n    }\n\n    public static async Task RemoveTunDevice()\n    {\n        try\n        {\n            var sum = MD5.HashData(Encoding.UTF8.GetBytes(\"wintunsingbox_tun\"));\n            var guid = new Guid(sum);\n            var pnpUtilPath = @\"C:\\Windows\\System32\\pnputil.exe\";\n            var arg = $$\"\"\" /remove-device  \"SWD\\Wintun\\{{{guid}}}\" \"\"\";\n\n            // Try to remove the device\n            _ = await Utils.GetCliWrapOutput(pnpUtilPath, arg);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Common/YamlUtils.cs",
    "content": "using YamlDotNet.Core;\nusing YamlDotNet.Serialization;\nusing YamlDotNet.Serialization.NamingConventions;\n\nnamespace ServiceLib.Common;\n\npublic class YamlUtils\n{\n    private static readonly string _tag = \"YamlUtils\";\n\n    #region YAML\n\n    /// <summary>\n    /// Deserialize\n    /// </summary>\n    /// <typeparam name=\"T\"></typeparam>\n    /// <param name=\"str\"></param>\n    /// <returns></returns>\n    public static T FromYaml<T>(string str)\n    {\n        var deserializer = new DeserializerBuilder()\n            .WithNamingConvention(PascalCaseNamingConvention.Instance)\n            .Build();\n        try\n        {\n            var obj = deserializer.Deserialize<T>(str);\n            return obj;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return deserializer.Deserialize<T>(\"\");\n        }\n    }\n\n    /// <summary>\n    /// Serialize\n    /// </summary>\n    /// <param name=\"obj\"></param>\n    /// <returns></returns>\n    public static string ToYaml(object? obj)\n    {\n        var result = string.Empty;\n        if (obj == null)\n        {\n            return result;\n        }\n        var serializer = new SerializerBuilder()\n                .WithNamingConvention(HyphenatedNamingConvention.Instance)\n                .Build();\n\n        try\n        {\n            result = serializer.Serialize(obj);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        return result;\n    }\n\n    public static string? PreprocessYaml(string str)\n    {\n        try\n        {\n            var mergingParser = new MergingParser(new Parser(new StringReader(str)));\n            var obj = new DeserializerBuilder().Build().Deserialize(mergingParser);\n            return ToYaml(obj);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return null;\n        }\n    }\n\n    #endregion YAML\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EConfigType.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EConfigType\n{\n    VMess = 1,\n    Custom = 2,\n    Shadowsocks = 3,\n    SOCKS = 4,\n    VLESS = 5,\n    Trojan = 6,\n    Hysteria2 = 7,\n    TUIC = 8,\n    WireGuard = 9,\n    HTTP = 10,\n    Anytls = 11,\n    PolicyGroup = 101,\n    ProxyChain = 102,\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/ECoreType.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum ECoreType\n{\n    v2fly = 1,\n    Xray = 2,\n    v2fly_v5 = 4,\n    mihomo = 13,\n    hysteria = 21,\n    naiveproxy = 22,\n    tuic = 23,\n    sing_box = 24,\n    juicity = 25,\n    hysteria2 = 26,\n    brook = 27,\n    overtls = 28,\n    shadowquic = 29,\n    mieru = 30,\n    v2rayN = 99\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EGirdOrientation.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EGirdOrientation\n{\n    Horizontal,\n    Vertical,\n    Tab,\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EGlobalHotkey.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EGlobalHotkey\n{\n    ShowForm = 0,\n    SystemProxyClear = 1,\n    SystemProxySet = 2,\n    SystemProxyUnchanged = 3,\n    SystemProxyPac = 4,\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EInboundProtocol.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EInboundProtocol\n{\n    socks = 0,\n    socks2,\n    socks3,\n    pac,\n    api,\n    api2,\n    mixed,\n    speedtest = 21\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EMove.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EMove\n{\n    Top = 1,\n    Up = 2,\n    Down = 3,\n    Bottom = 4,\n    Position = 5\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EMultipleLoad.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EMultipleLoad\n{\n    LeastPing,\n    Fallback,\n    Random,\n    RoundRobin,\n    LeastLoad\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EPresetType.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EPresetType\n{\n    Default = 0,\n    Russia = 1,\n    Iran = 2,\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/ERuleMode.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum ERuleMode\n{\n    Rule = 0,\n    Global = 1,\n    Direct = 2,\n    Unchanged = 3\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/ERuleType.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum ERuleType\n{\n    ALL = 0,\n    Routing = 1,\n    DNS = 2,\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EServerColName.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EServerColName\n{\n    Def = 0,\n    ConfigType,\n    Remarks,\n    Address,\n    Port,\n    Network,\n    StreamSecurity,\n    SubRemarks,\n    DelayVal,\n    SpeedVal,\n\n    TodayDown,\n    TodayUp,\n    TotalDown,\n    TotalUp\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/ESpeedActionType.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum ESpeedActionType\n{\n    Tcping,\n    Realping,\n    Speedtest,\n    Mixedtest,\n    FastRealping\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/ESysProxyType.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum ESysProxyType\n{\n    ForcedClear = 0,\n    ForcedChange = 1,\n    Unchanged = 2,\n    Pac = 3\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/ETheme.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum ETheme\n{\n    FollowSystem,\n    Dark,\n    Light,\n    Aquatic,\n    Desert,\n    Dusk,\n    NightSky\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/ETransport.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum ETransport\n{\n    tcp,\n    kcp,\n    ws,\n    httpupgrade,\n    xhttp,\n    h2,\n    http,\n    quic,\n    grpc\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Enums/EViewAction.cs",
    "content": "namespace ServiceLib.Enums;\n\npublic enum EViewAction\n{\n    CloseWindow,\n    ShowYesNo,\n    SaveFileDialog,\n    AddBatchRoutingRulesYesNo,\n    SetClipboardData,\n    AddServerViaClipboard,\n    ImportRulesFromClipboard,\n    ProfilesFocus,\n    ShareSub,\n    ShareServer,\n    ScanScreenTask,\n    ScanImageTask,\n    BrowseServer,\n    ImportRulesFromFile,\n    InitSettingFont,\n    PasswordInput,\n    SubEditWindow,\n    RoutingRuleSettingWindow,\n    RoutingRuleDetailsWindow,\n    AddServerWindow,\n    AddServer2Window,\n    AddGroupServerWindow,\n    DNSSettingWindow,\n    RoutingSettingWindow,\n    OptionSettingWindow,\n    FullConfigTemplateWindow,\n    GlobalHotkeySettingWindow,\n    SubSettingWindow,\n    DispatcherRefreshServersBiz,\n    DispatcherRefreshIcon,\n    DispatcherShowMsg,\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Events/AppEvents.cs",
    "content": "namespace ServiceLib.Events;\n\npublic static class AppEvents\n{\n    public static readonly EventChannel<Unit> ReloadRequested = new();\n    public static readonly EventChannel<bool?> ShowHideWindowRequested = new();\n    public static readonly EventChannel<Unit> AddServerViaScanRequested = new();\n    public static readonly EventChannel<Unit> AddServerViaClipboardRequested = new();\n    public static readonly EventChannel<bool> SubscriptionsUpdateRequested = new();\n\n    public static readonly EventChannel<Unit> ProfilesRefreshRequested = new();\n    public static readonly EventChannel<Unit> SubscriptionsRefreshRequested = new();\n    public static readonly EventChannel<Unit> ProxiesReloadRequested = new();\n    public static readonly EventChannel<ServerSpeedItem> DispatcherStatisticsRequested = new();\n\n    public static readonly EventChannel<string> SendSnackMsgRequested = new();\n    public static readonly EventChannel<string> SendMsgViewRequested = new();\n\n    public static readonly EventChannel<Unit> AppExitRequested = new();\n    public static readonly EventChannel<bool> ShutdownRequested = new();\n\n    public static readonly EventChannel<Unit> AdjustMainLvColWidthRequested = new();\n\n    public static readonly EventChannel<string> SetDefaultServerRequested = new();\n\n    public static readonly EventChannel<Unit> RoutingsMenuRefreshRequested = new();\n    public static readonly EventChannel<Unit> TestServerRequested = new();\n    public static readonly EventChannel<Unit> InboundDisplayRequested = new();\n    public static readonly EventChannel<ESysProxyType> SysProxyChangeRequested = new();\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Events/EventChannel.cs",
    "content": "using System.Reactive.Subjects;\n\nnamespace ServiceLib.Events;\n\npublic sealed class EventChannel<T>\n{\n    private readonly ISubject<T> _subject = Subject.Synchronize(new Subject<T>());\n\n    public IObservable<T> AsObservable()\n    {\n        return _subject.AsObservable();\n    }\n\n    public void Publish(T value)\n    {\n        _subject.OnNext(value);\n    }\n\n    public void Publish()\n    {\n        if (typeof(T) != typeof(Unit))\n        {\n            throw new InvalidOperationException(\"Publish() without value is only valid for EventChannel<Unit>.\");\n        }\n        _subject.OnNext((T)(object)Unit.Default);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/FodyWeavers.xml",
    "content": "﻿<Weavers xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n  <ReactiveUI />\n</Weavers>"
  },
  {
    "path": "v2rayN/ServiceLib/Global.cs",
    "content": "namespace ServiceLib;\n\npublic class Global\n{\n    #region const\n\n    public const string AppName = \"v2rayN\";\n    public const string GithubUrl = \"https://github.com\";\n    public const string GithubApiUrl = \"https://api.github.com/repos\";\n    public const string GeoUrl = \"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/{0}.dat\";\n    public const string SingboxRulesetUrl = @\"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs\";\n\n    public const string PromotionUrl = @\"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw=\";\n    public const string ConfigFileName = \"guiNConfig.json\";\n    public const string CoreConfigFileName = \"config.json\";\n    public const string CorePreConfigFileName = \"configPre.json\";\n    public const string CoreSpeedtestConfigFileName = \"configTest{0}.json\";\n    public const string ClashMixinConfigFileName = \"Mixin.yaml\";\n\n    public const string NamespaceSample = \"ServiceLib.Sample.\";\n    public const string V2raySampleClient = NamespaceSample + \"SampleClientConfig\";\n    public const string SingboxSampleClient = NamespaceSample + \"SingboxSampleClientConfig\";\n    public const string V2raySampleHttpRequestFileName = NamespaceSample + \"SampleHttpRequest\";\n    public const string V2raySampleHttpResponseFileName = NamespaceSample + \"SampleHttpResponse\";\n    public const string V2raySampleInbound = NamespaceSample + \"SampleInbound\";\n    public const string V2raySampleOutbound = NamespaceSample + \"SampleOutbound\";\n    public const string SingboxSampleOutbound = NamespaceSample + \"SingboxSampleOutbound\";\n    public const string CustomRoutingFileName = NamespaceSample + \"custom_routing_\";\n    public const string TunSingboxDNSFileName = NamespaceSample + \"tun_singbox_dns\";\n    public const string TunSingboxInboundFileName = NamespaceSample + \"tun_singbox_inbound\";\n    public const string TunSingboxRulesFileName = NamespaceSample + \"tun_singbox_rules\";\n    public const string DNSV2rayNormalFileName = NamespaceSample + \"dns_v2ray_normal\";\n    public const string DNSSingboxNormalFileName = NamespaceSample + \"dns_singbox_normal\";\n    public const string ClashMixinYaml = NamespaceSample + \"clash_mixin_yaml\";\n    public const string ClashTunYaml = NamespaceSample + \"clash_tun_yaml\";\n    public const string LinuxAutostartConfig = NamespaceSample + \"linux_autostart_config\";\n    public const string PacFileName = NamespaceSample + \"pac\";\n    public const string ProxySetOSXShellFileName = NamespaceSample + \"proxy_set_osx_sh\";\n    public const string ProxySetLinuxShellFileName = NamespaceSample + \"proxy_set_linux_sh\";\n    public const string KillAsSudoOSXShellFileName = NamespaceSample + \"kill_as_sudo_osx_sh\";\n    public const string KillAsSudoLinuxShellFileName = NamespaceSample + \"kill_as_sudo_linux_sh\";\n    public const string SingboxFakeIPFilterFileName = NamespaceSample + \"singbox_fakeip_filter\";\n\n    public const string DefaultSecurity = \"auto\";\n    public const string DefaultNetwork = \"tcp\";\n    public const string TcpHeaderHttp = \"http\";\n    public const string None = \"none\";\n    public const string ProxyTag = \"proxy\";\n    public const string DirectTag = \"direct\";\n    public const string BlockTag = \"block\";\n    public const string DnsTag = \"dns-module\";\n    public const string DirectDnsTag = \"direct-dns\";\n    public const string BalancerTagSuffix = \"-round\";\n    public const string StreamSecurity = \"tls\";\n    public const string StreamSecurityReality = \"reality\";\n    public const string Loopback = \"127.0.0.1\";\n    public const string InboundAPIProtocol = \"dokodemo-door\";\n    public const string HttpProtocol = \"http://\";\n    public const string HttpsProtocol = \"https://\";\n    public const string SocksProtocol = \"socks://\";\n    public const string Socks5Protocol = \"socks5://\";\n    public const string AsIs = \"AsIs\";\n    public const string IPIfNonMatch = \"IPIfNonMatch\";\n    public const string IPOnDemand = \"IPOnDemand\";\n\n    public const string UserEMail = \"t@t.tt\";\n    public const string AutoRunRegPath = @\"Software\\Microsoft\\Windows\\CurrentVersion\\Run\";\n    public const string AutoRunName = \"v2rayNAutoRun\";\n    public const string SystemProxyExceptionsWindows = \"localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*\";\n    public const string SystemProxyExceptionsLinux = \"localhost,127.0.0.0/8,::1\";\n    public const string RoutingRuleComma = \"<COMMA>\";\n    public const string GrpcGunMode = \"gun\";\n    public const string GrpcMultiMode = \"multi\";\n    public const int MaxPort = 65536;\n    public const int MinFontSize = 8;\n    public const int MinFontSizeCount = 13;\n    public const string RebootAs = \"rebootas\";\n    public const string AvaAssets = \"avares://v2rayN/Assets/\";\n    public const string LocalAppData = \"V2RAYN_LOCAL_APPLICATION_DATA_V2\";\n    public const string V2RayLocalAsset = \"V2RAY_LOCATION_ASSET\";\n    public const string XrayLocalAsset = \"XRAY_LOCATION_ASSET\";\n    public const string XrayLocalCert = \"XRAY_LOCATION_CERT\";\n    public const int SpeedTestPageSize = 1000;\n    public const string LinuxBash = \"/bin/bash\";\n\n    public const string SingboxDirectDNSTag = \"direct_dns\";\n    public const string SingboxRemoteDNSTag = \"remote_dns\";\n    public const string SingboxLocalDNSTag = \"local_local\";\n    public const string SingboxHostsDNSTag = \"hosts_dns\";\n    public const string SingboxFakeDNSTag = \"fake_dns\";\n\n    public const int Hysteria2DefaultHopInt = 10;\n\n    public const string PolicyGroupExcludeKeywords = @\"剩余|过期|到期|重置|[Rr]emaining|[Ee]xpir|[Rr]eset\";\n\n    public const string PolicyGroupDefaultAllFilter = $\"^(?!.*(?:{PolicyGroupExcludeKeywords})).*$\";\n\n    public static readonly List<string> PolicyGroupDefaultFilterList =\n    [\n        // All nodes (exclude traffic/expiry info)\n        PolicyGroupDefaultAllFilter,\n        // Low multiplier nodes, e.g. ×0.1, 0.5x, 0.1倍\n        @\"^.*(?:[×xX✕*]\\s*0\\.[0-9]+|0\\.[0-9]+\\s*[×xX✕*倍]).*$\",\n        // Dedicated line nodes, e.g. IPLC, IEPL\n        $@\"^(?!.*(?:{PolicyGroupExcludeKeywords})).*(?:专线|IPLC|IEPL|中转).*$\",\n        // Japan nodes\n        $@\"^(?!.*(?:{PolicyGroupExcludeKeywords})).*(?:日本|\\\\b[Jj][Pp]\\\\b|🇯🇵|[Jj]apan).*$\",\n    ];\n\n    public static readonly List<string> IEProxyProtocols =\n    [\n        \"{ip}:{http_port}\",\n        \"socks={ip}:{socks_port}\",\n        \"http={ip}:{http_port};https={ip}:{http_port};ftp={ip}:{http_port};socks={ip}:{socks_port}\",\n        \"http=http://{ip}:{http_port};https=http://{ip}:{http_port}\",\n        \"\"\n    ];\n\n    public static readonly List<string> SubConvertUrls =\n    [\n        @\"https://sub.xeton.dev/sub?url={0}\",\n        @\"https://api.dler.io/sub?url={0}\",\n        @\"http://127.0.0.1:25500/sub?url={0}\",\n        \"\"\n    ];\n\n    public static readonly List<string> SubConvertConfig =\n    [\n        @\"https://raw.githubusercontent.com/ACL4SSR/ACL4SSR/master/Clash/config/ACL4SSR_Online.ini\"\n    ];\n\n    public static readonly List<string> SubConvertTargets =\n    [\n        \"\",\n        \"mixed\",\n        \"v2ray\",\n        \"clash\",\n        \"ss\"\n    ];\n\n    public static readonly List<string> SpeedTestUrls =\n    [\n        @\"https://cachefly.cachefly.net/50mb.test\",\n        @\"https://speed.cloudflare.com/__down?bytes=10000000\",\n        @\"https://speed.cloudflare.com/__down?bytes=50000000\",\n        @\"https://speed.cloudflare.com/__down?bytes=100000000\",\n    ];\n\n    public static readonly List<string> SpeedPingTestUrls =\n    [\n        @\"https://www.google.com/generate_204\",\n        @\"https://www.gstatic.com/generate_204\",\n        @\"https://www.apple.com/library/test/success.html\",\n        @\"http://www.msftconnecttest.com/connecttest.txt\"\n    ];\n\n    public static readonly List<string> GeoFilesSources =\n    [\n        \"\",\n        @\"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat\",\n        @\"https://github.com/Chocolate4U/Iran-v2ray-rules/releases/latest/download/{0}.dat\"\n    ];\n\n    public static readonly List<string> SingboxRulesetSources =\n    [\n        \"\",\n        @\"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-rules-dat/release/sing-box/rule-set-{0}/{1}.srs\",\n        @\"https://raw.githubusercontent.com/chocolate4u/Iran-sing-box-rules/rule-set/{1}.srs\"\n    ];\n\n    public static readonly List<string> RoutingRulesSources =\n    [\n        \"\",\n        @\"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-custom-routing-list/main/v2rayN/template.json\",\n        @\"https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/main/v2rayN/template.json\"\n    ];\n\n    public static readonly List<string> DNSTemplateSources =\n    [\n        \"\",\n        @\"https://raw.githubusercontent.com/runetfreedom/russia-v2ray-custom-routing-list/main/v2rayN/\",\n        @\"https://raw.githubusercontent.com/Chocolate4U/Iran-v2ray-rules/main/v2rayN/\"\n    ];\n\n    public static readonly Dictionary<string, string> UserAgentTexts = new()\n    {\n        {\"chrome\",\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36\" },\n        {\"firefox\",\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0\" },\n        {\"safari\",\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.1 Safari/605.1.15\" },\n        {\"edge\",\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.70\" },\n        {\"none\",\"\"}\n    };\n\n    public const string Hysteria2ProtocolShare = \"hy2://\";\n\n    public static readonly Dictionary<EConfigType, string> ProtocolShares = new()\n    {\n        { EConfigType.VMess, \"vmess://\" },\n        { EConfigType.Shadowsocks, \"ss://\" },\n        { EConfigType.SOCKS, \"socks://\" },\n        { EConfigType.VLESS, \"vless://\" },\n        { EConfigType.Trojan, \"trojan://\" },\n        { EConfigType.Hysteria2, \"hysteria2://\" },\n        { EConfigType.TUIC, \"tuic://\" },\n        { EConfigType.WireGuard, \"wireguard://\" },\n        { EConfigType.Anytls, \"anytls://\" }\n    };\n\n    public static readonly Dictionary<EConfigType, string> ProtocolTypes = new()\n    {\n        { EConfigType.VMess, \"vmess\" },\n        { EConfigType.Shadowsocks, \"shadowsocks\" },\n        { EConfigType.SOCKS, \"socks\" },\n        { EConfigType.HTTP, \"http\" },\n        { EConfigType.VLESS, \"vless\" },\n        { EConfigType.Trojan, \"trojan\" },\n        { EConfigType.Hysteria2, \"hysteria2\" },\n        { EConfigType.TUIC, \"tuic\" },\n        { EConfigType.WireGuard, \"wireguard\" },\n        { EConfigType.Anytls, \"anytls\" }\n    };\n\n    public static readonly List<string> VmessSecurities =\n    [\n        \"aes-128-gcm\",\n        \"chacha20-poly1305\",\n        \"auto\",\n        \"none\",\n        \"zero\"\n    ];\n\n    public static readonly List<string> SsSecurities =\n    [\n        \"aes-256-gcm\",\n        \"aes-128-gcm\",\n        \"chacha20-poly1305\",\n        \"chacha20-ietf-poly1305\",\n        \"none\",\n        \"plain\"\n    ];\n\n    public static readonly List<string> SsSecuritiesInXray =\n    [\n        \"aes-256-gcm\",\n        \"aes-128-gcm\",\n        \"chacha20-poly1305\",\n        \"chacha20-ietf-poly1305\",\n        \"xchacha20-poly1305\",\n        \"xchacha20-ietf-poly1305\",\n        \"none\",\n        \"plain\",\n        \"2022-blake3-aes-128-gcm\",\n        \"2022-blake3-aes-256-gcm\",\n        \"2022-blake3-chacha20-poly1305\"\n    ];\n\n    public static readonly List<string> SsSecuritiesInSingbox =\n    [\n        \"aes-256-gcm\",\n        \"aes-192-gcm\",\n        \"aes-128-gcm\",\n        \"chacha20-ietf-poly1305\",\n        \"xchacha20-ietf-poly1305\",\n        \"none\",\n        \"2022-blake3-aes-128-gcm\",\n        \"2022-blake3-aes-256-gcm\",\n        \"2022-blake3-chacha20-poly1305\",\n        \"aes-128-ctr\",\n        \"aes-192-ctr\",\n        \"aes-256-ctr\",\n        \"aes-128-cfb\",\n        \"aes-192-cfb\",\n        \"aes-256-cfb\",\n        \"rc4-md5\",\n        \"chacha20-ietf\",\n        \"xchacha20\"\n    ];\n\n    public static readonly List<string> Flows =\n    [\n        \"\",\n        \"xtls-rprx-vision\",\n        \"xtls-rprx-vision-udp443\"\n    ];\n\n    public static readonly List<string> Networks =\n    [\n        \"tcp\",\n        \"kcp\",\n        \"ws\",\n        \"httpupgrade\",\n        \"xhttp\",\n        \"h2\",\n        \"quic\",\n        \"grpc\"\n    ];\n\n    public static readonly List<string> KcpHeaderTypes =\n    [\n        \"srtp\",\n        \"utp\",\n        \"wechat-video\",\n        \"dtls\",\n        \"wireguard\",\n        \"dns\"\n    ];\n\n    public static readonly Dictionary<string, string> KcpHeaderMaskMap = new()\n    {\n        { \"srtp\", \"header-srtp\" },\n        { \"utp\", \"header-utp\" },\n        { \"wechat-video\", \"header-wechat\" },\n        { \"dtls\", \"header-dtls\" },\n        { \"wireguard\", \"header-wireguard\" },\n        { \"dns\", \"header-dns\" }\n    };\n\n    public static readonly List<string> CoreTypes =\n    [\n        \"Xray\",\n        \"sing_box\"\n    ];\n\n    public static readonly HashSet<EConfigType> XraySupportConfigType =\n    [\n        EConfigType.VMess,\n        EConfigType.VLESS,\n        EConfigType.Shadowsocks,\n        EConfigType.Trojan,\n        EConfigType.Hysteria2,\n        EConfigType.WireGuard,\n        EConfigType.SOCKS,\n        EConfigType.HTTP,\n    ];\n\n    public static readonly HashSet<EConfigType> SingboxSupportConfigType =\n    [\n        EConfigType.VMess,\n        EConfigType.VLESS,\n        EConfigType.Shadowsocks,\n        EConfigType.Trojan,\n        EConfigType.Hysteria2,\n        EConfigType.TUIC,\n        EConfigType.Anytls,\n        EConfigType.WireGuard,\n        EConfigType.SOCKS,\n        EConfigType.HTTP,\n    ];\n\n    public static readonly HashSet<EConfigType> SingboxOnlyConfigType = SingboxSupportConfigType.Except(XraySupportConfigType).ToHashSet();\n\n    public static readonly List<string> DomainStrategies =\n    [\n        AsIs,\n        IPIfNonMatch,\n        IPOnDemand\n    ];\n\n    public static readonly List<string> DomainStrategies4Sbox =\n    [\n        \"\",\n        \"prefer_ipv4\",\n        \"prefer_ipv6\",\n        \"ipv4_only\",\n        \"ipv6_only\"\n    ];\n\n    public static readonly List<string> Fingerprints =\n    [\n        \"chrome\",\n        \"firefox\",\n        \"safari\",\n        \"ios\",\n        \"android\",\n        \"edge\",\n        \"360\",\n        \"qq\",\n        \"random\",\n        \"randomized\",\n        \"\"\n    ];\n\n    public static readonly List<string> UserAgent =\n    [\n        \"chrome\",\n        \"firefox\",\n        \"safari\",\n        \"edge\",\n        \"none\"\n    ];\n\n    public static readonly List<string> XhttpMode =\n    [\n        \"auto\",\n        \"packet-up\",\n        \"stream-up\",\n        \"stream-one\"\n    ];\n\n    public static readonly List<string> AllowInsecure =\n    [\n        \"true\",\n        \"false\",\n        \"\"\n    ];\n\n    public static readonly List<string> DomainStrategy =\n    [\n        \"AsIs\",\n        \"UseIP\",\n        \"UseIPv4v6\",\n        \"UseIPv6v4\",\n        \"UseIPv4\",\n        \"UseIPv6\",\n        \"\"\n    ];\n\n    public static readonly List<string> DomainDirectDNSAddress =\n    [\n        \"https://dns.alidns.com/dns-query\",\n        \"https://doh.pub/dns-query\",\n        \"https://dns.alidns.com/dns-query,https://doh.pub/dns-query\",\n        \"223.5.5.5\",\n        \"119.29.29.29\",\n        \"localhost\"\n    ];\n\n    public static readonly List<string> DomainRemoteDNSAddress =\n    [\n        \"https://cloudflare-dns.com/dns-query\",\n        \"https://dns.google/dns-query\",\n        \"https://cloudflare-dns.com/dns-query,https://dns.google/dns-query,8.8.8.8\",\n        \"https://dns.cloudflare.com/dns-query\",\n        \"https://doh.dns.sb/dns-query\",\n        \"https://doh.opendns.com/dns-query\",\n        \"https://common.dot.dns.yandex.net\",\n        \"8.8.8.8\",\n        \"1.1.1.1\",\n        \"185.222.222.222\",\n        \"208.67.222.222\",\n        \"77.88.8.8\"\n    ];\n\n    public static readonly List<string> DomainPureIPDNSAddress =\n    [\n        \"223.5.5.5\",\n        \"119.29.29.29\",\n        \"localhost\"\n    ];\n\n    public static readonly List<string> Languages =\n    [\n        \"zh-Hans\",\n        \"zh-Hant\",\n        \"en\",\n        \"fa-Ir\",\n        \"fr\",\n        \"ru\",\n        \"hu\"\n    ];\n\n    public static readonly List<string> Alpns =\n    [\n        \"h3\",\n        \"h2\",\n        \"http/1.1\",\n        \"h3,h2\",\n        \"h2,http/1.1\",\n        \"h3,h2,http/1.1\",\n        \"\"\n    ];\n\n    public static readonly List<string> LogLevels =\n    [\n        \"debug\",\n        \"info\",\n        \"warning\",\n        \"error\",\n        \"none\"\n    ];\n\n    public static readonly Dictionary<string, string> LogLevelColors = new()\n    {\n        { \"debug\",   \"#6C757D\" },\n        { \"info\",    \"#2ECC71\" },\n        { \"warning\", \"#FFA500\" },\n        { \"error\",   \"#E74C3C\" },\n    };\n\n    public static readonly List<string> InboundTags =\n    [\n        \"socks\",\n        \"socks2\",\n        \"socks3\"\n    ];\n\n    public static readonly List<string> RuleProtocols =\n    [\n        \"http\",\n        \"tls\",\n        \"bittorrent\"\n    ];\n\n    public static readonly List<string> RuleNetworks =\n    [\n        \"\",\n        \"tcp\",\n        \"udp\",\n        \"tcp,udp\"\n    ];\n\n    public static readonly List<string> destOverrideProtocols =\n    [\n        \"http\",\n        \"tls\",\n        \"quic\",\n        \"fakedns\",\n        \"fakedns+others\"\n    ];\n\n    public static readonly List<int> TunMtus =\n    [\n        1280,\n        1408,\n        1500,\n        4064,\n        9000,\n        65535\n    ];\n\n    public static readonly List<string> TunStacks =\n    [\n        \"gvisor\",\n        \"system\",\n        \"mixed\"\n    ];\n\n    public static readonly List<string> PresetMsgFilters =\n    [\n        \"proxy\",\n        \"direct\",\n        \"block\",\n        \"\"\n    ];\n\n    public static readonly List<string> SingboxMuxs =\n    [\n        \"h2mux\",\n        \"smux\",\n        \"yamux\",\n        \"\"\n    ];\n\n    public static readonly List<string> TuicCongestionControls =\n    [\n        \"cubic\",\n        \"new_reno\",\n        \"bbr\"\n    ];\n\n    public static readonly List<string> allowSelectType =\n    [\n        \"selector\",\n        \"urltest\",\n        \"loadbalance\",\n        \"fallback\"\n    ];\n\n    public static readonly List<string> notAllowTestType =\n    [\n        \"selector\",\n        \"urltest\",\n        \"direct\",\n        \"reject\",\n        \"compatible\",\n        \"pass\",\n        \"loadbalance\",\n        \"fallback\"\n    ];\n\n    public static readonly List<string> proxyVehicleType =\n    [\n        \"file\",\n        \"http\"\n    ];\n\n    public static readonly Dictionary<ECoreType, string> CoreUrls = new()\n    {\n        { ECoreType.v2fly, \"v2fly/v2ray-core\" },\n        { ECoreType.v2fly_v5, \"v2fly/v2ray-core\" },\n        { ECoreType.Xray, \"XTLS/Xray-core\" },\n        { ECoreType.sing_box, \"SagerNet/sing-box\" },\n        { ECoreType.mihomo, \"MetaCubeX/mihomo\" },\n        { ECoreType.hysteria, \"apernet/hysteria\" },\n        { ECoreType.hysteria2, \"apernet/hysteria\" },\n        { ECoreType.naiveproxy, \"klzgrad/naiveproxy\" },\n        { ECoreType.tuic, \"EAimTY/tuic\" },\n        { ECoreType.juicity, \"juicity/juicity\" },\n        { ECoreType.brook, \"txthinking/brook\" },\n        { ECoreType.overtls, \"ShadowsocksR-Live/overtls\" },\n        { ECoreType.shadowquic, \"spongebob888/shadowquic\" },\n        { ECoreType.mieru, \"enfein/mieru\" },\n        { ECoreType.v2rayN, \"2dust/v2rayN\" },\n    };\n\n    public static readonly List<string> OtherGeoUrls =\n    [\n        @\"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/geoip-only-cn-private.dat\",\n        @\"https://raw.githubusercontent.com/Loyalsoldier/geoip/release/Country.mmdb\",\n        @\"https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geoip.metadb\"\n    ];\n\n    public static readonly List<string> IPAPIUrls =\n    [\n        @\"https://api.ip.sb/geoip\",\n        @\"https://api-ipv4.ip.sb/geoip\",\n        @\"https://api-ipv6.ip.sb/geoip\",\n        @\"https://api.ipapi.is\",\n        @\"\"\n    ];\n\n    public static readonly List<string> OutboundTags =\n    [\n        ProxyTag,\n        DirectTag,\n        BlockTag\n    ];\n\n    public static readonly Dictionary<string, List<string>> PredefinedHosts = new()\n    {\n        { \"dns.google\", [\"8.8.8.8\", \"8.8.4.4\", \"2001:4860:4860::8888\", \"2001:4860:4860::8844\"] },\n        { \"dns.alidns.com\", [\"223.5.5.5\", \"223.6.6.6\", \"2400:3200::1\", \"2400:3200:baba::1\"] },\n        { \"one.one.one.one\", [\"1.1.1.1\", \"1.0.0.1\", \"2606:4700:4700::1111\", \"2606:4700:4700::1001\"] },\n        { \"1dot1dot1dot1.cloudflare-dns.com\", [\"1.1.1.1\", \"1.0.0.1\", \"2606:4700:4700::1111\", \"2606:4700:4700::1001\"] },\n        { \"cloudflare-dns.com\", [\"104.16.249.249\", \"104.16.248.249\", \"2606:4700::6810:f8f9\", \"2606:4700::6810:f9f9\"] },\n        { \"dns.cloudflare.com\", [\"104.16.132.229\", \"104.16.133.229\", \"2606:4700::6810:84e5\", \"2606:4700::6810:85e5\"] },\n        { \"dot.pub\", [\"1.12.12.12\", \"120.53.53.53\"] },\n        { \"doh.pub\", [\"1.12.12.12\", \"120.53.53.53\"] },\n        { \"dns.quad9.net\", [\"9.9.9.9\", \"149.112.112.112\", \"2620:fe::fe\", \"2620:fe::9\"] },\n        { \"dns.yandex.net\", [\"77.88.8.8\", \"77.88.8.1\", \"2a02:6b8::feed:0ff\", \"2a02:6b8:0:1::feed:0ff\"] },\n        { \"dns.sb\", [\"185.222.222.222\", \"2a09::\"] },\n        { \"dns.umbrella.com\", [\"208.67.220.220\", \"208.67.222.222\", \"2620:119:35::35\", \"2620:119:53::53\"] },\n        { \"dns.sse.cisco.com\", [\"208.67.220.220\", \"208.67.222.222\", \"2620:119:35::35\", \"2620:119:53::53\"] },\n        { \"engage.cloudflareclient.com\", [\"162.159.192.1\"] }\n    };\n\n    public static readonly List<string> ExpectedIPs =\n    [\n        \"geoip:cn\",\n        \"geoip:ir\",\n        \"geoip:ru\",\n        \"\"\n    ];\n\n    public static readonly List<string> EchForceQuerys =\n    [\n        \"none\",\n        \"half\",\n        \"full\",\n        \"\"\n    ];\n\n    #endregion const\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/GlobalUsings.cs",
    "content": "global using System.Collections.Concurrent;\nglobal using System.Diagnostics;\nglobal using System.Net;\nglobal using System.Net.NetworkInformation;\nglobal using System.Net.Sockets;\nglobal using System.Reactive;\nglobal using System.Reactive.Disposables;\nglobal using System.Reactive.Linq;\nglobal using System.Reflection;\nglobal using System.Runtime.InteropServices;\nglobal using System.Security.Cryptography;\nglobal using System.Text;\nglobal using System.Text.Encodings.Web;\nglobal using System.Text.Json;\nglobal using System.Text.Json.Nodes;\nglobal using System.Text.Json.Serialization;\nglobal using System.Text.RegularExpressions;\nglobal using DynamicData;\nglobal using DynamicData.Binding;\nglobal using ReactiveUI;\nglobal using ReactiveUI.Fody.Helpers;\nglobal using ServiceLib.Base;\nglobal using ServiceLib.Common;\nglobal using ServiceLib.Enums;\nglobal using ServiceLib.Events;\nglobal using ServiceLib.Handler;\nglobal using ServiceLib.Handler.Builder;\nglobal using ServiceLib.Handler.Fmt;\nglobal using ServiceLib.Handler.SysProxy;\nglobal using ServiceLib.Helper;\nglobal using ServiceLib.Manager;\nglobal using ServiceLib.Models;\nglobal using ServiceLib.Resx;\nglobal using ServiceLib.Services;\nglobal using ServiceLib.Services.CoreConfig;\nglobal using ServiceLib.Services.Statistics;\nglobal using SQLite;\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/AutoStartupHandler.cs",
    "content": "using System.Security.Principal;\n\nnamespace ServiceLib.Handler;\n\npublic static class AutoStartupHandler\n{\n    private static readonly string _tag = \"AutoStartupHandler\";\n\n    public static async Task<bool> UpdateTask(Config config)\n    {\n        if (Utils.IsWindows())\n        {\n            await ClearTaskWindows();\n\n            if (config.GuiItem.AutoRun)\n            {\n                await SetTaskWindows();\n            }\n        }\n        else if (Utils.IsLinux())\n        {\n            await ClearTaskLinux();\n\n            if (config.GuiItem.AutoRun)\n            {\n                await SetTaskLinux();\n            }\n        }\n        else if (Utils.IsMacOS())\n        {\n            await ClearTaskOSX();\n\n            if (config.GuiItem.AutoRun)\n            {\n                await SetTaskOSX();\n            }\n        }\n\n        return true;\n    }\n\n    #region Windows\n\n    private static async Task ClearTaskWindows()\n    {\n        var autoRunName = GetAutoRunNameWindows();\n        WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, \"\");\n        if (Utils.IsAdministrator())\n        {\n            AutoStartTaskService(autoRunName, \"\", \"\");\n        }\n\n        await Task.CompletedTask;\n    }\n\n    private static async Task SetTaskWindows()\n    {\n        try\n        {\n            var autoRunName = GetAutoRunNameWindows();\n            var exePath = Utils.GetExePath();\n            if (Utils.IsAdministrator())\n            {\n                AutoStartTaskService(autoRunName, exePath, \"\");\n            }\n            else\n            {\n                WindowsUtils.RegWriteValue(Global.AutoRunRegPath, autoRunName, exePath.AppendQuotes());\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        await Task.CompletedTask;\n    }\n\n    /// <summary>\n    /// Auto Start via TaskService\n    /// </summary>\n    /// <param name=\"taskName\"></param>\n    /// <param name=\"fileName\"></param>\n    /// <param name=\"description\"></param>\n    /// <exception cref=\"ArgumentNullException\"></exception>\n    public static void AutoStartTaskService(string taskName, string fileName, string description)\n    {\n        if (taskName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        var logonUser = WindowsIdentity.GetCurrent().Name;\n        using var taskService = new Microsoft.Win32.TaskScheduler.TaskService();\n        var tasks = taskService.RootFolder.GetTasks(new Regex(taskName));\n        if (fileName.IsNullOrEmpty())\n        {\n            foreach (var t in tasks)\n            {\n                taskService.RootFolder.DeleteTask(t.Name);\n            }\n            return;\n        }\n\n        var task = taskService.NewTask();\n        task.RegistrationInfo.Description = description;\n        task.Settings.DisallowStartIfOnBatteries = false;\n        task.Settings.StopIfGoingOnBatteries = false;\n        task.Settings.RunOnlyIfIdle = false;\n        task.Settings.IdleSettings.StopOnIdleEnd = false;\n        task.Settings.ExecutionTimeLimit = TimeSpan.Zero;\n        task.Triggers.Add(new Microsoft.Win32.TaskScheduler.LogonTrigger { UserId = logonUser, Delay = TimeSpan.FromSeconds(30) });\n        task.Principal.RunLevel = Microsoft.Win32.TaskScheduler.TaskRunLevel.Highest;\n        task.Actions.Add(new Microsoft.Win32.TaskScheduler.ExecAction(fileName.AppendQuotes(), null, Path.GetDirectoryName(fileName)));\n\n        taskService.RootFolder.RegisterTaskDefinition(taskName, task);\n    }\n\n    private static string GetAutoRunNameWindows()\n    {\n        return $\"{Global.AutoRunName}_{Utils.GetMd5(Utils.StartupPath())}\";\n    }\n\n    #endregion Windows\n\n    #region Linux\n\n    private static async Task ClearTaskLinux()\n    {\n        try\n        {\n            File.Delete(GetHomePathLinux());\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        await Task.CompletedTask;\n    }\n\n    private static async Task SetTaskLinux()\n    {\n        try\n        {\n            var linuxConfig = EmbedUtils.GetEmbedText(Global.LinuxAutostartConfig);\n            if (linuxConfig.IsNotEmpty())\n            {\n                linuxConfig = linuxConfig.Replace(\"$ExecPath$\", Utils.GetExePath());\n                Logging.SaveLog(linuxConfig);\n\n                var homePath = GetHomePathLinux();\n                await File.WriteAllTextAsync(homePath, linuxConfig);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private static string GetHomePathLinux()\n    {\n        var homePath = Path.Combine(Utils.GetHomePath(), \".config\", \"autostart\", $\"{Global.AppName}.desktop\");\n        Directory.CreateDirectory(Path.GetDirectoryName(homePath));\n        return homePath;\n    }\n\n    #endregion Linux\n\n    #region macOS\n\n    private static async Task ClearTaskOSX()\n    {\n        try\n        {\n            var launchAgentPath = GetLaunchAgentPathMacOS();\n            if (File.Exists(launchAgentPath))\n            {\n                var args = new[] { \"-c\", $\"launchctl unload -w \\\"{launchAgentPath}\\\"\" };\n                await Utils.GetCliWrapOutput(Global.LinuxBash, args);\n\n                File.Delete(launchAgentPath);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private static async Task SetTaskOSX()\n    {\n        try\n        {\n            var plistContent = GenerateLaunchAgentPlist();\n            var launchAgentPath = GetLaunchAgentPathMacOS();\n            await File.WriteAllTextAsync(launchAgentPath, plistContent);\n\n            var args = new[] { \"-c\", $\"launchctl load -w \\\"{launchAgentPath}\\\"\" };\n            await Utils.GetCliWrapOutput(Global.LinuxBash, args);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private static string GetLaunchAgentPathMacOS()\n    {\n        var homePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);\n        var launchAgentPath = Path.Combine(homePath, \"Library\", \"LaunchAgents\", $\"{Global.AppName}-LaunchAgent.plist\");\n        Directory.CreateDirectory(Path.GetDirectoryName(launchAgentPath));\n        return launchAgentPath;\n    }\n\n    private static string GenerateLaunchAgentPlist()\n    {\n        var exePath = Utils.GetExePath();\n        var appName = Path.GetFileNameWithoutExtension(exePath);\n        return $@\"<?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>Label</key>\n    <string>{Global.AppName}-LaunchAgent</string>\n    <key>ProgramArguments</key>\n    <array>\n        <string>/bin/sh</string>\n        <string>-c</string>\n        <string>if ! pgrep -x \"\"{appName}\"\" > /dev/null; then \"\"{exePath}\"\"; fi</string>\n    </array>\n    <key>RunAtLoad</key>\n    <true/>\n    <key>KeepAlive</key>\n    <false/>\n</dict>\n</plist>\";\n    }\n\n    #endregion macOS\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Builder/CoreConfigContextBuilder.cs",
    "content": "namespace ServiceLib.Handler.Builder;\n\npublic record CoreConfigContextBuilderResult(CoreConfigContext Context, NodeValidatorResult ValidatorResult)\n{\n    public bool Success => ValidatorResult.Success;\n}\n\n/// <summary>\n/// Holds the results of a full context build, including the main context and an optional\n/// pre-socks context (e.g. for TUN protection or pre-socks chaining).\n/// </summary>\npublic record CoreConfigContextBuilderAllResult(\n    CoreConfigContextBuilderResult MainResult,\n    CoreConfigContextBuilderResult? PreSocksResult)\n{\n    /// <summary>True only when both the main result and (if present) the pre-socks result succeeded.</summary>\n    public bool Success => MainResult.Success && (PreSocksResult?.Success ?? true);\n\n    /// <summary>\n    /// Merges all errors and warnings from the main result and the optional pre-socks result\n    /// into a single <see cref=\"NodeValidatorResult\"/> for unified notification.\n    /// </summary>\n    public NodeValidatorResult CombinedValidatorResult => new(\n        [.. MainResult.ValidatorResult.Errors, .. PreSocksResult?.ValidatorResult.Errors ?? []],\n        [.. MainResult.ValidatorResult.Warnings, .. PreSocksResult?.ValidatorResult.Warnings ?? []]);\n\n    /// <summary>\n    /// The main context with TunProtectSsPort/ProxyRelaySsPort and ProtectDomainList merged in\n    /// from the pre-socks result (if any). Pass this to the core runner.\n    /// </summary>\n    public CoreConfigContext ResolvedMainContext => PreSocksResult is not null\n        ? MainResult.Context with\n        {\n            TunProtectSsPort = PreSocksResult.Context.TunProtectSsPort,\n            ProxyRelaySsPort = PreSocksResult.Context.ProxyRelaySsPort,\n            ProtectDomainList = [.. MainResult.Context.ProtectDomainList ?? [], .. PreSocksResult.Context.ProtectDomainList ?? []],\n        }\n        : MainResult.Context;\n}\n\npublic class CoreConfigContextBuilder\n{\n    /// <summary>\n    /// Builds a <see cref=\"CoreConfigContext\"/> for the given node, resolves its proxy map,\n    /// and processes outbound nodes referenced by routing rules.\n    /// </summary>\n    public static async Task<CoreConfigContextBuilderResult> Build(Config config, ProfileItem node)\n    {\n        var runCoreType = AppManager.Instance.GetCoreType(node, node.ConfigType);\n        var coreType = runCoreType == ECoreType.sing_box ? ECoreType.sing_box : ECoreType.Xray;\n        var context = new CoreConfigContext()\n        {\n            Node = node,\n            RunCoreType = runCoreType,\n            AllProxiesMap = [],\n            AppConfig = config,\n            FullConfigTemplate = await AppManager.Instance.GetFullConfigTemplateItem(coreType),\n            IsTunEnabled = config.TunModeItem.EnableTun,\n            SimpleDnsItem = config.SimpleDNSItem,\n            ProtectDomainList = [],\n            TunProtectSsPort = 0,\n            ProxyRelaySsPort = 0,\n            RawDnsItem = await AppManager.Instance.GetDNSItem(coreType),\n            RoutingItem = await ConfigHandler.GetDefaultRouting(config),\n        };\n        var validatorResult = NodeValidatorResult.Empty();\n        var (actNode, nodeValidatorResult) = await ResolveNodeAsync(context, node);\n        if (!nodeValidatorResult.Success)\n        {\n            return new CoreConfigContextBuilderResult(context, nodeValidatorResult);\n        }\n        context = context with { Node = actNode };\n        validatorResult.Warnings.AddRange(nodeValidatorResult.Warnings);\n        if (!(context.RoutingItem?.RuleSet.IsNullOrEmpty() ?? true))\n        {\n            var rules = JsonUtils.Deserialize<List<RulesItem>>(context.RoutingItem?.RuleSet) ?? [];\n            foreach (var ruleItem in rules.Where(ruleItem => ruleItem.Enabled && !Global.OutboundTags.Contains(ruleItem.OutboundTag)))\n            {\n                if (ruleItem.OutboundTag.IsNullOrEmpty())\n                {\n                    validatorResult.Warnings.Add(string.Format(ResUI.MsgRoutingRuleEmptyOutboundTag, ruleItem.Remarks));\n                    ruleItem.OutboundTag = Global.ProxyTag;\n                    continue;\n                }\n                var ruleOutboundNode = await AppManager.Instance.GetProfileItemViaRemarks(ruleItem.OutboundTag);\n                if (ruleOutboundNode == null)\n                {\n                    validatorResult.Warnings.Add(string.Format(ResUI.MsgRoutingRuleOutboundNodeNotFound, ruleItem.Remarks, ruleItem.OutboundTag));\n                    ruleItem.OutboundTag = Global.ProxyTag;\n                    continue;\n                }\n\n                var (actRuleNode, ruleNodeValidatorResult) = await ResolveNodeAsync(context, ruleOutboundNode, false);\n                validatorResult.Warnings.AddRange(ruleNodeValidatorResult.Warnings.Select(w =>\n                    string.Format(ResUI.MsgRoutingRuleOutboundNodeWarning, ruleItem.Remarks, ruleItem.OutboundTag, w)));\n                if (!ruleNodeValidatorResult.Success)\n                {\n                    validatorResult.Warnings.AddRange(ruleNodeValidatorResult.Errors.Select(e =>\n                        string.Format(ResUI.MsgRoutingRuleOutboundNodeError, ruleItem.Remarks, ruleItem.OutboundTag, e)));\n                    ruleItem.OutboundTag = Global.ProxyTag;\n                    continue;\n                }\n\n                context.AllProxiesMap[$\"remark:{ruleItem.OutboundTag}\"] = actRuleNode;\n            }\n        }\n\n        return new CoreConfigContextBuilderResult(context, validatorResult);\n    }\n\n    /// <summary>\n    /// Builds the main <see cref=\"CoreConfigContext\"/> for <paramref name=\"node\"/> and, when\n    /// the main build succeeds, also builds the optional pre-socks context required for TUN\n    /// protection or pre-socks proxy chaining.\n    /// </summary>\n    public static async Task<CoreConfigContextBuilderAllResult> BuildAll(Config config, ProfileItem node)\n    {\n        var mainResult = await Build(config, node);\n        if (!mainResult.Success)\n        {\n            return new CoreConfigContextBuilderAllResult(mainResult, null);\n        }\n\n        var preResult = await BuildPreSocksIfNeeded(mainResult.Context);\n        return new CoreConfigContextBuilderAllResult(mainResult, preResult);\n    }\n\n    /// <summary>\n    /// Determines whether a pre-socks context is required for <paramref name=\"nodeContext\"/>\n    /// and, if so, builds and returns it. Returns <c>null</c> when no pre-socks core is needed.\n    /// </summary>\n    private static async Task<CoreConfigContextBuilderResult?> BuildPreSocksIfNeeded(CoreConfigContext nodeContext)\n    {\n        var config = nodeContext.AppConfig;\n        var node = nodeContext.Node;\n        var coreType = AppManager.Instance.GetCoreType(node, node.ConfigType);\n\n        var preSocksItem = ConfigHandler.GetPreSocksItem(config, node, coreType);\n        if (preSocksItem != null)\n        {\n            var preSocksResult = await Build(nodeContext.AppConfig, preSocksItem);\n            return preSocksResult with\n            {\n                Context = preSocksResult.Context with\n                {\n                    ProtectDomainList = [.. nodeContext.ProtectDomainList ?? [], .. preSocksResult.Context.ProtectDomainList ?? []],\n                }\n            };\n        }\n\n        if (!nodeContext.IsTunEnabled\n            || coreType != ECoreType.Xray\n            || node.ConfigType == EConfigType.Custom)\n        {\n            return null;\n        }\n\n        var tunProtectSsPort = Utils.GetFreePort();\n        var proxyRelaySsPort = Utils.GetFreePort();\n        var preItem = new ProfileItem()\n        {\n            CoreType = ECoreType.sing_box,\n            ConfigType = EConfigType.Shadowsocks,\n            Address = Global.Loopback,\n            Port = proxyRelaySsPort,\n            Password = Global.None,\n        };\n        preItem.SetProtocolExtra(preItem.GetProtocolExtra() with\n        {\n            SsMethod = Global.None,\n        });\n        var preResult2 = await Build(nodeContext.AppConfig, preItem);\n        return preResult2 with\n        {\n            Context = preResult2.Context with\n            {\n                ProtectDomainList = [.. nodeContext.ProtectDomainList ?? [], .. preResult2.Context.ProtectDomainList ?? []],\n                TunProtectSsPort = tunProtectSsPort,\n                ProxyRelaySsPort = proxyRelaySsPort,\n            }\n        };\n    }\n\n    /// <summary>\n    /// Resolves a node into the context, optionally wrapping it in a subscription-level proxy chain.\n    /// Returns the effective (possibly replaced) node and the validation result.\n    /// </summary>\n    public static async Task<(ProfileItem, NodeValidatorResult)> ResolveNodeAsync(CoreConfigContext context,\n        ProfileItem node,\n        bool includeSubChain = true)\n    {\n        if (node.IndexId.IsNullOrEmpty())\n        {\n            return (node, NodeValidatorResult.Empty());\n        }\n\n        if (includeSubChain)\n        {\n            var (virtualChainNode, chainValidatorResult) = await BuildSubscriptionChainNodeAsync(node);\n            if (virtualChainNode != null)\n            {\n                context.AllProxiesMap[virtualChainNode.IndexId] = virtualChainNode;\n                var (resolvedNode, resolvedResult) = await ResolveNodeAsync(context, virtualChainNode, false);\n                resolvedResult.Warnings.InsertRange(0, chainValidatorResult.Warnings);\n                return (resolvedNode, resolvedResult);\n            }\n            // Chain not built but warnings may still exist (e.g. missing profiles)\n            if (chainValidatorResult.Warnings.Count > 0)\n            {\n                var fillResult = await RegisterNodeAsync(context, node);\n                fillResult.Warnings.InsertRange(0, chainValidatorResult.Warnings);\n                return (node, fillResult);\n            }\n        }\n\n        var registerResult = await RegisterNodeAsync(context, node);\n        return (node, registerResult);\n    }\n\n    /// <summary>\n    /// If the node's subscription defines prev/next profiles, creates a virtual\n    /// <see cref=\"EConfigType.ProxyChain\"/> node that wraps them together.\n    /// Returns <c>null</c> as the chain item when no chain is needed.\n    /// Any warnings (e.g. missing prev/next profile) are returned in the validator result.\n    /// </summary>\n    private static async Task<(ProfileItem? ChainNode, NodeValidatorResult ValidatorResult)> BuildSubscriptionChainNodeAsync(ProfileItem node)\n    {\n        var result = NodeValidatorResult.Empty();\n\n        if (node.Subid.IsNullOrEmpty() || node.ConfigType == EConfigType.Custom)\n        {\n            return (null, result);\n        }\n\n        var subItem = await AppManager.Instance.GetSubItem(node.Subid);\n        if (subItem == null)\n        {\n            return (null, result);\n        }\n\n        ProfileItem? prevNode = null;\n        ProfileItem? nextNode = null;\n\n        if (!subItem.PrevProfile.IsNullOrEmpty())\n        {\n            prevNode = await AppManager.Instance.GetProfileItemViaRemarks(subItem.PrevProfile);\n            if (prevNode == null)\n            {\n                result.Warnings.Add(string.Format(ResUI.MsgSubscriptionPrevProfileNotFound, subItem.PrevProfile));\n            }\n        }\n        if (!subItem.NextProfile.IsNullOrEmpty())\n        {\n            nextNode = await AppManager.Instance.GetProfileItemViaRemarks(subItem.NextProfile);\n            if (nextNode == null)\n            {\n                result.Warnings.Add(string.Format(ResUI.MsgSubscriptionNextProfileNotFound, subItem.NextProfile));\n            }\n        }\n\n        if (prevNode is null && nextNode is null)\n        {\n            return (null, result);\n        }\n\n        // Build new proxy chain node\n        var chainNode = new ProfileItem()\n        {\n            IndexId = $\"inner-{Utils.GetGuid(false)}\",\n            ConfigType = EConfigType.ProxyChain,\n            CoreType = AppManager.Instance.GetCoreType(node, node.ConfigType),\n            Remarks = node.Remarks,\n        };\n        List<string?> childItems = [prevNode?.IndexId, node.IndexId, nextNode?.IndexId];\n        var chainExtraItem = chainNode.GetProtocolExtra() with\n        {\n            GroupType = chainNode.ConfigType.ToString(),\n            ChildItems = string.Join(\",\", childItems.Where(x => !x.IsNullOrEmpty())),\n        };\n        chainNode.SetProtocolExtra(chainExtraItem);\n        return (chainNode, result);\n    }\n\n    /// <summary>\n    /// Dispatches registration to either <see cref=\"RegisterGroupNodeAsync\"/> or\n    /// <see cref=\"RegisterSingleNodeAsync\"/> based on the node's config type.\n    /// </summary>\n    private static async Task<NodeValidatorResult> RegisterNodeAsync(CoreConfigContext context, ProfileItem node)\n    {\n        if (node.ConfigType.IsGroupType())\n        {\n            return await RegisterGroupNodeAsync(context, node);\n        }\n        else\n        {\n            return RegisterSingleNodeAsync(context, node);\n        }\n    }\n\n    /// <summary>\n    /// Validates a single (non-group) node and, on success, adds it to the proxy map\n    /// and records any domain addresses that should bypass the proxy.\n    /// </summary>\n    private static NodeValidatorResult RegisterSingleNodeAsync(CoreConfigContext context, ProfileItem node)\n    {\n        if (node.ConfigType.IsGroupType())\n        {\n            return NodeValidatorResult.Empty();\n        }\n\n        var nodeValidatorResult = NodeValidator.Validate(node, context.RunCoreType);\n        if (!nodeValidatorResult.Success)\n        {\n            return nodeValidatorResult;\n        }\n\n        context.AllProxiesMap[node.IndexId] = node;\n\n        var address = node.Address;\n        if (Utils.IsDomain(address))\n        {\n            context.ProtectDomainList.Add(address);\n        }\n\n        if (!node.EchConfigList.IsNullOrEmpty())\n        {\n            var echQuerySni = node.Sni;\n            if (node.StreamSecurity == Global.StreamSecurity\n                && node.EchConfigList?.Contains(\"://\") == true)\n            {\n                var idx = node.EchConfigList.IndexOf('+');\n                echQuerySni = idx > 0 ? node.EchConfigList[..idx] : node.Sni;\n            }\n\n            if (Utils.IsDomain(echQuerySni))\n            {\n                context.ProtectDomainList.Add(echQuerySni);\n            }\n        }\n\n        return nodeValidatorResult;\n    }\n\n    /// <summary>\n    /// Entry point for registering a group node. Initialises the visited/ancestor sets\n    /// and delegates to <see cref=\"TraverseGroupNodeAsync\"/>.\n    /// </summary>\n    private static async Task<NodeValidatorResult> RegisterGroupNodeAsync(CoreConfigContext context,\n        ProfileItem node)\n    {\n        if (!node.ConfigType.IsGroupType())\n        {\n            return NodeValidatorResult.Empty();\n        }\n\n        HashSet<string> ancestors = [node.IndexId];\n        HashSet<string> globalVisited = [node.IndexId];\n        return await TraverseGroupNodeAsync(context, node, globalVisited, ancestors);\n    }\n\n    /// <summary>\n    /// Recursively walks the children of a group node, registering valid leaf nodes\n    /// and nested groups. Detects cycles via <paramref name=\"ancestorsGroup\"/> and\n    /// deduplicates shared nodes via <paramref name=\"globalVisitedGroup\"/>.\n    /// </summary>\n    private static async Task<NodeValidatorResult> TraverseGroupNodeAsync(\n        CoreConfigContext context,\n        ProfileItem node,\n        HashSet<string> globalVisitedGroup,\n        HashSet<string> ancestorsGroup)\n    {\n        var (groupChildList, _) = await GroupProfileManager.GetChildProfileItems(node);\n        List<string> childIndexIdList = [];\n        var childNodeValidatorResult = NodeValidatorResult.Empty();\n        foreach (var childNode in groupChildList)\n        {\n            if (ancestorsGroup.Contains(childNode.IndexId))\n            {\n                childNodeValidatorResult.Errors.Add(\n                    string.Format(ResUI.MsgGroupCycleDependency, node.Remarks, childNode.Remarks));\n                continue;\n            }\n\n            if (globalVisitedGroup.Contains(childNode.IndexId))\n            {\n                childIndexIdList.Add(childNode.IndexId);\n                continue;\n            }\n\n            if (!childNode.ConfigType.IsGroupType())\n            {\n                var childNodeResult = RegisterSingleNodeAsync(context, childNode);\n                childNodeValidatorResult.Warnings.AddRange(childNodeResult.Warnings.Select(w =>\n                    string.Format(ResUI.MsgGroupChildNodeWarning, node.Remarks, childNode.Remarks, w)));\n                childNodeValidatorResult.Errors.AddRange(childNodeResult.Errors.Select(e =>\n                    string.Format(ResUI.MsgGroupChildNodeError, node.Remarks, childNode.Remarks, e)));\n                if (!childNodeResult.Success)\n                {\n                    continue;\n                }\n\n                globalVisitedGroup.Add(childNode.IndexId);\n                childIndexIdList.Add(childNode.IndexId);\n                continue;\n            }\n\n            var newAncestorsGroup = new HashSet<string>(ancestorsGroup) { childNode.IndexId };\n            var childGroupResult =\n                await TraverseGroupNodeAsync(context, childNode, globalVisitedGroup, newAncestorsGroup);\n            childNodeValidatorResult.Warnings.AddRange(childGroupResult.Warnings.Select(w =>\n                string.Format(ResUI.MsgGroupChildGroupNodeWarning, node.Remarks, childNode.Remarks, w)));\n            childNodeValidatorResult.Errors.AddRange(childGroupResult.Errors.Select(e =>\n                string.Format(ResUI.MsgGroupChildGroupNodeError, node.Remarks, childNode.Remarks, e)));\n            if (!childGroupResult.Success)\n            {\n                continue;\n            }\n\n            globalVisitedGroup.Add(childNode.IndexId);\n            childIndexIdList.Add(childNode.IndexId);\n        }\n\n        if (childIndexIdList.Count == 0)\n        {\n            childNodeValidatorResult.Errors.Add(string.Format(ResUI.MsgGroupNoValidChildNode, node.Remarks));\n            return childNodeValidatorResult;\n        }\n        else\n        {\n            childNodeValidatorResult.Warnings.AddRange(childNodeValidatorResult.Errors);\n            childNodeValidatorResult.Errors.Clear();\n        }\n\n        node.SetProtocolExtra(node.GetProtocolExtra() with { ChildItems = Utils.List2String(childIndexIdList), });\n        context.AllProxiesMap[node.IndexId] = node;\n        return childNodeValidatorResult;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Builder/NodeValidator.cs",
    "content": "namespace ServiceLib.Handler.Builder;\n\npublic record NodeValidatorResult(List<string> Errors, List<string> Warnings)\n{\n    public bool Success => Errors.Count == 0;\n\n    public static NodeValidatorResult Empty()\n    {\n        return new NodeValidatorResult([], []);\n    }\n}\n\npublic class NodeValidator\n{\n    // Static validator rules\n    private static readonly HashSet<string> SingboxUnsupportedTransports =\n        [nameof(ETransport.kcp), nameof(ETransport.xhttp)];\n\n    private static readonly HashSet<EConfigType> SingboxTransportSupportedProtocols =\n        [EConfigType.VMess, EConfigType.VLESS, EConfigType.Trojan, EConfigType.Shadowsocks];\n\n    private static readonly HashSet<string> SingboxShadowsocksAllowedTransports =\n        [nameof(ETransport.tcp), nameof(ETransport.ws), nameof(ETransport.quic)];\n\n    public static NodeValidatorResult Validate(ProfileItem item, ECoreType coreType)\n    {\n        var v = new ValidationContext();\n        ValidateNodeAndCoreSupport(item, coreType, v);\n        return v.ToResult();\n    }\n\n    private class ValidationContext\n    {\n        public List<string> Errors { get; } = [];\n        public List<string> Warnings { get; } = [];\n\n        public void Error(string message)\n        {\n            Errors.Add(message);\n        }\n\n        public void Warning(string message)\n        {\n            Warnings.Add(message);\n        }\n\n        public void Assert(bool condition, string errorMsg)\n        {\n            if (!condition)\n            {\n                Error(errorMsg);\n            }\n        }\n\n        public NodeValidatorResult ToResult()\n        {\n            return new NodeValidatorResult(Errors, Warnings);\n        }\n    }\n\n    private static void ValidateNodeAndCoreSupport(ProfileItem item, ECoreType coreType, ValidationContext v)\n    {\n        if (item.ConfigType is EConfigType.Custom)\n        {\n            return;\n        }\n\n        if (item.ConfigType.IsGroupType())\n        {\n            // Group logic is handled in ValidateGroupNode\n            return;\n        }\n\n        // Basic Property Validation\n        v.Assert(!item.Address.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, \"Address\"));\n        v.Assert(item.Port is > 0 and <= 65535, string.Format(ResUI.MsgInvalidProperty, \"Port\"));\n\n        // Network & Core Logic\n        var net = item.GetNetwork();\n        if (coreType == ECoreType.sing_box)\n        {\n            var transportError = ValidateSingboxTransport(item.ConfigType, net);\n            if (transportError != null)\n            {\n                v.Error(transportError);\n            }\n\n            if (!Global.SingboxSupportConfigType.Contains(item.ConfigType))\n            {\n                v.Error(string.Format(ResUI.MsgCoreNotSupportProtocol, nameof(ECoreType.sing_box), item.ConfigType));\n            }\n        }\n        else if (coreType is ECoreType.Xray)\n        {\n            if (!Global.XraySupportConfigType.Contains(item.ConfigType))\n            {\n                v.Error(string.Format(ResUI.MsgCoreNotSupportProtocol, nameof(ECoreType.Xray), item.ConfigType));\n            }\n        }\n\n        // Protocol Specifics\n        var protocolExtra = item.GetProtocolExtra();\n        switch (item.ConfigType)\n        {\n            case EConfigType.VMess:\n                v.Assert(!item.Password.IsNullOrEmpty() && Utils.IsGuidByParse(item.Password),\n                    string.Format(ResUI.MsgInvalidProperty, \"Password\"));\n                break;\n\n            case EConfigType.VLESS:\n                v.Assert(\n                    !item.Password.IsNullOrEmpty()\n                    && (Utils.IsGuidByParse(item.Password) || item.Password.Length <= 30),\n                    string.Format(ResUI.MsgInvalidProperty, \"Password\")\n                );\n                v.Assert(Global.Flows.Contains(protocolExtra.Flow ?? string.Empty),\n                    string.Format(ResUI.MsgInvalidProperty, \"Flow\"));\n                break;\n\n            case EConfigType.Shadowsocks:\n                v.Assert(!item.Password.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, \"Password\"));\n                v.Assert(\n                    !string.IsNullOrEmpty(protocolExtra.SsMethod) &&\n                    Global.SsSecuritiesInSingbox.Contains(protocolExtra.SsMethod),\n                    string.Format(ResUI.MsgInvalidProperty, \"SsMethod\"));\n                break;\n        }\n\n        // TLS & Security\n        if (item.StreamSecurity == Global.StreamSecurity)\n        {\n            if (!item.Cert.IsNullOrEmpty() && CertPemManager.ParsePemChain(item.Cert).Count == 0 &&\n                !item.CertSha.IsNullOrEmpty())\n            {\n                v.Error(string.Format(ResUI.MsgInvalidProperty, \"TLS Certificate\"));\n            }\n        }\n\n        if (item.StreamSecurity == Global.StreamSecurityReality)\n        {\n            v.Assert(!item.PublicKey.IsNullOrEmpty(), string.Format(ResUI.MsgInvalidProperty, \"PublicKey\"));\n        }\n\n        if (item.Network == nameof(ETransport.xhttp) && !item.Extra.IsNullOrEmpty())\n        {\n            if (JsonUtils.ParseJson(item.Extra) is null)\n            {\n                v.Error(string.Format(ResUI.MsgInvalidProperty, \"XHTTP Extra\"));\n            }\n        }\n    }\n\n    private static string? ValidateSingboxTransport(EConfigType configType, string net)\n    {\n        // sing-box does not support xhttp / kcp transports\n        if (SingboxUnsupportedTransports.Contains(net))\n        {\n            return string.Format(ResUI.MsgCoreNotSupportNetwork, nameof(ECoreType.sing_box), net);\n        }\n\n        // sing-box does not support non-tcp transports for protocols other than vmess/trojan/vless/shadowsocks\n        if (!SingboxTransportSupportedProtocols.Contains(configType) && net != nameof(ETransport.tcp))\n        {\n            return string.Format(ResUI.MsgCoreNotSupportProtocolTransport,\n                nameof(ECoreType.sing_box), configType.ToString(), net);\n        }\n\n        // sing-box shadowsocks only supports tcp/ws/quic transports\n        if (configType == EConfigType.Shadowsocks && !SingboxShadowsocksAllowedTransports.Contains(net))\n        {\n            return string.Format(ResUI.MsgCoreNotSupportProtocolTransport,\n                nameof(ECoreType.sing_box), configType.ToString(), net);\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/ConfigHandler.cs",
    "content": "using System.Data;\n\nnamespace ServiceLib.Handler;\n\npublic static class ConfigHandler\n{\n    private static readonly string _configRes = Global.ConfigFileName;\n    private static readonly string _tag = \"ConfigHandler\";\n\n    #region ConfigHandler\n\n    /// <summary>\n    /// Load the application configuration file\n    /// If the file exists, deserialize it from JSON\n    /// If not found, create a new Config object with default settings\n    /// Initialize default values for missing configuration sections\n    /// </summary>\n    /// <returns>Config object containing application settings or null if there's an error</returns>\n    public static Config? LoadConfig()\n    {\n        Config? config = null;\n        var result = EmbedUtils.LoadResource(Utils.GetConfigPath(_configRes));\n        if (result.IsNotEmpty())\n        {\n            config = JsonUtils.Deserialize<Config>(result);\n        }\n        else\n        {\n            if (File.Exists(Utils.GetConfigPath(_configRes)))\n            {\n                Logging.SaveLog(\"LoadConfig Exception\");\n                return null;\n            }\n        }\n\n        config ??= new Config();\n\n        config.CoreBasicItem ??= new()\n        {\n            LogEnabled = false,\n            Loglevel = \"warning\",\n            MuxEnabled = false,\n        };\n\n        if (config.Inbound == null)\n        {\n            config.Inbound = new List<InItem>();\n            InItem inItem = new()\n            {\n                Protocol = EInboundProtocol.socks.ToString(),\n                LocalPort = 10808,\n                UdpEnabled = true,\n                SniffingEnabled = true,\n                RouteOnly = false,\n            };\n\n            config.Inbound.Add(inItem);\n        }\n        else\n        {\n            if (config.Inbound.Count > 0)\n            {\n                config.Inbound.First().Protocol = EInboundProtocol.socks.ToString();\n            }\n        }\n\n        config.RoutingBasicItem ??= new();\n        if (config.RoutingBasicItem.DomainStrategy.IsNullOrEmpty())\n        {\n            config.RoutingBasicItem.DomainStrategy = Global.DomainStrategies.First();\n        }\n\n        config.KcpItem ??= new KcpItem\n        {\n            Mtu = 1350,\n            Tti = 50,\n            UplinkCapacity = 12,\n            DownlinkCapacity = 100,\n            ReadBufferSize = 2,\n            WriteBufferSize = 2,\n            Congestion = false\n        };\n        config.GrpcItem ??= new GrpcItem\n        {\n            IdleTimeout = 60,\n            HealthCheckTimeout = 20,\n            PermitWithoutStream = false,\n            InitialWindowsSize = 0,\n        };\n        config.TunModeItem ??= new TunModeItem\n        {\n            EnableTun = false,\n            Mtu = 9000,\n        };\n        config.GuiItem ??= new();\n        config.MsgUIItem ??= new();\n\n        config.UiItem ??= new();\n        config.UiItem.MainColumnItem ??= new();\n        config.UiItem.WindowSizeItem ??= new();\n\n        if (config.UiItem.CurrentLanguage.IsNullOrEmpty())\n        {\n            config.UiItem.CurrentLanguage = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName.Equals(\"zh\", StringComparison.CurrentCultureIgnoreCase)\n                ? Global.Languages.First()\n                : Global.Languages[2];\n        }\n\n        config.ConstItem ??= new ConstItem();\n\n        config.SimpleDNSItem ??= InitBuiltinSimpleDNS();\n        config.SimpleDNSItem.GlobalFakeIp ??= true;\n        config.SimpleDNSItem.BootstrapDNS ??= Global.DomainPureIPDNSAddress.FirstOrDefault();\n        config.SimpleDNSItem.ServeStale ??= false;\n        config.SimpleDNSItem.ParallelQuery ??= false;\n\n        config.SpeedTestItem ??= new();\n        if (config.SpeedTestItem.SpeedTestTimeout < 10)\n        {\n            config.SpeedTestItem.SpeedTestTimeout = 10;\n        }\n        if (config.SpeedTestItem.SpeedTestUrl.IsNullOrEmpty())\n        {\n            config.SpeedTestItem.SpeedTestUrl = Global.SpeedTestUrls.First();\n        }\n        if (config.SpeedTestItem.SpeedPingTestUrl.IsNullOrEmpty())\n        {\n            config.SpeedTestItem.SpeedPingTestUrl = Global.SpeedPingTestUrls.First();\n        }\n        if (config.SpeedTestItem.MixedConcurrencyCount < 1)\n        {\n            config.SpeedTestItem.MixedConcurrencyCount = 5;\n        }\n\n        config.Mux4RayItem ??= new()\n        {\n            Concurrency = 8,\n            XudpConcurrency = 16,\n            XudpProxyUDP443 = \"reject\"\n        };\n\n        config.Mux4SboxItem ??= new()\n        {\n            Protocol = Global.SingboxMuxs.First(),\n            MaxConnections = 8\n        };\n\n        config.HysteriaItem ??= new()\n        {\n            UpMbps = 100,\n            DownMbps = 100\n        };\n        config.ClashUIItem ??= new();\n        config.ClashUIItem.ConnectionsColumnItem ??= new();\n        config.SystemProxyItem ??= new();\n        config.WebDavItem ??= new();\n        config.CheckUpdateItem ??= new();\n        config.Fragment4RayItem ??= new()\n        {\n            Packets = \"tlshello\",\n            Length = \"100-200\",\n            Interval = \"10-20\"\n        };\n        config.GlobalHotkeys ??= new();\n\n        if (config.SystemProxyItem.SystemProxyExceptions.IsNullOrEmpty())\n        {\n            config.SystemProxyItem.SystemProxyExceptions = Utils.IsWindows() ? Global.SystemProxyExceptionsWindows : Global.SystemProxyExceptionsLinux;\n        }\n\n        return config;\n    }\n\n    /// <summary>\n    /// Save the configuration to a file\n    /// First writes to a temporary file, then replaces the original file\n    /// </summary>\n    /// <param name=\"config\">Configuration object to be saved</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> SaveConfig(Config config)\n    {\n        try\n        {\n            //save temp file\n            var resPath = Utils.GetConfigPath(_configRes);\n            var tempPath = $\"{resPath}_temp\";\n\n            var content = JsonUtils.Serialize(config, true, true);\n            if (content.IsNullOrEmpty())\n            {\n                return -1;\n            }\n            await File.WriteAllTextAsync(tempPath, content);\n\n            //rename\n            File.Move(tempPath, resPath, true);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return -1;\n        }\n\n        return 0;\n    }\n\n    #endregion ConfigHandler\n\n    #region Server\n\n    /// <summary>\n    /// Add a server profile to the configuration\n    /// Dispatches the request to the appropriate method based on the config type\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Server profile to add</param>\n    /// <returns>Result of the operation (0 if successful, -1 if failed)</returns>\n    public static async Task<int> AddServer(Config config, ProfileItem profileItem)\n    {\n        var item = await AppManager.Instance.GetProfileItem(profileItem.IndexId);\n        if (item is null)\n        {\n            item = profileItem;\n        }\n        else\n        {\n            item.CoreType = profileItem.CoreType;\n            item.Remarks = profileItem.Remarks;\n            item.Address = profileItem.Address;\n            item.Port = profileItem.Port;\n\n            item.Username = profileItem.Username;\n            item.Password = profileItem.Password;\n\n            item.Network = profileItem.Network;\n            item.HeaderType = profileItem.HeaderType;\n            item.RequestHost = profileItem.RequestHost;\n            item.Path = profileItem.Path;\n\n            item.StreamSecurity = profileItem.StreamSecurity;\n            item.Sni = profileItem.Sni;\n            item.AllowInsecure = profileItem.AllowInsecure;\n            item.Fingerprint = profileItem.Fingerprint;\n            item.Alpn = profileItem.Alpn;\n\n            item.PublicKey = profileItem.PublicKey;\n            item.ShortId = profileItem.ShortId;\n            item.SpiderX = profileItem.SpiderX;\n            item.Mldsa65Verify = profileItem.Mldsa65Verify;\n            item.Extra = profileItem.Extra;\n            item.MuxEnabled = profileItem.MuxEnabled;\n            item.Cert = profileItem.Cert;\n            item.CertSha = profileItem.CertSha;\n            item.EchConfigList = profileItem.EchConfigList;\n            item.EchForceQuery = profileItem.EchForceQuery;\n            item.Finalmask = profileItem.Finalmask;\n            item.ProtoExtra = profileItem.ProtoExtra;\n        }\n\n        var ret = item.ConfigType switch\n        {\n            EConfigType.VMess => await AddVMessServer(config, item),\n            EConfigType.Shadowsocks => await AddShadowsocksServer(config, item),\n            EConfigType.SOCKS => await AddSocksServer(config, item),\n            EConfigType.HTTP => await AddHttpServer(config, item),\n            EConfigType.Trojan => await AddTrojanServer(config, item),\n            EConfigType.VLESS => await AddVlessServer(config, item),\n            EConfigType.Hysteria2 => await AddHysteria2Server(config, item),\n            EConfigType.TUIC => await AddTuicServer(config, item),\n            EConfigType.WireGuard => await AddWireguardServer(config, item),\n            EConfigType.Anytls => await AddAnytlsServer(config, item),\n            _ => -1,\n        };\n        return ret;\n    }\n\n    /// <summary>\n    /// Add or edit a VMess server\n    /// Validates and processes VMess-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">VMess profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddVMessServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.VMess;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        profileItem.SetProtocolExtra(profileItem.GetProtocolExtra() with\n        {\n            VmessSecurity = profileItem.GetProtocolExtra().VmessSecurity?.TrimEx()\n        });\n        profileItem.Network = profileItem.Network.TrimEx();\n        profileItem.HeaderType = profileItem.HeaderType.TrimEx();\n        profileItem.RequestHost = profileItem.RequestHost.TrimEx();\n        profileItem.Path = profileItem.Path.TrimEx();\n        profileItem.StreamSecurity = profileItem.StreamSecurity.TrimEx();\n\n        if (!Global.VmessSecurities.Contains(profileItem.GetProtocolExtra().VmessSecurity))\n        {\n            return -1;\n        }\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Remove multiple servers from the configuration\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"indexes\">List of server profiles to remove</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> RemoveServers(Config config, List<ProfileItem> indexes)\n    {\n        var subid = \"TempRemoveSubId\";\n        foreach (var item in indexes)\n        {\n            item.Subid = subid;\n        }\n\n        await SQLiteHelper.Instance.UpdateAllAsync(indexes);\n        await RemoveServersViaSubid(config, subid, false);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Clone server profiles\n    /// Creates copies of the specified server profiles with \"-clone\" appended to the remarks\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"indexes\">List of server profiles to clone</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> CopyServer(Config config, List<ProfileItem> indexes)\n    {\n        foreach (var it in indexes)\n        {\n            var item = await AppManager.Instance.GetProfileItem(it.IndexId);\n            if (item is null)\n            {\n                continue;\n            }\n\n            var profileItem = JsonUtils.DeepCopy(item);\n            profileItem.IndexId = string.Empty;\n            profileItem.Remarks = $\"{item.Remarks}-clone\";\n\n            if (profileItem.ConfigType == EConfigType.Custom)\n            {\n                profileItem.Address = Utils.GetConfigPath(profileItem.Address);\n                if (await AddCustomServer(config, profileItem, false) == 0)\n                {\n                }\n            }\n            else\n            {\n                await AddServerCommon(config, profileItem, true);\n            }\n        }\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Set the default server by its index ID\n    /// Updates the configuration to use the specified server as default\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"indexId\">Index ID of the server to set as default</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> SetDefaultServerIndex(Config config, string? indexId)\n    {\n        if (indexId.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        config.IndexId = indexId;\n\n        await SaveConfig(config);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Set a default server from the provided list of profiles\n    /// Ensures there's always a valid default server selected\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"lstProfile\">List of profile models to choose from</param>\n    /// <returns>Result of SetDefaultServerIndex operation</returns>\n    public static async Task<int> SetDefaultServer(Config config, List<ProfileItemModel> lstProfile)\n    {\n        if (lstProfile.Exists(t => t.IndexId == config.IndexId))\n        {\n            return 0;\n        }\n\n        if (await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(t => t.IndexId == config.IndexId) != null)\n        {\n            return 0;\n        }\n        if (lstProfile.Count > 0)\n        {\n            return await SetDefaultServerIndex(config, lstProfile.FirstOrDefault(t => t.Port > 0)?.IndexId);\n        }\n\n        var item = await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(t => t.Port > 0);\n        return await SetDefaultServerIndex(config, item?.IndexId);\n    }\n\n    /// <summary>\n    /// Get the current default server profile\n    /// If the current default is invalid, selects a new default\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <returns>The default profile item or null if none exists</returns>\n    public static async Task<ProfileItem?> GetDefaultServer(Config config)\n    {\n        var item = await AppManager.Instance.GetProfileItem(config.IndexId);\n        if (item is null)\n        {\n            var item2 = await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync();\n            await SetDefaultServerIndex(config, item2?.IndexId);\n            return item2;\n        }\n\n        return item;\n    }\n\n    /// <summary>\n    /// Move a server in the list to a different position\n    /// Supports moving to top, up, down, bottom or specific position\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"lstProfile\">List of server profiles</param>\n    /// <param name=\"index\">Index of the server to move</param>\n    /// <param name=\"eMove\">Direction to move the server</param>\n    /// <param name=\"pos\">Target position when using EMove.Position</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> MoveServer(Config config, List<ProfileItem> lstProfile, int index, EMove eMove, int pos = -1)\n    {\n        var count = lstProfile.Count;\n        if (index < 0 || index > lstProfile.Count - 1)\n        {\n            return -1;\n        }\n\n        for (var i = 0; i < lstProfile.Count; i++)\n        {\n            ProfileExManager.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);\n        }\n\n        var sort = 0;\n        switch (eMove)\n        {\n            case EMove.Top:\n                {\n                    if (index == 0)\n                    {\n                        return 0;\n                    }\n                    sort = ProfileExManager.Instance.GetSort(lstProfile.First().IndexId) - 1;\n\n                    break;\n                }\n            case EMove.Up:\n                {\n                    if (index == 0)\n                    {\n                        return 0;\n                    }\n                    sort = ProfileExManager.Instance.GetSort(lstProfile[index - 1].IndexId) - 1;\n\n                    break;\n                }\n\n            case EMove.Down:\n                {\n                    if (index == count - 1)\n                    {\n                        return 0;\n                    }\n                    sort = ProfileExManager.Instance.GetSort(lstProfile[index + 1].IndexId) + 1;\n\n                    break;\n                }\n            case EMove.Bottom:\n                {\n                    if (index == count - 1)\n                    {\n                        return 0;\n                    }\n                    sort = ProfileExManager.Instance.GetSort(lstProfile[^1].IndexId) + 1;\n\n                    break;\n                }\n            case EMove.Position:\n                sort = (pos * 10) + 1;\n                break;\n        }\n\n        ProfileExManager.Instance.SetSort(lstProfile[index].IndexId, sort);\n        return await Task.FromResult(0);\n    }\n\n    /// <summary>\n    /// Add a custom server configuration from a file\n    /// Copies the configuration file to the app's config directory\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Profile item with the file path in Address</param>\n    /// <param name=\"blDelete\">Whether to delete the source file after copying</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddCustomServer(Config config, ProfileItem profileItem, bool blDelete)\n    {\n        var fileName = profileItem.Address;\n        if (!File.Exists(fileName))\n        {\n            return -1;\n        }\n        var ext = Path.GetExtension(fileName);\n        var newFileName = $\"{Utils.GetGuid()}{ext}\";\n        //newFileName = Path.Combine(Utile.GetTempPath(), newFileName);\n\n        try\n        {\n            File.Copy(fileName, Utils.GetConfigPath(newFileName));\n            if (blDelete)\n            {\n                File.Delete(fileName);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return -1;\n        }\n\n        profileItem.Address = newFileName;\n        profileItem.ConfigType = EConfigType.Custom;\n        if (profileItem.Remarks.IsNullOrEmpty())\n        {\n            profileItem.Remarks = $\"import custom@{DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")}\";\n        }\n\n        await AddServerCommon(config, profileItem, true);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Edit an existing custom server configuration\n    /// Updates the server's properties without changing the file\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Profile item with updated properties</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> EditCustomServer(Config config, ProfileItem profileItem)\n    {\n        var item = await AppManager.Instance.GetProfileItem(profileItem.IndexId);\n        if (item is null)\n        {\n            item = profileItem;\n        }\n        else\n        {\n            item.Remarks = profileItem.Remarks;\n            item.Address = profileItem.Address;\n            item.CoreType = profileItem.CoreType;\n            item.DisplayLog = profileItem.DisplayLog;\n            item.PreSocksPort = profileItem.PreSocksPort;\n        }\n\n        if (await SQLiteHelper.Instance.UpdateAsync(item) > 0)\n        {\n            return 0;\n        }\n        else\n        {\n            return -1;\n        }\n\n        //ToJsonFile(config);\n    }\n\n    /// <summary>\n    /// Add or edit a Shadowsocks server\n    /// Validates and processes Shadowsocks-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Shadowsocks profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddShadowsocksServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.Shadowsocks;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        profileItem.SetProtocolExtra(profileItem.GetProtocolExtra() with\n        {\n            SsMethod = profileItem.GetProtocolExtra().SsMethod?.TrimEx()\n        });\n\n        if (!AppManager.Instance.GetShadowsocksSecurities(profileItem).Contains(profileItem.GetProtocolExtra().SsMethod))\n        {\n            return -1;\n        }\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit a SOCKS server\n    /// Processes SOCKS-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">SOCKS profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddSocksServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.SOCKS;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit an HTTP server\n    /// Processes HTTP-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">HTTP profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddHttpServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.HTTP;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit a Trojan server\n    /// Validates and processes Trojan-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Trojan profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddTrojanServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.Trojan;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        if (profileItem.StreamSecurity.IsNullOrEmpty())\n        {\n            profileItem.StreamSecurity = Global.StreamSecurity;\n        }\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit a Hysteria2 server\n    /// Validates and processes Hysteria2-specific settings\n    /// Sets the core type to sing_box as required by Hysteria2\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Hysteria2 profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddHysteria2Server(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.Hysteria2;\n        //profileItem.CoreType = ECoreType.sing_box;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        profileItem.Network = string.Empty;\n\n        if (profileItem.StreamSecurity.IsNullOrEmpty())\n        {\n            profileItem.StreamSecurity = Global.StreamSecurity;\n        }\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n        profileItem.SetProtocolExtra(profileItem.GetProtocolExtra() with\n        {\n            SalamanderPass = profileItem.GetProtocolExtra().SalamanderPass?.TrimEx(),\n            HopInterval = profileItem.GetProtocolExtra().HopInterval?.TrimEx(),\n        });\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit a TUIC server\n    /// Validates and processes TUIC-specific settings\n    /// Sets the core type to sing_box as required by TUIC\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">TUIC profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddTuicServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.TUIC;\n        profileItem.CoreType = ECoreType.sing_box;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Username = profileItem.Username.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        profileItem.Network = string.Empty;\n\n        if (!Global.TuicCongestionControls.Contains(profileItem.HeaderType))\n        {\n            profileItem.HeaderType = Global.TuicCongestionControls.FirstOrDefault()!;\n        }\n\n        if (profileItem.StreamSecurity.IsNullOrEmpty())\n        {\n            profileItem.StreamSecurity = Global.StreamSecurity;\n        }\n        if (profileItem.Alpn.IsNullOrEmpty())\n        {\n            profileItem.Alpn = \"h3\";\n        }\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit a WireGuard server\n    /// Validates and processes WireGuard-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">WireGuard profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddWireguardServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.WireGuard;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        profileItem.SetProtocolExtra(profileItem.GetProtocolExtra() with\n        {\n            WgPublicKey = profileItem.GetProtocolExtra().WgPublicKey?.TrimEx(),\n            WgPresharedKey = profileItem.GetProtocolExtra().WgPresharedKey?.TrimEx(),\n            WgInterfaceAddress = profileItem.GetProtocolExtra().WgInterfaceAddress?.TrimEx(),\n            WgReserved = profileItem.GetProtocolExtra().WgReserved?.TrimEx(),\n            WgMtu = profileItem.GetProtocolExtra().WgMtu is null or <= 0 ? Global.TunMtus.First() : profileItem.GetProtocolExtra().WgMtu,\n        });\n\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit a Anytls server\n    /// Validates and processes Anytls-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Anytls profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddAnytlsServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.Anytls;\n        profileItem.CoreType = ECoreType.sing_box;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        profileItem.Network = string.Empty;\n        if (profileItem.StreamSecurity.IsNullOrEmpty())\n        {\n            profileItem.StreamSecurity = Global.StreamSecurity;\n        }\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n        await AddServerCommon(config, profileItem, toFile);\n        return 0;\n    }\n\n    /// <summary>\n    /// Sort the server list by the specified column\n    /// Updates the sort order in the profile extension data\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"subId\">Subscription ID to filter servers</param>\n    /// <param name=\"colName\">Column name to sort by</param>\n    /// <param name=\"asc\">Sort in ascending order if true, descending if false</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> SortServers(Config config, string subId, string colName, bool asc)\n    {\n        var lstModel = await AppManager.Instance.ProfileModels(subId, \"\");\n        if (lstModel.Count <= 0)\n        {\n            return -1;\n        }\n        var lstServerStat = (config.GuiItem.EnableStatistics ? StatisticsManager.Instance.ServerStat : null) ?? [];\n        var lstProfileExs = await ProfileExManager.Instance.GetProfileExs();\n        var lstProfile = (from t in lstModel\n                          join t2 in lstServerStat on t.IndexId equals t2.IndexId into t2b\n                          from t22 in t2b.DefaultIfEmpty()\n                          join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b\n                          from t33 in t3b.DefaultIfEmpty()\n                          select new ProfileItemModel\n                          {\n                              IndexId = t.IndexId,\n                              ConfigType = t.ConfigType,\n                              Remarks = t.Remarks,\n                              Address = t.Address,\n                              Port = t.Port,\n                              //Security = t.Security,\n                              Network = t.Network,\n                              StreamSecurity = t.StreamSecurity,\n                              Delay = t33?.Delay ?? 0,\n                              Speed = t33?.Speed ?? 0,\n                              Sort = t33?.Sort ?? 0,\n                              TodayDown = (t22?.TodayDown ?? 0).ToString(\"D16\"),\n                              TodayUp = (t22?.TodayUp ?? 0).ToString(\"D16\"),\n                              TotalDown = (t22?.TotalDown ?? 0).ToString(\"D16\"),\n                              TotalUp = (t22?.TotalUp ?? 0).ToString(\"D16\"),\n                          }).ToList();\n\n        Enum.TryParse(colName, true, out EServerColName name);\n\n        if (asc)\n        {\n            lstProfile = name switch\n            {\n                EServerColName.ConfigType => lstProfile.OrderBy(t => t.ConfigType).ToList(),\n                EServerColName.Remarks => lstProfile.OrderBy(t => t.Remarks).ToList(),\n                EServerColName.Address => lstProfile.OrderBy(t => t.Address).ToList(),\n                EServerColName.Port => lstProfile.OrderBy(t => t.Port).ToList(),\n                EServerColName.Network => lstProfile.OrderBy(t => t.Network).ToList(),\n                EServerColName.StreamSecurity => lstProfile.OrderBy(t => t.StreamSecurity).ToList(),\n                EServerColName.DelayVal => lstProfile.OrderBy(t => t.Delay).ToList(),\n                EServerColName.SpeedVal => lstProfile.OrderBy(t => t.Speed).ToList(),\n                EServerColName.SubRemarks => lstProfile.OrderBy(t => t.Subid).ToList(),\n                EServerColName.TodayDown => lstProfile.OrderBy(t => t.TodayDown).ToList(),\n                EServerColName.TodayUp => lstProfile.OrderBy(t => t.TodayUp).ToList(),\n                EServerColName.TotalDown => lstProfile.OrderBy(t => t.TotalDown).ToList(),\n                EServerColName.TotalUp => lstProfile.OrderBy(t => t.TotalUp).ToList(),\n                _ => lstProfile\n            };\n        }\n        else\n        {\n            lstProfile = name switch\n            {\n                EServerColName.ConfigType => lstProfile.OrderByDescending(t => t.ConfigType).ToList(),\n                EServerColName.Remarks => lstProfile.OrderByDescending(t => t.Remarks).ToList(),\n                EServerColName.Address => lstProfile.OrderByDescending(t => t.Address).ToList(),\n                EServerColName.Port => lstProfile.OrderByDescending(t => t.Port).ToList(),\n                EServerColName.Network => lstProfile.OrderByDescending(t => t.Network).ToList(),\n                EServerColName.StreamSecurity => lstProfile.OrderByDescending(t => t.StreamSecurity).ToList(),\n                EServerColName.DelayVal => lstProfile.OrderByDescending(t => t.Delay).ToList(),\n                EServerColName.SpeedVal => lstProfile.OrderByDescending(t => t.Speed).ToList(),\n                EServerColName.SubRemarks => lstProfile.OrderByDescending(t => t.Subid).ToList(),\n                EServerColName.TodayDown => lstProfile.OrderByDescending(t => t.TodayDown).ToList(),\n                EServerColName.TodayUp => lstProfile.OrderByDescending(t => t.TodayUp).ToList(),\n                EServerColName.TotalDown => lstProfile.OrderByDescending(t => t.TotalDown).ToList(),\n                EServerColName.TotalUp => lstProfile.OrderByDescending(t => t.TotalUp).ToList(),\n                _ => lstProfile\n            };\n        }\n\n        for (var i = 0; i < lstProfile.Count; i++)\n        {\n            ProfileExManager.Instance.SetSort(lstProfile[i].IndexId, (i + 1) * 10);\n        }\n        switch (name)\n        {\n            case EServerColName.DelayVal:\n                {\n                    var maxSort = lstProfile.Max(t => t.Sort) + 10;\n                    foreach (var item in lstProfile.Where(item => item.Delay <= 0))\n                    {\n                        ProfileExManager.Instance.SetSort(item.IndexId, maxSort);\n                    }\n\n                    break;\n                }\n            case EServerColName.SpeedVal:\n                {\n                    var maxSort = lstProfile.Max(t => t.Sort) + 10;\n                    foreach (var item in lstProfile.Where(item => item.Speed <= 0))\n                    {\n                        ProfileExManager.Instance.SetSort(item.IndexId, maxSort);\n                    }\n\n                    break;\n                }\n        }\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Add or edit a VLESS server\n    /// Validates and processes VLESS-specific settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">VLESS profile to add</param>\n    /// <param name=\"toFile\">Whether to save to file</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddVlessServer(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigType = EConfigType.VLESS;\n\n        profileItem.Address = profileItem.Address.TrimEx();\n        profileItem.Password = profileItem.Password.TrimEx();\n        profileItem.Network = profileItem.Network.TrimEx();\n        profileItem.HeaderType = profileItem.HeaderType.TrimEx();\n        profileItem.RequestHost = profileItem.RequestHost.TrimEx();\n        profileItem.Path = profileItem.Path.TrimEx();\n        profileItem.StreamSecurity = profileItem.StreamSecurity.TrimEx();\n\n        var vlessEncryption = profileItem.GetProtocolExtra().VlessEncryption?.TrimEx();\n        var flow = profileItem.GetProtocolExtra().Flow?.TrimEx() ?? string.Empty;\n        profileItem.SetProtocolExtra(profileItem.GetProtocolExtra() with\n        {\n            VlessEncryption = vlessEncryption.IsNullOrEmpty() ? Global.None : vlessEncryption,\n            Flow = Global.Flows.Contains(flow) ? flow : Global.Flows.First(),\n        });\n\n        if (profileItem.Password.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        await AddServerCommon(config, profileItem, toFile);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Remove duplicate servers from a subscription\n    /// Compares servers based on their properties rather than just names\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"subId\">Subscription ID to deduplicate</param>\n    /// <returns>Tuple with total count and remaining count after deduplication</returns>\n    public static async Task<Tuple<int, int>> DedupServerList(Config config, string subId)\n    {\n        var lstProfile = await AppManager.Instance.ProfileItems(subId);\n        if (lstProfile == null)\n        {\n            return new Tuple<int, int>(0, 0);\n        }\n\n        List<ProfileItem> lstKeep = new();\n        List<ProfileItem> lstRemove = new();\n        if (!config.GuiItem.KeepOlderDedupl)\n        {\n            lstProfile.Reverse();\n        }\n\n        foreach (var item in lstProfile)\n        {\n            if (!lstKeep.Exists(i => CompareProfileItem(i, item, false)))\n            {\n                lstKeep.Add(item);\n            }\n            else\n            {\n                lstRemove.Add(item);\n            }\n        }\n        await RemoveServers(config, lstRemove);\n\n        return new Tuple<int, int>(lstProfile.Count, lstKeep.Count);\n    }\n\n    /// <summary>\n    /// Common server addition logic used by all server types\n    /// Sets common properties and handles sorting and persistence\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"profileItem\">Profile item to add</param>\n    /// <param name=\"toFile\">Whether to save to database</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> AddServerCommon(Config config, ProfileItem profileItem, bool toFile = true)\n    {\n        profileItem.ConfigVersion = 3;\n\n        if (profileItem.StreamSecurity.IsNotEmpty())\n        {\n            if (profileItem.StreamSecurity is not Global.StreamSecurity\n                 and not Global.StreamSecurityReality)\n            {\n                profileItem.StreamSecurity = string.Empty;\n            }\n            else\n            {\n                if (profileItem.AllowInsecure.IsNullOrEmpty())\n                {\n                    profileItem.AllowInsecure = config.CoreBasicItem.DefAllowInsecure.ToString().ToLower();\n                }\n                if (profileItem.Fingerprint.IsNullOrEmpty() && profileItem.StreamSecurity == Global.StreamSecurityReality)\n                {\n                    profileItem.Fingerprint = config.CoreBasicItem.DefFingerprint;\n                }\n            }\n        }\n\n        if (profileItem.Network.IsNotEmpty() && !Global.Networks.Contains(profileItem.Network))\n        {\n            profileItem.Network = Global.DefaultNetwork;\n        }\n\n        var maxSort = -1;\n        if (profileItem.IndexId.IsNullOrEmpty())\n        {\n            profileItem.IndexId = Utils.GetGuid(false);\n            maxSort = ProfileExManager.Instance.GetMaxSort();\n        }\n        if (!toFile && maxSort < 0)\n        {\n            maxSort = ProfileExManager.Instance.GetMaxSort();\n        }\n        if (maxSort > 0)\n        {\n            ProfileExManager.Instance.SetSort(profileItem.IndexId, maxSort + 1);\n        }\n\n        if (toFile)\n        {\n            profileItem.SetProtocolExtra();\n            await SQLiteHelper.Instance.ReplaceAsync(profileItem);\n        }\n        return 0;\n    }\n\n    /// <summary>\n    /// Compare two profile items to determine if they represent the same server\n    /// Used for deduplication and server matching\n    /// </summary>\n    /// <param name=\"o\">First profile item</param>\n    /// <param name=\"n\">Second profile item</param>\n    /// <param name=\"remarks\">Whether to compare remarks</param>\n    /// <returns>True if the profiles match, false otherwise</returns>\n    private static bool CompareProfileItem(ProfileItem? o, ProfileItem? n, bool remarks)\n    {\n        if (o == null || n == null)\n        {\n            return false;\n        }\n\n        var oProtocolExtra = o.GetProtocolExtra();\n        var nProtocolExtra = n.GetProtocolExtra();\n\n        return o.ConfigType == n.ConfigType\n               && AreEqual(o.Address, n.Address)\n               && o.Port == n.Port\n               && AreEqual(o.Password, n.Password)\n               && AreEqual(oProtocolExtra.VlessEncryption, nProtocolExtra.VlessEncryption)\n               && AreEqual(oProtocolExtra.SsMethod, nProtocolExtra.SsMethod)\n               && AreEqual(oProtocolExtra.VmessSecurity, nProtocolExtra.VmessSecurity)\n               && AreEqual(o.Network, n.Network)\n               && AreEqual(o.HeaderType, n.HeaderType)\n               && AreEqual(o.RequestHost, n.RequestHost)\n               && AreEqual(o.Path, n.Path)\n               && (o.ConfigType == EConfigType.Trojan || o.StreamSecurity == n.StreamSecurity)\n               && AreEqual(oProtocolExtra.Flow, nProtocolExtra.Flow)\n               && AreEqual(oProtocolExtra.SalamanderPass, nProtocolExtra.SalamanderPass)\n               && AreEqual(o.Sni, n.Sni)\n               && AreEqual(o.Alpn, n.Alpn)\n               && AreEqual(o.Fingerprint, n.Fingerprint)\n               && AreEqual(o.PublicKey, n.PublicKey)\n               && AreEqual(o.ShortId, n.ShortId)\n               && AreEqual(o.Finalmask, n.Finalmask)\n               && (!remarks || o.Remarks == n.Remarks);\n\n        static bool AreEqual(string? a, string? b)\n        {\n            return string.Equals(a, b) || (string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b));\n        }\n    }\n\n    /// <summary>\n    /// Searches the specified collection for a profile item that matches the target profile item based on a series of\n    /// criteria.\n    /// </summary>\n    /// <remarks>The method attempts to find a match by comparing the target's remarks, address, port, and\n    /// password in various combinations. The search is performed in order of specificity, starting with the most\n    /// detailed comparison. If no match is found at any stage, the method returns null.</remarks>\n    /// <param name=\"source\">An enumerable collection of profile items to search. This parameter can be null.</param>\n    /// <param name=\"target\">The profile item to match against items in the source collection. This parameter can be null.</param>\n    /// <returns>A profile item from the source collection that matches the target item according to defined criteria; otherwise,\n    /// null if no match is found or if either parameter is null.</returns>\n    private static ProfileItem? FindMatchedProfileItem(IEnumerable<ProfileItem>? source, ProfileItem? target)\n    {\n        if (source == null || target == null)\n        {\n            return null;\n        }\n\n        var matchedItem = source.FirstOrDefault(t => CompareProfileItem(t, target, true));\n        if (matchedItem != null)\n        {\n            return matchedItem;\n        }\n\n        if (target.Remarks.IsNotEmpty())\n        {\n            matchedItem = source.FirstOrDefault(t => t.Remarks == target.Remarks);\n            if (matchedItem != null)\n            {\n                return matchedItem;\n            }\n        }\n\n        if (target.Address.IsNotEmpty() && target.Port > 0 && target.Password.IsNotEmpty())\n        {\n            matchedItem = source.FirstOrDefault(t =>\n                IsSameText(t.Address, target.Address) &&\n                t.Port == target.Port &&\n                IsSameText(t.Password, target.Password));\n            if (matchedItem != null)\n            {\n                return matchedItem;\n            }\n        }\n\n        if (target.Address.IsNotEmpty() && target.Port > 0)\n        {\n            matchedItem = source.FirstOrDefault(t =>\n                IsSameText(t.Address, target.Address) &&\n                t.Port == target.Port);\n            if (matchedItem != null)\n            {\n                return matchedItem;\n            }\n        }\n\n        if (target.Address.IsNotEmpty())\n        {\n            matchedItem = source.FirstOrDefault(t => IsSameText(t.Address, target.Address));\n            if (matchedItem != null)\n            {\n                return matchedItem;\n            }\n        }\n\n        return null;\n\n        static bool IsSameText(string? left, string? right)\n        {\n            if (left.IsNullOrEmpty() || right.IsNullOrEmpty())\n            {\n                return false;\n            }\n\n            return string.Equals(left.TrimEx(), right.TrimEx(), StringComparison.OrdinalIgnoreCase);\n        }\n    }\n\n    /// <summary>\n    /// Remove a single server profile by its index ID\n    /// Deletes the configuration file if it's a custom config\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"indexId\">Index ID of the profile to remove</param>\n    /// <returns>0 if successful</returns>\n    private static async Task<int> RemoveProfileItem(Config config, string indexId)\n    {\n        try\n        {\n            var item = await AppManager.Instance.GetProfileItem(indexId);\n            if (item == null)\n            {\n                return 0;\n            }\n            if (item.ConfigType == EConfigType.Custom)\n            {\n                File.Delete(Utils.GetConfigPath(item.Address));\n            }\n\n            await SQLiteHelper.Instance.DeleteAsync(item);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Create a group server that combines multiple servers for load balancing\n    /// Generates a PolicyGroup profile with references to the sub-items\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"subItem\">Sub-item for grouping</param>\n    /// <returns>Result object with success state and data</returns>\n    public static async Task<RetResult> AddGroupAllServer(Config config, SubItem? subItem)\n    {\n        var result = new RetResult();\n\n        var subId = subItem?.Id;\n        if (subId.IsNullOrEmpty())\n        {\n            result.Success = false;\n            return result;\n        }\n\n        var indexId = Utils.GetGuid(false);\n        var remark = $\"{subItem.Remarks} - {ResUI.TbConfigTypePolicyGroup}\";\n        var profile = new ProfileItem\n        {\n            IndexId = indexId,\n            CoreType = ECoreType.Xray,\n            ConfigType = EConfigType.PolicyGroup,\n            Remarks = remark,\n            IsSub = false\n        };\n        if (!subId.IsNullOrEmpty())\n        {\n            profile.Subid = subId;\n        }\n        var extraItem = new ProtocolExtraItem\n        {\n            MultipleLoad = EMultipleLoad.LeastPing,\n            GroupType = profile.ConfigType.ToString(),\n            SubChildItems = subId,\n            Filter = Global.PolicyGroupDefaultAllFilter,\n        };\n        profile.SetProtocolExtra(extraItem);\n        var ret = await AddServerCommon(config, profile, true);\n        result.Success = ret == 0;\n        result.Data = indexId;\n        return result;\n    }\n\n    private static string CombineWithDefaultAllFilter(string regionPattern)\n    {\n        return $\"^(?!.*(?:{Global.PolicyGroupExcludeKeywords})).*(?:{regionPattern}).*$\";\n    }\n\n    private static readonly Dictionary<string, string> PolicyGroupRegionFilters = new()\n    {\n        { \"JP\", \"日本|\\\\b[Jj][Pp]\\\\b|🇯🇵|[Jj]apan\" },\n        { \"US\", \"美国|\\\\b[Uu][Ss]\\\\b|🇺🇸|[Uu]nited [Ss]tates|\\\\b[Uu][Ss][Aa]\\\\b\" },\n        { \"HK\", \"香港|\\\\b[Hh][Kk]\\\\b|🇭🇰|[Hh]ong ?[Kk]ong\" },\n        { \"TW\", \"台湾|台灣|\\\\b[Tt][Ww]\\\\b|🇹🇼|[Tt]aiwan\" },\n        { \"KR\", \"韩国|\\\\b[Kk][Rr]\\\\b|🇰🇷|[Kk]orea\" },\n        { \"SG\", \"新加坡|\\\\b[Ss][Gg]\\\\b|🇸🇬|[Ss]ingapore\" },\n        { \"DE\", \"德国|\\\\b[Dd][Ee]\\\\b|🇩🇪|[Gg]ermany\" },\n        { \"FR\", \"法国|\\\\b[Ff][Rr]\\\\b|🇫🇷|[Ff]rance\" },\n        { \"GB\", \"英国|\\\\b[Gg][Bb]\\\\b|🇬🇧|[Uu]nited [Kk]ingdom|[Bb]ritain\" },\n        { \"CA\", \"加拿大|🇨🇦|[Cc]anada\" },\n        { \"AU\", \"澳大利亚|\\\\b[Aa][Uu]\\\\b|🇦🇺|[Aa]ustralia\" },\n        { \"RU\", \"俄罗斯|\\\\b[Rr][Uu]\\\\b|🇷🇺|[Rr]ussia\" },\n        { \"BR\", \"巴西|\\\\b[Bb][Rr]\\\\b|🇧🇷|[Bb]razil\" },\n        { \"IN\", \"印度|🇮🇳|[Ii]ndia\" },\n        { \"VN\", \"越南|\\\\b[Vv][Nn]\\\\b|🇻🇳|[Vv]ietnam\" },\n        { \"ID\", \"印度尼西亚|\\\\b[Ii][Dd]\\\\b|🇮🇩|[Ii]ndonesia\" },\n        { \"MX\", \"墨西哥|\\\\b[Mm][Xx]\\\\b|🇲🇽|[Mm]exico\" }\n    };\n\n    public static async Task<RetResult> AddGroupRegionServer(Config config, SubItem? subItem)\n    {\n        var result = new RetResult();\n        var subId = subItem?.Id;\n        if (subId.IsNullOrEmpty())\n        {\n            result.Success = false;\n            return result;\n        }\n        var childProfiles = await AppManager.Instance.ProfileItems(subId);\n        List<string> indexIdList = [];\n\n        foreach (var regionFilter in PolicyGroupRegionFilters)\n        {\n            var indexId = Utils.GetGuid(false);\n            var remark = $\"{subItem.Remarks} - {ResUI.TbConfigTypePolicyGroup} - {regionFilter.Key}\";\n            var profile = new ProfileItem\n            {\n                IndexId = indexId,\n                CoreType = ECoreType.Xray,\n                ConfigType = EConfigType.PolicyGroup,\n                Remarks = remark,\n                IsSub = false\n            };\n            if (!subId.IsNullOrEmpty())\n            {\n                profile.Subid = subId;\n            }\n            var extraItem = new ProtocolExtraItem\n            {\n                MultipleLoad = EMultipleLoad.LeastPing,\n                GroupType = profile.ConfigType.ToString(),\n                SubChildItems = subId,\n                Filter = CombineWithDefaultAllFilter(regionFilter.Value),\n            };\n            profile.SetProtocolExtra(extraItem);\n\n            var matchedChildProfiles = childProfiles?.Where(p =>\n                    p != null &&\n                    p.IsValid() &&\n                    !p.ConfigType.IsComplexType() &&\n                    (extraItem.Filter.IsNullOrEmpty() || Regex.IsMatch(p.Remarks, extraItem.Filter))\n                )\n                .ToList() ?? [];\n            if (matchedChildProfiles.Count == 0)\n            {\n                continue;\n            }\n\n            var ret = await AddServerCommon(config, profile, true);\n            if (ret == 0)\n            {\n                indexIdList.Add(indexId);\n            }\n        }\n        result.Success = indexIdList.Count > 0;\n        result.Data = indexIdList;\n        return result;\n    }\n\n    /// <summary>\n    /// Get a SOCKS server profile for pre-SOCKS functionality\n    /// Used when TUN mode is enabled or when a custom config has a pre-SOCKS port\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"node\">Server node that might need pre-SOCKS</param>\n    /// <param name=\"coreType\">Core type being used</param>\n    /// <returns>A SOCKS profile item or null if not needed</returns>\n    public static ProfileItem? GetPreSocksItem(Config config, ProfileItem node, ECoreType coreType)\n    {\n        if (node.ConfigType != EConfigType.Custom || !(node.PreSocksPort > 0))\n        {\n            return null;\n        }\n        ProfileItem? itemSocks = null;\n        var preCoreType = AppManager.Instance.RunningCoreType = config.TunModeItem.EnableTun ? ECoreType.sing_box : ECoreType.Xray;\n        itemSocks = new ProfileItem()\n        {\n            CoreType = preCoreType,\n            ConfigType = EConfigType.SOCKS,\n            Address = Global.Loopback,\n            Port = node.PreSocksPort.Value,\n        };\n        return itemSocks;\n    }\n\n    /// <summary>\n    /// Remove servers with invalid test results (timeout)\n    /// Useful for cleaning up subscription lists\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"subid\">Subscription ID to filter servers</param>\n    /// <returns>Number of removed servers or -1 if failed</returns>\n    public static async Task<int> RemoveInvalidServerResult(Config config, string subid)\n    {\n        var lstModel = await AppManager.Instance.ProfileModels(subid, \"\");\n        lstModel.RemoveAll(t => t.ConfigType.IsComplexType());\n        if (lstModel is { Count: <= 0 })\n        {\n            return -1;\n        }\n        var lstProfileExs = await ProfileExManager.Instance.GetProfileExs();\n        var lstProfile = (from t in lstModel\n                          join t2 in lstProfileExs on t.IndexId equals t2.IndexId\n                          where t2.Delay == -1\n                          select t).ToList();\n\n        await RemoveServers(config, JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstProfile)));\n\n        return lstProfile.Count;\n    }\n\n    #endregion Server\n\n    #region Batch add servers\n\n    /// <summary>\n    /// Add multiple servers from string data (common protocols)\n    /// Parses the string data into server profiles\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"strData\">String data containing server information</param>\n    /// <param name=\"subid\">Subscription ID to associate with the servers</param>\n    /// <param name=\"isSub\">Whether this is from a subscription</param>\n    /// <returns>Number of successfully imported servers or -1 if failed</returns>\n    private static async Task<int> AddBatchServersCommon(Config config, string strData, string subid, bool isSub)\n    {\n        if (strData.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        var subFilter = string.Empty;\n        //remove sub items\n        if (isSub && subid.IsNotEmpty())\n        {\n            await RemoveServersViaSubid(config, subid, isSub);\n            subFilter = (await AppManager.Instance.GetSubItem(subid))?.Filter ?? \"\";\n        }\n\n        var countServers = 0;\n        List<ProfileItem> lstAdd = new();\n        var arrData = strData.Split(Environment.NewLine.ToCharArray()).Where(t => !t.IsNullOrEmpty());\n        if (isSub)\n        {\n            arrData = arrData.Distinct();\n        }\n        foreach (var str in arrData)\n        {\n            //maybe sub\n            if (!isSub && (str.StartsWith(Global.HttpsProtocol) || str.StartsWith(Global.HttpProtocol)))\n            {\n                if (await AddSubItem(config, str) == 0)\n                {\n                    countServers++;\n                }\n                continue;\n            }\n            var profileItem = FmtHandler.ResolveConfig(str, out var msg);\n            if (profileItem is null)\n            {\n                continue;\n            }\n\n            //exist sub items //filter\n            if (isSub && subid.IsNotEmpty() && subFilter.IsNotEmpty())\n            {\n                if (!Regex.IsMatch(profileItem.Remarks, subFilter))\n                {\n                    continue;\n                }\n            }\n            profileItem.Subid = subid;\n            profileItem.IsSub = isSub;\n\n            var addStatus = profileItem.ConfigType switch\n            {\n                EConfigType.VMess => await AddVMessServer(config, profileItem, false),\n                EConfigType.Shadowsocks => await AddShadowsocksServer(config, profileItem, false),\n                EConfigType.SOCKS => await AddSocksServer(config, profileItem, false),\n                EConfigType.Trojan => await AddTrojanServer(config, profileItem, false),\n                EConfigType.VLESS => await AddVlessServer(config, profileItem, false),\n                EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem, false),\n                EConfigType.TUIC => await AddTuicServer(config, profileItem, false),\n                EConfigType.WireGuard => await AddWireguardServer(config, profileItem, false),\n                EConfigType.Anytls => await AddAnytlsServer(config, profileItem, false),\n                _ => -1,\n            };\n\n            if (addStatus == 0)\n            {\n                countServers++;\n                lstAdd.Add(profileItem);\n            }\n        }\n\n        if (lstAdd.Count > 0)\n        {\n            await SQLiteHelper.Instance.InsertAllAsync(lstAdd);\n        }\n\n        await SaveConfig(config);\n        return countServers;\n    }\n\n    /// <summary>\n    /// Add servers from custom configuration formats (sing-box, v2ray, etc.)\n    /// Handles various configuration formats and imports them as custom configs\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"strData\">String data containing server information</param>\n    /// <param name=\"subid\">Subscription ID to associate with the servers</param>\n    /// <param name=\"isSub\">Whether this is from a subscription</param>\n    /// <returns>Number of successfully imported servers or -1 if failed</returns>\n    private static async Task<int> AddBatchServers4Custom(Config config, string strData, string subid, bool isSub)\n    {\n        if (strData.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        var subItem = await AppManager.Instance.GetSubItem(subid);\n        var subRemarks = subItem?.Remarks;\n        var preSocksPort = subItem?.PreSocksPort;\n\n        List<ProfileItem>? lstProfiles = null;\n        //Is sing-box array configuration\n        if (lstProfiles is null || lstProfiles.Count <= 0)\n        {\n            lstProfiles = SingboxFmt.ResolveFullArray(strData, subRemarks);\n        }\n        //Is v2ray array configuration\n        if (lstProfiles is null || lstProfiles.Count <= 0)\n        {\n            lstProfiles = V2rayFmt.ResolveFullArray(strData, subRemarks);\n        }\n        if (lstProfiles != null && lstProfiles.Count > 0)\n        {\n            if (isSub && subid.IsNotEmpty())\n            {\n                await RemoveServersViaSubid(config, subid, isSub);\n            }\n            var count = 0;\n            foreach (var it in lstProfiles)\n            {\n                it.Subid = subid;\n                it.IsSub = isSub;\n                it.PreSocksPort = preSocksPort;\n                if (await AddCustomServer(config, it, true) == 0)\n                {\n                    count++;\n                }\n            }\n            if (count > 0)\n            {\n                return count;\n            }\n        }\n\n        ProfileItem? profileItem = null;\n        //Is sing-box configuration\n        if (profileItem is null)\n        {\n            profileItem = SingboxFmt.ResolveFull(strData, subRemarks);\n        }\n        //Is v2ray configuration\n        if (profileItem is null)\n        {\n            profileItem = V2rayFmt.ResolveFull(strData, subRemarks);\n        }\n        //Is Html Page\n        if (profileItem is null && HtmlPageFmt.IsHtmlPage(strData))\n        {\n            return -1;\n        }\n        //Is Clash configuration\n        if (profileItem is null)\n        {\n            profileItem = ClashFmt.ResolveFull(strData, subRemarks);\n        }\n        //Is hysteria configuration\n        if (profileItem is null)\n        {\n            profileItem = Hysteria2Fmt.ResolveFull2(strData, subRemarks);\n        }\n        if (profileItem is null || profileItem.Address.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        if (isSub && subid.IsNotEmpty())\n        {\n            await RemoveServersViaSubid(config, subid, isSub);\n        }\n\n        profileItem.Subid = subid;\n        profileItem.IsSub = isSub;\n        profileItem.PreSocksPort = preSocksPort;\n        if (await AddCustomServer(config, profileItem, true) == 0)\n        {\n            return 1;\n        }\n        else\n        {\n            return -1;\n        }\n    }\n\n    /// <summary>\n    /// Add Shadowsocks servers from SIP008 format\n    /// SIP008 is a JSON-based format for Shadowsocks servers\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"strData\">String data in SIP008 format</param>\n    /// <param name=\"subid\">Subscription ID to associate with the servers</param>\n    /// <param name=\"isSub\">Whether this is from a subscription</param>\n    /// <returns>Number of successfully imported servers or -1 if failed</returns>\n    private static async Task<int> AddBatchServers4SsSIP008(Config config, string strData, string subid, bool isSub)\n    {\n        if (strData.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        if (isSub && subid.IsNotEmpty())\n        {\n            await RemoveServersViaSubid(config, subid, isSub);\n        }\n\n        var lstSsServer = ShadowsocksFmt.ResolveSip008(strData);\n        if (lstSsServer?.Count > 0)\n        {\n            var counter = 0;\n            foreach (var ssItem in lstSsServer)\n            {\n                ssItem.Subid = subid;\n                ssItem.IsSub = isSub;\n                if (await AddShadowsocksServer(config, ssItem) == 0)\n                {\n                    counter++;\n                }\n            }\n            await SaveConfig(config);\n            return counter;\n        }\n\n        return -1;\n    }\n\n    /// <summary>\n    /// Main entry point for adding batch servers from various formats\n    /// Tries different parsing methods to import as many servers as possible\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"strData\">String data containing server information</param>\n    /// <param name=\"subid\">Subscription ID to associate with the servers</param>\n    /// <param name=\"isSub\">Whether this is from a subscription</param>\n    /// <returns>Number of successfully imported servers or -1 if failed</returns>\n    public static async Task<int> AddBatchServers(Config config, string strData, string subid, bool isSub)\n    {\n        if (strData.IsNullOrEmpty())\n        {\n            return -1;\n        }\n        List<ProfileItem>? lstOriSub = null;\n        ProfileItem? activeProfile = null;\n        if (isSub && subid.IsNotEmpty())\n        {\n            lstOriSub = await AppManager.Instance.ProfileItems(subid);\n            activeProfile = lstOriSub?.FirstOrDefault(t => t.IndexId == config.IndexId);\n        }\n\n        var counter = 0;\n        if (Utils.IsBase64String(strData))\n        {\n            counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);\n        }\n        if (counter < 1)\n        {\n            counter = await AddBatchServersCommon(config, strData, subid, isSub);\n        }\n        if (counter < 1)\n        {\n            counter = await AddBatchServersCommon(config, Utils.Base64Decode(strData), subid, isSub);\n        }\n\n        if (counter < 1)\n        {\n            counter = await AddBatchServers4SsSIP008(config, strData, subid, isSub);\n        }\n\n        //maybe other sub\n        if (counter < 1)\n        {\n            counter = await AddBatchServers4Custom(config, strData, subid, isSub);\n        }\n\n        //Select active node\n        if (activeProfile != null)\n        {\n            var lstSub = await AppManager.Instance.ProfileItems(subid);\n            var existItem = FindMatchedProfileItem(lstSub, activeProfile);\n            if (existItem != null)\n            {\n                await ConfigHandler.SetDefaultServerIndex(config, existItem.IndexId);\n            }\n        }\n\n        //Keep the last traffic statistics\n        if (lstOriSub != null)\n        {\n            var lstSub = await AppManager.Instance.ProfileItems(subid);\n            foreach (var item in lstSub)\n            {\n                var existItem = FindMatchedProfileItem(lstOriSub, item);\n                if (existItem != null)\n                {\n                    await StatisticsManager.Instance.CloneServerStatItem(existItem.IndexId, item.IndexId);\n                }\n            }\n        }\n\n        return counter;\n    }\n\n    #endregion Batch add servers\n\n    #region Sub & Group\n\n    /// <summary>\n    /// Add a subscription item from URL\n    /// Creates a new subscription with default settings\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"url\">Subscription URL</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddSubItem(Config config, string url)\n    {\n        //already exists\n        var count = await SQLiteHelper.Instance.TableAsync<SubItem>().CountAsync(e => e.Url == url);\n        if (count > 0)\n        {\n            return 0;\n        }\n        SubItem subItem = new()\n        {\n            Id = string.Empty,\n            Url = url\n        };\n\n        var uri = Utils.TryUri(url);\n        if (uri == null)\n        {\n            return -1;\n        }\n        //Do not allow http protocol\n        if (url.StartsWith(Global.HttpProtocol) && !Utils.IsPrivateNetwork(uri.IdnHost))\n        {\n            //TODO Temporary reminder to be removed later\n            NoticeManager.Instance.Enqueue(ResUI.InsecureUrlProtocol);\n            //return -1;\n        }\n\n        var queryVars = Utils.ParseQueryString(uri.Query);\n        subItem.Remarks = queryVars[\"remarks\"] ?? \"import_sub\";\n\n        return await AddSubItem(config, subItem);\n    }\n\n    /// <summary>\n    /// Add or update a subscription item\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"subItem\">Subscription item to add or update</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddSubItem(Config config, SubItem subItem)\n    {\n        var item = await AppManager.Instance.GetSubItem(subItem.Id);\n        if (item is null)\n        {\n            item = subItem;\n        }\n        else\n        {\n            item.Remarks = subItem.Remarks;\n            item.Url = subItem.Url;\n            item.MoreUrl = subItem.MoreUrl;\n            item.Enabled = subItem.Enabled;\n            item.AutoUpdateInterval = subItem.AutoUpdateInterval;\n            item.UserAgent = subItem.UserAgent;\n            item.Sort = subItem.Sort;\n            item.Filter = subItem.Filter;\n            item.UpdateTime = subItem.UpdateTime;\n            item.ConvertTarget = subItem.ConvertTarget;\n            item.PrevProfile = subItem.PrevProfile;\n            item.NextProfile = subItem.NextProfile;\n            item.PreSocksPort = subItem.PreSocksPort;\n            item.Memo = subItem.Memo;\n        }\n\n        if (item.Id.IsNullOrEmpty())\n        {\n            item.Id = Utils.GetGuid(false);\n\n            if (item.Sort <= 0)\n            {\n                var maxSort = 0;\n                if (await SQLiteHelper.Instance.TableAsync<SubItem>().CountAsync() > 0)\n                {\n                    var lstSubs = await AppManager.Instance.SubItems();\n                    maxSort = lstSubs.LastOrDefault()?.Sort ?? 0;\n                }\n                item.Sort = maxSort + 1;\n            }\n        }\n        if (await SQLiteHelper.Instance.ReplaceAsync(item) > 0)\n        {\n            return 0;\n        }\n        else\n        {\n            return -1;\n        }\n    }\n\n    /// <summary>\n    /// Remove servers associated with a subscription ID\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"subid\">Subscription ID</param>\n    /// <param name=\"isSub\">Whether to only remove servers marked as subscription items</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> RemoveServersViaSubid(Config config, string subid, bool isSub)\n    {\n        if (subid.IsNullOrEmpty())\n        {\n            return -1;\n        }\n        var customProfile = await SQLiteHelper.Instance.TableAsync<ProfileItem>().Where(t => t.Subid == subid && t.ConfigType == EConfigType.Custom).ToListAsync();\n        if (isSub)\n        {\n            await SQLiteHelper.Instance.ExecuteAsync($\"delete from ProfileItem where isSub = 1 and subid = '{subid}'\");\n        }\n        else\n        {\n            await SQLiteHelper.Instance.ExecuteAsync($\"delete from ProfileItem where subid = '{subid}'\");\n        }\n        foreach (var item in customProfile)\n        {\n            File.Delete(Utils.GetConfigPath(item.Address));\n        }\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Delete a subscription item and all its associated servers\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"id\">Subscription ID to delete</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> DeleteSubItem(Config config, string id)\n    {\n        var item = await AppManager.Instance.GetSubItem(id);\n        if (item is null)\n        {\n            return 0;\n        }\n        await SQLiteHelper.Instance.DeleteAsync(item);\n        await RemoveServersViaSubid(config, id, false);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Move servers to a different group (subscription)\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"lstProfile\">List of profiles to move</param>\n    /// <param name=\"subid\">Target subscription ID</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> MoveToGroup(Config config, List<ProfileItem> lstProfile, string subid)\n    {\n        foreach (var item in lstProfile)\n        {\n            item.Subid = subid;\n        }\n        await SQLiteHelper.Instance.UpdateAllAsync(lstProfile);\n\n        return 0;\n    }\n\n    #endregion Sub & Group\n\n    #region Routing\n\n    /// <summary>\n    /// Save a routing item to the database\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"item\">Routing item to save</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> SaveRoutingItem(Config config, RoutingItem item)\n    {\n        if (item.Id.IsNullOrEmpty())\n        {\n            item.Id = Utils.GetGuid(false);\n        }\n\n        if (await SQLiteHelper.Instance.ReplaceAsync(item) > 0)\n        {\n            return 0;\n        }\n        else\n        {\n            return -1;\n        }\n    }\n\n    /// <summary>\n    /// Add multiple routing rules to a routing item\n    /// </summary>\n    /// <param name=\"routingItem\">Routing item to add rules to</param>\n    /// <param name=\"strData\">JSON string containing rules data</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> AddBatchRoutingRules(RoutingItem routingItem, string strData)\n    {\n        if (strData.IsNullOrEmpty())\n        {\n            return -1;\n        }\n\n        var lstRules = JsonUtils.Deserialize<List<RulesItem>>(strData);\n        if (lstRules == null)\n        {\n            return -1;\n        }\n\n        foreach (var item in lstRules)\n        {\n            item.Id = Utils.GetGuid(false);\n        }\n        routingItem.RuleNum = lstRules.Count;\n        routingItem.RuleSet = JsonUtils.Serialize(lstRules, false);\n\n        if (routingItem.Id.IsNullOrEmpty())\n        {\n            routingItem.Id = Utils.GetGuid(false);\n        }\n\n        if (await SQLiteHelper.Instance.ReplaceAsync(routingItem) > 0)\n        {\n            return 0;\n        }\n        else\n        {\n            return -1;\n        }\n    }\n\n    /// <summary>\n    /// Move a routing rule within a rules list\n    /// Supports moving to top, up, down, bottom or specific position\n    /// </summary>\n    /// <param name=\"rules\">List of routing rules</param>\n    /// <param name=\"index\">Index of the rule to move</param>\n    /// <param name=\"eMove\">Direction to move the rule</param>\n    /// <param name=\"pos\">Target position when using EMove.Position</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> MoveRoutingRule(List<RulesItem> rules, int index, EMove eMove, int pos = -1)\n    {\n        var count = rules.Count;\n        if (index < 0 || index > rules.Count - 1)\n        {\n            return -1;\n        }\n        switch (eMove)\n        {\n            case EMove.Top:\n                {\n                    if (index == 0)\n                    {\n                        return 0;\n                    }\n                    var item = JsonUtils.DeepCopy(rules[index]);\n                    rules.RemoveAt(index);\n                    rules.Insert(0, item);\n\n                    break;\n                }\n            case EMove.Up:\n                {\n                    if (index == 0)\n                    {\n                        return 0;\n                    }\n                    var item = JsonUtils.DeepCopy(rules[index]);\n                    rules.RemoveAt(index);\n                    rules.Insert(index - 1, item);\n\n                    break;\n                }\n\n            case EMove.Down:\n                {\n                    if (index == count - 1)\n                    {\n                        return 0;\n                    }\n                    var item = JsonUtils.DeepCopy(rules[index]);\n                    rules.RemoveAt(index);\n                    rules.Insert(index + 1, item);\n\n                    break;\n                }\n            case EMove.Bottom:\n                {\n                    if (index == count - 1)\n                    {\n                        return 0;\n                    }\n                    var item = JsonUtils.DeepCopy(rules[index]);\n                    rules.RemoveAt(index);\n                    rules.Add(item);\n\n                    break;\n                }\n            case EMove.Position:\n                {\n                    var removeItem = rules[index];\n                    var item = JsonUtils.DeepCopy(rules[index]);\n                    rules.Insert(pos, item);\n                    rules.Remove(removeItem);\n                    break;\n                }\n        }\n        return await Task.FromResult(0);\n    }\n\n    /// <summary>\n    /// Set the default routing configuration\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"routingItem\">Routing item to set as default</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> SetDefaultRouting(Config config, RoutingItem routingItem)\n    {\n        var items = await AppManager.Instance.RoutingItems();\n        if (items.Any(t => t.Id == routingItem.Id && t.IsActive == true))\n        {\n            return -1;\n        }\n\n        foreach (var item in items)\n        {\n            if (item.Id == routingItem.Id)\n            {\n                item.IsActive = true;\n            }\n            else\n            {\n                item.IsActive = false;\n            }\n        }\n\n        await SQLiteHelper.Instance.UpdateAllAsync(items);\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Get the current default routing configuration\n    /// If no default is set, selects the first available routing item\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <returns>The default routing item</returns>\n    public static async Task<RoutingItem> GetDefaultRouting(Config config)\n    {\n        var item = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.IsActive == true);\n        if (item is null)\n        {\n            var item2 = await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync();\n            await SetDefaultRouting(config, item2);\n            return item2;\n        }\n\n        return item;\n    }\n\n    /// <summary>\n    /// Initialize routing rules from built-in or external templates\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"blImportAdvancedRules\">Whether to import advanced rules</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> InitRouting(Config config, bool blImportAdvancedRules = false)\n    {\n        if (config.ConstItem.RouteRulesTemplateSourceUrl.IsNullOrEmpty())\n        {\n            await InitBuiltinRouting(config, blImportAdvancedRules);\n        }\n        else\n        {\n            await InitExternalRouting(config, blImportAdvancedRules);\n        }\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Initialize routing rules from external templates\n    /// Downloads and processes routing templates from a URL\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"blImportAdvancedRules\">Whether to import advanced rules</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> InitExternalRouting(Config config, bool blImportAdvancedRules = false)\n    {\n        var downloadHandle = new DownloadService();\n        var templateContent = await downloadHandle.TryDownloadString(config.ConstItem.RouteRulesTemplateSourceUrl, true, \"\");\n        if (templateContent.IsNullOrEmpty())\n        {\n            return await InitBuiltinRouting(config, blImportAdvancedRules); // fallback\n        }\n\n        var template = JsonUtils.Deserialize<RoutingTemplate>(templateContent);\n        if (template == null)\n        {\n            return await InitBuiltinRouting(config, blImportAdvancedRules); // fallback\n        }\n\n        var items = await AppManager.Instance.RoutingItems();\n        var maxSort = items.Count;\n        if (!blImportAdvancedRules && items.Where(t => t.Remarks.StartsWith(template.Version)).ToList().Count > 0)\n        {\n            return 0;\n        }\n        for (var i = 0; i < template.RoutingItems.Length; i++)\n        {\n            var item = template.RoutingItems[i];\n\n            if (item.Url.IsNullOrEmpty() && item.RuleSet.IsNullOrEmpty())\n            {\n                continue;\n            }\n\n            var ruleSetsString = !item.RuleSet.IsNullOrEmpty()\n                ? item.RuleSet\n                : await downloadHandle.TryDownloadString(item.Url, true, \"\");\n\n            if (ruleSetsString.IsNullOrEmpty())\n            {\n                continue;\n            }\n\n            item.Remarks = $\"{template.Version}-{item.Remarks}\";\n            item.Enabled = true;\n            item.Sort = ++maxSort;\n            item.Url = string.Empty;\n\n            await AddBatchRoutingRules(item, ruleSetsString);\n\n            //first rule as default at first startup\n            if (!blImportAdvancedRules && i == 0)\n            {\n                await SetDefaultRouting(config, item);\n            }\n        }\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Initialize built-in routing rules\n    /// Creates default routing configurations (whitelist, blacklist, global)\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"blImportAdvancedRules\">Whether to import advanced rules</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> InitBuiltinRouting(Config config, bool blImportAdvancedRules = false)\n    {\n        var ver = \"V4-\";\n        var items = await AppManager.Instance.RoutingItems();\n\n        //TODO Temporary code to be removed later\n        var lockItem = items?.FirstOrDefault(t => t.Locked == true);\n        if (lockItem != null)\n        {\n            await ConfigHandler.RemoveRoutingItem(lockItem);\n            items = await AppManager.Instance.RoutingItems();\n        }\n\n        if (!blImportAdvancedRules && items.Count(u => u.Remarks.StartsWith(ver)) > 0)\n        {\n            //migrate\n            //TODO Temporary code to be removed later\n            if (config.RoutingBasicItem.RoutingIndexId.IsNotEmpty())\n            {\n                var item = items.FirstOrDefault(t => t.Id == config.RoutingBasicItem.RoutingIndexId);\n                if (item != null)\n                {\n                    await SetDefaultRouting(config, item);\n                }\n                config.RoutingBasicItem.RoutingIndexId = string.Empty;\n            }\n\n            return 0;\n        }\n\n        var maxSort = items.Count;\n        //Bypass the mainland\n        var item2 = new RoutingItem()\n        {\n            Remarks = $\"{ver}绕过大陆(Whitelist)\",\n            Url = string.Empty,\n            Sort = maxSort + 1,\n        };\n        await AddBatchRoutingRules(item2, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + \"white\"));\n\n        //Blacklist\n        var item3 = new RoutingItem()\n        {\n            Remarks = $\"{ver}黑名单(Blacklist)\",\n            Url = string.Empty,\n            Sort = maxSort + 2,\n        };\n        await AddBatchRoutingRules(item3, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + \"black\"));\n\n        //Global\n        var item1 = new RoutingItem()\n        {\n            Remarks = $\"{ver}全局(Global)\",\n            Url = string.Empty,\n            Sort = maxSort + 3,\n        };\n        await AddBatchRoutingRules(item1, EmbedUtils.GetEmbedText(Global.CustomRoutingFileName + \"global\"));\n\n        if (!blImportAdvancedRules)\n        {\n            await SetDefaultRouting(config, item2);\n        }\n        return 0;\n    }\n\n    /// <summary>\n    /// Remove a routing item from the database\n    /// </summary>\n    /// <param name=\"routingItem\">Routing item to remove</param>\n    public static async Task RemoveRoutingItem(RoutingItem routingItem)\n    {\n        await SQLiteHelper.Instance.DeleteAsync(routingItem);\n    }\n\n    #endregion Routing\n\n    #region DNS\n\n    /// <summary>\n    /// Initialize built-in DNS configurations\n    /// Creates default DNS items for V2Ray and sing-box\n    /// Also checks existing DNS items and disables those with empty NormalDNS\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <returns>0 if successful</returns>\n    public static async Task<int> InitBuiltinDNS(Config config)\n    {\n        var items = await AppManager.Instance.DNSItems();\n\n        // Check existing DNS items and disable those with empty NormalDNS\n        var needsUpdate = false;\n        foreach (var existingItem in items)\n        {\n            if (existingItem.NormalDNS.IsNullOrEmpty() && existingItem.Enabled)\n            {\n                existingItem.Enabled = false;\n                needsUpdate = true;\n            }\n        }\n\n        // Update items if any changes were made\n        if (needsUpdate)\n        {\n            await SQLiteHelper.Instance.UpdateAllAsync(items);\n        }\n\n        if (items.Count <= 0)\n        {\n            var item = new DNSItem()\n            {\n                Remarks = \"V2ray\",\n                CoreType = ECoreType.Xray,\n                Enabled = false,\n            };\n            await SaveDNSItems(config, item);\n\n            var item2 = new DNSItem()\n            {\n                Remarks = \"sing-box\",\n                CoreType = ECoreType.sing_box,\n                Enabled = false,\n            };\n            await SaveDNSItems(config, item2);\n        }\n\n        return 0;\n    }\n\n    /// <summary>\n    /// Save a DNS item to the database\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"item\">DNS item to save</param>\n    /// <returns>0 if successful, -1 if failed</returns>\n    public static async Task<int> SaveDNSItems(Config config, DNSItem item)\n    {\n        if (item == null)\n        {\n            return -1;\n        }\n\n        if (item.Id.IsNullOrEmpty())\n        {\n            item.Id = Utils.GetGuid(false);\n        }\n\n        if (await SQLiteHelper.Instance.ReplaceAsync(item) > 0)\n        {\n            return 0;\n        }\n        else\n        {\n            return -1;\n        }\n    }\n\n    /// <summary>\n    /// Get an external DNS configuration from URL\n    /// Downloads and processes DNS templates\n    /// </summary>\n    /// <param name=\"type\">Core type (Xray or sing-box)</param>\n    /// <param name=\"url\">URL of the DNS template</param>\n    /// <returns>DNS item with configuration from the URL</returns>\n    public static async Task<DNSItem> GetExternalDNSItem(ECoreType type, string url)\n    {\n        var currentItem = await AppManager.Instance.GetDNSItem(type);\n\n        var downloadHandle = new DownloadService();\n        var templateContent = await downloadHandle.TryDownloadString(url, true, \"\");\n        if (templateContent.IsNullOrEmpty())\n        {\n            return currentItem;\n        }\n\n        var template = JsonUtils.Deserialize<DNSItem>(templateContent);\n        if (template == null)\n        {\n            return currentItem;\n        }\n\n        if (!template.NormalDNS.IsNullOrEmpty())\n        {\n            template.NormalDNS = await downloadHandle.TryDownloadString(template.NormalDNS, true, \"\");\n        }\n\n        if (!template.TunDNS.IsNullOrEmpty())\n        {\n            template.TunDNS = await downloadHandle.TryDownloadString(template.TunDNS, true, \"\");\n        }\n\n        template.Id = currentItem.Id;\n        template.Enabled = currentItem.Enabled;\n        template.Remarks = currentItem.Remarks;\n        template.CoreType = type;\n\n        return template;\n    }\n\n    #endregion DNS\n\n    #region Simple DNS\n\n    public static SimpleDNSItem InitBuiltinSimpleDNS()\n    {\n        return new SimpleDNSItem()\n        {\n            UseSystemHosts = false,\n            AddCommonHosts = true,\n            FakeIP = false,\n            GlobalFakeIp = true,\n            BlockBindingQuery = true,\n            DirectDNS = Global.DomainDirectDNSAddress.FirstOrDefault(),\n            RemoteDNS = Global.DomainRemoteDNSAddress.FirstOrDefault(),\n            BootstrapDNS = Global.DomainPureIPDNSAddress.FirstOrDefault(),\n        };\n    }\n\n    public static async Task<SimpleDNSItem> GetExternalSimpleDNSItem(string url)\n    {\n        var downloadHandle = new DownloadService();\n        var templateContent = await downloadHandle.TryDownloadString(url, true, \"\");\n        if (templateContent.IsNullOrEmpty())\n        {\n            return null;\n        }\n\n        var template = JsonUtils.Deserialize<SimpleDNSItem>(templateContent);\n        if (template == null)\n        {\n            return null;\n        }\n\n        return template;\n    }\n\n    #endregion Simple DNS\n\n    #region Custom Config\n\n    public static async Task<int> InitBuiltinFullConfigTemplate(Config config)\n    {\n        var items = await AppManager.Instance.FullConfigTemplateItem();\n        if (items.Count <= 0)\n        {\n            var item = new FullConfigTemplateItem()\n            {\n                Remarks = \"V2ray\",\n                CoreType = ECoreType.Xray,\n            };\n            await SaveFullConfigTemplate(config, item);\n\n            var item2 = new FullConfigTemplateItem()\n            {\n                Remarks = \"sing-box\",\n                CoreType = ECoreType.sing_box,\n            };\n            await SaveFullConfigTemplate(config, item2);\n        }\n\n        return 0;\n    }\n\n    public static async Task<int> SaveFullConfigTemplate(Config config, FullConfigTemplateItem item)\n    {\n        if (item == null)\n        {\n            return -1;\n        }\n\n        if (item.Id.IsNullOrEmpty())\n        {\n            item.Id = Utils.GetGuid(false);\n        }\n\n        if (await SQLiteHelper.Instance.ReplaceAsync(item) > 0)\n        {\n            return 0;\n        }\n        else\n        {\n            return -1;\n        }\n    }\n\n    #endregion Custom Config\n\n    #region Regional Presets\n\n    /// <summary>\n    /// Apply regional presets for geo-specific configurations\n    /// Sets up geo files, routing rules, and DNS for specific regions\n    /// </summary>\n    /// <param name=\"config\">Current configuration</param>\n    /// <param name=\"type\">Type of preset (Default, Russia, Iran)</param>\n    /// <returns>True if successful</returns>\n    public static async Task<bool> ApplyRegionalPreset(Config config, EPresetType type)\n    {\n        switch (type)\n        {\n            case EPresetType.Default:\n                config.ConstItem.GeoSourceUrl = \"\";\n                config.ConstItem.SrsSourceUrl = \"\";\n                config.ConstItem.RouteRulesTemplateSourceUrl = \"\";\n\n                await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>();\n                await InitBuiltinDNS(config);\n\n                config.SimpleDNSItem = InitBuiltinSimpleDNS();\n                break;\n\n            case EPresetType.Russia:\n                config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[1];\n                config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[1];\n                config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[1];\n\n                var xrayDnsRussia = await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[1] + \"v2ray.json\");\n                var singboxDnsRussia = await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[1] + \"sing_box.json\");\n                var simpleDnsRussia = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[1] + \"simple_dns.json\");\n\n                if (simpleDnsRussia == null)\n                {\n                    xrayDnsRussia.Enabled = true;\n                    singboxDnsRussia.Enabled = true;\n                    config.SimpleDNSItem = InitBuiltinSimpleDNS();\n                }\n                else\n                {\n                    config.SimpleDNSItem = simpleDnsRussia;\n                }\n                await SaveDNSItems(config, xrayDnsRussia);\n                await SaveDNSItems(config, singboxDnsRussia);\n                break;\n\n            case EPresetType.Iran:\n                config.ConstItem.GeoSourceUrl = Global.GeoFilesSources[2];\n                config.ConstItem.SrsSourceUrl = Global.SingboxRulesetSources[2];\n                config.ConstItem.RouteRulesTemplateSourceUrl = Global.RoutingRulesSources[2];\n\n                var xrayDnsIran = await GetExternalDNSItem(ECoreType.Xray, Global.DNSTemplateSources[2] + \"v2ray.json\");\n                var singboxDnsIran = await GetExternalDNSItem(ECoreType.sing_box, Global.DNSTemplateSources[2] + \"sing_box.json\");\n                var simpleDnsIran = await GetExternalSimpleDNSItem(Global.DNSTemplateSources[2] + \"simple_dns.json\");\n\n                if (simpleDnsIran == null)\n                {\n                    xrayDnsIran.Enabled = true;\n                    singboxDnsIran.Enabled = true;\n                    config.SimpleDNSItem = InitBuiltinSimpleDNS();\n                }\n                else\n                {\n                    config.SimpleDNSItem = simpleDnsIran;\n                }\n                await SaveDNSItems(config, xrayDnsIran);\n                await SaveDNSItems(config, singboxDnsIran);\n                break;\n        }\n\n        return true;\n    }\n\n    #endregion Regional Presets\n\n    #region UIItem\n\n    public static WindowSizeItem? GetWindowSizeItem(Config config, string typeName)\n    {\n        var sizeItem = config?.UiItem?.WindowSizeItem?.FirstOrDefault(t => t.TypeName == typeName);\n        if (sizeItem == null || sizeItem.Width <= 0 || sizeItem.Height <= 0)\n        {\n            return null;\n        }\n\n        return sizeItem;\n    }\n\n    public static int SaveWindowSizeItem(Config config, string typeName, double width, double height)\n    {\n        var sizeItem = config?.UiItem?.WindowSizeItem?.FirstOrDefault(t => t.TypeName == typeName);\n        if (sizeItem == null)\n        {\n            sizeItem = new WindowSizeItem { TypeName = typeName };\n            config.UiItem.WindowSizeItem.Add(sizeItem);\n        }\n\n        sizeItem.Width = (int)width;\n        sizeItem.Height = (int)height;\n\n        return 0;\n    }\n\n    public static int SaveMainGirdHeight(Config config, double height1, double height2)\n    {\n        var uiItem = config.UiItem ?? new();\n\n        uiItem.MainGirdHeight1 = (int)(height1 + 0.1);\n        uiItem.MainGirdHeight2 = (int)(height2 + 0.1);\n\n        return 0;\n    }\n\n    #endregion UIItem\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/ConnectionHandler.cs",
    "content": "namespace ServiceLib.Handler;\n\npublic static class ConnectionHandler\n{\n    private static readonly string _tag = \"ConnectionHandler\";\n\n    public static async Task<string> RunAvailabilityCheck()\n    {\n        var time = await GetRealPingTimeInfo();\n        var ip = time > 0 ? await GetIPInfo() ?? Global.None : Global.None;\n\n        return string.Format(ResUI.TestMeOutput, time, ip);\n    }\n\n    private static async Task<string?> GetIPInfo()\n    {\n        var url = AppManager.Instance.Config.SpeedTestItem.IPAPIUrl;\n        if (url.IsNullOrEmpty())\n        {\n            return null;\n        }\n\n        var downloadHandle = new DownloadService();\n        var result = await downloadHandle.TryDownloadString(url, true, \"\");\n        if (result == null)\n        {\n            return null;\n        }\n\n        var ipInfo = JsonUtils.Deserialize<IPAPIInfo>(result);\n        if (ipInfo == null)\n        {\n            return null;\n        }\n\n        var ip = ipInfo.ip ?? ipInfo.clientIp ?? ipInfo.ip_addr ?? ipInfo.query;\n        var country = ipInfo.country_code ?? ipInfo.country ?? ipInfo.countryCode ?? ipInfo.location?.country_code;\n\n        return $\"({country ?? \"unknown\"}) {ip}\";\n    }\n\n    private static async Task<int> GetRealPingTimeInfo()\n    {\n        var responseTime = -1;\n        try\n        {\n            var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);\n            var webProxy = new WebProxy($\"socks5://{Global.Loopback}:{port}\");\n            var url = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;\n\n            for (var i = 0; i < 2; i++)\n            {\n                responseTime = await GetRealPingTime(url, webProxy, 10);\n                if (responseTime > 0)\n                {\n                    break;\n                }\n                await Task.Delay(500);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return -1;\n        }\n        return responseTime;\n    }\n\n    public static async Task<int> GetRealPingTime(string url, IWebProxy? webProxy, int downloadTimeout)\n    {\n        var responseTime = -1;\n        try\n        {\n            using var cts = new CancellationTokenSource();\n            cts.CancelAfter(TimeSpan.FromSeconds(downloadTimeout));\n            using var client = new HttpClient(new SocketsHttpHandler()\n            {\n                Proxy = webProxy,\n                UseProxy = webProxy != null\n            });\n\n            List<int> oneTime = new();\n            for (var i = 0; i < 2; i++)\n            {\n                var timer = Stopwatch.StartNew();\n                await client.GetAsync(url, cts.Token).ConfigureAwait(false);\n                timer.Stop();\n                oneTime.Add((int)timer.Elapsed.TotalMilliseconds);\n                await Task.Delay(100);\n            }\n            responseTime = oneTime.Where(x => x > 0).OrderBy(x => x).FirstOrDefault();\n        }\n        catch\n        {\n        }\n        return responseTime;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/CoreConfigHandler.cs",
    "content": "namespace ServiceLib.Handler;\n\n/// <summary>\n/// Core configuration file processing class\n/// </summary>\npublic static class CoreConfigHandler\n{\n    private static readonly string _tag = \"CoreConfigHandler\";\n\n    public static async Task<RetResult> GenerateClientConfig(CoreConfigContext context, string? fileName)\n    {\n        var config = AppManager.Instance.Config;\n        var result = new RetResult();\n        var node = context.Node;\n\n        if (node.ConfigType == EConfigType.Custom)\n        {\n            result = node.CoreType switch\n            {\n                ECoreType.mihomo => await new CoreConfigClashService(config).GenerateClientCustomConfig(node, fileName),\n                _ => await GenerateClientCustomConfig(node, fileName)\n            };\n        }\n        else if (context.RunCoreType == ECoreType.sing_box)\n        {\n            result = new CoreConfigSingboxService(context).GenerateClientConfigContent();\n        }\n        else\n        {\n            result = new CoreConfigV2rayService(context).GenerateClientConfigContent();\n        }\n        if (result.Success != true)\n        {\n            return result;\n        }\n        if (fileName.IsNotEmpty() && result.Data != null)\n        {\n            await File.WriteAllTextAsync(fileName, result.Data.ToString());\n        }\n\n        return result;\n    }\n\n    private static async Task<RetResult> GenerateClientCustomConfig(ProfileItem node, string? fileName)\n    {\n        var ret = new RetResult();\n        try\n        {\n            if (node == null || fileName is null)\n            {\n                ret.Msg = ResUI.CheckServerSettings;\n                return ret;\n            }\n\n            if (File.Exists(fileName))\n            {\n                File.SetAttributes(fileName, FileAttributes.Normal); //If the file has a read-only attribute, direct deletion will fail\n                File.Delete(fileName);\n            }\n\n            var addressFileName = node.Address;\n            if (!File.Exists(addressFileName))\n            {\n                addressFileName = Utils.GetConfigPath(addressFileName);\n            }\n            if (!File.Exists(addressFileName))\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n            File.Copy(addressFileName, fileName);\n            File.SetAttributes(fileName, FileAttributes.Normal); //Copy will keep the attributes of addressFileName, so we need to add write permissions to fileName just in case of addressFileName is a read-only file.\n\n            //check again\n            if (!File.Exists(fileName))\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            ret.Msg = string.Format(ResUI.SuccessfulConfiguration, \"\");\n            ret.Success = true;\n            return await Task.FromResult(ret);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, string fileName, List<ServerTestItem> selecteds, ECoreType coreType)\n    {\n        var result = new RetResult();\n        var dummyNode = new ProfileItem\n        {\n            CoreType = coreType\n        };\n        var builderResult = await CoreConfigContextBuilder.Build(config, dummyNode);\n        var context = builderResult.Context;\n        foreach (var testItem in selecteds)\n        {\n            var node = testItem.Profile;\n            var (actNode, _) = await CoreConfigContextBuilder.ResolveNodeAsync(context, node, true);\n            if (node.IndexId == actNode.IndexId)\n            {\n                continue;\n            }\n            context.ServerTestItemMap[node.IndexId] = actNode.IndexId;\n        }\n        if (coreType == ECoreType.sing_box)\n        {\n            result = new CoreConfigSingboxService(context).GenerateClientSpeedtestConfig(selecteds);\n        }\n        else if (coreType == ECoreType.Xray)\n        {\n            result = new CoreConfigV2rayService(context).GenerateClientSpeedtestConfig(selecteds);\n        }\n        if (result.Success != true)\n        {\n            return result;\n        }\n        await File.WriteAllTextAsync(fileName, result.Data.ToString());\n        return result;\n    }\n\n    public static async Task<RetResult> GenerateClientSpeedtestConfig(Config config, CoreConfigContext context, ServerTestItem testItem, string fileName)\n    {\n        var result = new RetResult();\n        var initPort = AppManager.Instance.GetLocalPort(EInboundProtocol.speedtest);\n        var port = Utils.GetFreePort(initPort + testItem.QueueNum);\n        testItem.Port = port;\n\n        if (context.RunCoreType == ECoreType.sing_box)\n        {\n            result = new CoreConfigSingboxService(context).GenerateClientSpeedtestConfig(port);\n        }\n        else\n        {\n            result = new CoreConfigV2rayService(context).GenerateClientSpeedtestConfig(port);\n        }\n        if (result.Success != true)\n        {\n            return result;\n        }\n\n        await File.WriteAllTextAsync(fileName, result.Data.ToString());\n        return result;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/AnytlsFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class AnytlsFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n\n        var parsedUrl = Utils.TryUri(str);\n        if (parsedUrl == null)\n        {\n            return null;\n        }\n\n        ProfileItem item = new()\n        {\n            ConfigType = EConfigType.Anytls,\n            Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),\n            Address = parsedUrl.IdnHost,\n            Port = parsedUrl.Port,\n        };\n        var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);\n        item.Password = rawUserInfo;\n\n        var query = Utils.ParseQueryString(parsedUrl.Query);\n        ResolveUriQuery(query, ref item);\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n        var pw = item.Password;\n        var dicQuery = new Dictionary<string, string>();\n        ToUriQuery(item, Global.None, ref dicQuery);\n\n        return ToUri(EConfigType.Anytls, item.Address, item.Port, pw, dicQuery, remark);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/BaseFmt.cs",
    "content": "using System.Collections.Specialized;\n\nnamespace ServiceLib.Handler.Fmt;\n\npublic class BaseFmt\n{\n    private static readonly string[] _allowInsecureArray = new[] { \"insecure\", \"allowInsecure\", \"allow_insecure\" };\n\n    protected static string GetIpv6(string address)\n    {\n        if (Utils.IsIpv6(address))\n        {\n            // Check if the address is already surrounded by square brackets, if not, add square brackets\n            return address.StartsWith('[') && address.EndsWith(']') ? address : $\"[{address}]\";\n        }\n        else\n        {\n            return address;\n        }\n    }\n\n    protected static int ToUriQuery(ProfileItem item, string? securityDef, ref Dictionary<string, string> dicQuery)\n    {\n        if (item.StreamSecurity.IsNotEmpty())\n        {\n            dicQuery.Add(\"security\", item.StreamSecurity);\n        }\n        else\n        {\n            if (securityDef != null)\n            {\n                dicQuery.Add(\"security\", securityDef);\n            }\n        }\n        if (item.Sni.IsNotEmpty())\n        {\n            dicQuery.Add(\"sni\", Utils.UrlEncode(item.Sni));\n        }\n        if (item.Fingerprint.IsNotEmpty())\n        {\n            dicQuery.Add(\"fp\", Utils.UrlEncode(item.Fingerprint));\n        }\n        if (item.PublicKey.IsNotEmpty())\n        {\n            dicQuery.Add(\"pbk\", Utils.UrlEncode(item.PublicKey));\n        }\n        if (item.ShortId.IsNotEmpty())\n        {\n            dicQuery.Add(\"sid\", Utils.UrlEncode(item.ShortId));\n        }\n        if (item.SpiderX.IsNotEmpty())\n        {\n            dicQuery.Add(\"spx\", Utils.UrlEncode(item.SpiderX));\n        }\n        if (item.Mldsa65Verify.IsNotEmpty())\n        {\n            dicQuery.Add(\"pqv\", Utils.UrlEncode(item.Mldsa65Verify));\n        }\n\n        if (item.StreamSecurity.Equals(Global.StreamSecurity))\n        {\n            if (item.Alpn.IsNotEmpty())\n            {\n                dicQuery.Add(\"alpn\", Utils.UrlEncode(item.Alpn));\n            }\n            ToUriQueryAllowInsecure(item, ref dicQuery);\n        }\n        if (item.EchConfigList.IsNotEmpty())\n        {\n            dicQuery.Add(\"ech\", Utils.UrlEncode(item.EchConfigList));\n        }\n        if (item.CertSha.IsNotEmpty())\n        {\n            dicQuery.Add(\"pcs\", Utils.UrlEncode(item.CertSha));\n        }\n        if (item.Finalmask.IsNotEmpty())\n        {\n            var node = JsonUtils.ParseJson(item.Finalmask);\n            var finalmask = node != null\n                ? JsonUtils.Serialize(node, new JsonSerializerOptions\n                {\n                    WriteIndented = false,\n                    DefaultIgnoreCondition = JsonIgnoreCondition.Never,\n                    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n                })\n                : item.Finalmask;\n            dicQuery.Add(\"fm\", Utils.UrlEncode(finalmask));\n        }\n\n        dicQuery.Add(\"type\", item.Network.IsNotEmpty() ? item.Network : nameof(ETransport.tcp));\n\n        switch (item.Network)\n        {\n            case nameof(ETransport.tcp):\n                dicQuery.Add(\"headerType\", item.HeaderType.IsNotEmpty() ? item.HeaderType : Global.None);\n                if (item.RequestHost.IsNotEmpty())\n                {\n                    dicQuery.Add(\"host\", Utils.UrlEncode(item.RequestHost));\n                }\n                break;\n\n            case nameof(ETransport.kcp):\n                dicQuery.Add(\"headerType\", item.HeaderType.IsNotEmpty() ? item.HeaderType : Global.None);\n                if (item.Path.IsNotEmpty())\n                {\n                    dicQuery.Add(\"seed\", Utils.UrlEncode(item.Path));\n                }\n                break;\n\n            case nameof(ETransport.ws):\n            case nameof(ETransport.httpupgrade):\n                if (item.RequestHost.IsNotEmpty())\n                {\n                    dicQuery.Add(\"host\", Utils.UrlEncode(item.RequestHost));\n                }\n                if (item.Path.IsNotEmpty())\n                {\n                    dicQuery.Add(\"path\", Utils.UrlEncode(item.Path));\n                }\n                break;\n\n            case nameof(ETransport.xhttp):\n                if (item.RequestHost.IsNotEmpty())\n                {\n                    dicQuery.Add(\"host\", Utils.UrlEncode(item.RequestHost));\n                }\n                if (item.Path.IsNotEmpty())\n                {\n                    dicQuery.Add(\"path\", Utils.UrlEncode(item.Path));\n                }\n                if (item.HeaderType.IsNotEmpty() && Global.XhttpMode.Contains(item.HeaderType))\n                {\n                    dicQuery.Add(\"mode\", Utils.UrlEncode(item.HeaderType));\n                }\n                if (item.Extra.IsNotEmpty())\n                {\n                    var node = JsonUtils.ParseJson(item.Extra);\n                    var extra = node != null\n                        ? JsonUtils.Serialize(node, new JsonSerializerOptions\n                        {\n                            WriteIndented = false,\n                            DefaultIgnoreCondition = JsonIgnoreCondition.Never,\n                            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n                        })\n                        : item.Extra;\n                    dicQuery.Add(\"extra\", Utils.UrlEncode(extra));\n                }\n                break;\n\n            case nameof(ETransport.http):\n            case nameof(ETransport.h2):\n                dicQuery[\"type\"] = nameof(ETransport.http);\n                if (item.RequestHost.IsNotEmpty())\n                {\n                    dicQuery.Add(\"host\", Utils.UrlEncode(item.RequestHost));\n                }\n                if (item.Path.IsNotEmpty())\n                {\n                    dicQuery.Add(\"path\", Utils.UrlEncode(item.Path));\n                }\n                break;\n\n            case nameof(ETransport.quic):\n                dicQuery.Add(\"headerType\", item.HeaderType.IsNotEmpty() ? item.HeaderType : Global.None);\n                dicQuery.Add(\"quicSecurity\", Utils.UrlEncode(item.RequestHost));\n                dicQuery.Add(\"key\", Utils.UrlEncode(item.Path));\n                break;\n\n            case nameof(ETransport.grpc):\n                if (item.Path.IsNotEmpty())\n                {\n                    dicQuery.Add(\"authority\", Utils.UrlEncode(item.RequestHost));\n                    dicQuery.Add(\"serviceName\", Utils.UrlEncode(item.Path));\n                    if (item.HeaderType is Global.GrpcGunMode or Global.GrpcMultiMode)\n                    {\n                        dicQuery.Add(\"mode\", Utils.UrlEncode(item.HeaderType));\n                    }\n                }\n                break;\n        }\n        return 0;\n    }\n\n    protected static int ToUriQueryLite(ProfileItem item, ref Dictionary<string, string> dicQuery)\n    {\n        if (item.Sni.IsNotEmpty())\n        {\n            dicQuery.Add(\"sni\", Utils.UrlEncode(item.Sni));\n        }\n        if (item.Alpn.IsNotEmpty())\n        {\n            dicQuery.Add(\"alpn\", Utils.UrlEncode(item.Alpn));\n        }\n\n        ToUriQueryAllowInsecure(item, ref dicQuery);\n\n        return 0;\n    }\n\n    private static int ToUriQueryAllowInsecure(ProfileItem item, ref Dictionary<string, string> dicQuery)\n    {\n        if (item.AllowInsecure.Equals(Global.AllowInsecure.First()))\n        {\n            // Add two for compatibility\n            dicQuery.Add(\"insecure\", \"1\");\n            dicQuery.Add(\"allowInsecure\", \"1\");\n        }\n        else\n        {\n            dicQuery.Add(\"insecure\", \"0\");\n            dicQuery.Add(\"allowInsecure\", \"0\");\n        }\n\n        return 0;\n    }\n\n    protected static int ResolveUriQuery(NameValueCollection query, ref ProfileItem item)\n    {\n        item.StreamSecurity = GetQueryValue(query, \"security\");\n        item.Sni = GetQueryValue(query, \"sni\");\n        item.Alpn = GetQueryDecoded(query, \"alpn\");\n        item.Fingerprint = GetQueryDecoded(query, \"fp\");\n        item.PublicKey = GetQueryDecoded(query, \"pbk\");\n        item.ShortId = GetQueryDecoded(query, \"sid\");\n        item.SpiderX = GetQueryDecoded(query, \"spx\");\n        item.Mldsa65Verify = GetQueryDecoded(query, \"pqv\");\n        item.EchConfigList = GetQueryDecoded(query, \"ech\");\n        item.CertSha = GetQueryDecoded(query, \"pcs\");\n\n        var finalmaskDecoded = GetQueryDecoded(query, \"fm\");\n        if (finalmaskDecoded.IsNotEmpty())\n        {\n            var node = JsonUtils.ParseJson(finalmaskDecoded);\n            item.Finalmask = node != null\n                ? JsonUtils.Serialize(node, new JsonSerializerOptions\n                {\n                    WriteIndented = true,\n                    DefaultIgnoreCondition = JsonIgnoreCondition.Never,\n                    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n                })\n                : finalmaskDecoded;\n        }\n        else\n        {\n            item.Finalmask = string.Empty;\n        }\n\n        if (_allowInsecureArray.Any(k => GetQueryDecoded(query, k) == \"1\"))\n        {\n            item.AllowInsecure = Global.AllowInsecure.First();\n        }\n        else if (_allowInsecureArray.Any(k => GetQueryDecoded(query, k) == \"0\"))\n        {\n            item.AllowInsecure = Global.AllowInsecure.Skip(1).First();\n        }\n        else\n        {\n            item.AllowInsecure = string.Empty;\n        }\n\n        item.Network = GetQueryValue(query, \"type\", nameof(ETransport.tcp));\n        switch (item.Network)\n        {\n            case nameof(ETransport.tcp):\n                item.HeaderType = GetQueryValue(query, \"headerType\", Global.None);\n                item.RequestHost = GetQueryDecoded(query, \"host\");\n                break;\n\n            case nameof(ETransport.kcp):\n                item.HeaderType = GetQueryValue(query, \"headerType\", Global.None);\n                item.Path = GetQueryDecoded(query, \"seed\");\n                break;\n\n            case nameof(ETransport.ws):\n            case nameof(ETransport.httpupgrade):\n                item.RequestHost = GetQueryDecoded(query, \"host\");\n                item.Path = GetQueryDecoded(query, \"path\", \"/\");\n                break;\n\n            case nameof(ETransport.xhttp):\n                item.RequestHost = GetQueryDecoded(query, \"host\");\n                item.Path = GetQueryDecoded(query, \"path\", \"/\");\n                item.HeaderType = GetQueryDecoded(query, \"mode\");\n                var extraDecoded = GetQueryDecoded(query, \"extra\");\n                if (extraDecoded.IsNotEmpty())\n                {\n                    var node = JsonUtils.ParseJson(extraDecoded);\n                    if (node != null)\n                    {\n                        extraDecoded = JsonUtils.Serialize(node, new JsonSerializerOptions\n                        {\n                            WriteIndented = true,\n                            DefaultIgnoreCondition = JsonIgnoreCondition.Never,\n                            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping\n                        });\n                    }\n                }\n                item.Extra = extraDecoded;\n                break;\n\n            case nameof(ETransport.http):\n            case nameof(ETransport.h2):\n                item.Network = nameof(ETransport.h2);\n                item.RequestHost = GetQueryDecoded(query, \"host\");\n                item.Path = GetQueryDecoded(query, \"path\", \"/\");\n                break;\n\n            case nameof(ETransport.quic):\n                item.HeaderType = GetQueryValue(query, \"headerType\", Global.None);\n                item.RequestHost = GetQueryValue(query, \"quicSecurity\", Global.None);\n                item.Path = GetQueryDecoded(query, \"key\");\n                break;\n\n            case nameof(ETransport.grpc):\n                item.RequestHost = GetQueryDecoded(query, \"authority\");\n                item.Path = GetQueryDecoded(query, \"serviceName\");\n                item.HeaderType = GetQueryDecoded(query, \"mode\", Global.GrpcGunMode);\n                break;\n\n            default:\n                break;\n        }\n        return 0;\n    }\n\n    protected static bool Contains(string str, params string[] s)\n    {\n        return s.All(item => str.Contains(item, StringComparison.OrdinalIgnoreCase));\n    }\n\n    protected static string WriteAllText(string strData, string ext = \"json\")\n    {\n        var fileName = Utils.GetTempPath($\"{Utils.GetGuid(false)}.{ext}\");\n        File.WriteAllText(fileName, strData);\n        return fileName;\n    }\n\n    protected static string ToUri(EConfigType eConfigType, string address, object port, string userInfo, Dictionary<string, string>? dicQuery, string? remark)\n    {\n        var query = dicQuery != null\n            ? (\"?\" + string.Join(\"&\", dicQuery.Select(x => x.Key + \"=\" + x.Value).ToArray()))\n            : string.Empty;\n\n        var url = $\"{Utils.UrlEncode(userInfo)}@{GetIpv6(address)}:{port}\";\n        return $\"{Global.ProtocolShares[eConfigType]}{url}{query}{remark}\";\n    }\n\n    protected static string GetQueryValue(NameValueCollection query, string key, string defaultValue = \"\")\n    {\n        return query[key] ?? defaultValue;\n    }\n\n    protected static string GetQueryDecoded(NameValueCollection query, string key, string defaultValue = \"\")\n    {\n        return Utils.UrlDecode(GetQueryValue(query, key, defaultValue));\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/ClashFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class ClashFmt : BaseFmt\n{\n    public static ProfileItem? ResolveFull(string strData, string? subRemarks)\n    {\n        if (Contains(strData, \"rules\", \"-port\", \"proxies\"))\n        {\n            var fileName = WriteAllText(strData, \"yaml\");\n\n            var profileItem = new ProfileItem\n            {\n                CoreType = ECoreType.mihomo,\n                Address = fileName,\n                Remarks = subRemarks ?? \"clash_custom\"\n            };\n            return profileItem;\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/FmtHandler.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class FmtHandler\n{\n    private static readonly string _tag = \"FmtHandler\";\n\n    public static string? GetShareUri(ProfileItem item)\n    {\n        try\n        {\n            var url = item.ConfigType switch\n            {\n                EConfigType.VMess => VmessFmt.ToUri(item),\n                EConfigType.Shadowsocks => ShadowsocksFmt.ToUri(item),\n                EConfigType.SOCKS => SocksFmt.ToUri(item),\n                EConfigType.Trojan => TrojanFmt.ToUri(item),\n                EConfigType.VLESS => VLESSFmt.ToUri(item),\n                EConfigType.Hysteria2 => Hysteria2Fmt.ToUri(item),\n                EConfigType.TUIC => TuicFmt.ToUri(item),\n                EConfigType.WireGuard => WireguardFmt.ToUri(item),\n                EConfigType.Anytls => AnytlsFmt.ToUri(item),\n                _ => null,\n            };\n\n            return url;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return string.Empty;\n        }\n    }\n\n    public static ProfileItem? ResolveConfig(string config, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n\n        try\n        {\n            var str = config.TrimEx();\n            if (str.IsNullOrEmpty())\n            {\n                msg = ResUI.FailedReadConfiguration;\n                return null;\n            }\n\n            if (str.StartsWith(Global.ProtocolShares[EConfigType.VMess]))\n            {\n                return VmessFmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.Shadowsocks]))\n            {\n                return ShadowsocksFmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.SOCKS]))\n            {\n                return SocksFmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.Trojan]))\n            {\n                return TrojanFmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.VLESS]))\n            {\n                return VLESSFmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.Hysteria2]) || str.StartsWith(Global.Hysteria2ProtocolShare))\n            {\n                return Hysteria2Fmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.TUIC]))\n            {\n                return TuicFmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.WireGuard]))\n            {\n                return WireguardFmt.Resolve(str, out msg);\n            }\n            else if (str.StartsWith(Global.ProtocolShares[EConfigType.Anytls]))\n            {\n                return AnytlsFmt.Resolve(str, out msg);\n            }\n            else\n            {\n                msg = ResUI.NonvmessOrssProtocol;\n                return null;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            msg = ResUI.Incorrectconfiguration;\n            return null;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/HtmlPageFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class HtmlPageFmt : BaseFmt\n{\n    public static bool IsHtmlPage(string strData)\n    {\n        return Contains(strData, \"<html\", \"<!doctype html\", \"<head\");\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/Hysteria2Fmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class Hysteria2Fmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n        ProfileItem item = new()\n        {\n            ConfigType = EConfigType.Hysteria2\n        };\n\n        var url = Utils.TryUri(str);\n        if (url == null)\n        {\n            return null;\n        }\n\n        item.Address = url.IdnHost;\n        item.Port = url.Port;\n        item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);\n        item.Password = Utils.UrlDecode(url.UserInfo);\n\n        var query = Utils.ParseQueryString(url.Query);\n        ResolveUriQuery(query, ref item);\n        if (item.CertSha.IsNullOrEmpty())\n        {\n            item.CertSha = GetQueryDecoded(query, \"pinSHA256\");\n        }\n        item.SetProtocolExtra(item.GetProtocolExtra() with\n        {\n            Ports = GetQueryDecoded(query, \"mport\"),\n            SalamanderPass = GetQueryDecoded(query, \"obfs-password\"),\n        });\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n\n        var url = string.Empty;\n\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n        var dicQuery = new Dictionary<string, string>();\n        ToUriQueryLite(item, ref dicQuery);\n        var protocolExtraItem = item.GetProtocolExtra();\n\n        if (!protocolExtraItem.SalamanderPass.IsNullOrEmpty())\n        {\n            dicQuery.Add(\"obfs\", \"salamander\");\n            dicQuery.Add(\"obfs-password\", Utils.UrlEncode(protocolExtraItem.SalamanderPass));\n        }\n        if (!protocolExtraItem.Ports.IsNullOrEmpty())\n        {\n            dicQuery.Add(\"mport\", Utils.UrlEncode(protocolExtraItem.Ports.Replace(':', '-')));\n        }\n        if (!item.CertSha.IsNullOrEmpty())\n        {\n            var sha = item.CertSha;\n            var idx = sha.IndexOf(',');\n            if (idx > 0)\n            {\n                sha = sha[..idx];\n            }\n            dicQuery.Add(\"pinSHA256\", Utils.UrlEncode(sha));\n        }\n\n        return ToUri(EConfigType.Hysteria2, item.Address, item.Port, item.Password, dicQuery, remark);\n    }\n\n    public static ProfileItem? ResolveFull2(string strData, string? subRemarks)\n    {\n        if (Contains(strData, \"server\", \"auth\", \"up\", \"down\", \"listen\"))\n        {\n            var fileName = WriteAllText(strData);\n\n            var profileItem = new ProfileItem\n            {\n                CoreType = ECoreType.hysteria2,\n                Address = fileName,\n                Remarks = subRemarks ?? \"hysteria2_custom\"\n            };\n            return profileItem;\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/ShadowsocksFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class ShadowsocksFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n        ProfileItem? item;\n\n        item = ResolveSSLegacy(str) ?? ResolveSip002(str);\n        if (item == null)\n        {\n            return null;\n        }\n\n        if (item.Address.Length == 0 || item.Port == 0 || item.GetProtocolExtra().SsMethod.IsNullOrEmpty() || item.Password.Length == 0)\n        {\n            return null;\n        }\n\n        item.ConfigType = EConfigType.Shadowsocks;\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n        //url = string.Format(\"{0}:{1}@{2}:{3}\",\n        //    item.security,\n        //    item.id,\n        //    item.address,\n        //    item.port);\n        //url = Utile.Base64Encode(url);\n        //new Sip002\n        var pw = Utils.Base64Encode($\"{item.GetProtocolExtra().SsMethod}:{item.Password}\", true);\n\n        // plugin\n        var plugin = string.Empty;\n        var pluginArgs = string.Empty;\n\n        if (item.Network == nameof(ETransport.tcp) && item.HeaderType == Global.TcpHeaderHttp)\n        {\n            plugin = \"obfs-local\";\n            pluginArgs = $\"obfs=http;obfs-host={item.RequestHost};\";\n        }\n        else\n        {\n            if (item.Network == nameof(ETransport.ws))\n            {\n                pluginArgs += \"mode=websocket;\";\n                pluginArgs += $\"host={item.RequestHost};\";\n                // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172\n                // Equal signs and commas [and backslashes] must be escaped with a backslash.\n                var path = item.Path.Replace(\"\\\\\", \"\\\\\\\\\").Replace(\"=\", \"\\\\=\").Replace(\",\", \"\\\\,\");\n                pluginArgs += $\"path={path};\";\n            }\n            else if (item.Network == nameof(ETransport.quic))\n            {\n                pluginArgs += \"mode=quic;\";\n            }\n            if (item.StreamSecurity == Global.StreamSecurity)\n            {\n                pluginArgs += \"tls;\";\n                var certs = CertPemManager.ParsePemChain(item.Cert);\n                if (certs.Count > 0)\n                {\n                    var cert = certs.First();\n                    const string beginMarker = \"-----BEGIN CERTIFICATE-----\\n\";\n                    const string endMarker = \"\\n-----END CERTIFICATE-----\";\n\n                    var base64Content = cert.Replace(beginMarker, \"\").Replace(endMarker, \"\").Trim();\n\n                    base64Content = base64Content.Replace(\"=\", \"\\\\=\");\n\n                    pluginArgs += $\"certRaw={base64Content};\";\n                }\n            }\n            if (pluginArgs.Length > 0)\n            {\n                plugin = \"v2ray-plugin\";\n                pluginArgs += \"mux=0;\";\n            }\n        }\n\n        var dicQuery = new Dictionary<string, string>();\n        if (plugin.IsNotEmpty())\n        {\n            var pluginStr = plugin + \";\" + pluginArgs;\n            // pluginStr remove last ';' and url encode\n            if (pluginStr.EndsWith(';'))\n            {\n                pluginStr = pluginStr[..^1];\n            }\n            dicQuery[\"plugin\"] = Utils.UrlEncode(pluginStr);\n        }\n\n        return ToUri(EConfigType.Shadowsocks, item.Address, item.Port, pw, dicQuery, remark);\n    }\n\n    private static readonly Regex UrlFinder = new(@\"ss://(?<base64>[A-Za-z0-9+-/=_]+)(?:#(?<tag>\\S+))?\", RegexOptions.IgnoreCase | RegexOptions.Compiled);\n    private static readonly Regex DetailsParser = new(@\"^((?<method>.+?):(?<password>.*)@(?<hostname>.+?):(?<port>\\d+?))$\", RegexOptions.IgnoreCase | RegexOptions.Compiled);\n\n    private static ProfileItem? ResolveSSLegacy(string result)\n    {\n        var match = UrlFinder.Match(result);\n        if (!match.Success)\n        {\n            return null;\n        }\n\n        ProfileItem item = new();\n        var base64 = match.Groups[\"base64\"].Value.TrimEnd('/');\n        var tag = match.Groups[\"tag\"].Value;\n        if (tag.IsNotEmpty())\n        {\n            item.Remarks = Utils.UrlDecode(tag);\n        }\n        Match details;\n        try\n        {\n            details = DetailsParser.Match(Utils.Base64Decode(base64));\n        }\n        catch (FormatException)\n        {\n            return null;\n        }\n        if (!details.Success)\n        {\n            return null;\n        }\n        item.SetProtocolExtra(item.GetProtocolExtra() with { SsMethod = details.Groups[\"method\"].Value });\n        item.Password = details.Groups[\"password\"].Value;\n        item.Address = details.Groups[\"hostname\"].Value;\n        item.Port = details.Groups[\"port\"].Value.ToInt();\n        return item;\n    }\n\n    private static ProfileItem? ResolveSip002(string result)\n    {\n        var parsedUrl = Utils.TryUri(result);\n        if (parsedUrl == null)\n        {\n            return null;\n        }\n\n        ProfileItem item = new()\n        {\n            Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),\n            Address = parsedUrl.IdnHost,\n            Port = parsedUrl.Port,\n        };\n        var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);\n        //2022-blake3\n        if (rawUserInfo.Contains(':'))\n        {\n            var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);\n            if (userInfoParts.Length != 2)\n            {\n                return null;\n            }\n            item.SetProtocolExtra(item.GetProtocolExtra() with { SsMethod = userInfoParts.First() });\n            item.Password = Utils.UrlDecode(userInfoParts.Last());\n        }\n        else\n        {\n            // parse base64 UserInfo\n            var userInfo = Utils.Base64Decode(rawUserInfo);\n            var userInfoParts = userInfo.Split(new[] { ':' }, 2);\n            if (userInfoParts.Length != 2)\n            {\n                return null;\n            }\n            item.SetProtocolExtra(item.GetProtocolExtra() with { SsMethod = userInfoParts.First() });\n            item.Password = userInfoParts.Last();\n        }\n\n        var queryParameters = Utils.ParseQueryString(parsedUrl.Query);\n        if (queryParameters[\"plugin\"] != null)\n        {\n            var pluginStr = queryParameters[\"plugin\"];\n            var pluginParts = pluginStr.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);\n\n            if (pluginParts.Length == 0)\n            {\n                return null;\n            }\n\n            var pluginName = pluginParts[0];\n\n            // A typo in https://github.com/shadowsocks/shadowsocks-org/blob/6b1c064db4129de99c516294960e731934841c94/docs/doc/sip002.md?plain=1#L15\n            // \"simple-obfs\" should be \"obfs-local\"\n            if (pluginName == \"simple-obfs\")\n            {\n                pluginName = \"obfs-local\";\n            }\n\n            // Parse obfs-local plugin\n            if (pluginName == \"obfs-local\")\n            {\n                var obfsMode = pluginParts.FirstOrDefault(t => t.StartsWith(\"obfs=\"));\n                var obfsHost = pluginParts.FirstOrDefault(t => t.StartsWith(\"obfs-host=\"));\n\n                if ((!obfsMode.IsNullOrEmpty()) && obfsMode.Contains(\"obfs=http\") && obfsHost.IsNotEmpty())\n                {\n                    obfsHost = obfsHost.Replace(\"obfs-host=\", \"\");\n                    item.Network = Global.DefaultNetwork;\n                    item.HeaderType = Global.TcpHeaderHttp;\n                    item.RequestHost = obfsHost;\n                }\n            }\n            // Parse v2ray-plugin\n            else if (pluginName == \"v2ray-plugin\")\n            {\n                var mode = pluginParts.FirstOrDefault(t => t.StartsWith(\"mode=\"), \"websocket\");\n                var host = pluginParts.FirstOrDefault(t => t.StartsWith(\"host=\"));\n                var path = pluginParts.FirstOrDefault(t => t.StartsWith(\"path=\"));\n                var hasTls = pluginParts.Any(t => t == \"tls\");\n                var certRaw = pluginParts.FirstOrDefault(t => t.StartsWith(\"certRaw=\"));\n                var mux = pluginParts.FirstOrDefault(t => t.StartsWith(\"mux=\"));\n\n                var modeValue = mode.Replace(\"mode=\", \"\");\n                if (modeValue == \"websocket\")\n                {\n                    item.Network = nameof(ETransport.ws);\n                    if (!host.IsNullOrEmpty())\n                    {\n                        item.RequestHost = host.Replace(\"host=\", \"\");\n                        item.Sni = item.RequestHost;\n                    }\n                    if (!path.IsNullOrEmpty())\n                    {\n                        var pathValue = path.Replace(\"path=\", \"\");\n                        pathValue = pathValue.Replace(\"\\\\=\", \"=\").Replace(\"\\\\,\", \",\").Replace(\"\\\\\\\\\", \"\\\\\");\n                        item.Path = pathValue;\n                    }\n                }\n                else if (modeValue == \"quic\")\n                {\n                    item.Network = nameof(ETransport.quic);\n                }\n\n                if (hasTls)\n                {\n                    item.StreamSecurity = Global.StreamSecurity;\n\n                    if (!certRaw.IsNullOrEmpty())\n                    {\n                        var certBase64 = certRaw.Replace(\"certRaw=\", \"\");\n\n                        certBase64 = certBase64.Replace(\"\\\\=\", \"=\");\n\n                        const string beginMarker = \"-----BEGIN CERTIFICATE-----\\n\";\n                        const string endMarker = \"\\n-----END CERTIFICATE-----\";\n                        var certPem = beginMarker + certBase64 + endMarker;\n                        item.Cert = certPem;\n                    }\n                }\n\n                if (!mux.IsNullOrEmpty())\n                {\n                    var muxValue = mux.Replace(\"mux=\", \"\");\n                    var muxCount = muxValue.ToInt();\n                    if (muxCount > 0)\n                    {\n                        return null;\n                    }\n                }\n            }\n        }\n        return item;\n    }\n\n    public static List<ProfileItem>? ResolveSip008(string result)\n    {\n        //SsSIP008\n        var lstSsServer = JsonUtils.Deserialize<List<SsServer>>(result);\n        if (lstSsServer?.Count <= 0)\n        {\n            var ssSIP008 = JsonUtils.Deserialize<SsSIP008>(result);\n            if (ssSIP008?.servers?.Count > 0)\n            {\n                lstSsServer = ssSIP008.servers;\n            }\n        }\n\n        if (lstSsServer?.Count > 0)\n        {\n            List<ProfileItem> lst = [];\n            foreach (var it in lstSsServer)\n            {\n                var ssItem = new ProfileItem()\n                {\n                    Remarks = it.remarks,\n                    Password = it.password,\n                    Address = it.server,\n                    Port = it.server_port.ToInt()\n                };\n                ssItem.SetProtocolExtra(new ProtocolExtraItem() { SsMethod = it.method });\n                lst.Add(ssItem);\n            }\n            return lst;\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/SingboxFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class SingboxFmt : BaseFmt\n{\n    public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks)\n    {\n        var configObjects = JsonUtils.Deserialize<object[]>(strData);\n        if (configObjects is not { Length: > 0 })\n        {\n            return null;\n        }\n\n        List<ProfileItem> lstResult = [];\n        foreach (var configObject in configObjects)\n        {\n            var objectString = JsonUtils.Serialize(configObject);\n            var profileIt = ResolveFull(objectString, subRemarks);\n            if (profileIt != null)\n            {\n                lstResult.Add(profileIt);\n            }\n        }\n        return lstResult;\n    }\n\n    public static ProfileItem? ResolveFull(string strData, string? subRemarks)\n    {\n        var config = JsonUtils.ParseJson(strData);\n        if (config?[\"inbounds\"] == null\n            || config[\"outbounds\"] == null\n            || config[\"route\"] == null\n            || config[\"dns\"] == null)\n        {\n            return null;\n        }\n\n        var fileName = WriteAllText(strData);\n        var profileItem = new ProfileItem\n        {\n            CoreType = ECoreType.sing_box,\n            Address = fileName,\n            Remarks = subRemarks ?? \"singbox_custom\"\n        };\n\n        return profileItem;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/SocksFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class SocksFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n\n        var item = ResolveSocksNew(str) ?? ResolveSocks(str);\n        if (item == null)\n        {\n            return null;\n        }\n        if (item.Address.Length == 0 || item.Port == 0)\n        {\n            return null;\n        }\n\n        item.ConfigType = EConfigType.SOCKS;\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n        //new\n        var pw = Utils.Base64Encode($\"{item.Username}:{item.Password}\", true);\n        return ToUri(EConfigType.SOCKS, item.Address, item.Port, pw, null, remark);\n    }\n\n    private static ProfileItem? ResolveSocks(string result)\n    {\n        ProfileItem item = new()\n        {\n            ConfigType = EConfigType.SOCKS\n        };\n        result = result[Global.ProtocolShares[EConfigType.SOCKS].Length..];\n        //remark\n        var indexRemark = result.IndexOf('#');\n        if (indexRemark > 0)\n        {\n            try\n            {\n                item.Remarks = Utils.UrlDecode(result.Substring(indexRemark + 1));\n            }\n            catch { }\n            result = result[..indexRemark];\n        }\n        //part decode\n        var indexS = result.IndexOf('@');\n        if (indexS > 0)\n        {\n        }\n        else\n        {\n            result = Utils.Base64Decode(result);\n        }\n\n        var arr1 = result.Split('@');\n        if (arr1.Length != 2)\n        {\n            return null;\n        }\n        var arr21 = arr1.First().Split(':');\n        var indexPort = arr1.Last().LastIndexOf(\":\");\n        if (arr21.Length != 2 || indexPort < 0)\n        {\n            return null;\n        }\n        item.Address = arr1[1][..indexPort];\n        item.Port = arr1[1][(indexPort + 1)..].ToInt();\n        item.Username = arr21.First();\n        item.Password = arr21[1];\n        return item;\n    }\n\n    private static ProfileItem? ResolveSocksNew(string result)\n    {\n        var parsedUrl = Utils.TryUri(result);\n        if (parsedUrl == null)\n        {\n            return null;\n        }\n\n        ProfileItem item = new()\n        {\n            Remarks = parsedUrl.GetComponents(UriComponents.Fragment, UriFormat.Unescaped),\n            Address = parsedUrl.IdnHost,\n            Port = parsedUrl.Port,\n        };\n        // parse base64 UserInfo\n        var rawUserInfo = Utils.UrlDecode(parsedUrl.UserInfo);\n        var userInfo = Utils.Base64Decode(rawUserInfo);\n        var userInfoParts = userInfo.Split([':'], 2);\n        if (userInfoParts.Length == 2)\n        {\n            item.Username = userInfoParts.First();\n            item.Password = userInfoParts[1];\n        }\n\n        return item;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/TrojanFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class TrojanFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n\n        ProfileItem item = new()\n        {\n            ConfigType = EConfigType.Trojan\n        };\n\n        var url = Utils.TryUri(str);\n        if (url == null)\n        {\n            return null;\n        }\n\n        item.Address = url.IdnHost;\n        item.Port = url.Port;\n        item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);\n        item.Password = Utils.UrlDecode(url.UserInfo);\n\n        var query = Utils.ParseQueryString(url.Query);\n        item.SetProtocolExtra(item.GetProtocolExtra() with { Flow = GetQueryValue(query, \"flow\") });\n        ResolveUriQuery(query, ref item);\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n        var dicQuery = new Dictionary<string, string>();\n        if (!item.GetProtocolExtra().Flow.IsNullOrEmpty())\n        {\n            dicQuery.Add(\"flow\", item.GetProtocolExtra().Flow);\n        }\n        ToUriQuery(item, null, ref dicQuery);\n\n        return ToUri(EConfigType.Trojan, item.Address, item.Port, item.Password, dicQuery, remark);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/TuicFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class TuicFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n\n        ProfileItem item = new()\n        {\n            ConfigType = EConfigType.TUIC\n        };\n\n        var url = Utils.TryUri(str);\n        if (url == null)\n        {\n            return null;\n        }\n\n        item.Address = url.IdnHost;\n        item.Port = url.Port;\n        item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);\n        var rawUserInfo = Utils.UrlDecode(url.UserInfo);\n        var userInfoParts = rawUserInfo.Split(new[] { ':' }, 2);\n        if (userInfoParts.Length == 2)\n        {\n            item.Username = userInfoParts.First();\n            item.Password = userInfoParts.Last();\n        }\n\n        var query = Utils.ParseQueryString(url.Query);\n        ResolveUriQuery(query, ref item);\n        item.HeaderType = GetQueryValue(query, \"congestion_control\");\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n\n        var dicQuery = new Dictionary<string, string>();\n        ToUriQueryLite(item, ref dicQuery);\n\n        dicQuery.Add(\"congestion_control\", item.HeaderType);\n\n        return ToUri(EConfigType.TUIC, item.Address, item.Port, $\"{item.Username ?? \"\"}:{item.Password}\", dicQuery, remark);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/V2rayFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class V2rayFmt : BaseFmt\n{\n    public static List<ProfileItem>? ResolveFullArray(string strData, string? subRemarks)\n    {\n        var configObjects = JsonUtils.Deserialize<object[]>(strData);\n        if (configObjects is not { Length: > 0 })\n        {\n            return null;\n        }\n\n        List<ProfileItem> lstResult = [];\n        foreach (var configObject in configObjects)\n        {\n            var objectString = JsonUtils.Serialize(configObject);\n            var profileIt = ResolveFull(objectString, subRemarks);\n            if (profileIt != null)\n            {\n                lstResult.Add(profileIt);\n            }\n        }\n\n        return lstResult;\n    }\n\n    public static ProfileItem? ResolveFull(string strData, string? subRemarks)\n    {\n        var config = JsonUtils.ParseJson(strData);\n        if (config?[\"inbounds\"] == null\n            || config[\"outbounds\"] == null\n            || config[\"routing\"] == null)\n        {\n            return null;\n        }\n\n        var fileName = WriteAllText(strData);\n\n        var profileItem = new ProfileItem\n        {\n            CoreType = ECoreType.Xray,\n            Address = fileName,\n            Remarks = config?[\"remarks\"]?.ToString() ?? subRemarks ?? \"v2ray_custom\"\n        };\n\n        return profileItem;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/VLESSFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class VLESSFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n\n        ProfileItem item = new()\n        {\n            ConfigType = EConfigType.VLESS,\n        };\n\n        var url = Utils.TryUri(str);\n        if (url == null)\n        {\n            return null;\n        }\n\n        item.Address = url.IdnHost;\n        item.Port = url.Port;\n        item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);\n        item.Password = Utils.UrlDecode(url.UserInfo);\n\n        var query = Utils.ParseQueryString(url.Query);\n        item.SetProtocolExtra(item.GetProtocolExtra() with\n        {\n            VlessEncryption = GetQueryValue(query, \"encryption\", Global.None),\n            Flow = GetQueryValue(query, \"flow\")\n        });\n        item.StreamSecurity = GetQueryValue(query, \"security\");\n        ResolveUriQuery(query, ref item);\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n        var dicQuery = new Dictionary<string, string>();\n        dicQuery.Add(\"encryption\",\n            !item.GetProtocolExtra().VlessEncryption.IsNullOrEmpty() ? item.GetProtocolExtra().VlessEncryption : Global.None);\n        if (!item.GetProtocolExtra().Flow.IsNullOrEmpty())\n        {\n            dicQuery.Add(\"flow\", item.GetProtocolExtra().Flow);\n        }\n        ToUriQuery(item, Global.None, ref dicQuery);\n\n        return ToUri(EConfigType.VLESS, item.Address, item.Port, item.Password, dicQuery, remark);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/VmessFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class VmessFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n        ProfileItem? item;\n        if (str.IndexOf('@') > 0)\n        {\n            item = ResolveStdVmess(str) ?? ResolveVmess(str, out msg);\n        }\n        else\n        {\n            item = ResolveVmess(str, out msg);\n        }\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n\n        var vmessQRCode = new VmessQRCode\n        {\n            v = 2,\n            ps = item.Remarks.TrimEx(),\n            add = item.Address,\n            port = item.Port,\n            id = item.Password,\n            aid = int.TryParse(item.GetProtocolExtra()?.AlterId, out var result) ? result : 0,\n            scy = item.GetProtocolExtra().VmessSecurity ?? \"\",\n            net = item.Network,\n            type = item.HeaderType,\n            host = item.RequestHost,\n            path = item.Path,\n            tls = item.StreamSecurity,\n            sni = item.Sni,\n            alpn = item.Alpn,\n            fp = item.Fingerprint,\n            insecure = item.AllowInsecure.Equals(Global.AllowInsecure.First()) ? \"1\" : \"0\"\n        };\n\n        var url = JsonUtils.Serialize(vmessQRCode);\n        url = Utils.Base64Encode(url);\n        url = $\"{Global.ProtocolShares[EConfigType.VMess]}{url}\";\n\n        return url;\n    }\n\n    private static ProfileItem? ResolveVmess(string result, out string msg)\n    {\n        msg = string.Empty;\n        var item = new ProfileItem\n        {\n            ConfigType = EConfigType.VMess\n        };\n\n        result = result[Global.ProtocolShares[EConfigType.VMess].Length..];\n        result = Utils.Base64Decode(result);\n\n        var vmessQRCode = JsonUtils.Deserialize<VmessQRCode>(result);\n        if (vmessQRCode == null)\n        {\n            msg = ResUI.FailedConversionConfiguration;\n            return null;\n        }\n\n        item.Network = Global.DefaultNetwork;\n        item.HeaderType = Global.None;\n\n        //item.ConfigVersion = vmessQRCode.v;\n        item.Remarks = Utils.ToString(vmessQRCode.ps);\n        item.Address = Utils.ToString(vmessQRCode.add);\n        item.Port = vmessQRCode.port;\n        item.Password = Utils.ToString(vmessQRCode.id);\n        item.SetProtocolExtra(new ProtocolExtraItem\n        {\n            AlterId = vmessQRCode.aid.ToString(),\n            VmessSecurity = vmessQRCode.scy.IsNullOrEmpty() ? Global.DefaultSecurity : vmessQRCode.scy,\n        });\n        if (vmessQRCode.net.IsNotEmpty())\n        {\n            item.Network = vmessQRCode.net;\n        }\n        if (vmessQRCode.type.IsNotEmpty())\n        {\n            item.HeaderType = vmessQRCode.type;\n        }\n\n        item.RequestHost = Utils.ToString(vmessQRCode.host);\n        item.Path = Utils.ToString(vmessQRCode.path);\n        item.StreamSecurity = Utils.ToString(vmessQRCode.tls);\n        item.Sni = Utils.ToString(vmessQRCode.sni);\n        item.Alpn = Utils.ToString(vmessQRCode.alpn);\n        item.Fingerprint = Utils.ToString(vmessQRCode.fp);\n        item.AllowInsecure = vmessQRCode.insecure == \"1\" ? Global.AllowInsecure.First() : string.Empty;\n\n        return item;\n    }\n\n    public static ProfileItem? ResolveStdVmess(string str)\n    {\n        var item = new ProfileItem\n        {\n            ConfigType = EConfigType.VMess,\n        };\n\n        var url = Utils.TryUri(str);\n        if (url == null)\n        {\n            return null;\n        }\n\n        item.Address = url.IdnHost;\n        item.Port = url.Port;\n        item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);\n        item.Password = Utils.UrlDecode(url.UserInfo);\n\n        item.SetProtocolExtra(new ProtocolExtraItem\n        {\n            VmessSecurity = \"auto\",\n        });\n\n        var query = Utils.ParseQueryString(url.Query);\n        ResolveUriQuery(query, ref item);\n\n        return item;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/Fmt/WireguardFmt.cs",
    "content": "namespace ServiceLib.Handler.Fmt;\n\npublic class WireguardFmt : BaseFmt\n{\n    public static ProfileItem? Resolve(string str, out string msg)\n    {\n        msg = ResUI.ConfigurationFormatIncorrect;\n\n        ProfileItem item = new()\n        {\n            ConfigType = EConfigType.WireGuard\n        };\n\n        var url = Utils.TryUri(str);\n        if (url == null)\n        {\n            return null;\n        }\n\n        item.Address = url.IdnHost;\n        item.Port = url.Port;\n        item.Remarks = url.GetComponents(UriComponents.Fragment, UriFormat.Unescaped);\n        item.Password = Utils.UrlDecode(url.UserInfo);\n\n        var query = Utils.ParseQueryString(url.Query);\n\n        item.SetProtocolExtra(item.GetProtocolExtra() with\n        {\n            WgPublicKey = GetQueryDecoded(query, \"publickey\"),\n            WgReserved = GetQueryDecoded(query, \"reserved\"),\n            WgInterfaceAddress = GetQueryDecoded(query, \"address\"),\n            WgMtu = int.TryParse(GetQueryDecoded(query, \"mtu\"), out var mtuVal) ? mtuVal : 1280,\n        });\n\n        return item;\n    }\n\n    public static string? ToUri(ProfileItem? item)\n    {\n        if (item == null)\n        {\n            return null;\n        }\n\n        var remark = string.Empty;\n        if (item.Remarks.IsNotEmpty())\n        {\n            remark = \"#\" + Utils.UrlEncode(item.Remarks);\n        }\n\n        var dicQuery = new Dictionary<string, string>();\n        if (!item.GetProtocolExtra().WgPublicKey.IsNullOrEmpty())\n        {\n            dicQuery.Add(\"publickey\", Utils.UrlEncode(item.GetProtocolExtra().WgPublicKey));\n        }\n        if (!item.GetProtocolExtra().WgReserved.IsNullOrEmpty())\n        {\n            dicQuery.Add(\"reserved\", Utils.UrlEncode(item.GetProtocolExtra().WgReserved));\n        }\n        if (!item.GetProtocolExtra().WgInterfaceAddress.IsNullOrEmpty())\n        {\n            dicQuery.Add(\"address\", Utils.UrlEncode(item.GetProtocolExtra().WgInterfaceAddress));\n        }\n        dicQuery.Add(\"mtu\", Utils.UrlEncode(item.GetProtocolExtra().WgMtu > 0 ? item.GetProtocolExtra().WgMtu.ToString() : \"1280\"));\n        return ToUri(EConfigType.WireGuard, item.Address, item.Port, item.Password, dicQuery, remark);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/SubscriptionHandler.cs",
    "content": "namespace ServiceLib.Handler;\n\npublic static class SubscriptionHandler\n{\n    public static async Task UpdateProcess(Config config, string subId, bool blProxy, Func<bool, string, Task> updateFunc)\n    {\n        await updateFunc?.Invoke(false, ResUI.MsgUpdateSubscriptionStart);\n        var subItem = await AppManager.Instance.SubItems();\n\n        if (subItem is not { Count: > 0 })\n        {\n            await updateFunc?.Invoke(false, ResUI.MsgNoValidSubscription);\n            return;\n        }\n\n        var successCount = 0;\n        foreach (var item in subItem)\n        {\n            try\n            {\n                if (!IsValidSubscription(item, subId))\n                {\n                    continue;\n                }\n\n                var hashCode = $\"{item.Remarks}->\";\n                if (item.Enabled == false)\n                {\n                    await updateFunc?.Invoke(false, $\"{hashCode}{ResUI.MsgSkipSubscriptionUpdate}\");\n                    continue;\n                }\n\n                // Create download handler\n                var downloadHandle = CreateDownloadHandler(hashCode, updateFunc);\n                await updateFunc?.Invoke(false, $\"{hashCode}{ResUI.MsgStartGettingSubscriptions}\");\n\n                // Get all subscription content (main subscription + additional subscriptions)\n                var result = await DownloadAllSubscriptions(config, item, blProxy, downloadHandle);\n\n                // Process download result\n                if (await ProcessDownloadResult(config, item.Id, result, hashCode, updateFunc))\n                {\n                    successCount++;\n                }\n\n                await updateFunc?.Invoke(false, \"-------------------------------------------------------\");\n            }\n            catch (Exception ex)\n            {\n                var hashCode = $\"{item.Remarks}->\";\n                Logging.SaveLog(\"UpdateSubscription\", ex);\n                await updateFunc?.Invoke(false, $\"{hashCode}{ResUI.MsgFailedImportSubscription}: {ex.Message}\");\n                await updateFunc?.Invoke(false, \"-------------------------------------------------------\");\n            }\n        }\n\n        await updateFunc?.Invoke(successCount > 0, $\"{ResUI.MsgUpdateSubscriptionEnd}\");\n    }\n\n    private static bool IsValidSubscription(SubItem item, string subId)\n    {\n        var id = item.Id.TrimEx();\n        var url = item.Url.TrimEx();\n\n        if (id.IsNullOrEmpty() || url.IsNullOrEmpty())\n        {\n            return false;\n        }\n\n        if (subId.IsNotEmpty() && item.Id != subId)\n        {\n            return false;\n        }\n\n        if (!url.StartsWith(Global.HttpsProtocol) && !url.StartsWith(Global.HttpProtocol))\n        {\n            return false;\n        }\n\n        return true;\n    }\n\n    private static DownloadService CreateDownloadHandler(string hashCode, Func<bool, string, Task> updateFunc)\n    {\n        var downloadHandle = new DownloadService();\n        downloadHandle.Error += (sender2, args) =>\n        {\n            updateFunc?.Invoke(false, $\"{hashCode}{args.GetException().Message}\");\n        };\n        return downloadHandle;\n    }\n\n    private static async Task<string> DownloadSubscriptionContent(DownloadService downloadHandle, string url, bool blProxy, string userAgent)\n    {\n        var result = await downloadHandle.TryDownloadString(url, blProxy, userAgent);\n\n        // If download with proxy fails, try direct connection\n        if (blProxy && result.IsNullOrEmpty())\n        {\n            result = await downloadHandle.TryDownloadString(url, false, userAgent);\n        }\n\n        return result ?? string.Empty;\n    }\n\n    private static async Task<string> DownloadAllSubscriptions(Config config, SubItem item, bool blProxy, DownloadService downloadHandle)\n    {\n        // Download main subscription content\n        var result = await DownloadMainSubscription(config, item, blProxy, downloadHandle);\n\n        // Process additional subscription links (if any)\n        if (item.ConvertTarget.IsNullOrEmpty() && item.MoreUrl.TrimEx().IsNotEmpty())\n        {\n            result = await DownloadAdditionalSubscriptions(item, result, blProxy, downloadHandle);\n        }\n\n        return result;\n    }\n\n    private static async Task<string> DownloadMainSubscription(Config config, SubItem item, bool blProxy, DownloadService downloadHandle)\n    {\n        // Prepare subscription URL and download directly\n        var url = Utils.GetPunycode(item.Url.TrimEx());\n\n        // If conversion is needed\n        if (item.ConvertTarget.IsNotEmpty())\n        {\n            var subConvertUrl = config.ConstItem.SubConvertUrl.IsNullOrEmpty()\n                ? Global.SubConvertUrls.FirstOrDefault()\n                : config.ConstItem.SubConvertUrl;\n\n            url = string.Format(subConvertUrl!, Utils.UrlEncode(url));\n\n            if (!url.Contains(\"target=\"))\n            {\n                url += string.Format(\"&target={0}\", item.ConvertTarget);\n            }\n\n            if (!url.Contains(\"config=\"))\n            {\n                url += string.Format(\"&config={0}\", Global.SubConvertConfig.FirstOrDefault());\n            }\n        }\n\n        // Download and return result directly\n        return await DownloadSubscriptionContent(downloadHandle, url, blProxy, item.UserAgent);\n    }\n\n    private static async Task<string> DownloadAdditionalSubscriptions(SubItem item, string mainResult, bool blProxy, DownloadService downloadHandle)\n    {\n        var result = mainResult;\n\n        // If main subscription result is Base64 encoded, decode it first\n        if (result.IsNotEmpty() && Utils.IsBase64String(result))\n        {\n            result = Utils.Base64Decode(result);\n        }\n\n        // Process additional URL list\n        var lstUrl = item.MoreUrl.TrimEx().Split(\",\") ?? [];\n        foreach (var it in lstUrl)\n        {\n            var url2 = Utils.GetPunycode(it);\n            if (url2.IsNullOrEmpty())\n            {\n                continue;\n            }\n\n            var additionalResult = await DownloadSubscriptionContent(downloadHandle, url2, blProxy, item.UserAgent);\n\n            if (additionalResult.IsNotEmpty())\n            {\n                // Process additional subscription results, add to main result\n                if (Utils.IsBase64String(additionalResult))\n                {\n                    result += Environment.NewLine + Utils.Base64Decode(additionalResult);\n                }\n                else\n                {\n                    result += Environment.NewLine + additionalResult;\n                }\n            }\n        }\n\n        return result;\n    }\n\n    private static async Task<bool> ProcessDownloadResult(Config config, string id, string result, string hashCode, Func<bool, string, Task> updateFunc)\n    {\n        if (result.IsNullOrEmpty())\n        {\n            await updateFunc?.Invoke(false, $\"{hashCode}{ResUI.MsgSubscriptionDecodingFailed}\");\n            return false;\n        }\n\n        await updateFunc?.Invoke(false, $\"{hashCode}{ResUI.MsgGetSubscriptionSuccessfully}\");\n\n        // If result is too short, display content directly\n        if (result.Length < 99)\n        {\n            await updateFunc?.Invoke(false, $\"{hashCode}{result}\");\n        }\n\n        await updateFunc?.Invoke(false, $\"{hashCode}{ResUI.MsgStartParsingSubscription}\");\n\n        // Add servers to configuration\n        var ret = await ConfigHandler.AddBatchServers(config, result, id, true);\n        if (ret <= 0)\n        {\n            Logging.SaveLog(\"FailedImportSubscription\");\n            Logging.SaveLog(result);\n        }\n\n        // Update completion message\n        await updateFunc?.Invoke(false, ret > 0\n                ? $\"{hashCode}{ResUI.MsgUpdateSubscriptionEnd}\"\n                : $\"{hashCode}{ResUI.MsgFailedImportSubscription}\");\n\n        return ret > 0;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/SysProxy/ProxySettingLinux.cs",
    "content": "namespace ServiceLib.Handler.SysProxy;\n\npublic static class ProxySettingLinux\n{\n    private static readonly string _proxySetFileName = $\"{Global.ProxySetLinuxShellFileName.Replace(Global.NamespaceSample, \"\")}.sh\";\n\n    public static async Task SetProxy(string host, int port, string exceptions)\n    {\n        List<string> args = [\"manual\", host, port.ToString(), exceptions];\n        await ExecCmd(args);\n    }\n\n    public static async Task UnsetProxy()\n    {\n        List<string> args = [\"none\"];\n        await ExecCmd(args);\n    }\n\n    private static async Task ExecCmd(List<string> args)\n    {\n        var customSystemProxyScriptPath = AppManager.Instance.Config.SystemProxyItem?.CustomSystemProxyScriptPath;\n        var fileName = (customSystemProxyScriptPath.IsNotEmpty() && File.Exists(customSystemProxyScriptPath))\n            ? customSystemProxyScriptPath\n            : await FileUtils.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false);\n\n        // TODO: temporarily notify which script is being used\n        NoticeManager.Instance.SendMessage(fileName);\n\n        await Utils.GetCliWrapOutput(fileName, args);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs",
    "content": "namespace ServiceLib.Handler.SysProxy;\n\npublic static class ProxySettingOSX\n{\n    private static readonly string _proxySetFileName = $\"{Global.ProxySetOSXShellFileName.Replace(Global.NamespaceSample, \"\")}.sh\";\n\n    public static async Task SetProxy(string host, int port, string exceptions)\n    {\n        List<string> args = [\"set\", host, port.ToString()];\n        if (exceptions.IsNotEmpty())\n        {\n            args.AddRange(exceptions.Split(','));\n        }\n\n        await ExecCmd(args);\n    }\n\n    public static async Task UnsetProxy()\n    {\n        List<string> args = [\"clear\"];\n        await ExecCmd(args);\n    }\n\n    private static async Task ExecCmd(List<string> args)\n    {\n        var customSystemProxyScriptPath = AppManager.Instance.Config.SystemProxyItem?.CustomSystemProxyScriptPath;\n        var fileName = (customSystemProxyScriptPath.IsNotEmpty() && File.Exists(customSystemProxyScriptPath))\n            ? customSystemProxyScriptPath\n            : await FileUtils.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false);\n\n        // TODO: temporarily notify which script is being used\n        NoticeManager.Instance.SendMessage(fileName);\n\n        await Utils.GetCliWrapOutput(fileName, args);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/SysProxy/ProxySettingWindows.cs",
    "content": "using static ServiceLib.Handler.SysProxy.ProxySettingWindows.InternetConnectionOption;\n\nnamespace ServiceLib.Handler.SysProxy;\n\npublic static class ProxySettingWindows\n{\n    private const string _regPath = @\"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\";\n\n    private static bool SetProxyFallback(string? strProxy, string? exceptions, int type)\n    {\n        if (type == 1)\n        {\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyEnable\", 0);\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyServer\", string.Empty);\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyOverride\", string.Empty);\n            WindowsUtils.RegWriteValue(_regPath, \"AutoConfigURL\", string.Empty);\n        }\n        if (type == 2)\n        {\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyEnable\", 1);\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyServer\", strProxy ?? string.Empty);\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyOverride\", exceptions ?? string.Empty);\n            WindowsUtils.RegWriteValue(_regPath, \"AutoConfigURL\", string.Empty);\n        }\n        else if (type == 4)\n        {\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyEnable\", 0);\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyServer\", string.Empty);\n            WindowsUtils.RegWriteValue(_regPath, \"ProxyOverride\", string.Empty);\n            WindowsUtils.RegWriteValue(_regPath, \"AutoConfigURL\", strProxy ?? string.Empty);\n        }\n        return true;\n    }\n\n    /// <summary>\n    // set to use no proxy\n    /// </summary>\n    /// <exception cref=\"ApplicationException\">Error message with win32 error code</exception>\n    public static bool UnsetProxy()\n    {\n        return SetProxy(null, null, 1);\n    }\n\n    /// <summary>\n    /// Set system proxy settings\n    /// </summary>\n    /// <param name=\"strProxy\"> proxy address</param>\n    /// <param name=\"exceptions\">exception addresses that do not use proxy</param>\n    /// <param name=\"type\">type of proxy defined in PerConnFlags\n    ///     PROXY_TYPE_DIRECT           = 0x00000001, // direct connection (no proxy)\n    ///     PROXY_TYPE_PROXY            = 0x00000002, // via named proxy\n    ///     PROXY_TYPE_AUTO_PROXY_URL   = 0x00000004, // autoproxy script URL\n    ///     PROXY_TYPE_AUTO_DETECT      = 0x00000008  // use autoproxy detection\n    /// </param>\n    /// <exception cref=\"ApplicationException\">Error message with win32 error code</exception>\n    /// <returns>true: one of connection is successfully updated proxy settings</returns>\n    public static bool SetProxy(string? strProxy, string? exceptions, int type)\n    {\n        try\n        {\n            // set proxy for LAN\n            var result = SetConnectionProxy(null, strProxy, exceptions, type);\n            // set proxy for dial up connections\n            var connections = EnumerateRasEntries();\n            foreach (var connection in connections)\n            {\n                result |= SetConnectionProxy(connection, strProxy, exceptions, type);\n            }\n            return result;\n        }\n        catch\n        {\n            _ = SetProxyFallback(strProxy, exceptions, type);\n            return false;\n        }\n    }\n\n    private static bool SetConnectionProxy(string? connectionName, string? strProxy, string? exceptions, int type)\n    {\n        var list = new InternetPerConnOptionList();\n\n        var optionCount = 1;\n        if (type == 1) // No proxy\n        {\n            optionCount = 1;\n        }\n        else if (type is 2 or 4) // named proxy or autoproxy script URL\n        {\n            optionCount = exceptions.IsNullOrEmpty() ? 2 : 3;\n        }\n\n        var m_Int = (int)PerConnFlags.PROXY_TYPE_DIRECT;\n        var m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS;\n        if (type == 2) // named proxy\n        {\n            m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_PROXY);\n            m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_SERVER;\n        }\n        else if (type == 4) // autoproxy script url\n        {\n            m_Int = (int)(PerConnFlags.PROXY_TYPE_DIRECT | PerConnFlags.PROXY_TYPE_AUTO_PROXY_URL);\n            m_Option = PerConnOption.INTERNET_PER_CONN_AUTOCONFIG_URL;\n        }\n\n        var options = new InternetConnectionOption[optionCount];\n        // USE a proxy server ...\n        options[0].m_Option = PerConnOption.INTERNET_PER_CONN_FLAGS;\n        options[0].m_Value.m_Int = m_Int;\n        // use THIS proxy server\n        if (optionCount > 1)\n        {\n            options[1].m_Option = m_Option;\n            options[1].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(strProxy); // !! remember to deallocate memory 1\n                                                                                    // except for these addresses ...\n            if (optionCount > 2)\n            {\n                options[2].m_Option = PerConnOption.INTERNET_PER_CONN_PROXY_BYPASS;\n                options[2].m_Value.m_StringPtr = Marshal.StringToHGlobalAuto(exceptions); // !! remember to deallocate memory 2\n            }\n        }\n\n        // default stuff\n        list.dwSize = Marshal.SizeOf(list);\n        if (connectionName != null)\n        {\n            list.szConnection = Marshal.StringToHGlobalAuto(connectionName); // !! remember to deallocate memory 3\n        }\n        else\n        {\n            list.szConnection = nint.Zero;\n        }\n        list.dwOptionCount = options.Length;\n        list.dwOptionError = 0;\n\n        var optSize = Marshal.SizeOf(typeof(InternetConnectionOption));\n        // make a pointer out of all that ...\n        var optionsPtr = Marshal.AllocCoTaskMem(optSize * options.Length); // !! remember to deallocate memory 4\n                                                                           // copy the array over into that spot in memory ...\n        for (var i = 0; i < options.Length; ++i)\n        {\n            if (Environment.Is64BitOperatingSystem)\n            {\n                var opt = new nint(optionsPtr.ToInt64() + (i * optSize));\n                Marshal.StructureToPtr(options[i], opt, false);\n            }\n            else\n            {\n                var opt = new nint(optionsPtr.ToInt32() + (i * optSize));\n                Marshal.StructureToPtr(options[i], opt, false);\n            }\n        }\n\n        list.options = optionsPtr;\n\n        // and then make a pointer out of the whole list\n        var ipcoListPtr = Marshal.AllocCoTaskMem(list.dwSize); // !! remember to deallocate memory 5\n        Marshal.StructureToPtr(list, ipcoListPtr, false);\n\n        // and finally, call the API method!\n        var isSuccess = NativeMethods.InternetSetOption(nint.Zero,\n           InternetOption.INTERNET_OPTION_PER_CONNECTION_OPTION,\n           ipcoListPtr, list.dwSize);\n        var returnvalue = 0; // ERROR_SUCCESS\n        if (!isSuccess)\n        {  // get the error codes, they might be helpful\n            returnvalue = Marshal.GetLastPInvokeError();\n        }\n        else\n        {\n            // Notify the system that the registry settings have been changed and cause them to be refreshed\n            _ = NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_SETTINGS_CHANGED, nint.Zero, 0);\n            _ = NativeMethods.InternetSetOption(nint.Zero, InternetOption.INTERNET_OPTION_REFRESH, nint.Zero, 0);\n        }\n\n        // FREE the data ASAP\n        if (list.szConnection != nint.Zero)\n        {\n            Marshal.FreeHGlobal(list.szConnection); // release mem 3\n        }\n        if (optionCount > 1)\n        {\n            Marshal.FreeHGlobal(options[1].m_Value.m_StringPtr); // release mem 1\n            if (optionCount > 2)\n            {\n                Marshal.FreeHGlobal(options[2].m_Value.m_StringPtr); // release mem 2\n            }\n        }\n        Marshal.FreeCoTaskMem(optionsPtr); // release mem 4\n        Marshal.FreeCoTaskMem(ipcoListPtr); // release mem 5\n        if (returnvalue != 0)\n        {\n            // throw the error codes, they might be helpful\n            throw new ApplicationException($\"Set Internet Proxy failed with error code: {Marshal.GetLastWin32Error()}\");\n        }\n\n        return true;\n    }\n\n    /// <summary>\n    /// Retrieve list of connections including LAN and WAN to support PPPoE connection\n    /// </summary>\n    /// <returns>A list of RAS connection names. May be empty list if no dial up connection.</returns>\n    /// <exception cref=\"ApplicationException\">Error message with win32 error code</exception>\n    private static IEnumerable<string> EnumerateRasEntries()\n    {\n        var entries = 0;\n        // attempt to query with 1 entry buffer\n        var rasEntryNames = new RASENTRYNAME[1];\n        var bufferSize = Marshal.SizeOf(typeof(RASENTRYNAME));\n        rasEntryNames[0].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME));\n\n        var result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries);\n        // increase buffer if the buffer is not large enough\n        if (result == (uint)ErrorCode.ERROR_BUFFER_TOO_SMALL)\n        {\n            rasEntryNames = new RASENTRYNAME[bufferSize / Marshal.SizeOf(typeof(RASENTRYNAME))];\n            for (var i = 0; i < rasEntryNames.Length; i++)\n            {\n                rasEntryNames[i].dwSize = Marshal.SizeOf(typeof(RASENTRYNAME));\n            }\n\n            result = NativeMethods.RasEnumEntries(null, null, rasEntryNames, ref bufferSize, ref entries);\n        }\n        if (result == 0)\n        {\n            var entryNames = new List<string>();\n            for (var i = 0; i < entries; i++)\n            {\n                entryNames.Add(rasEntryNames[i].szEntryName);\n            }\n\n            return entryNames;\n        }\n        throw new ApplicationException($\"RasEnumEntries failed with error code: {result}\");\n    }\n\n    #region WinInet structures\n\n    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]\n    public struct InternetPerConnOptionList\n    {\n        public int dwSize;               // size of the INTERNET_PER_CONN_OPTION_LIST struct\n        public nint szConnection;         // connection name to set/query options\n        public int dwOptionCount;        // number of options to set/query\n        public int dwOptionError;           // on error, which option failed\n\n        //[MarshalAs(UnmanagedType.)]\n        public nint options;\n    }\n\n    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]\n    public struct InternetConnectionOption\n    {\n        private static readonly int Size;\n        public PerConnOption m_Option;\n        public InternetConnectionOptionValue m_Value;\n\n        static InternetConnectionOption()\n        {\n            Size = Marshal.SizeOf(typeof(InternetConnectionOption));\n        }\n\n        // Nested Types\n        [StructLayout(LayoutKind.Explicit)]\n        public struct InternetConnectionOptionValue\n        {\n            // Fields\n            [FieldOffset(0)]\n            public System.Runtime.InteropServices.ComTypes.FILETIME m_FileTime;\n\n            [FieldOffset(0)]\n            public int m_Int;\n\n            [FieldOffset(0)]\n            public nint m_StringPtr;\n        }\n\n        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]\n        public struct RASENTRYNAME\n        {\n            public int dwSize;\n\n            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = RAS_MaxEntryName + 1)]\n            public string szEntryName;\n\n            public int dwFlags;\n\n            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 1)]\n            public string szPhonebookPath;\n        }\n\n        // Constants\n        public const int RAS_MaxEntryName = 256;\n\n        public const int MAX_PATH = 260; // Standard MAX_PATH value in Windows\n    }\n\n    #endregion WinInet structures\n\n    #region WinInet enums\n\n    //\n    // options manifests for Internet{Query|Set}Option\n    //\n    public enum InternetOption : uint\n    {\n        INTERNET_OPTION_PER_CONNECTION_OPTION = 75,\n        INTERNET_OPTION_REFRESH = 37,\n        INTERNET_OPTION_SETTINGS_CHANGED = 39\n    }\n\n    //\n    // Options used in INTERNET_PER_CONN_OPTON struct\n    //\n    public enum PerConnOption\n    {\n        INTERNET_PER_CONN_FLAGS = 1, // Sets or retrieves the connection type. The Value member will contain one or more of the values from PerConnFlags\n        INTERNET_PER_CONN_PROXY_SERVER = 2, // Sets or retrieves a string containing the proxy servers.\n        INTERNET_PER_CONN_PROXY_BYPASS = 3, // Sets or retrieves a string containing the URLs that do not use the proxy server.\n        INTERNET_PER_CONN_AUTOCONFIG_URL = 4//, // Sets or retrieves a string containing the URL to the automatic configuration script.\n    }\n\n    //\n    // PER_CONN_FLAGS\n    //\n    [Flags]\n    public enum PerConnFlags\n    {\n        PROXY_TYPE_DIRECT = 0x00000001,  // direct to net\n        PROXY_TYPE_PROXY = 0x00000002,  // via named proxy\n        PROXY_TYPE_AUTO_PROXY_URL = 0x00000004,  // autoproxy URL\n        PROXY_TYPE_AUTO_DETECT = 0x00000008   // use autoproxy detection\n    }\n\n    public enum ErrorCode : uint\n    {\n        ERROR_BUFFER_TOO_SMALL = 603,\n        ERROR_INVALID_SIZE = 632\n    }\n\n    #endregion WinInet enums\n\n    internal static class NativeMethods\n    {\n        [DllImport(\"WinInet.dll\", SetLastError = true, CharSet = CharSet.Auto)]\n        [return: MarshalAs(UnmanagedType.Bool)]\n        public static extern bool InternetSetOption(nint hInternet, InternetOption dwOption, nint lpBuffer, int dwBufferLength);\n\n        [DllImport(\"Rasapi32.dll\", CharSet = CharSet.Auto)]\n        public static extern uint RasEnumEntries(\n            string? reserved,          // Reserved, must be null\n            string? lpszPhonebook,     // Pointer to full path and filename of phone-book file. If this parameter is NULL, the entries are enumerated from all the remote access phone-book files\n            [In, Out] RASENTRYNAME[]? lprasentryname, // Buffer to receive RAS entry names\n            ref int lpcb,             // Size of the buffer\n            ref int lpcEntries        // Number of entries written to the buffer\n        );\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Handler/SysProxy/SysProxyHandler.cs",
    "content": "namespace ServiceLib.Handler.SysProxy;\n\npublic static class SysProxyHandler\n{\n    private static readonly string _tag = \"SysProxyHandler\";\n\n    public static async Task<bool> UpdateSysProxy(Config config, bool forceDisable)\n    {\n        var type = config.SystemProxyItem.SysProxyType;\n\n        if (forceDisable && type != ESysProxyType.Unchanged)\n        {\n            type = ESysProxyType.ForcedClear;\n        }\n\n        try\n        {\n            var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);\n            var exceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(\" \", \"\");\n            if (port <= 0)\n            {\n                return false;\n            }\n            switch (type)\n            {\n                case ESysProxyType.ForcedChange when Utils.IsWindows():\n                    {\n                        GetWindowsProxyString(config, port, out var strProxy, out var strExceptions);\n                        ProxySettingWindows.SetProxy(strProxy, strExceptions, 2);\n                        break;\n                    }\n                case ESysProxyType.ForcedChange when Utils.IsLinux():\n                    await ProxySettingLinux.SetProxy(Global.Loopback, port, exceptions);\n                    break;\n\n                case ESysProxyType.ForcedChange when Utils.IsMacOS():\n                    await ProxySettingOSX.SetProxy(Global.Loopback, port, exceptions);\n                    break;\n\n                case ESysProxyType.ForcedClear when Utils.IsWindows():\n                    ProxySettingWindows.UnsetProxy();\n                    break;\n\n                case ESysProxyType.ForcedClear when Utils.IsLinux():\n                    await ProxySettingLinux.UnsetProxy();\n                    break;\n\n                case ESysProxyType.ForcedClear when Utils.IsMacOS():\n                    await ProxySettingOSX.UnsetProxy();\n                    break;\n\n                case ESysProxyType.Pac when Utils.IsWindows():\n                    await SetWindowsProxyPac(port);\n                    break;\n            }\n\n            if (type != ESysProxyType.Pac && Utils.IsWindows())\n            {\n                PacManager.Instance.Stop();\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        return true;\n    }\n\n    private static void GetWindowsProxyString(Config config, int port, out string strProxy, out string strExceptions)\n    {\n        strExceptions = config.SystemProxyItem.SystemProxyExceptions.Replace(\" \", \"\");\n        if (config.SystemProxyItem.NotProxyLocalAddress)\n        {\n            strExceptions = $\"<local>;{strExceptions}\";\n        }\n\n        strProxy = string.Empty;\n        if (config.SystemProxyItem.SystemProxyAdvancedProtocol.IsNullOrEmpty())\n        {\n            strProxy = $\"{Global.Loopback}:{port}\";\n        }\n        else\n        {\n            strProxy = config.SystemProxyItem.SystemProxyAdvancedProtocol\n                .Replace(\"{ip}\", Global.Loopback)\n                .Replace(\"{http_port}\", port.ToString())\n                .Replace(\"{socks_port}\", port.ToString());\n        }\n    }\n\n    private static async Task SetWindowsProxyPac(int port)\n    {\n        var portPac = AppManager.Instance.GetLocalPort(EInboundProtocol.pac);\n        await PacManager.Instance.StartAsync(port, portPac);\n        var strProxy = $\"{Global.HttpProtocol}{Global.Loopback}:{portPac}/pac?t={DateTime.Now.Ticks}\";\n        ProxySettingWindows.SetProxy(strProxy, \"\", 4);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Helper/DownloaderHelper.cs",
    "content": "using Downloader;\n\nnamespace ServiceLib.Helper;\n\npublic class DownloaderHelper\n{\n    private static readonly Lazy<DownloaderHelper> _instance = new(() => new());\n    public static DownloaderHelper Instance => _instance.Value;\n\n    public async Task<string?> DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return null;\n        }\n\n        Uri uri = new(url);\n        //Authorization Header\n        var headers = new WebHeaderCollection();\n        if (uri.UserInfo.IsNotEmpty())\n        {\n            headers.Add(HttpRequestHeader.Authorization, \"Basic \" + Utils.Base64Encode(uri.UserInfo));\n        }\n\n        var downloadOpt = new DownloadConfiguration()\n        {\n            BlockTimeout = timeout * 1000,\n            MaxTryAgainOnFailure = 2,\n            RequestConfiguration =\n                {\n                    Headers = headers,\n                    UserAgent = userAgent,\n                    ConnectTimeout = timeout * 1000,\n                    Proxy = webProxy\n                }\n        };\n\n        await using var downloader = new Downloader.DownloadService(downloadOpt);\n        downloader.DownloadFileCompleted += (sender, value) =>\n        {\n            if (value.Error != null)\n            {\n                throw value.Error;\n            }\n        };\n\n        using var cts = new CancellationTokenSource();\n        await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);\n        using StreamReader reader = new(stream);\n\n        downloadOpt = null;\n\n        return await reader.ReadToEndAsync(cts.Token);\n    }\n\n    public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress<string> progress, int timeout)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            throw new ArgumentNullException(nameof(url));\n        }\n\n        var downloadOpt = new DownloadConfiguration()\n        {\n            BlockTimeout = timeout * 1000,\n            MaxTryAgainOnFailure = 2,\n            RequestConfiguration =\n                {\n                    ConnectTimeout= timeout * 1000,\n                    Proxy = webProxy\n                }\n        };\n\n        var lastUpdateTime = DateTime.Now;\n        var hasValue = false;\n        double maxSpeed = 0;\n        await using var downloader = new Downloader.DownloadService(downloadOpt);\n\n        downloader.DownloadProgressChanged += (sender, value) =>\n        {\n            if (progress != null && value.BytesPerSecondSpeed > 0)\n            {\n                hasValue = true;\n                if (value.BytesPerSecondSpeed > maxSpeed)\n                {\n                    maxSpeed = value.BytesPerSecondSpeed;\n                }\n\n                var ts = DateTime.Now - lastUpdateTime;\n                if (ts.TotalMilliseconds >= 1000)\n                {\n                    lastUpdateTime = DateTime.Now;\n                    var speed = (maxSpeed / 1000 / 1000).ToString(\"#0.0\");\n                    progress.Report(speed);\n                }\n            }\n        };\n        downloader.DownloadFileCompleted += (sender, value) =>\n        {\n            if (progress != null)\n            {\n                if (hasValue && maxSpeed > 0)\n                {\n                    var finalSpeed = (maxSpeed / 1000 / 1000).ToString(\"#0.0\");\n                    progress.Report(finalSpeed);\n                }\n                else if (value.Error != null)\n                {\n                    progress.Report(value.Error?.Message);\n                }\n                else\n                {\n                    progress.Report(\"0\");\n                }\n            }\n        };\n        //progress.Report(\"......\");\n        using var cts = new CancellationTokenSource();\n        cts.CancelAfter(timeout * 1000);\n        await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);\n\n        downloadOpt = null;\n    }\n\n    public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress<double> progress, int timeout)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            throw new ArgumentNullException(nameof(url));\n        }\n        if (fileName.IsNullOrEmpty())\n        {\n            throw new ArgumentNullException(nameof(fileName));\n        }\n        if (File.Exists(fileName))\n        {\n            File.Delete(fileName);\n        }\n\n        var downloadOpt = new DownloadConfiguration()\n        {\n            BlockTimeout = timeout * 1000,\n            MaxTryAgainOnFailure = 2,\n            RequestConfiguration =\n                {\n                    ConnectTimeout= timeout * 1000,\n                    Proxy = webProxy\n                }\n        };\n\n        var progressPercentage = 0;\n        var hasValue = false;\n        await using var downloader = new Downloader.DownloadService(downloadOpt);\n        downloader.DownloadStarted += (sender, value) => progress?.Report(0);\n        downloader.DownloadProgressChanged += (sender, value) =>\n        {\n            hasValue = true;\n            var percent = (int)value.ProgressPercentage;//   Convert.ToInt32((totalRead * 1d) / (total * 1d) * 100);\n            if (progressPercentage != percent && percent % 10 == 0)\n            {\n                progressPercentage = percent;\n                progress.Report(percent);\n            }\n        };\n        downloader.DownloadFileCompleted += (sender, value) =>\n        {\n            if (progress != null)\n            {\n                if (hasValue && value.Error == null)\n                {\n                    progress.Report(101);\n                }\n                else if (value.Error != null)\n                {\n                    throw value.Error;\n                }\n            }\n        };\n\n        using var cts = new CancellationTokenSource();\n        await downloader.DownloadFileTaskAsync(url, fileName, cts.Token);\n\n        downloadOpt = null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Helper/HttpClientHelper.cs",
    "content": "using System.Net.Http.Headers;\nusing System.Net.Mime;\n\nnamespace ServiceLib.Helper;\n\n/// <summary>\n/// </summary>\npublic class HttpClientHelper\n{\n    private static readonly Lazy<HttpClientHelper> _instance = new(() =>\n    {\n        SocketsHttpHandler handler = new() { UseCookies = false };\n        HttpClientHelper helper = new(new HttpClient(handler));\n        return helper;\n    });\n\n    public static HttpClientHelper Instance => _instance.Value;\n    private readonly HttpClient httpClient;\n\n    private HttpClientHelper(HttpClient httpClient)\n    {\n        this.httpClient = httpClient;\n    }\n\n    public async Task<string?> TryGetAsync(string url)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return null;\n        }\n\n        try\n        {\n            var response = await httpClient.GetAsync(url);\n            return await response.Content.ReadAsStringAsync();\n        }\n        catch\n        {\n            return null;\n        }\n    }\n\n    public async Task<string?> GetAsync(string url)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return null;\n        }\n        return await httpClient.GetStringAsync(url);\n    }\n\n    public async Task PutAsync(string url, Dictionary<string, string> headers)\n    {\n        var jsonContent = JsonUtils.Serialize(headers);\n        var content = new StringContent(jsonContent, Encoding.UTF8, MediaTypeNames.Application.Json);\n\n        await httpClient.PutAsync(url, content);\n    }\n\n    public async Task PatchAsync(string url, Dictionary<string, string> headers)\n    {\n        var myContent = JsonUtils.Serialize(headers);\n        var buffer = Encoding.UTF8.GetBytes(myContent);\n        var byteContent = new ByteArrayContent(buffer);\n        byteContent.Headers.ContentType = new MediaTypeHeaderValue(\"application/json\");\n\n        await httpClient.PatchAsync(url, byteContent);\n    }\n\n    public async Task DeleteAsync(string url)\n    {\n        await httpClient.DeleteAsync(url);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Helper/SqliteHelper.cs",
    "content": "using System.Collections;\n\nnamespace ServiceLib.Helper;\n\npublic sealed class SQLiteHelper\n{\n    private static readonly Lazy<SQLiteHelper> _instance = new(() => new());\n    public static SQLiteHelper Instance => _instance.Value;\n    private readonly string _connstr;\n    private SQLiteConnection _db;\n    private SQLiteAsyncConnection _dbAsync;\n    private readonly string _configDB = \"guiNDB.db\";\n\n    public SQLiteHelper()\n    {\n        _connstr = Utils.GetConfigPath(_configDB);\n        _db = new SQLiteConnection(_connstr, false);\n        _dbAsync = new SQLiteAsyncConnection(_connstr, false);\n    }\n\n    public CreateTableResult CreateTable<T>()\n    {\n        return _db.CreateTable<T>();\n    }\n\n    public async Task<int> InsertAllAsync(IEnumerable models)\n    {\n        return await _dbAsync.InsertAllAsync(models, runInTransaction: true).ConfigureAwait(false);\n    }\n\n    public async Task<int> InsertAsync(object model)\n    {\n        return await _dbAsync.InsertAsync(model);\n    }\n\n    public async Task<int> ReplaceAsync(object model)\n    {\n        return await _dbAsync.InsertOrReplaceAsync(model);\n    }\n\n    public async Task<int> UpdateAsync(object model)\n    {\n        return await _dbAsync.UpdateAsync(model);\n    }\n\n    public async Task<int> UpdateAllAsync(IEnumerable models)\n    {\n        return await _dbAsync.UpdateAllAsync(models, runInTransaction: true).ConfigureAwait(false);\n    }\n\n    public async Task<int> DeleteAsync(object model)\n    {\n        return await _dbAsync.DeleteAsync(model);\n    }\n\n    public async Task<int> DeleteAllAsync<T>()\n    {\n        return await _dbAsync.DeleteAllAsync<T>();\n    }\n\n    public async Task<int> ExecuteAsync(string sql)\n    {\n        return await _dbAsync.ExecuteAsync(sql);\n    }\n\n    public async Task<List<T>> QueryAsync<T>(string sql) where T : new()\n    {\n        return await _dbAsync.QueryAsync<T>(sql);\n    }\n\n    public AsyncTableQuery<T> TableAsync<T>() where T : new()\n    {\n        return _dbAsync.Table<T>();\n    }\n\n    public async Task DisposeDbConnectionAsync()\n    {\n        await Task.Factory.StartNew(() =>\n        {\n            _db?.Close();\n            _db?.Dispose();\n            _db = null;\n\n            _dbAsync?.GetConnection()?.Close();\n            _dbAsync?.GetConnection()?.Dispose();\n            _dbAsync = null;\n        });\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/AppManager.cs",
    "content": "namespace ServiceLib.Manager;\n\npublic sealed class AppManager\n{\n    #region Property\n\n    private static readonly Lazy<AppManager> _instance = new(() => new());\n    private Config _config;\n    private int? _statePort;\n    private int? _statePort2;\n    public static AppManager Instance => _instance.Value;\n    public Config Config => _config;\n\n    public int StatePort\n    {\n        get\n        {\n            _statePort ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api));\n            return _statePort.Value;\n        }\n    }\n\n    public int StatePort2\n    {\n        get\n        {\n            _statePort2 ??= Utils.GetFreePort(GetLocalPort(EInboundProtocol.api2));\n            return _statePort2.Value + (_config.TunModeItem.EnableTun ? 1 : 0);\n        }\n    }\n\n    public string LinuxSudoPwd { get; set; }\n\n    public bool ShowInTaskbar { get; set; }\n\n    public ECoreType RunningCoreType { get; set; }\n\n    public bool IsRunningCore(ECoreType type)\n    {\n        switch (type)\n        {\n            case ECoreType.Xray when RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5:\n            case ECoreType.sing_box when RunningCoreType is ECoreType.sing_box or ECoreType.mihomo:\n                return true;\n\n            default:\n                return false;\n        }\n    }\n\n    #endregion Property\n\n    #region App\n\n    public bool InitApp()\n    {\n        if (Utils.HasWritePermission() == false)\n        {\n            Environment.SetEnvironmentVariable(Global.LocalAppData, \"1\", EnvironmentVariableTarget.Process);\n        }\n\n        Logging.Setup();\n        var config = ConfigHandler.LoadConfig();\n        if (config == null)\n        {\n            return false;\n        }\n        _config = config;\n        Thread.CurrentThread.CurrentUICulture = new(_config.UiItem.CurrentLanguage);\n\n        //Under Win10\n        if (Utils.IsWindows() && Environment.OSVersion.Version.Major < 10)\n        {\n            Environment.SetEnvironmentVariable(\"DOTNET_EnableWriteXorExecute\", \"0\", EnvironmentVariableTarget.User);\n        }\n\n        SQLiteHelper.Instance.CreateTable<SubItem>();\n        SQLiteHelper.Instance.CreateTable<ProfileItem>();\n        SQLiteHelper.Instance.CreateTable<ServerStatItem>();\n        SQLiteHelper.Instance.CreateTable<RoutingItem>();\n        SQLiteHelper.Instance.CreateTable<ProfileExItem>();\n        SQLiteHelper.Instance.CreateTable<DNSItem>();\n        SQLiteHelper.Instance.CreateTable<FullConfigTemplateItem>();\n#pragma warning disable CS0618\n        SQLiteHelper.Instance.CreateTable<ProfileGroupItem>();\n#pragma warning restore CS0618\n        return true;\n    }\n\n    public bool InitComponents()\n    {\n        Logging.SaveLog($\"v2rayN start up | {Utils.GetRuntimeInfo()}\");\n        Logging.LoggingEnabled(_config.GuiItem.EnableLog);\n\n        //First determine the port value\n        _ = StatePort;\n        _ = StatePort2;\n\n        Task.Run(async () =>\n        {\n            await MigrateProfileExtra();\n        }).Wait();\n\n        return true;\n    }\n\n    public bool Reset()\n    {\n        _statePort = null;\n        _statePort2 = null;\n        return true;\n    }\n\n    public async Task AppExitAsync(bool needShutdown)\n    {\n        try\n        {\n            Logging.SaveLog(\"AppExitAsync Begin\");\n\n            await SysProxyHandler.UpdateSysProxy(_config, true);\n            AppEvents.AppExitRequested.Publish();\n            await Task.Delay(50); //Wait for AppExitRequested to be processed\n\n            await ConfigHandler.SaveConfig(_config);\n            await ProfileExManager.Instance.SaveTo();\n            await StatisticsManager.Instance.SaveTo();\n            await CoreManager.Instance.CoreStop();\n            StatisticsManager.Instance.Close();\n\n            Logging.SaveLog(\"AppExitAsync End\");\n        }\n        catch { }\n        finally\n        {\n            if (needShutdown)\n            {\n                Shutdown(false);\n            }\n        }\n    }\n\n    public void Shutdown(bool byUser)\n    {\n        AppEvents.ShutdownRequested.Publish(byUser);\n    }\n\n    public async Task RebootAsAdmin()\n    {\n        ProcUtils.RebootAsAdmin();\n        await AppManager.Instance.AppExitAsync(true);\n    }\n\n    #endregion App\n\n    #region Config\n\n    public int GetLocalPort(EInboundProtocol protocol)\n    {\n        var localPort = _config.Inbound.FirstOrDefault(t => t.Protocol == nameof(EInboundProtocol.socks))?.LocalPort ?? 10808;\n        return localPort + (int)protocol;\n    }\n\n    #endregion Config\n\n    #region SqliteHelper\n\n    public async Task<List<SubItem>?> SubItems()\n    {\n        return await SQLiteHelper.Instance.TableAsync<SubItem>().OrderBy(t => t.Sort).ToListAsync();\n    }\n\n    public async Task<SubItem?> GetSubItem(string? subid)\n    {\n        return await SQLiteHelper.Instance.TableAsync<SubItem>().FirstOrDefaultAsync(t => t.Id == subid);\n    }\n\n    public async Task<List<ProfileItem>?> ProfileItems(string subid)\n    {\n        if (subid.IsNullOrEmpty())\n        {\n            return await SQLiteHelper.Instance.TableAsync<ProfileItem>().ToListAsync();\n        }\n        else\n        {\n            return await SQLiteHelper.Instance.TableAsync<ProfileItem>().Where(t => t.Subid == subid).ToListAsync();\n        }\n    }\n\n    public async Task<List<string>?> ProfileItemIndexes(string subid)\n    {\n        return (await ProfileItems(subid))?.Select(t => t.IndexId)?.ToList();\n    }\n\n    public async Task<List<ProfileItemModel>?> ProfileModels(string subid, string filter)\n    {\n        var sql = @$\"select a.IndexId\n                           ,a.ConfigType\n                           ,a.Remarks\n                           ,a.Address\n                           ,a.Port\n                           ,a.Network\n                           ,a.StreamSecurity\n                           ,a.Subid\n                           ,b.remarks as subRemarks\n                        from ProfileItem a\n                        left join SubItem b on a.subid = b.id\n                        where 1=1 \";\n        if (subid.IsNotEmpty())\n        {\n            sql += $\" and a.subid = '{subid}'\";\n        }\n        if (filter.IsNotEmpty())\n        {\n            if (filter.Contains('\\''))\n            {\n                filter = filter.Replace(\"'\", \"\");\n            }\n            sql += string.Format(\" and (a.remarks like '%{0}%' or a.address like '%{0}%') \", filter);\n        }\n\n        return await SQLiteHelper.Instance.QueryAsync<ProfileItemModel>(sql);\n    }\n\n    public async Task<ProfileItem?> GetProfileItem(string indexId)\n    {\n        if (indexId.IsNullOrEmpty())\n        {\n            return null;\n        }\n        return await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(it => it.IndexId == indexId);\n    }\n\n    public async Task<List<ProfileItem>> GetProfileItemsByIndexIds(IEnumerable<string> indexIds)\n    {\n        var ids = indexIds.Where(id => !id.IsNullOrEmpty()).Distinct().ToList();\n        if (ids.Count == 0)\n        {\n            return [];\n        }\n        return await SQLiteHelper.Instance.TableAsync<ProfileItem>()\n            .Where(it => ids.Contains(it.IndexId))\n            .ToListAsync();\n    }\n\n    public async Task<Dictionary<string, ProfileItem>> GetProfileItemsByIndexIdsAsMap(IEnumerable<string> indexIds)\n    {\n        var items = await GetProfileItemsByIndexIds(indexIds);\n        return items.ToDictionary(it => it.IndexId);\n    }\n\n    public async Task<List<ProfileItem>> GetProfileItemsOrderedByIndexIds(IEnumerable<string> indexIds)\n    {\n        var idList = indexIds.Where(id => !id.IsNullOrEmpty()).Distinct().ToList();\n        if (idList.Count == 0)\n        {\n            return [];\n        }\n\n        var items = await SQLiteHelper.Instance.TableAsync<ProfileItem>()\n            .Where(it => idList.Contains(it.IndexId))\n            .ToListAsync();\n        var itemMap = items.ToDictionary(it => it.IndexId);\n\n        return idList.Select(id => itemMap.GetValueOrDefault(id))\n            .Where(item => item != null)\n            .ToList();\n    }\n\n    public async Task<ProfileItem?> GetProfileItemViaRemarks(string? remarks)\n    {\n        if (remarks.IsNullOrEmpty())\n        {\n            return null;\n        }\n        return await SQLiteHelper.Instance.TableAsync<ProfileItem>().FirstOrDefaultAsync(it => it.Remarks == remarks);\n    }\n\n    public async Task<List<RoutingItem>?> RoutingItems()\n    {\n        return await SQLiteHelper.Instance.TableAsync<RoutingItem>().OrderBy(t => t.Sort).ToListAsync();\n    }\n\n    public async Task<RoutingItem?> GetRoutingItem(string id)\n    {\n        return await SQLiteHelper.Instance.TableAsync<RoutingItem>().FirstOrDefaultAsync(it => it.Id == id);\n    }\n\n    public async Task<List<DNSItem>?> DNSItems()\n    {\n        return await SQLiteHelper.Instance.TableAsync<DNSItem>().ToListAsync();\n    }\n\n    public async Task<DNSItem?> GetDNSItem(ECoreType eCoreType)\n    {\n        return await SQLiteHelper.Instance.TableAsync<DNSItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);\n    }\n\n    public async Task<List<FullConfigTemplateItem>?> FullConfigTemplateItem()\n    {\n        return await SQLiteHelper.Instance.TableAsync<FullConfigTemplateItem>().ToListAsync();\n    }\n\n    public async Task<FullConfigTemplateItem?> GetFullConfigTemplateItem(ECoreType eCoreType)\n    {\n        return await SQLiteHelper.Instance.TableAsync<FullConfigTemplateItem>().FirstOrDefaultAsync(it => it.CoreType == eCoreType);\n    }\n\n    public async Task MigrateProfileExtra()\n    {\n        await MigrateProfileExtraGroup();\n\n#pragma warning disable CS0618\n\n        const int pageSize = 100;\n        var offset = 0;\n\n        while (true)\n        {\n            var sql = $\"SELECT * FROM ProfileItem \" +\n                $\"WHERE ConfigVersion < 3 \" +\n                $\"AND ConfigType NOT IN ({(int)EConfigType.PolicyGroup}, {(int)EConfigType.ProxyChain}) \" +\n                $\"LIMIT {pageSize} OFFSET {offset}\";\n            var batch = await SQLiteHelper.Instance.QueryAsync<ProfileItem>(sql);\n            if (batch is null || batch.Count == 0)\n            {\n                break;\n            }\n\n            var batchSuccessCount = await MigrateProfileExtraSub(batch);\n\n            // Only increment offset by the number of failed items that remain in the result set\n            // Successfully updated items are automatically excluded from future queries due to ConfigVersion = 3\n            offset += batch.Count - batchSuccessCount;\n        }\n\n        //await ProfileGroupItemManager.Instance.ClearAll();\n#pragma warning restore CS0618\n    }\n\n    private async Task<int> MigrateProfileExtraSub(List<ProfileItem> batch)\n    {\n        var updateProfileItems = new List<ProfileItem>();\n\n        foreach (var item in batch)\n        {\n            try\n            {\n                var extra = item.GetProtocolExtra();\n                switch (item.ConfigType)\n                {\n                    case EConfigType.Shadowsocks:\n                        extra = extra with { SsMethod = item.Security.NullIfEmpty() };\n                        break;\n\n                    case EConfigType.VMess:\n                        extra = extra with\n                        {\n                            AlterId = item.AlterId.ToString(),\n                            VmessSecurity = item.Security.NullIfEmpty(),\n                        };\n                        break;\n\n                    case EConfigType.VLESS:\n                        extra = extra with\n                        {\n                            Flow = item.Flow.NullIfEmpty(),\n                            VlessEncryption = item.Security,\n                        };\n                        break;\n\n                    case EConfigType.Hysteria2:\n                        extra = extra with\n                        {\n                            SalamanderPass = item.Path.NullIfEmpty(),\n                            Ports = item.Ports.NullIfEmpty(),\n                            UpMbps = _config.HysteriaItem.UpMbps,\n                            DownMbps = _config.HysteriaItem.DownMbps,\n                            HopInterval = _config.HysteriaItem.HopInterval.ToString(),\n                        };\n                        break;\n\n                    case EConfigType.TUIC:\n                        item.Username = item.Id;\n                        item.Id = item.Security;\n                        item.Password = item.Security;\n                        break;\n\n                    case EConfigType.HTTP:\n                    case EConfigType.SOCKS:\n                        item.Username = item.Security;\n                        break;\n\n                    case EConfigType.WireGuard:\n                        extra = extra with\n                        {\n                            WgPublicKey = item.PublicKey.NullIfEmpty(),\n                            WgInterfaceAddress = item.RequestHost.NullIfEmpty(),\n                            WgReserved = item.Path.NullIfEmpty(),\n                            WgMtu = int.TryParse(item.ShortId, out var mtu) ? mtu : 1280\n                        };\n                        break;\n                }\n\n                item.SetProtocolExtra(extra);\n\n                item.Password = item.Id;\n\n                item.ConfigVersion = 3;\n\n                updateProfileItems.Add(item);\n            }\n            catch (Exception ex)\n            {\n                Logging.SaveLog($\"MigrateProfileExtra Error: {ex}\");\n            }\n        }\n\n        if (updateProfileItems.Count > 0)\n        {\n            try\n            {\n                var count = await SQLiteHelper.Instance.UpdateAllAsync(updateProfileItems);\n                return count;\n            }\n            catch (Exception ex)\n            {\n                Logging.SaveLog($\"MigrateProfileExtraGroup update error: {ex}\");\n                return 0;\n            }\n        }\n        else\n        {\n            return 0;\n        }\n    }\n\n    private async Task<bool> MigrateProfileExtraGroup()\n    {\n#pragma warning disable CS0618\n        var list = await SQLiteHelper.Instance.TableAsync<ProfileGroupItem>().ToListAsync();\n        var groupItems = new ConcurrentDictionary<string, ProfileGroupItem>(list.Where(t => !string.IsNullOrEmpty(t.IndexId)).ToDictionary(t => t.IndexId!));\n\n        var sql = $\"SELECT * FROM ProfileItem WHERE ConfigVersion < 3 AND ConfigType IN ({(int)EConfigType.PolicyGroup}, {(int)EConfigType.ProxyChain})\";\n        var items = await SQLiteHelper.Instance.QueryAsync<ProfileItem>(sql);\n\n        if (items is null || items.Count == 0)\n        {\n            Logging.SaveLog(\"MigrateProfileExtraGroup: No items to migrate.\");\n            return true;\n        }\n\n        Logging.SaveLog($\"MigrateProfileExtraGroup: Found {items.Count} group items to migrate.\");\n\n        var updateProfileItems = new List<ProfileItem>();\n\n        foreach (var item in items)\n        {\n            try\n            {\n                var extra = item.GetProtocolExtra();\n\n                extra = extra with { GroupType = nameof(item.ConfigType) };\n                groupItems.TryGetValue(item.IndexId, out var groupItem);\n                if (groupItem != null && !groupItem.NotHasChild())\n                {\n                    extra = extra with\n                    {\n                        ChildItems = groupItem.ChildItems,\n                        SubChildItems = groupItem.SubChildItems,\n                        Filter = groupItem.Filter,\n                        MultipleLoad = groupItem.MultipleLoad,\n                    };\n                }\n\n                item.SetProtocolExtra(extra);\n\n                item.ConfigVersion = 3;\n                updateProfileItems.Add(item);\n            }\n            catch (Exception ex)\n            {\n                Logging.SaveLog($\"MigrateProfileExtraGroup item error [{item.IndexId}]: {ex}\");\n            }\n        }\n\n        if (updateProfileItems.Count > 0)\n        {\n            try\n            {\n                var count = await SQLiteHelper.Instance.UpdateAllAsync(updateProfileItems);\n                Logging.SaveLog($\"MigrateProfileExtraGroup: Successfully updated {updateProfileItems.Count} items.\");\n                return updateProfileItems.Count == count;\n            }\n            catch (Exception ex)\n            {\n                Logging.SaveLog($\"MigrateProfileExtraGroup update error: {ex}\");\n                return false;\n            }\n        }\n\n        return true;\n\n        //await ProfileGroupItemManager.Instance.ClearAll();\n#pragma warning restore CS0618\n    }\n\n    #endregion SqliteHelper\n\n    #region Core Type\n\n    public List<string> GetShadowsocksSecurities(ProfileItem profileItem)\n    {\n        var coreType = GetCoreType(profileItem, EConfigType.Shadowsocks);\n        switch (coreType)\n        {\n            case ECoreType.v2fly:\n                return Global.SsSecurities;\n\n            case ECoreType.Xray:\n                return Global.SsSecuritiesInXray;\n\n            case ECoreType.sing_box:\n                return Global.SsSecuritiesInSingbox;\n        }\n        return Global.SsSecuritiesInSingbox;\n    }\n\n    public ECoreType GetCoreType(ProfileItem profileItem, EConfigType eConfigType)\n    {\n        if (profileItem?.CoreType != null)\n        {\n            return (ECoreType)profileItem.CoreType;\n        }\n\n        var item = _config.CoreTypeItem?.FirstOrDefault(it => it.ConfigType == eConfigType);\n        return item?.CoreType ?? ECoreType.Xray;\n    }\n\n    #endregion Core Type\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/CertPemManager.cs",
    "content": "using System.Net.Security;\nusing System.Security.Cryptography.X509Certificates;\n\nnamespace ServiceLib.Manager;\n\n/// <summary>\n/// Manager for certificate operations with CA pinning to prevent MITM attacks\n/// </summary>\npublic class CertPemManager\n{\n    private static readonly string _tag = \"CertPemManager\";\n    private static readonly Lazy<CertPemManager> _instance = new(() => new());\n    public static CertPemManager Instance => _instance.Value;\n\n    /// <summary>\n    /// Trusted CA certificate thumbprints (SHA256) to prevent MITM attacks\n    /// </summary>\n    private static readonly HashSet<string> TrustedCaThumbprints = new(StringComparer.OrdinalIgnoreCase)\n    {\n        \"EBD41040E4BB3EC742C9E381D31EF2A41A48B6685C96E7CEF3C1DF6CD4331C99\", // GlobalSign Root CA\n        \"6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177\", // Entrust.net Premium 2048 Secure Server CA\n        \"73C176434F1BC6D5ADF45B0E76E727287C8DE57616C1E6E6141A2B2CBC7D8E4C\", // Entrust Root Certification Authority\n        \"D8E0FEBC1DB2E38D00940F37D27D41344D993E734B99D5656D9778D4D8143624\", // Certum Root CA\n        \"D7A7A0FB5D7E2731D771E9484EBCDEF71D5F0C3E0A2948782BC83EE0EA699EF4\", // Comodo AAA Services root\n        \"85A0DD7DD720ADB7FF05F83D542B209DC7FF4528F7D677B18389FEA5E5C49E86\", // QuoVadis Root CA 2\n        \"18F1FC7F205DF8ADDDEB7FE007DD57E3AF375A9C4D8D73546BF4F1FED1E18D35\", // QuoVadis Root CA 3\n        \"CECDDC905099D8DADFC5B1D209B737CBE2C18CFB2C10C0FF0BCF0D3286FC1AA2\", // XRamp Global CA Root\n        \"C3846BF24B9E93CA64274C0EC67C1ECC5E024FFCACD2D74019350E81FE546AE4\", // Go Daddy Class 2 CA\n        \"1465FA205397B876FAA6F0A9958E5590E40FCC7FAA4FB7C2C8677521FB5FB658\", // Starfield Class 2 CA\n        \"3E9099B5015E8F486C00BCEA9D111EE721FABA355A89BCF1DF69561E3DC6325C\", // DigiCert Assured ID Root CA\n        \"4348A0E9444C78CB265E058D5E8944B4D84F9662BD26DB257F8934A443C70161\", // DigiCert Global Root CA\n        \"7431E5F4C3C1CE4690774F0B61E05440883BA9A01ED00BA6ABD7806ED3B118CF\", // DigiCert High Assurance EV Root CA\n        \"62DD0BE9B9F50A163EA0F8E75C053B1ECA57EA55C8688F647C6881F2C8357B95\", // SwissSign Gold CA - G2\n        \"F1C1B50AE5A20DD8030EC9F6BC24823DD367B5255759B4E71B61FCE9F7375D73\", // SecureTrust CA\n        \"4200F5043AC8590EBB527D209ED1503029FBCBD41CA1B506EC27F15ADE7DAC69\", // Secure Global CA\n        \"0C2CD63DF7806FA399EDE809116B575BF87989F06518F9808C860503178BAF66\", // COMODO Certification Authority\n        \"1793927A0614549789ADCE2F8F34F7F0B66D0F3AE3A3B84D21EC15DBBA4FADC7\", // COMODO ECC Certification Authority\n        \"41C923866AB4CAD6B7AD578081582E020797A6CBDF4FFF78CE8396B38937D7F5\", // OISTE WISeKey Global Root GA CA\n        \"E3B6A2DB2ED7CE48842F7AC53241C7B71D54144BFB40C11F3F1D0B42F5EEA12D\", // Certigna\n        \"C0A6F4DC63A24BFDCF54EF2A6A082A0A72DE35803E2FF5FF527AE5D87206DFD5\", // ePKI Root Certification Authority\n        \"EAA962C4FA4A6BAFEBE415196D351CCD888D4F53F3FA8AE6D7C466A94E6042BB\", // certSIGN ROOT CA\n        \"6C61DAC3A2DEF031506BE036D2A6FE401994FBD13DF9C8D466599274C446EC98\", // NetLock Arany (Class Gold) Főtanúsítvány\n        \"3C5F81FEA5FAB82C64BFA2EAECAFCDE8E077FC8620A7CAE537163DF36EDBF378\", // Microsec e-Szigno Root CA 2009\n        \"CBB522D7B7F127AD6A0113865BDF1CD4102E7D0759AF635A7CF4720DC963C53B\", // GlobalSign Root CA - R3\n        \"2530CC8E98321502BAD96F9B1FBA1B099E2D299E0F4548BB914F363BC0D4531F\", // Izenpe.com\n        \"45140B3247EB9CC8C5B4F0D7B53091F73292089E6E5A63E2749DD3ACA9198EDA\", // Go Daddy Root Certificate Authority - G2\n        \"2CE1CB0BF9D2F9E102993FBE215152C3B2DD0CABDE1C68E5319B839154DBB7F5\", // Starfield Root Certificate Authority - G2\n        \"568D6905A2C88708A4B3025190EDCFEDB1974A606A13C6E5290FCB2AE63EDAB5\", // Starfield Services Root Certificate Authority - G2\n        \"0376AB1D54C5F9803CE4B2E201A0EE7EEF7B57B636E8A93C9B8D4860C96F5FA7\", // AffirmTrust Commercial\n        \"0A81EC5A929777F145904AF38D5D509F66B5E2C58FCDB531058B0E17F3F0B41B\", // AffirmTrust Networking\n        \"70A73F7F376B60074248904534B11482D5BF0E698ECC498DF52577EBF2E93B9A\", // AffirmTrust Premium\n        \"BD71FDF6DA97E4CF62D1647ADD2581B07D79ADF8397EB4ECBA9C5E8488821423\", // AffirmTrust Premium ECC\n        \"5C58468D55F58E497E743982D2B50010B6D165374ACF83A7D4A32DB768C4408E\", // Certum Trusted Network CA\n        \"BFD88FE1101C41AE3E801BF8BE56350EE9BAD1A6B9BD515EDC5C6D5B8711AC44\", // TWCA Root Certification Authority\n        \"513B2CECB810D4CDE5DD85391ADFC6C2DD60D87BB736D2B521484AA47A0EBEF6\", // Security Communication RootCA2\n        \"55926084EC963A64B96E2ABE01CE0BA86A64FBFEBCC7AAB5AFC155B37FD76066\", // Actalis Authentication Root CA\n        \"9A114025197C5BB95D94E63D55CD43790847B646B23CDF11ADA4A00EFF15FB48\", // Buypass Class 2 Root CA\n        \"EDF7EBBCA27A2A384D387B7D4010C666E2EDB4843E4C29B4AE1D5B9332E6B24D\", // Buypass Class 3 Root CA\n        \"FD73DAD31C644FF1B43BEF0CCDDA96710B9CD9875ECA7E31707AF3E96D522BBD\", // T-TeleSec GlobalRoot Class 3\n        \"49E7A442ACF0EA6287050054B52564B650E4F49E42E348D6AA38E039E957B1C1\", // D-TRUST Root Class 3 CA 2 2009\n        \"EEC5496B988CE98625B934092EEC2908BED0B0F316C2D4730C84EAF1F3D34881\", // D-TRUST Root Class 3 CA 2 EV 2009\n        \"E23D4A036D7B70E9F595B1422079D2B91EDFBB1FB651A0633EAA8A9DC5F80703\", // CA Disig Root R2\n        \"9A6EC012E1A7DA9DBE34194D478AD7C0DB1822FB071DF12981496ED104384113\", // ACCVRAIZ1\n        \"59769007F7685D0FCD50872F9F95D5755A5B2B457D81F3692B610A98672F0E1B\", // TWCA Global Root CA\n        \"DD6936FE21F8F077C123A1A521C12224F72255B73E03A7260693E8A24B0FA389\", // TeliaSonera Root CA v1\n        \"91E2F5788D5810EBA7BA58737DE1548A8ECACD014598BC0B143E041B17052552\", // T-TeleSec GlobalRoot Class 2\n        \"F356BEA244B7A91EB35D53CA9AD7864ACE018E2D35D5F8F96DDF68A6F41AA474\", // Atos TrustedRoot 2011\n        \"8A866FD1B276B57E578E921C65828A2BED58E9F2F288054134B7F1F4BFC9CC74\", // QuoVadis Root CA 1 G3\n        \"8FE4FB0AF93A4D0D67DB0BEBB23E37C71BF325DCBCDD240EA04DAF58B47E1840\", // QuoVadis Root CA 2 G3\n        \"88EF81DE202EB018452E43F864725CEA5FBD1FC2D9D205730709C5D8B8690F46\", // QuoVadis Root CA 3 G3\n        \"7D05EBB682339F8C9451EE094EEBFEFA7953A114EDB2F44949452FAB7D2FC185\", // DigiCert Assured ID Root G2\n        \"7E37CB8B4C47090CAB36551BA6F45DB840680FBA166A952DB100717F43053FC2\", // DigiCert Assured ID Root G3\n        \"CB3CCBB76031E5E0138F8DD39A23F9DE47FFC35E43C1144CEA27D46A5AB1CB5F\", // DigiCert Global Root G2\n        \"31AD6648F8104138C738F39EA4320133393E3A18CC02296EF97C2AC9EF6731D0\", // DigiCert Global Root G3\n        \"552F7BDCF1A7AF9E6CE672017F4F12ABF77240C78E761AC203D1D9D20AC89988\", // DigiCert Trusted Root G4\n        \"52F0E1C4E58EC629291B60317F074671B85D7EA80D5B07273463534B32B40234\", // COMODO RSA Certification Authority\n        \"E793C9B02FD8AA13E21C31228ACCB08119643B749C898964B1746D46C3D4CBD2\", // USERTrust RSA Certification Authority\n        \"4FF460D54B9C86DABFBCFC5712E0400D2BED3FBC4D4FBDAA86E06ADCD2A9AD7A\", // USERTrust ECC Certification Authority\n        \"179FBC148A3DD00FD24EA13458CC43BFA7F59C8182D783A513F6EBEC100C8924\", // GlobalSign ECC Root CA - R5\n        \"3C4FB0B95AB8B30032F432B86F535FE172C185D0FD39865837CF36187FA6F428\", // Staat der Nederlanden Root CA - G3\n        \"5D56499BE4D2E08BCFCAD08A3E38723D50503BDE706948E42F55603019E528AE\", // IdenTrust Commercial Root CA 1\n        \"30D0895A9A448A262091635522D1F52010B5867ACAE12C78EF958FD4F4389F2F\", // IdenTrust Public Sector Root CA 1\n        \"43DF5774B03E7FEF5FE40D931A7BEDF1BB2E6B42738C4E6D3841103D3AA7F339\", // Entrust Root Certification Authority - G2\n        \"02ED0EB28C14DA45165C566791700D6451D7FB56F0B2AB1D3B8EB070E56EDFF5\", // Entrust Root Certification Authority - EC1\n        \"5CC3D78E4E1D5E45547A04E6873E64F90CF9536D1CCC2EF800F355C4C5FD70FD\", // CFCA EV ROOT\n        \"6B9C08E86EB0F767CFAD65CD98B62149E5494A67F5845E7BD1ED019F27B86BD6\", // OISTE WISeKey Global Root GB CA\n        \"A1339D33281A0B56E557D3D32B1CE7F9367EB094BD5FA72A7E5004C8DED7CAFE\", // SZAFIR ROOT CA2\n        \"B676F2EDDAE8775CD36CB0F63CD1D4603961F49E6265BA013A2F0307B6D0B804\", // Certum Trusted Network CA 2\n        \"A040929A02CE53B4ACF4F2FFC6981CE4496F755E6D45FE0B2A692BCD52523F36\", // Hellenic Academic and Research Institutions RootCA 2015\n        \"44B545AA8A25E65A73CA15DC27FC36D24C1CB9953A066539B11582DC487B4833\", // Hellenic Academic and Research Institutions ECC RootCA 2015\n        \"96BCEC06264976F37460779ACF28C5A7CFE8A3C0AAE11A8FFCEE05C0BDDF08C6\", // ISRG Root X1\n        \"EBC5570C29018C4D67B1AA127BAF12F703B4611EBC17B7DAB5573894179B93FA\", // AC RAIZ FNMT-RCM\n        \"8ECDE6884F3D87B1125BA31AC3FCB13D7016DE7F57CC904FE1CB97C6AE98196E\", // Amazon Root CA 1\n        \"1BA5B2AA8C65401A82960118F80BEC4F62304D83CEC4713A19C39C011EA46DB4\", // Amazon Root CA 2\n        \"18CE6CFE7BF14E60B2E347B8DFE868CB31D02EBB3ADA271569F50343B46DB3A4\", // Amazon Root CA 3\n        \"E35D28419ED02025CFA69038CD623962458DA5C695FBDEA3C22B0BFB25897092\", // Amazon Root CA 4\n        \"A1A86D04121EB87F027C66F53303C28E5739F943FC84B38AD6AF009035DD9457\", // D-TRUST Root CA 3 2013\n        \"46EDC3689046D53A453FB3104AB80DCAEC658B2660EA1629DD7E867990648716\", // TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1\n        \"BFFF8FD04433487D6A8AA60C1A29767A9FC2BBB05E420F713A13B992891D3893\", // GDCA TrustAUTH R5 ROOT\n        \"85666A562EE0BE5CE925C1D8890A6F76A87EC16D4D7D5F29EA7419CF20123B69\", // SSL.com Root Certification Authority RSA\n        \"3417BB06CC6007DA1B961C920B8AB4CE3FAD820E4AA30B9ACBC4A74EBDCEBC65\", // SSL.com Root Certification Authority ECC\n        \"2E7BF16CC22485A7BBE2AA8696750761B0AE39BE3B2FE9D0CC6D4EF73491425C\", // SSL.com EV Root Certification Authority RSA R2\n        \"22A2C1F7BDED704CC1E701B5F408C310880FE956B5DE2A4A44F99C873A25A7C8\", // SSL.com EV Root Certification Authority ECC\n        \"2CABEAFE37D06CA22ABA7391C0033D25982952C453647349763A3AB5AD6CCF69\", // GlobalSign Root CA - R6\n        \"8560F91C3624DABA9570B5FEA0DBE36FF11A8323BE9486854FB3F34A5571198D\", // OISTE WISeKey Global Root GC CA\n        \"9BEA11C976FE014764C1BE56A6F914B5A560317ABD9988393382E5161AA0493C\", // UCA Global G2 Root\n        \"D43AF9B35473755C9684FC06D7D8CB70EE5C28E773FB294EB41EE71722924D24\", // UCA Extended Validation Root\n        \"D48D3D23EEDB50A459E55197601C27774B9D7B18C94D5A059511A10250B93168\", // Certigna Root CA\n        \"40F6AF0346A99AA1CD1D555A4E9CCE62C7F9634603EE406615833DC8C8D00367\", // emSign Root CA - G1\n        \"86A1ECBA089C4A8D3BBE2734C612BA341D813E043CF9E8A862CD5C57A36BBE6B\", // emSign ECC Root CA - G3\n        \"125609AA301DA0A249B97A8239CB6A34216F44DCAC9F3954B14292F2E8C8608F\", // emSign Root CA - C1\n        \"BC4D809B15189D78DB3E1D8CF4F9726A795DA1643CA5F1358E1DDB0EDC0D7EB3\", // emSign ECC Root CA - C3\n        \"5A2FC03F0C83B090BBFA40604B0988446C7636183DF9846E17101A447FB8EFD6\", // Hongkong Post Root CA 3\n        \"DB3517D1F6732A2D5AB97C533EC70779EE3270A62FB4AC4238372460E6F01E88\", // Entrust Root Certification Authority - G4\n        \"358DF39D764AF9E1B766E9C972DF352EE15CFAC227AF6AD1D70E8E4A6EDCBA02\", // Microsoft ECC Root Certificate Authority 2017\n        \"C741F70F4B2A8D88BF2E71C14122EF53EF10EBA0CFA5E64CFA20F418853073E0\", // Microsoft RSA Root Certificate Authority 2017\n        \"BEB00B30839B9BC32C32E4447905950641F26421B15ED089198B518AE2EA1B99\", // e-Szigno Root CA 2017\n        \"657CFE2FA73FAA38462571F332A2363A46FCE7020951710702CDFBB6EEDA3305\", // certSIGN Root CA G2\n        \"97552015F5DDFC3C8788C006944555408894450084F100867086BC1A2BB58DC8\", // Trustwave Global Certification Authority\n        \"945BBC825EA554F489D1FD51A73DDF2EA624AC7019A05205225C22A78CCFA8B4\", // Trustwave Global ECC P256 Certification Authority\n        \"55903859C8C0C3EBB8759ECE4E2557225FF5758BBD38EBD48276601E1BD58097\", // Trustwave Global ECC P384 Certification Authority\n        \"88F438DCF8FFD1FA8F429115FFE5F82AE1E06E0C70C375FAAD717B34A49E7265\", // NAVER Global Root Certification Authority\n        \"554153B13D2CF9DDB753BFBE1A4E0AE08D0AA4187058FE60A2B862B2E4B87BCB\", // AC RAIZ FNMT-RCM SERVIDORES SEGUROS\n        \"319AF0A7729E6F89269C131EA6A3A16FCD86389FDCAB3C47A4A675C161A3F974\", // GlobalSign Secure Mail Root R45\n        \"5CBF6FB81FD417EA4128CD6F8172A3C9402094F74AB2ED3A06B4405D04F30B19\", // GlobalSign Secure Mail Root E45\n        \"4FA3126D8D3A11D1C4855A4F807CBAD6CF919D3A5A88B03BEA2C6372D93C40C9\", // GlobalSign Root R46\n        \"CBB9C44D84B8043E1050EA31A69F514955D7BFD2E2C6B49301019AD61D9F5058\", // GlobalSign Root E46\n        \"9A296A5182D1D451A2E37F439B74DAAFA267523329F90F9A0D2007C334E23C9A\", // GLOBALTRUST 2020\n        \"FB8FEC759169B9106B1E511644C618C51304373F6C0643088D8BEFFD1B997599\", // ANF Secure Server Root CA\n        \"6B328085625318AA50D173C98D8BDA09D57E27413D114CF787A0F5D06C030CF6\", // Certum EC-384 CA\n        \"FE7696573855773E37A95E7AD4D9CC96C30157C15D31765BA9B15704E1AE78FD\", // Certum Trusted Root CA\n        \"2E44102AB58CB85419451C8E19D9ACF3662CAFBC614B6A53960A30F7D0E2EB41\", // TunTrust Root CA\n        \"D95D0E8EDA79525BF9BEB11B14D2100D3294985F0C62D9FABD9CD999ECCB7B1D\", // HARICA TLS RSA Root CA 2021\n        \"3F99CC474ACFCE4DFED58794665E478D1547739F2E780F1BB4CA9B133097D401\", // HARICA TLS ECC Root CA 2021\n        \"1BE7ABE30686B16348AFD1C61B6866A0EA7F4821E67D5E8AF937CF8011BC750D\", // HARICA Client RSA Root CA 2021\n        \"8DD4B5373CB0DE36769C12339280D82746B3AA6CD426E797A31BABE4279CF00B\", // HARICA Client ECC Root CA 2021\n        \"57DE0583EFD2B26E0361DA99DA9DF4648DEF7EE8441C3B728AFA9BCDE0F9B26A\", // Autoridad de Certificacion Firmaprofesional CIF A62634068\n        \"30FBBA2C32238E2A98547AF97931E550428B9B3F1C8EEB6633DCFA86C5B27DD3\", // vTrus ECC Root CA\n        \"8A71DE6559336F426C26E53880D00D88A18DA4C6A91F0DCB6194E206C5C96387\", // vTrus Root CA\n        \"69729B8E15A86EFC177A57AFB7171DFC64ADD28C2FCA8CF1507E34453CCB1470\", // ISRG Root X2\n        \"F015CE3CC239BFEF064BE9F1D2C417E1A0264A0A94BE1F0C8D121864EB6949CC\", // HiPKI Root CA - G1\n        \"B085D70B964F191A73E4AF0D54AE7A0E07AAFDAF9B71DD0862138AB7325A24A2\", // GlobalSign ECC Root CA - R4\n        \"D947432ABDE7B7FA90FC2E6B59101B1280E0E1C7E4E40FA3C6887FFF57A7F4CF\", // GTS Root R1\n        \"8D25CD97229DBF70356BDA4EB3CC734031E24CF00FAFCFD32DC76EB5841C7EA8\", // GTS Root R2\n        \"34D8A73EE208D9BCDB0D956520934B4E40E69482596E8B6F73C8426B010A6F48\", // GTS Root R3\n        \"349DFA4058C5E263123B398AE795573C4E1313C83FE68F93556CD5E8031B3C7D\", // GTS Root R4\n        \"242B69742FCB1E5B2ABF98898B94572187544E5B4D9911786573621F6A74B82C\", // Telia Root CA v2\n        \"E59AAA816009C22BFF5B25BAD37DF306F049797C1F81D85AB089E657BD8F0044\", // D-TRUST BR Root CA 1 2020\n        \"08170D1AA36453901A2F959245E347DB0C8D37ABAABC56B81AA100DC958970DB\", // D-TRUST EV Root CA 1 2020\n        \"018E13F0772532CF809BD1B17281867283FC48C6E13BE9C69812854A490C1B05\", // DigiCert TLS ECC P384 Root G5\n        \"371A00DC0533B3721A7EEB40E8419E70799D2B0A0F2C1D80693165F7CEC4AD75\", // DigiCert TLS RSA4096 Root G5\n        \"E8E8176536A60CC2C4E10187C3BEFCA20EF263497018F566D5BEA0F94D0C111B\", // DigiCert SMIME ECC P384 Root G5\n        \"90370D3EFA88BF58C30105BA25104A358460A7FA52DFC2011DF233A0F417912A\", // DigiCert SMIME RSA4096 Root G5\n        \"77B82CD8644C4305F7ACC5CB156B45675004033D51C60C6202A8E0C33467D3A0\", // Certainly Root R1\n        \"B4585F22E4AC756A4E8612A1361C5D9D031A93FD84FEBB778FA3068B0FC42DC2\", // Certainly Root E1\n        \"82BD5D851ACF7F6E1BA7BFCBC53030D0E7BC3C21DF772D858CAB41D199BDF595\", // DIGITALSIGN GLOBAL ROOT RSA CA\n        \"261D7114AE5F8FF2D8C7209A9DE4289E6AFC9D717023D85450909199F1857CFE\", // DIGITALSIGN GLOBAL ROOT ECDSA CA\n        \"E74FBDA55BD564C473A36B441AA799C8A68E077440E8288B9FA1E50E4BBACA11\", // Security Communication ECC RootCA1\n        \"F3896F88FE7C0A882766A7FA6AD2749FB57A7F3E98FB769C1FA7B09C2C44D5AE\", // BJCA Global Root CA1\n        \"574DF6931E278039667B720AFDC1600FC27EB66DD3092979FB73856487212882\", // BJCA Global Root CA2\n        \"48E1CF9E43B688A51044160F46D773B8277FE45BEAAD0E4DF90D1974382FEA99\", // LAWtrust Root CA2 (4096)\n        \"22D9599234D60F1D4BC7C7E96F43FA555B07301FD475175089DAFB8C25E477B3\", // Sectigo Public Email Protection Root E46\n        \"D5917A7791EB7CF20A2E57EB98284A67B28A57E89182DA53D546678C9FDE2B4F\", // Sectigo Public Email Protection Root R46\n        \"C90F26F0FB1B4018B22227519B5CA2B53E2CA5B3BE5CF18EFE1BEF47380C5383\", // Sectigo Public Server Authentication Root E46\n        \"7BB647A62AEEAC88BF257AA522D01FFEA395E0AB45C73F93F65654EC38F25A06\", // Sectigo Public Server Authentication Root R46\n        \"8FAF7D2E2CB4709BB8E0B33666BF75A5DD45B5DE480F8EA8D4BFE6BEBC17F2ED\", // SSL.com TLS RSA Root CA 2022\n        \"C32FFD9F46F936D16C3673990959434B9AD60AAFBB9E7CF33654F144CC1BA143\", // SSL.com TLS ECC Root CA 2022\n        \"AD7DD58D03AEDB22A30B5084394920CE12230C2D8017AD9B81AB04079BDD026B\", // SSL.com Client ECC Root CA 2022\n        \"1D4CA4A2AB21D0093659804FC0EB2175A617279B56A2475245C9517AFEB59153\", // SSL.com Client RSA Root CA 2022\n        \"E38655F4B0190C84D3B3893D840A687E190A256D98052F159E6D4A39F589A6EB\", // Atos TrustedRoot Root CA ECC G2 2020\n        \"78833A783BB2986C254B9370D3C20E5EBA8FA7840CBF63FE17297A0B0119685E\", // Atos TrustedRoot Root CA RSA G2 2020\n        \"B2FAE53E14CCD7AB9212064701AE279C1D8988FACB775FA8A008914E663988A8\", // Atos TrustedRoot Root CA ECC TLS 2021\n        \"81A9088EA59FB364C548A6F85559099B6F0405EFBF18E5324EC9F457BA00112F\", // Atos TrustedRoot Root CA RSA TLS 2021\n        \"E0D3226AEB1163C2E48FF9BE3B50B4C6431BE7BB1EACC5C36B5D5EC509039A08\", // TrustAsia Global Root CA G3\n        \"BE4B56CB5056C0136A526DF444508DAA36A0B54F42E4AC38F72AF470E479654C\", // TrustAsia Global Root CA G4\n        \"D92C171F5CF890BA428019292927FE22F3207FD2B54449CB6F675AF4922146E2\", // D-Trust SBR Root CA 1 2022\n        \"DBA84DD7EF622D485463A90137EA4D574DF8550928F6AFA03B4D8B1141E636CC\", // D-Trust SBR Root CA 2 2022\n        \"3AE6DF7E0D637A65A8C81612EC6F9A142F85A16834C10280D88E707028518755\", // Telekom Security SMIME ECC Root 2021\n        \"578AF4DED0853F4E5998DB4AEAF9CBEA8D945F60B620A38D1A3C13B2BC7BA8E1\", // Telekom Security TLS ECC Root 2020\n        \"78A656344F947E9CC0F734D9053D32F6742086B6B9CD2CAE4FAE1A2E4EFDE048\", // Telekom Security SMIME RSA Root 2023\n        \"EFC65CADBB59ADB6EFE84DA22311B35624B71B3B1EA0DA8B6655174EC8978646\", // Telekom Security TLS RSA Root 2023\n        \"BEF256DAF26E9C69BDEC1602359798F3CAF71821A03E018257C53C65617F3D4A\", // FIRMAPROFESIONAL CA ROOT-A WEB\n        \"3F63BB2814BE174EC8B6439CF08D6D56F0B7C405883A5648A334424D6B3EC558\", // TWCA CYBER Root CA\n        \"3A0072D49FFC04E996C59AEB75991D3C340F3615D6FD4DCE90AC0B3D88EAD4F4\", // TWCA Global Root CA G2\n        \"3F034BB5704D44B2D08545A02057DE93EBF3905FCE721ACBC730C06DDAEE904E\", // SecureSign Root CA12\n        \"4B009C1034494F9AB56BBA3BA1D62731FC4D20D8955ADCEC10A925607261E338\", // SecureSign Root CA14\n        \"E778F0F095FE843729CD1A0082179E5314A9C291442805E1FB1D8FB6B8886C3A\", // SecureSign Root CA15\n        \"0552E6F83FDF65E8FA9670E666DF28A4E21340B510CBE52566F97C4FB94B2BD1\", // D-TRUST BR Root CA 2 2023\n        \"436472C1009A325C54F1A5BBB5468A7BAEECCBE05DE5F099CB70D3FE41E13C16\", // TrustAsia SMIME ECC Root CA\n        \"C7796BEB62C101BB143D262A7C96A0C6168183223EF50D699632D86E03B8CC9B\", // TrustAsia SMIME RSA Root CA\n        \"C0076B9EF0531FB1A656D67C4EBE97CD5DBAA41EF44598ACC2489878C92D8711\", // TrustAsia TLS ECC Root CA\n        \"06C08D7DAFD876971EB1124FE67F847EC0C7A158D3EA53CBE940E2EA9791F4C3\", // TrustAsia TLS RSA Root CA\n        \"8E8221B2E7D4007836A1672F0DCC299C33BC07D316F132FA1A206D587150F1CE\", // D-TRUST EV Root CA 2 2023\n        \"9A12C392BFE57891A0C545309D4D9FD567E480CB613D6342278B195C79A7931F\", // SwissSign RSA SMIME Root CA 2022 - 1\n        \"193144F431E0FDDB740717D4DE926A571133884B4360D30E272913CBE660CE41\", // SwissSign RSA TLS Root CA 2022 - 1\n        \"D9A32485A8CCA85539CEF12FFFFF711378A17851D73DA2732AB4302D763BD62B\", // OISTE Client Root ECC G1\n        \"D02A0F994A868C66395F2E7A880DF509BD0C29C96DE16015A0FD501EDA4F96A9\", // OISTE Client Root RSA G1\n        \"EEC997C0C30F216F7E3B8B307D2BAE42412D753FC8219DAFD1520B2572850F49\", // OISTE Server Root ECC G1\n        \"9AE36232A5189FFDDB353DFD26520C015395D22777DAC59DB57B98C089A651E6\", // OISTE Server Root RSA G1\n        \"B49141502D00663D740F2E7EC340C52800962666121A36D09CF7DD2B90384FB4\", // e-Szigno TLS Root CA 2023\n    };\n\n    /// <summary>\n    /// Get certificate in PEM format from a server with CA pinning validation\n    /// </summary>\n    public async Task<(string?, string?)> GetCertPemAsync(string target, string serverName, int timeout = 4)\n    {\n        try\n        {\n            var (domain, _, port, _) = Utils.ParseUrl(target);\n\n            using var cts = new CancellationTokenSource();\n            cts.CancelAfter(TimeSpan.FromSeconds(timeout));\n\n            using var client = new TcpClient();\n            await client.ConnectAsync(domain, port > 0 ? port : 443, cts.Token);\n\n            await using var ssl = new SslStream(client.GetStream(), false, ValidateServerCertificate);\n\n            var sslOptions = new SslClientAuthenticationOptions\n            {\n                TargetHost = serverName,\n                RemoteCertificateValidationCallback = ValidateServerCertificate\n            };\n\n            await ssl.AuthenticateAsClientAsync(sslOptions, cts.Token);\n\n            var remote = ssl.RemoteCertificate;\n            if (remote == null)\n            {\n                return (null, null);\n            }\n\n            var leaf = new X509Certificate2(remote);\n            return (ExportCertToPem(leaf), null);\n        }\n        catch (OperationCanceledException)\n        {\n            Logging.SaveLog(_tag, new TimeoutException($\"Connection timeout after {timeout} seconds\"));\n            return (null, $\"Connection timeout after {timeout} seconds\");\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return (null, ex.Message);\n        }\n    }\n\n    /// <summary>\n    /// Get certificate chain in PEM format from a server with CA pinning validation\n    /// </summary>\n    public async Task<(List<string>, string?)> GetCertChainPemAsync(string target, string serverName, int timeout = 4)\n    {\n        var pemList = new List<string>();\n        try\n        {\n            var (domain, _, port, _) = Utils.ParseUrl(target);\n\n            using var cts = new CancellationTokenSource();\n            cts.CancelAfter(TimeSpan.FromSeconds(timeout));\n\n            using var client = new TcpClient();\n            await client.ConnectAsync(domain, port > 0 ? port : 443, cts.Token);\n\n            await using var ssl = new SslStream(client.GetStream(), false, ValidateServerCertificate);\n\n            var sslOptions = new SslClientAuthenticationOptions\n            {\n                TargetHost = serverName,\n                RemoteCertificateValidationCallback = ValidateServerCertificate\n            };\n\n            await ssl.AuthenticateAsClientAsync(sslOptions, cts.Token);\n\n            if (ssl.RemoteCertificate is not X509Certificate2 certChain)\n            {\n                return (pemList, null);\n            }\n\n            var chain = new X509Chain();\n            chain.Build(certChain);\n\n            pemList.AddRange(chain.ChainElements.Select(element => ExportCertToPem(element.Certificate)));\n\n            return (pemList, null);\n        }\n        catch (OperationCanceledException)\n        {\n            Logging.SaveLog(_tag, new TimeoutException($\"Connection timeout after {timeout} seconds\"));\n            return (pemList, $\"Connection timeout after {timeout} seconds\");\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return (pemList, ex.Message);\n        }\n    }\n\n    /// <summary>\n    /// Validate server certificate with CA pinning\n    /// </summary>\n    private bool ValidateServerCertificate(\n        object sender,\n        X509Certificate? certificate,\n        X509Chain? chain,\n        SslPolicyErrors sslPolicyErrors)\n    {\n        if (certificate == null)\n        {\n            return false;\n        }\n\n        // Check certificate name mismatch\n        if (sslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateNameMismatch))\n        {\n            return false;\n        }\n\n        // Build certificate chain\n        var cert2 = certificate as X509Certificate2 ?? new X509Certificate2(certificate);\n        var certChain = chain ?? new X509Chain();\n\n        certChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;\n        certChain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;\n        certChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;\n        certChain.ChainPolicy.VerificationTime = DateTime.Now;\n\n        certChain.Build(cert2);\n\n        // Find root CA\n        if (certChain.ChainElements.Count == 0)\n        {\n            return false;\n        }\n\n        var rootCert = certChain.ChainElements[certChain.ChainElements.Count - 1].Certificate;\n        var rootThumbprint = rootCert.GetCertHashString(HashAlgorithmName.SHA256);\n\n        return TrustedCaThumbprints.Contains(rootThumbprint);\n    }\n\n    public static string ExportCertToPem(X509Certificate2 cert)\n    {\n        var der = cert.Export(X509ContentType.Cert);\n        var b64 = Convert.ToBase64String(der);\n        return $\"-----BEGIN CERTIFICATE-----\\n{b64}\\n-----END CERTIFICATE-----\\n\";\n    }\n\n    /// <summary>\n    /// Parse concatenated PEM certificates string into a list of individual certificates\n    /// Normalizes format: removes line breaks from base64 content for better compatibility\n    /// </summary>\n    /// <param name=\"pemChain\">Concatenated PEM certificates string (supports both \\r\\n and \\n line endings)</param>\n    /// <returns>List of individual PEM certificate strings with normalized format</returns>\n    public static List<string> ParsePemChain(string pemChain)\n    {\n        var certs = new List<string>();\n        if (string.IsNullOrWhiteSpace(pemChain))\n        {\n            return certs;\n        }\n\n        // Normalize line endings (CRLF -> LF) at the beginning\n        pemChain = pemChain.Replace(\"\\r\\n\", \"\\n\").Replace(\"\\r\", \"\\n\");\n\n        const string beginMarker = \"-----BEGIN CERTIFICATE-----\";\n        const string endMarker = \"-----END CERTIFICATE-----\";\n\n        var index = 0;\n        while (index < pemChain.Length)\n        {\n            var beginIndex = pemChain.IndexOf(beginMarker, index, StringComparison.Ordinal);\n            if (beginIndex == -1)\n            {\n                break;\n            }\n\n            var endIndex = pemChain.IndexOf(endMarker, beginIndex, StringComparison.Ordinal);\n            if (endIndex == -1)\n            {\n                break;\n            }\n\n            // Extract certificate content\n            var base64Start = beginIndex + beginMarker.Length;\n            var base64Content = pemChain.Substring(base64Start, endIndex - base64Start);\n\n            // Remove all whitespace from base64 content\n            base64Content = new string(base64Content.Where(c => !char.IsWhiteSpace(c)).ToArray());\n\n            // Reconstruct with clean format: BEGIN marker + base64 (no line breaks) + END marker\n            var normalizedCert = $\"{beginMarker}\\n{base64Content}\\n{endMarker}\\n\";\n            certs.Add(normalizedCert);\n\n            // Move to next certificate\n            index = endIndex + endMarker.Length;\n        }\n\n        return certs;\n    }\n\n    /// <summary>\n    /// Concatenate a list of PEM certificates into a single string\n    /// </summary>\n    /// <param name=\"pemList\">List of individual PEM certificate strings</param>\n    /// <returns>Concatenated PEM certificates string</returns>\n    public static string ConcatenatePemChain(IEnumerable<string> pemList)\n    {\n        if (pemList == null)\n        {\n            return string.Empty;\n        }\n\n        return string.Concat(pemList);\n    }\n\n    public static string GetCertSha256Thumbprint(string pemCert, bool includeColon = false)\n    {\n        try\n        {\n            var cert = X509Certificate2.CreateFromPem(pemCert);\n            var thumbprint = cert.GetCertHashString(HashAlgorithmName.SHA256);\n            if (includeColon)\n            {\n                return string.Join(\":\", thumbprint.Chunk(2).Select(c => new string(c)));\n            }\n            return thumbprint;\n        }\n        catch\n        {\n            return string.Empty;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/ClashApiManager.cs",
    "content": "using static ServiceLib.Models.ClashProxies;\n\nnamespace ServiceLib.Manager;\n\npublic sealed class ClashApiManager\n{\n    private static readonly Lazy<ClashApiManager> instance = new(() => new());\n    public static ClashApiManager Instance => instance.Value;\n\n    private static readonly string _tag = \"ClashApiHandler\";\n    private Dictionary<string, ProxiesItem>? _proxies;\n    public Dictionary<string, object> ProfileContent { get; set; }\n\n    public async Task<Tuple<ClashProxies, ClashProviders>?> GetClashProxiesAsync()\n    {\n        for (var i = 0; i < 3; i++)\n        {\n            var url = $\"{GetApiUrl()}/proxies\";\n            var result = await HttpClientHelper.Instance.TryGetAsync(url);\n            var clashProxies = JsonUtils.Deserialize<ClashProxies>(result);\n\n            var url2 = $\"{GetApiUrl()}/providers/proxies\";\n            var result2 = await HttpClientHelper.Instance.TryGetAsync(url2);\n            var clashProviders = JsonUtils.Deserialize<ClashProviders>(result2);\n\n            if (clashProxies != null || clashProviders != null)\n            {\n                _proxies = clashProxies?.proxies;\n                return new Tuple<ClashProxies, ClashProviders>(clashProxies, clashProviders);\n            }\n\n            await Task.Delay(2000);\n        }\n\n        return null;\n    }\n\n    public void ClashProxiesDelayTest(bool blAll, List<ClashProxyModel> lstProxy, Func<ClashProxyModel?, string, Task> updateFunc)\n    {\n        Task.Run(async () =>\n        {\n            if (blAll)\n            {\n                if (_proxies == null)\n                {\n                    await GetClashProxiesAsync();\n                }\n                lstProxy = new List<ClashProxyModel>();\n                foreach (var kv in _proxies ?? [])\n                {\n                    if (Global.notAllowTestType.Contains(kv.Value.type?.ToLower()))\n                    {\n                        continue;\n                    }\n                    lstProxy.Add(new ClashProxyModel()\n                    {\n                        Name = kv.Value.name,\n                        Type = kv.Value.type?.ToLower(),\n                    });\n                }\n            }\n\n            if (lstProxy is not { Count: > 0 })\n            {\n                return;\n            }\n            var urlBase = $\"{GetApiUrl()}/proxies\";\n            urlBase += @\"/{0}/delay?timeout=10000&url=\" + AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl;\n\n            var tasks = new List<Task>();\n            foreach (var it in lstProxy)\n            {\n                if (Global.notAllowTestType.Contains(it.Type.ToLower()))\n                {\n                    continue;\n                }\n                var name = it.Name;\n                var url = string.Format(urlBase, name);\n                tasks.Add(Task.Run(async () =>\n                {\n                    var result = await HttpClientHelper.Instance.TryGetAsync(url);\n                    await updateFunc?.Invoke(it, result);\n                }));\n            }\n            await Task.WhenAll(tasks);\n            await Task.Delay(1000);\n            await updateFunc?.Invoke(null, \"\");\n        });\n    }\n\n    public List<ProxiesItem>? GetClashProxyGroups()\n    {\n        try\n        {\n            var fileContent = ProfileContent;\n            if (fileContent is null || fileContent?.ContainsKey(\"proxy-groups\") == false)\n            {\n                return null;\n            }\n            return JsonUtils.Deserialize<List<ProxiesItem>>(JsonUtils.Serialize(fileContent[\"proxy-groups\"]));\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return null;\n        }\n    }\n\n    public async Task ClashSetActiveProxy(string name, string nameNode)\n    {\n        try\n        {\n            var url = $\"{GetApiUrl()}/proxies/{name}\";\n            var headers = new Dictionary<string, string>();\n            headers.Add(\"name\", nameNode);\n            await HttpClientHelper.Instance.PutAsync(url, headers);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public async Task ClashConfigUpdate(Dictionary<string, string> headers)\n    {\n        if (_proxies == null)\n        {\n            return;\n        }\n\n        var urlBase = $\"{GetApiUrl()}/configs\";\n\n        await HttpClientHelper.Instance.PatchAsync(urlBase, headers);\n    }\n\n    public async Task ClashConfigReload(string filePath)\n    {\n        await ClashConnectionClose(\"\");\n        try\n        {\n            var url = $\"{GetApiUrl()}/configs?force=true\";\n            var headers = new Dictionary<string, string>();\n            headers.Add(\"path\", filePath);\n            await HttpClientHelper.Instance.PutAsync(url, headers);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public async Task<ClashConnections?> GetClashConnectionsAsync()\n    {\n        try\n        {\n            var url = $\"{GetApiUrl()}/connections\";\n            var result = await HttpClientHelper.Instance.TryGetAsync(url);\n            var clashConnections = JsonUtils.Deserialize<ClashConnections>(result);\n\n            return clashConnections;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        return null;\n    }\n\n    public async Task ClashConnectionClose(string id)\n    {\n        try\n        {\n            var url = $\"{GetApiUrl()}/connections/{id}\";\n            await HttpClientHelper.Instance.DeleteAsync(url);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private string GetApiUrl()\n    {\n        return $\"{Global.HttpProtocol}{Global.Loopback}:{AppManager.Instance.StatePort2}\";\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/CoreAdminManager.cs",
    "content": "using CliWrap;\nusing CliWrap.Buffered;\n\nnamespace ServiceLib.Manager;\n\npublic class CoreAdminManager\n{\n    private static readonly Lazy<CoreAdminManager> _instance = new(() => new());\n    public static CoreAdminManager Instance => _instance.Value;\n    private Config _config;\n    private Func<bool, string, Task>? _updateFunc;\n    private int _linuxSudoPid = -1;\n    private const string _tag = \"CoreAdminHandler\";\n\n    public async Task Init(Config config, Func<bool, string, Task> updateFunc)\n    {\n        if (_config != null)\n        {\n            return;\n        }\n        _config = config;\n        _updateFunc = updateFunc;\n\n        await Task.CompletedTask;\n    }\n\n    private async Task UpdateFunc(bool notify, string msg)\n    {\n        await _updateFunc?.Invoke(notify, msg);\n    }\n\n    public async Task<ProcessService?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath)\n    {\n        StringBuilder sb = new();\n        sb.AppendLine(\"#!/bin/bash\");\n        var cmdLine = $\"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}\";\n        sb.AppendLine($\"exec sudo -S -- {cmdLine}\");\n        var shFilePath = await FileUtils.CreateLinuxShellFile(\"run_as_sudo.sh\", sb.ToString(), true);\n\n        var procService = new ProcessService(\n            fileName: shFilePath,\n            arguments: \"\",\n            workingDirectory: Utils.GetBinConfigPath(),\n            displayLog: true,\n            redirectInput: true,\n            environmentVars: null,\n            updateFunc: _updateFunc\n        );\n\n        await procService.StartAsync(AppManager.Instance.LinuxSudoPwd);\n\n        if (procService is null or { HasExited: true })\n        {\n            throw new Exception(ResUI.FailedToRunCore);\n        }\n        _linuxSudoPid = procService.Id;\n\n        return procService;\n    }\n\n    public async Task KillProcessAsLinuxSudo()\n    {\n        if (_linuxSudoPid < 0)\n        {\n            return;\n        }\n\n        try\n        {\n            var shellFileName = Utils.IsMacOS() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName;\n            var shFilePath = await FileUtils.CreateLinuxShellFile(\"kill_as_sudo.sh\", EmbedUtils.GetEmbedText(shellFileName), true);\n            if (shFilePath.Contains(' '))\n            {\n                shFilePath = shFilePath.AppendQuotes();\n            }\n            var arg = new List<string>() { \"-c\", $\"sudo -S {shFilePath} {_linuxSudoPid}\" };\n            var result = await Cli.Wrap(Global.LinuxBash)\n                .WithArguments(arg)\n                .WithStandardInputPipe(PipeSource.FromString(AppManager.Instance.LinuxSudoPwd))\n                .ExecuteBufferedAsync();\n\n            await UpdateFunc(false, result.StandardOutput.ToString());\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n\n        _linuxSudoPid = -1;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/CoreInfoManager.cs",
    "content": "namespace ServiceLib.Manager;\n\npublic sealed class CoreInfoManager\n{\n    private static readonly Lazy<CoreInfoManager> _instance = new(() => new());\n    private List<CoreInfo>? _coreInfo;\n    public static CoreInfoManager Instance => _instance.Value;\n\n    public CoreInfoManager()\n    {\n        InitCoreInfo();\n    }\n\n    public CoreInfo? GetCoreInfo(ECoreType coreType)\n    {\n        if (_coreInfo == null)\n        {\n            InitCoreInfo();\n        }\n        return _coreInfo?.FirstOrDefault(t => t.CoreType == coreType);\n    }\n\n    public List<CoreInfo> GetCoreInfo()\n    {\n        if (_coreInfo == null)\n        {\n            InitCoreInfo();\n        }\n        return _coreInfo ?? [];\n    }\n\n    public string GetCoreExecFile(CoreInfo? coreInfo, out string msg)\n    {\n        var fileName = string.Empty;\n        msg = string.Empty;\n        foreach (var name in coreInfo?.CoreExes)\n        {\n            var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());\n            if (File.Exists(vName))\n            {\n                fileName = vName;\n                break;\n            }\n        }\n        if (fileName.IsNullOrEmpty())\n        {\n            msg = string.Format(ResUI.NotFoundCore, Utils.GetBinPath(\"\", coreInfo?.CoreType.ToString()), coreInfo?.CoreExes?.LastOrDefault(), coreInfo?.Url);\n            Logging.SaveLog(msg);\n        }\n        return fileName;\n    }\n\n    private void InitCoreInfo()\n    {\n        var urlN = GetCoreUrl(ECoreType.v2rayN);\n        var urlXray = GetCoreUrl(ECoreType.Xray);\n        var urlMihomo = GetCoreUrl(ECoreType.mihomo);\n        var urlSingbox = GetCoreUrl(ECoreType.sing_box);\n\n        _coreInfo =\n        [\n            new CoreInfo\n                {\n                    CoreType = ECoreType.v2rayN,\n                    Url = GetCoreUrl(ECoreType.v2rayN),\n                    ReleaseApiUrl = urlN.Replace(Global.GithubUrl, Global.GithubApiUrl),\n                    DownloadUrlWin64 = urlN + \"/download/{0}/v2rayN-windows-64.zip\",\n                    DownloadUrlWinArm64 = urlN + \"/download/{0}/v2rayN-windows-arm64.zip\",\n                    DownloadUrlLinux64 = urlN + \"/download/{0}/v2rayN-linux-64.zip\",\n                    DownloadUrlLinuxArm64 = urlN + \"/download/{0}/v2rayN-linux-arm64.zip\",\n                    DownloadUrlOSX64 = urlN + \"/download/{0}/v2rayN-macos-64.zip\",\n                    DownloadUrlOSXArm64 = urlN + \"/download/{0}/v2rayN-macos-arm64.zip\",\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.v2fly,\n                    CoreExes = [\"v2ray\"],\n                    Arguments = \"{0}\",\n                    Url = GetCoreUrl(ECoreType.v2fly),\n                    Match = \"V2Ray\",\n                    VersionArg = \"-version\",\n                    Environment = new Dictionary<string, string?>()\n                    {\n                        { Global.V2RayLocalAsset, Utils.GetBinPath(\"\") },\n                    },\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.v2fly_v5,\n                    CoreExes = [\"v2ray\"],\n                    Arguments = \"run -c {0} -format jsonv5\",\n                    Url = GetCoreUrl(ECoreType.v2fly_v5),\n                    Match = \"V2Ray\",\n                    VersionArg = \"version\",\n                    Environment = new Dictionary<string, string?>()\n                    {\n                        { Global.V2RayLocalAsset, Utils.GetBinPath(\"\") },\n                    },\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.Xray,\n                    CoreExes = [\"xray\"],\n                    Arguments = \"run -c {0}\",\n                    Url = GetCoreUrl(ECoreType.Xray),\n                    ReleaseApiUrl = urlXray.Replace(Global.GithubUrl, Global.GithubApiUrl),\n                    DownloadUrlWin64 = urlXray + \"/download/{0}/Xray-windows-64.zip\",\n                    DownloadUrlWinArm64 = urlXray + \"/download/{0}/Xray-windows-arm64-v8a.zip\",\n                    DownloadUrlLinux64 = urlXray + \"/download/{0}/Xray-linux-64.zip\",\n                    DownloadUrlLinuxArm64 = urlXray + \"/download/{0}/Xray-linux-arm64-v8a.zip\",\n                    DownloadUrlOSX64 = urlXray + \"/download/{0}/Xray-macos-64.zip\",\n                    DownloadUrlOSXArm64 = urlXray + \"/download/{0}/Xray-macos-arm64-v8a.zip\",\n                    Match = \"Xray\",\n                    VersionArg = \"-version\",\n                    Environment = new Dictionary<string, string?>()\n                    {\n                        { Global.XrayLocalAsset, Utils.GetBinPath(\"\") },\n                        { Global.XrayLocalCert, Utils.GetBinPath(\"\") },\n                    },\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.mihomo,\n                    CoreExes = GetMihomoCoreExes(),\n                    Arguments = \"-f {0}\" + PortableMode(),\n                    Url = GetCoreUrl(ECoreType.mihomo),\n                    ReleaseApiUrl = urlMihomo.Replace(Global.GithubUrl, Global.GithubApiUrl),\n                    DownloadUrlWin64 = urlMihomo + \"/download/{0}/mihomo-windows-amd64-v1-{0}.zip\",\n                    DownloadUrlWinArm64 = urlMihomo + \"/download/{0}/mihomo-windows-arm64-{0}.zip\",\n                    DownloadUrlLinux64 = urlMihomo + \"/download/{0}/mihomo-linux-amd64-v1-{0}.gz\",\n                    DownloadUrlLinuxArm64 = urlMihomo + \"/download/{0}/mihomo-linux-arm64-{0}.gz\",\n                    DownloadUrlOSX64 = urlMihomo + \"/download/{0}/mihomo-darwin-amd64-v1-{0}.gz\",\n                    DownloadUrlOSXArm64 = urlMihomo + \"/download/{0}/mihomo-darwin-arm64-{0}.gz\",\n                    Match = \"Mihomo\",\n                    VersionArg = \"-v\",\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.hysteria,\n                    CoreExes = [\"hysteria\"],\n                    Arguments = \"\",\n                    Url = GetCoreUrl(ECoreType.hysteria),\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.naiveproxy,\n                    CoreExes = [ \"naive\", \"naiveproxy\"],\n                    Arguments = \"{0}\",\n                    Url = GetCoreUrl(ECoreType.naiveproxy),\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.tuic,\n                    CoreExes = [\"tuic-client\", \"tuic\"],\n                    Arguments = \"-c {0}\",\n                    Url = GetCoreUrl(ECoreType.tuic),\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.sing_box,\n                    CoreExes = [\"sing-box-client\", \"sing-box\"],\n                    Arguments = \"run -c {0} --disable-color\",\n                    Url = GetCoreUrl(ECoreType.sing_box),\n\n                    ReleaseApiUrl = urlSingbox.Replace(Global.GithubUrl, Global.GithubApiUrl),\n                    DownloadUrlWin64 = urlSingbox + \"/download/{0}/sing-box-{1}-windows-amd64.zip\",\n                    DownloadUrlWinArm64 = urlSingbox + \"/download/{0}/sing-box-{1}-windows-arm64.zip\",\n                    DownloadUrlLinux64 = urlSingbox + \"/download/{0}/sing-box-{1}-linux-amd64.tar.gz\",\n                    DownloadUrlLinuxArm64 = urlSingbox + \"/download/{0}/sing-box-{1}-linux-arm64.tar.gz\",\n                    DownloadUrlOSX64 = urlSingbox + \"/download/{0}/sing-box-{1}-darwin-amd64.tar.gz\",\n                    DownloadUrlOSXArm64 = urlSingbox + \"/download/{0}/sing-box-{1}-darwin-arm64.tar.gz\",\n                    Match = \"sing-box\",\n                    VersionArg = \"version\",\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.juicity,\n                    CoreExes = [\"juicity-client\", \"juicity\"],\n                    Arguments = \"run -c {0}\",\n                    Url = GetCoreUrl(ECoreType.juicity)\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.hysteria2,\n                    CoreExes = [\"hysteria-windows-amd64\", \"hysteria-linux-amd64\", \"hysteria\"],\n                    Arguments = \"\",\n                    Url = GetCoreUrl(ECoreType.hysteria2),\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.brook,\n                    CoreExes = [\"brook_windows_amd64\", \"brook_linux_amd64\", \"brook\"],\n                    Arguments = \" {0}\",\n                    Url = GetCoreUrl(ECoreType.brook),\n                    AbsolutePath = true,\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.overtls,\n                    CoreExes = [ \"overtls-bin\", \"overtls\"],\n                    Arguments = \"-r client -c {0}\",\n                    Url =  GetCoreUrl(ECoreType.overtls),\n                    AbsolutePath = false,\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.shadowquic,\n                    CoreExes = [ \"shadowquic\" ],\n                    Arguments = \"-c {0}\",\n                    Url =  GetCoreUrl(ECoreType.shadowquic),\n                    AbsolutePath = false,\n                },\n\n                new CoreInfo\n                {\n                    CoreType = ECoreType.mieru,\n                    CoreExes = [ \"mieru\" ],\n                    Arguments = \"run\",\n                    Url =  GetCoreUrl(ECoreType.mieru),\n                    AbsolutePath = false,\n                    Environment = new Dictionary<string, string?>()\n                    {\n                        { \"MIERU_CONFIG_JSON_FILE\", \"{0}\" },\n                    },\n                },\n        ];\n    }\n\n    private static string PortableMode()\n    {\n        return $\" -d {Utils.GetBinPath(\"\").AppendQuotes()}\";\n    }\n\n    private static string GetCoreUrl(ECoreType eCoreType)\n    {\n        return $\"{Global.GithubUrl}/{Global.CoreUrls[eCoreType]}/releases\";\n    }\n\n    private static List<string>? GetMihomoCoreExes()\n    {\n        var names = new List<string>();\n\n        if (Utils.IsWindows())\n        {\n            names.Add(\"mihomo-windows-amd64-v1\");\n            names.Add(\"mihomo-windows-amd64-compatible\");\n            names.Add(\"mihomo-windows-amd64\");\n            names.Add(\"mihomo-windows-arm64\");\n        }\n        else if (Utils.IsLinux())\n        {\n            names.Add(\"mihomo-linux-amd64-v1\");\n            names.Add(\"mihomo-linux-amd64\");\n            names.Add(\"mihomo-linux-arm64\");\n        }\n        else if (Utils.IsMacOS())\n        {\n            names.Add(\"mihomo-darwin-amd64-v1\");\n            names.Add(\"mihomo-darwin-amd64\");\n            names.Add(\"mihomo-darwin-arm64\");\n        }\n\n        names.Add(\"clash\");\n        names.Add(\"mihomo\");\n\n        return names;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/CoreManager.cs",
    "content": "namespace ServiceLib.Manager;\n\n/// <summary>\n/// Core process processing class\n/// </summary>\npublic class CoreManager\n{\n    private static readonly Lazy<CoreManager> _instance = new(() => new());\n    public static CoreManager Instance => _instance.Value;\n    private Config _config;\n    private WindowsJobService? _processJob;\n    private ProcessService? _processService;\n    private ProcessService? _processPreService;\n    private bool _linuxSudo = false;\n    private Func<bool, string, Task>? _updateFunc;\n    private const string _tag = \"CoreHandler\";\n\n    public async Task Init(Config config, Func<bool, string, Task> updateFunc)\n    {\n        _config = config;\n        _updateFunc = updateFunc;\n\n        //Copy the bin folder to the storage location (for init)\n        if (Environment.GetEnvironmentVariable(Global.LocalAppData) == \"1\")\n        {\n            var fromPath = Utils.GetBaseDirectory(\"bin\");\n            var toPath = Utils.GetBinPath(\"\");\n            if (fromPath != toPath)\n            {\n                FileUtils.CopyDirectory(fromPath, toPath, true, false);\n            }\n        }\n\n        if (Utils.IsNonWindows())\n        {\n            var coreInfo = CoreInfoManager.Instance.GetCoreInfo();\n            foreach (var it in coreInfo)\n            {\n                if (it.CoreType == ECoreType.v2rayN)\n                {\n                    if (Utils.UpgradeAppExists(out var upgradeFileName))\n                    {\n                        await Utils.SetLinuxChmod(upgradeFileName);\n                    }\n                    continue;\n                }\n\n                foreach (var name in it.CoreExes)\n                {\n                    var exe = Utils.GetBinPath(Utils.GetExeName(name), it.CoreType.ToString());\n                    if (File.Exists(exe))\n                    {\n                        await Utils.SetLinuxChmod(exe);\n                    }\n                }\n            }\n        }\n    }\n\n    /// <param name=\"mainContext\">Resolved main context (with pre-socks ports already merged if applicable).</param>\n    /// <param name=\"preContext\">Optional pre-socks context passed to <see cref=\"CoreStartPreService\"/>.</param>\n    public async Task LoadCore(CoreConfigContext? mainContext, CoreConfigContext? preContext)\n    {\n        if (mainContext == null)\n        {\n            await UpdateFunc(false, ResUI.CheckServerSettings);\n            return;\n        }\n\n        var node = mainContext.Node;\n        var fileName = Utils.GetBinConfigPath(Global.CoreConfigFileName);\n        var result = await CoreConfigHandler.GenerateClientConfig(mainContext, fileName);\n        if (result.Success != true)\n        {\n            await UpdateFunc(true, result.Msg);\n            return;\n        }\n\n        await UpdateFunc(false, $\"{node.GetSummary()}\");\n        await UpdateFunc(false, $\"{Utils.GetRuntimeInfo()}\");\n        await UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")));\n        await CoreStop();\n        await Task.Delay(100);\n\n        if (Utils.IsWindows() && _config.TunModeItem.EnableTun)\n        {\n            await Task.Delay(100);\n            await WindowsUtils.RemoveTunDevice();\n        }\n\n        await CoreStart(mainContext);\n        await CoreStartPreService(preContext);\n        if (_processService != null)\n        {\n            await UpdateFunc(true, $\"{node.GetSummary()}\");\n        }\n    }\n\n    public async Task<ProcessService?> LoadCoreConfigSpeedtest(List<ServerTestItem> selecteds)\n    {\n        var coreType = selecteds.FirstOrDefault()?.CoreType == ECoreType.sing_box ? ECoreType.sing_box : ECoreType.Xray;\n        var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));\n        var configPath = Utils.GetBinConfigPath(fileName);\n        var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, configPath, selecteds, coreType);\n        await UpdateFunc(false, result.Msg);\n        if (result.Success != true)\n        {\n            return null;\n        }\n\n        await UpdateFunc(false, string.Format(ResUI.StartService, DateTime.Now.ToString(\"yyyy/MM/dd HH:mm:ss\")));\n        await UpdateFunc(false, configPath);\n\n        var coreInfo = CoreInfoManager.Instance.GetCoreInfo(coreType);\n        return await RunProcess(coreInfo, fileName, true, false);\n    }\n\n    public async Task<ProcessService?> LoadCoreConfigSpeedtest(ServerTestItem testItem)\n    {\n        var node = await AppManager.Instance.GetProfileItem(testItem.IndexId);\n        if (node is null)\n        {\n            return null;\n        }\n\n        var fileName = string.Format(Global.CoreSpeedtestConfigFileName, Utils.GetGuid(false));\n        var configPath = Utils.GetBinConfigPath(fileName);\n        var (context, _) = await CoreConfigContextBuilder.Build(_config, node);\n        var result = await CoreConfigHandler.GenerateClientSpeedtestConfig(_config, context, testItem, configPath);\n        if (result.Success != true)\n        {\n            return null;\n        }\n\n        var coreType = context.RunCoreType;\n        var coreInfo = CoreInfoManager.Instance.GetCoreInfo(coreType);\n        return await RunProcess(coreInfo, fileName, true, false);\n    }\n\n    public async Task CoreStop()\n    {\n        try\n        {\n            if (_linuxSudo)\n            {\n                await CoreAdminManager.Instance.KillProcessAsLinuxSudo();\n                _linuxSudo = false;\n            }\n\n            if (_processService != null)\n            {\n                await _processService.StopAsync();\n                _processService.Dispose();\n                _processService = null;\n            }\n\n            if (_processPreService != null)\n            {\n                await _processPreService.StopAsync();\n                _processPreService.Dispose();\n                _processPreService = null;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    #region Private\n\n    private async Task CoreStart(CoreConfigContext context)\n    {\n        var node = context.Node;\n        var coreType = AppManager.Instance.RunningCoreType = AppManager.Instance.GetCoreType(node, node.ConfigType);\n        var coreInfo = CoreInfoManager.Instance.GetCoreInfo(coreType);\n\n        var displayLog = node.ConfigType != EConfigType.Custom || node.DisplayLog;\n        var proc = await RunProcess(coreInfo, Global.CoreConfigFileName, displayLog, true);\n        if (proc is null)\n        {\n            return;\n        }\n        _processService = proc;\n    }\n\n    private async Task CoreStartPreService(CoreConfigContext? preContext)\n    {\n        if (_processService is { HasExited: false } && preContext != null)\n        {\n            var preCoreType = preContext?.Node?.CoreType ?? ECoreType.sing_box;\n            var fileName = Utils.GetBinConfigPath(Global.CorePreConfigFileName);\n            var result = await CoreConfigHandler.GenerateClientConfig(preContext, fileName);\n            if (result.Success)\n            {\n                var coreInfo = CoreInfoManager.Instance.GetCoreInfo(preCoreType);\n                var proc = await RunProcess(coreInfo, Global.CorePreConfigFileName, true, true);\n                if (proc is null)\n                {\n                    return;\n                }\n                _processPreService = proc;\n            }\n        }\n    }\n\n    private async Task UpdateFunc(bool notify, string msg)\n    {\n        await _updateFunc?.Invoke(notify, msg);\n    }\n\n    #endregion Private\n\n    #region Process\n\n    private async Task<ProcessService?> RunProcess(CoreInfo? coreInfo, string configPath, bool displayLog, bool mayNeedSudo)\n    {\n        var fileName = CoreInfoManager.Instance.GetCoreExecFile(coreInfo, out var msg);\n        if (fileName.IsNullOrEmpty())\n        {\n            await UpdateFunc(false, msg);\n            return null;\n        }\n\n        try\n        {\n            if (mayNeedSudo\n                && _config.TunModeItem.EnableTun\n                && (coreInfo.CoreType is ECoreType.sing_box or ECoreType.mihomo)\n                && Utils.IsNonWindows())\n            {\n                _linuxSudo = true;\n                await CoreAdminManager.Instance.Init(_config, _updateFunc);\n                return await CoreAdminManager.Instance.RunProcessAsLinuxSudo(fileName, coreInfo, configPath);\n            }\n\n            return await RunProcessNormal(fileName, coreInfo, configPath, displayLog);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            await UpdateFunc(mayNeedSudo, ex.Message);\n            return null;\n        }\n    }\n\n    private async Task<ProcessService?> RunProcessNormal(string fileName, CoreInfo? coreInfo, string configPath, bool displayLog)\n    {\n        var environmentVars = new Dictionary<string, string>();\n        foreach (var kv in coreInfo.Environment)\n        {\n            environmentVars[kv.Key] = string.Format(kv.Value, coreInfo.AbsolutePath ? Utils.GetBinConfigPath(configPath).AppendQuotes() : configPath);\n        }\n\n        var procService = new ProcessService(\n            fileName: fileName,\n            arguments: string.Format(coreInfo.Arguments, coreInfo.AbsolutePath ? Utils.GetBinConfigPath(configPath).AppendQuotes() : configPath),\n            workingDirectory: Utils.GetBinConfigPath(),\n            displayLog: displayLog,\n            redirectInput: false,\n            environmentVars: environmentVars,\n            updateFunc: _updateFunc\n        );\n\n        await procService.StartAsync();\n\n        await Task.Delay(100);\n\n        if (procService is null or { HasExited: true })\n        {\n            throw new Exception(ResUI.FailedToRunCore);\n        }\n        AddProcessJob(procService.Handle);\n\n        return procService;\n    }\n\n    private void AddProcessJob(nint processHandle)\n    {\n        if (Utils.IsWindows())\n        {\n            _processJob ??= new();\n            try\n            {\n                _processJob?.AddProcess(processHandle);\n            }\n            catch { }\n        }\n    }\n\n    #endregion Process\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/GroupProfileManager.cs",
    "content": "namespace ServiceLib.Manager;\n\npublic class GroupProfileManager\n{\n    public static async Task<bool> HasCycle(ProfileItem item)\n    {\n        return await HasCycle(item.IndexId, item.GetProtocolExtra());\n    }\n\n    public static async Task<bool> HasCycle(string? indexId, ProtocolExtraItem? extraInfo)\n    {\n        return await HasCycle(indexId, extraInfo, new HashSet<string>(), new HashSet<string>());\n    }\n\n    private static async Task<bool> HasCycle(string? indexId, ProtocolExtraItem? extraInfo, HashSet<string> visited, HashSet<string> stack)\n    {\n        if (indexId.IsNullOrEmpty() || extraInfo == null)\n        {\n            return false;\n        }\n\n        if (stack.Contains(indexId))\n        {\n            return true;\n        }\n\n        if (visited.Contains(indexId))\n        {\n            return false;\n        }\n\n        visited.Add(indexId);\n        stack.Add(indexId);\n\n        try\n        {\n            if (extraInfo.GroupType.IsNullOrEmpty())\n            {\n                return false;\n            }\n\n            if (extraInfo.ChildItems.IsNullOrEmpty())\n            {\n                return false;\n            }\n\n            var childIds = Utils.String2List(extraInfo.ChildItems)\n                ?.Where(p => !string.IsNullOrEmpty(p))\n                .ToList();\n            if (childIds == null)\n            {\n                return false;\n            }\n\n            var childItems = await AppManager.Instance.GetProfileItemsByIndexIds(childIds);\n            foreach (var childItem in childItems)\n            {\n                if (await HasCycle(childItem.IndexId, childItem?.GetProtocolExtra(), visited, stack))\n                {\n                    return true;\n                }\n            }\n\n            return false;\n        }\n        finally\n        {\n            stack.Remove(indexId);\n        }\n    }\n\n    public static async Task<(List<ProfileItem> Items, ProtocolExtraItem? Extra)> GetChildProfileItems(ProfileItem profileItem)\n    {\n        var protocolExtra = profileItem?.GetProtocolExtra();\n        return (await GetChildProfileItemsByProtocolExtra(protocolExtra), protocolExtra);\n    }\n\n    public static async Task<List<ProfileItem>> GetChildProfileItemsByProtocolExtra(ProtocolExtraItem? protocolExtra)\n    {\n        if (protocolExtra == null)\n        {\n            return [];\n        }\n\n        var items = new List<ProfileItem>();\n        items.AddRange(await GetSubChildProfileItems(protocolExtra));\n        items.AddRange(await GetSelectedChildProfileItems(protocolExtra));\n\n        return items;\n    }\n\n    private static async Task<List<ProfileItem>> GetSelectedChildProfileItems(ProtocolExtraItem? extra)\n    {\n        if (extra == null || extra.ChildItems.IsNullOrEmpty())\n        {\n            return [];\n        }\n        var childProfileIds = Utils.String2List(extra.ChildItems)\n            ?.Where(p => !string.IsNullOrEmpty(p))\n            .ToList() ?? [];\n        if (childProfileIds.Count == 0)\n        {\n            return [];\n        }\n\n        var ordered = await AppManager.Instance.GetProfileItemsOrderedByIndexIds(childProfileIds);\n        return ordered;\n    }\n\n    private static async Task<List<ProfileItem>> GetSubChildProfileItems(ProtocolExtraItem? extra)\n    {\n        if (extra == null || extra.SubChildItems.IsNullOrEmpty())\n        {\n            return [];\n        }\n        var childProfiles = await AppManager.Instance.ProfileItems(extra.SubChildItems ?? string.Empty);\n\n        return childProfiles?.Where(p =>\n                p != null &&\n                p.IsValid() &&\n                !p.ConfigType.IsComplexType() &&\n                (extra.Filter.IsNullOrEmpty() || Regex.IsMatch(p.Remarks, extra.Filter))\n            )\n            .ToList() ?? [];\n    }\n\n    public static async Task<Dictionary<string, ProfileItem>> GetAllChildProfileItems(ProfileItem profileItem)\n    {\n        var itemMap = new Dictionary<string, ProfileItem>();\n        var visited = new HashSet<string>();\n\n        await CollectChildItems(profileItem, itemMap, visited);\n\n        return itemMap;\n    }\n\n    private static async Task CollectChildItems(ProfileItem profileItem, Dictionary<string, ProfileItem> itemMap,\n        HashSet<string> visited)\n    {\n        var (childItems, _) = await GetChildProfileItems(profileItem);\n        foreach (var child in childItems.Where(child => visited.Add(child.IndexId)))\n        {\n            itemMap[child.IndexId] = child;\n\n            if (child.ConfigType.IsGroupType())\n            {\n                await CollectChildItems(child, itemMap, visited);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/NoticeManager.cs",
    "content": "namespace ServiceLib.Manager;\n\npublic class NoticeManager\n{\n    private static readonly Lazy<NoticeManager> _instance = new(() => new());\n    public static NoticeManager Instance => _instance.Value;\n\n    public void Enqueue(string? content)\n    {\n        if (content.IsNullOrEmpty())\n        {\n            return;\n        }\n        AppEvents.SendSnackMsgRequested.Publish(content);\n    }\n\n    public void SendMessage(string? content)\n    {\n        if (content.IsNullOrEmpty())\n        {\n            return;\n        }\n        AppEvents.SendMsgViewRequested.Publish(content);\n    }\n\n    public void SendMessageEx(string? content)\n    {\n        if (content.IsNullOrEmpty())\n        {\n            return;\n        }\n        content = $\"{DateTime.Now:yyyy/MM/dd HH:mm:ss} {content}\";\n        SendMessage(content);\n    }\n\n    public void SendMessageAndEnqueue(string? msg)\n    {\n        Enqueue(msg);\n        SendMessage(msg);\n    }\n\n    /// <summary>\n    /// Sends each error and warning in <paramref name=\"validatorResult\"/> to the message panel\n    /// and enqueues a summary snack notification (capped at 10 messages).\n    /// Returns <c>true</c> when there were any messages so the caller can decide on early-return\n    /// based on <see cref=\"NodeValidatorResult.Success\"/>.\n    /// </summary>\n    public bool NotifyValidatorResult(NodeValidatorResult validatorResult)\n    {\n        var msgs = new List<string>([.. validatorResult.Errors, .. validatorResult.Warnings]);\n        if (msgs.Count == 0)\n        {\n            return false;\n        }\n        foreach (var msg in msgs)\n        {\n            SendMessage(msg);\n        }\n        Enqueue(Utils.List2String(msgs.Take(10).ToList(), true));\n        return true;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/PacManager.cs",
    "content": "namespace ServiceLib.Manager;\n\npublic class PacManager\n{\n    private static readonly Lazy<PacManager> _instance = new(() => new PacManager());\n    public static PacManager Instance => _instance.Value;\n\n    private int _httpPort;\n    private int _pacPort;\n    private TcpListener? _tcpListener;\n    private byte[] _writeContent;\n    private bool _isRunning;\n    private bool _needRestart = true;\n\n    public async Task StartAsync(int httpPort, int pacPort)\n    {\n        _needRestart = httpPort != _httpPort || pacPort != _pacPort || !_isRunning;\n\n        _httpPort = httpPort;\n        _pacPort = pacPort;\n\n        await InitText();\n\n        if (_needRestart)\n        {\n            Stop();\n            RunListener();\n        }\n    }\n\n    private async Task InitText()\n    {\n        var customSystemProxyPacPath = AppManager.Instance.Config.SystemProxyItem?.CustomSystemProxyPacPath;\n        var fileName = (customSystemProxyPacPath.IsNotEmpty() && File.Exists(customSystemProxyPacPath))\n            ? customSystemProxyPacPath\n            : Path.Combine(Utils.GetConfigPath(), \"pac.txt\");\n\n        // TODO: temporarily notify which script is being used\n        NoticeManager.Instance.SendMessage(fileName);\n\n        if (!File.Exists(fileName))\n        {\n            var pac = EmbedUtils.GetEmbedText(Global.PacFileName);\n            await File.AppendAllTextAsync(fileName, pac);\n        }\n\n        var pacText = await File.ReadAllTextAsync(fileName);\n        pacText = pacText.Replace(\"__PROXY__\", $\"PROXY 127.0.0.1:{_httpPort};DIRECT;\");\n\n        var sb = new StringBuilder();\n        sb.AppendLine(\"HTTP/1.0 200 OK\");\n        sb.AppendLine(\"Content-type:application/x-ns-proxy-autoconfig\");\n        sb.AppendLine(\"Connection:close\");\n        sb.AppendLine(\"Content-Length:\" + Encoding.UTF8.GetByteCount(pacText));\n        sb.AppendLine();\n        sb.Append(pacText);\n        _writeContent = Encoding.UTF8.GetBytes(sb.ToString());\n    }\n\n    private void RunListener()\n    {\n        _tcpListener = TcpListener.Create(_pacPort);\n        _isRunning = true;\n        _tcpListener.Start();\n        Task.Factory.StartNew(async () =>\n        {\n            while (_isRunning)\n            {\n                try\n                {\n                    if (!_tcpListener.Pending())\n                    {\n                        await Task.Delay(10);\n                        continue;\n                    }\n\n                    var client = await _tcpListener.AcceptTcpClientAsync();\n                    await Task.Run(() => WriteContent(client));\n                }\n                catch\n                {\n                    // ignored\n                }\n            }\n        }, TaskCreationOptions.LongRunning);\n    }\n\n    private void WriteContent(TcpClient client)\n    {\n        var stream = client.GetStream();\n        stream.Write(_writeContent, 0, _writeContent.Length);\n        stream.Flush();\n    }\n\n    public void Stop()\n    {\n        if (_tcpListener == null)\n        {\n            return;\n        }\n        try\n        {\n            _isRunning = false;\n            _tcpListener.Stop();\n            _tcpListener = null;\n        }\n        catch\n        {\n            // ignored\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/ProfileExManager.cs",
    "content": "//using System.Reactive.Linq;\n\nnamespace ServiceLib.Manager;\n\npublic class ProfileExManager\n{\n    private static readonly Lazy<ProfileExManager> _instance = new(() => new());\n    private ConcurrentBag<ProfileExItem> _lstProfileEx = [];\n    private readonly Queue<string> _queIndexIds = new();\n    public static ProfileExManager Instance => _instance.Value;\n    private static readonly string _tag = \"ProfileExHandler\";\n\n    public ProfileExManager()\n    {\n        //Init();\n    }\n\n    public async Task Init()\n    {\n        await InitData();\n    }\n\n    public async Task<ConcurrentBag<ProfileExItem>> GetProfileExs()\n    {\n        return await Task.FromResult(_lstProfileEx);\n    }\n\n    private async Task InitData()\n    {\n        await SQLiteHelper.Instance.ExecuteAsync($\"delete from ProfileExItem where indexId not in ( select indexId from ProfileItem )\");\n\n        _lstProfileEx = new(await SQLiteHelper.Instance.TableAsync<ProfileExItem>().ToListAsync());\n    }\n\n    private void IndexIdEnqueue(string indexId)\n    {\n        if (indexId.IsNotEmpty() && !_queIndexIds.Contains(indexId))\n        {\n            _queIndexIds.Enqueue(indexId);\n        }\n    }\n\n    private async Task SaveQueueIndexIds()\n    {\n        var cnt = _queIndexIds.Count;\n        if (cnt > 0)\n        {\n            var lstExists = await SQLiteHelper.Instance.TableAsync<ProfileExItem>().ToListAsync();\n            List<ProfileExItem> lstInserts = [];\n            List<ProfileExItem> lstUpdates = [];\n\n            for (var i = 0; i < cnt; i++)\n            {\n                var id = _queIndexIds.Dequeue();\n                var item = lstExists.FirstOrDefault(t => t.IndexId == id);\n                var itemNew = _lstProfileEx?.FirstOrDefault(t => t.IndexId == id);\n                if (itemNew is null)\n                {\n                    continue;\n                }\n\n                if (item is not null)\n                {\n                    lstUpdates.Add(itemNew);\n                }\n                else\n                {\n                    lstInserts.Add(itemNew);\n                }\n            }\n\n            try\n            {\n                if (lstInserts.Count > 0)\n                {\n                    await SQLiteHelper.Instance.InsertAllAsync(lstInserts);\n                }\n\n                if (lstUpdates.Count > 0)\n                {\n                    await SQLiteHelper.Instance.UpdateAllAsync(lstUpdates);\n                }\n            }\n            catch (Exception ex)\n            {\n                Logging.SaveLog(_tag, ex);\n            }\n        }\n    }\n\n    private ProfileExItem AddProfileEx(string indexId)\n    {\n        var profileEx = new ProfileExItem()\n        {\n            IndexId = indexId,\n            Delay = 0,\n            Speed = 0,\n            Sort = 0,\n            Message = string.Empty\n        };\n        _lstProfileEx.Add(profileEx);\n        IndexIdEnqueue(indexId);\n        return profileEx;\n    }\n\n    private ProfileExItem GetProfileExItem(string? indexId)\n    {\n        return _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId) ?? AddProfileEx(indexId);\n    }\n\n    public async Task ClearAll()\n    {\n        await SQLiteHelper.Instance.ExecuteAsync($\"delete from ProfileExItem \");\n        _lstProfileEx = new();\n    }\n\n    public async Task SaveTo()\n    {\n        try\n        {\n            await SaveQueueIndexIds();\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public void SetTestDelay(string indexId, int delay)\n    {\n        var profileEx = GetProfileExItem(indexId);\n\n        profileEx.Delay = delay;\n        IndexIdEnqueue(indexId);\n    }\n\n    public void SetTestSpeed(string indexId, decimal speed)\n    {\n        var profileEx = GetProfileExItem(indexId);\n\n        profileEx.Speed = speed;\n        IndexIdEnqueue(indexId);\n    }\n\n    public void SetTestMessage(string indexId, string message)\n    {\n        var profileEx = GetProfileExItem(indexId);\n\n        profileEx.Message = message;\n        IndexIdEnqueue(indexId);\n    }\n\n    public void SetSort(string indexId, int sort)\n    {\n        var profileEx = GetProfileExItem(indexId);\n\n        profileEx.Sort = sort;\n        IndexIdEnqueue(indexId);\n    }\n\n    public int GetSort(string indexId)\n    {\n        var profileEx = _lstProfileEx.FirstOrDefault(t => t.IndexId == indexId);\n        if (profileEx == null)\n        {\n            return 0;\n        }\n        return profileEx.Sort;\n    }\n\n    public int GetMaxSort()\n    {\n        if (_lstProfileEx.Count <= 0)\n        {\n            return 0;\n        }\n        return _lstProfileEx.Max(t => t == null ? 0 : t.Sort);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/StatisticsManager.cs",
    "content": "namespace ServiceLib.Manager;\n\npublic class StatisticsManager\n{\n    private static readonly Lazy<StatisticsManager> instance = new(() => new());\n    public static StatisticsManager Instance => instance.Value;\n\n    private Config _config;\n    private ServerStatItem? _serverStatItem;\n    private List<ServerStatItem> _lstServerStat;\n    private Func<ServerSpeedItem, Task>? _updateFunc;\n\n    private StatisticsXrayService? _statisticsXray;\n    private StatisticsSingboxService? _statisticsSingbox;\n    private static readonly string _tag = \"StatisticsHandler\";\n    public List<ServerStatItem> ServerStat => _lstServerStat;\n\n    public async Task Init(Config config, Func<ServerSpeedItem, Task> updateFunc)\n    {\n        _config = config;\n        _updateFunc = updateFunc;\n        if (config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)\n        {\n            await InitData();\n\n            _statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler);\n            _statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler);\n        }\n    }\n\n    public void Close()\n    {\n        try\n        {\n            _statisticsXray?.Close();\n            _statisticsSingbox?.Close();\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public async Task ClearAllServerStatistics()\n    {\n        await SQLiteHelper.Instance.ExecuteAsync($\"delete from ServerStatItem \");\n        _serverStatItem = null;\n        _lstServerStat = new();\n    }\n\n    public async Task SaveTo()\n    {\n        try\n        {\n            if (_lstServerStat != null)\n            {\n                await SQLiteHelper.Instance.UpdateAllAsync(_lstServerStat);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    public async Task CloneServerStatItem(string indexId, string toIndexId)\n    {\n        if (_lstServerStat == null)\n        {\n            return;\n        }\n\n        if (indexId == toIndexId)\n        {\n            return;\n        }\n\n        var stat = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);\n        if (stat == null)\n        {\n            return;\n        }\n\n        var toStat = JsonUtils.DeepCopy(stat);\n        toStat.IndexId = toIndexId;\n        await SQLiteHelper.Instance.ReplaceAsync(toStat);\n        _lstServerStat.Add(toStat);\n    }\n\n    private async Task InitData()\n    {\n        await SQLiteHelper.Instance.ExecuteAsync($\"delete from ServerStatItem where indexId not in ( select indexId from ProfileItem )\");\n\n        var ticks = DateTime.Now.Date.Ticks;\n        await SQLiteHelper.Instance.ExecuteAsync($\"update ServerStatItem set todayUp = 0,todayDown=0,dateNow={ticks} where dateNow<>{ticks}\");\n\n        _lstServerStat = await SQLiteHelper.Instance.TableAsync<ServerStatItem>().ToListAsync();\n    }\n\n    private async Task UpdateServerStatHandler(ServerSpeedItem server)\n    {\n        await UpdateServerStat(server);\n    }\n\n    private async Task UpdateServerStat(ServerSpeedItem server)\n    {\n        await GetServerStatItem(_config.IndexId);\n\n        if (_serverStatItem is null)\n        {\n            return;\n        }\n        if (server.ProxyUp != 0 || server.ProxyDown != 0)\n        {\n            _serverStatItem.TodayUp += server.ProxyUp;\n            _serverStatItem.TodayDown += server.ProxyDown;\n            _serverStatItem.TotalUp += server.ProxyUp;\n            _serverStatItem.TotalDown += server.ProxyDown;\n        }\n\n        server.IndexId = _config.IndexId;\n        server.TodayUp = _serverStatItem.TodayUp;\n        server.TodayDown = _serverStatItem.TodayDown;\n        server.TotalUp = _serverStatItem.TotalUp;\n        server.TotalDown = _serverStatItem.TotalDown;\n        await _updateFunc?.Invoke(server);\n    }\n\n    private async Task GetServerStatItem(string indexId)\n    {\n        var ticks = DateTime.Now.Date.Ticks;\n        if (_serverStatItem != null && _serverStatItem.IndexId != indexId)\n        {\n            _serverStatItem = null;\n        }\n\n        if (_serverStatItem == null)\n        {\n            _serverStatItem = _lstServerStat.FirstOrDefault(t => t.IndexId == indexId);\n            if (_serverStatItem == null)\n            {\n                _serverStatItem = new ServerStatItem\n                {\n                    IndexId = indexId,\n                    TotalUp = 0,\n                    TotalDown = 0,\n                    TodayUp = 0,\n                    TodayDown = 0,\n                    DateNow = ticks\n                };\n                await SQLiteHelper.Instance.ReplaceAsync(_serverStatItem);\n                _lstServerStat.Add(_serverStatItem);\n            }\n        }\n\n        if (_serverStatItem.DateNow != ticks)\n        {\n            _serverStatItem.TodayUp = 0;\n            _serverStatItem.TodayDown = 0;\n            _serverStatItem.DateNow = ticks;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/TaskManager.cs",
    "content": "namespace ServiceLib.Manager;\n\npublic class TaskManager\n{\n    private static readonly Lazy<TaskManager> _instance = new(() => new());\n    public static TaskManager Instance => _instance.Value;\n    private Config _config;\n    private Func<bool, string, Task>? _updateFunc;\n\n    public void RegUpdateTask(Config config, Func<bool, string, Task> updateFunc)\n    {\n        _config = config;\n        _updateFunc = updateFunc;\n\n        Task.Run(ScheduledTasks);\n    }\n\n    private async Task ScheduledTasks()\n    {\n        Logging.SaveLog(\"Setup Scheduled Tasks\");\n\n        var numOfExecuted = 1;\n        while (true)\n        {\n            //1 minute\n            await Task.Delay(1000 * 60);\n\n            //Execute once 1 minute\n            try\n            {\n                await UpdateTaskRunSubscription();\n            }\n            catch (Exception ex)\n            {\n                Logging.SaveLog(\"ScheduledTasks - UpdateTaskRunSubscription\", ex);\n            }\n\n            //Execute once 20 minute\n            if (numOfExecuted % 20 == 0)\n            {\n                //Logging.SaveLog(\"Execute save config\");\n\n                try\n                {\n                    await ConfigHandler.SaveConfig(_config);\n                    await ProfileExManager.Instance.SaveTo();\n                }\n                catch (Exception ex)\n                {\n                    Logging.SaveLog(\"ScheduledTasks - SaveConfig\", ex);\n                }\n            }\n\n            //Execute once 1 hour\n            if (numOfExecuted % 60 == 0)\n            {\n                //Logging.SaveLog(\"Execute delete expired files\");\n\n                FileUtils.DeleteExpiredFiles(Utils.GetBinConfigPath(), DateTime.Now.AddHours(-1));\n                FileUtils.DeleteExpiredFiles(Utils.GetLogPath(), DateTime.Now.AddMonths(-1));\n                FileUtils.DeleteExpiredFiles(Utils.GetTempPath(), DateTime.Now.AddMonths(-1));\n\n                try\n                {\n                    await UpdateTaskRunGeo(numOfExecuted / 60);\n                }\n                catch (Exception ex)\n                {\n                    Logging.SaveLog(\"ScheduledTasks - UpdateTaskRunGeo\", ex);\n                }\n            }\n\n            numOfExecuted++;\n        }\n    }\n\n    private async Task UpdateTaskRunSubscription()\n    {\n        var updateTime = ((DateTimeOffset)DateTime.Now).ToUnixTimeSeconds();\n        var lstSubs = (await AppManager.Instance.SubItems())?\n            .Where(t => t.AutoUpdateInterval > 0)\n            .Where(t => updateTime - t.UpdateTime >= t.AutoUpdateInterval * 60)\n            .ToList();\n\n        if (lstSubs is not { Count: > 0 })\n        {\n            return;\n        }\n\n        Logging.SaveLog(\"Execute update subscription\");\n\n        foreach (var item in lstSubs)\n        {\n            await SubscriptionHandler.UpdateProcess(_config, item.Id, true, async (success, msg) =>\n            {\n                await _updateFunc?.Invoke(success, msg);\n                if (success)\n                {\n                    Logging.SaveLog($\"Update subscription end. {msg}\");\n                }\n            });\n            item.UpdateTime = updateTime;\n            await ConfigHandler.AddSubItem(_config, item);\n            await Task.Delay(1000);\n        }\n    }\n\n    private async Task UpdateTaskRunGeo(int hours)\n    {\n        if (_config.GuiItem.AutoUpdateInterval > 0 && hours > 0 && hours % _config.GuiItem.AutoUpdateInterval == 0)\n        {\n            Logging.SaveLog(\"Execute update geo files\");\n\n            await new UpdateService(_config, async (success, msg) =>\n            {\n                await _updateFunc?.Invoke(false, msg);\n            }).UpdateGeoFileAll();\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Manager/WebDavManager.cs",
    "content": "using WebDav;\n\nnamespace ServiceLib.Manager;\n\npublic sealed class WebDavManager\n{\n    private static readonly Lazy<WebDavManager> _instance = new(() => new());\n    public static WebDavManager Instance => _instance.Value;\n\n    private readonly Config? _config;\n    private WebDavClient? _client;\n    private string? _lastDescription;\n    private string _webDir = Global.AppName + \"_backup\";\n    private readonly string _webFileName = \"backup.zip\";\n    private readonly string _tag = \"WebDav--\";\n\n    public WebDavManager()\n    {\n        _config = AppManager.Instance.Config;\n    }\n\n    private async Task<bool> GetClient()\n    {\n        try\n        {\n            if (_config.WebDavItem.Url.IsNullOrEmpty()\n            || _config.WebDavItem.UserName.IsNullOrEmpty()\n            || _config.WebDavItem.Password.IsNullOrEmpty())\n            {\n                throw new ArgumentException(\"webdav parameter error or null\");\n            }\n            if (_client != null)\n            {\n                _client?.Dispose();\n                _client = null;\n            }\n            if (_config.WebDavItem.DirName.IsNullOrEmpty())\n            {\n                _webDir = Global.AppName + \"_backup\";\n            }\n            else\n            {\n                _webDir = _config.WebDavItem.DirName.TrimEx();\n            }\n\n            // Ensure BaseAddress URL ends with a trailing slash\n            var baseUrl = _config.WebDavItem.Url.Trim().TrimEnd('/') + \"/\";\n\n            var clientParams = new WebDavClientParams\n            {\n                BaseAddress = new Uri(baseUrl),\n                Credentials = new NetworkCredential(_config.WebDavItem.UserName, _config.WebDavItem.Password)\n            };\n            _client = new WebDavClient(clientParams);\n        }\n        catch (Exception ex)\n        {\n            SaveLog(ex);\n            return false;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private async Task<bool> TryCreateDir()\n    {\n        if (_client is null)\n        {\n            return false;\n        }\n        try\n        {\n            var result2 = await _client.Mkcol(_webDir);\n            if (result2.IsSuccessful)\n            {\n                return true;\n            }\n            SaveLog(result2.Description);\n        }\n        catch (Exception ex)\n        {\n            SaveLog(ex);\n        }\n        return false;\n    }\n\n    private void SaveLog(string desc)\n    {\n        _lastDescription = desc;\n        Logging.SaveLog(_tag + desc);\n    }\n\n    private void SaveLog(Exception ex)\n    {\n        _lastDescription = ex.Message;\n        Logging.SaveLog(_tag, ex);\n    }\n\n    public async Task<bool> CheckConnection()\n    {\n        if (await GetClient() == false)\n        {\n            return false;\n        }\n        await TryCreateDir();\n\n        try\n        {\n            var testName = \"readme_test\";\n            var myContent = new StringContent(testName);\n            var result = await _client.PutFile($\"{_webDir}/{testName}\", myContent);\n            if (result.IsSuccessful)\n            {\n                await _client.Delete($\"{_webDir}/{testName}\");\n                return true;\n            }\n            else\n            {\n                SaveLog(result.Description);\n            }\n        }\n        catch (Exception ex)\n        {\n            SaveLog(ex);\n        }\n        return false;\n    }\n\n    public async Task<bool> PutFile(string fileName)\n    {\n        if (await GetClient() == false)\n        {\n            return false;\n        }\n        await TryCreateDir();\n\n        try\n        {\n            await using var fs = File.OpenRead(fileName);\n            var result = await _client.PutFile($\"{_webDir}/{_webFileName}\", fs); // upload a resource\n            if (result.IsSuccessful)\n            {\n                return true;\n            }\n\n            SaveLog(result.Description);\n        }\n        catch (Exception ex)\n        {\n            SaveLog(ex);\n        }\n        return false;\n    }\n\n    public async Task<bool> GetRawFile(string fileName)\n    {\n        if (await GetClient() == false)\n        {\n            return false;\n        }\n        await TryCreateDir();\n\n        try\n        {\n            var response = await _client.GetRawFile($\"{_webDir}/{_webFileName}\");\n            if (!response.IsSuccessful)\n            {\n                SaveLog(response.Description);\n                return false;\n            }\n\n            await using var outputFileStream = new FileStream(fileName, FileMode.Create);\n            await response.Stream.CopyToAsync(outputFileStream);\n            return true;\n        }\n        catch (Exception ex)\n        {\n            SaveLog(ex);\n        }\n        return false;\n    }\n\n    public string GetLastError() => _lastDescription ?? string.Empty;\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/CheckUpdateModel.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class CheckUpdateModel : ReactiveObject\n{\n    public bool? IsSelected { get; set; }\n    public string? CoreType { get; set; }\n    [Reactive] public string? Remarks { get; set; }\n    public string? FileName { get; set; }\n    public bool? IsFinished { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ClashConnectionModel.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class ClashConnectionModel\n{\n    public string? Id { get; set; }\n    public string? Network { get; set; }\n    public string? Type { get; set; }\n    public string? Host { get; set; }\n    public ulong Upload { get; set; }\n    public ulong Download { get; set; }\n    public string? UploadTraffic { get; set; }\n    public string? DownloadTraffic { get; set; }\n    public double Time { get; set; }\n    public string? Elapsed { get; set; }\n    public string? Chain { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ClashConnections.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class ClashConnections\n{\n    public ulong downloadTotal { get; set; }\n    public ulong uploadTotal { get; set; }\n    public List<ConnectionItem>? connections { get; set; }\n}\n\npublic class ConnectionItem\n{\n    public string? id { get; set; }\n    public MetadataItem? metadata { get; set; }\n    public ulong upload { get; set; }\n    public ulong download { get; set; }\n    public DateTime start { get; set; }\n    public List<string>? chains { get; set; }\n    public string? rule { get; set; }\n    public string? rulePayload { get; set; }\n}\n\npublic class MetadataItem\n{\n    public string? network { get; set; }\n    public string? type { get; set; }\n    public string? sourceIP { get; set; }\n    public string? destinationIP { get; set; }\n    public string? sourcePort { get; set; }\n    public string? destinationPort { get; set; }\n    public string? host { get; set; }\n    public string? nsMode { get; set; }\n    public object? uid { get; set; }\n    public string? process { get; set; }\n    public string? processPath { get; set; }\n    public string? remoteDestination { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ClashProviders.cs",
    "content": "using static ServiceLib.Models.ClashProxies;\n\nnamespace ServiceLib.Models;\n\npublic class ClashProviders\n{\n    public Dictionary<string, ProvidersItem>? providers { get; set; }\n\n    public class ProvidersItem\n    {\n        public string? name { get; set; }\n        public List<ProxiesItem>? proxies { get; set; }\n        public string? type { get; set; }\n        public string? vehicleType { get; set; }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ClashProxies.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class ClashProxies\n{\n    public Dictionary<string, ProxiesItem>? proxies { get; set; }\n\n    public class ProxiesItem\n    {\n        public List<string>? all { get; set; }\n        public List<HistoryItem>? history { get; set; }\n        public string? name { get; set; }\n        public string? type { get; set; }\n        public bool udp { get; set; }\n        public string? now { get; set; }\n        public int delay { get; set; }\n    }\n\n    public class HistoryItem\n    {\n        public string? time { get; set; }\n        public int delay { get; set; }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ClashProxyModel.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class ClashProxyModel : ReactiveObject\n{\n    public string? Name { get; set; }\n\n    public string? Type { get; set; }\n\n    public string? Now { get; set; }\n\n    [Reactive] public int Delay { get; set; }\n\n    [Reactive] public string? DelayName { get; set; }\n\n    public bool IsActive { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/CmdItem.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class CmdItem\n{\n    public string? Cmd { get; set; }\n    public List<string>? Arguments { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ComboItem.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class ComboItem\n{\n    public string? ID\n    {\n        get; set;\n    }\n\n    public string? Text\n    {\n        get; set;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/Config.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class Config\n{\n    #region property\n\n    public string IndexId { get; set; }\n    public string SubIndexId { get; set; }\n\n    #endregion property\n\n    #region other entities\n\n    public CoreBasicItem CoreBasicItem { get; set; }\n    public TunModeItem TunModeItem { get; set; }\n    public KcpItem KcpItem { get; set; }\n    public GrpcItem GrpcItem { get; set; }\n    public RoutingBasicItem RoutingBasicItem { get; set; }\n    public GUIItem GuiItem { get; set; }\n    public MsgUIItem MsgUIItem { get; set; }\n    public UIItem UiItem { get; set; }\n    public ConstItem ConstItem { get; set; }\n    public SpeedTestItem SpeedTestItem { get; set; }\n    public Mux4RayItem Mux4RayItem { get; set; }\n    public Mux4SboxItem Mux4SboxItem { get; set; }\n    public HysteriaItem HysteriaItem { get; set; }\n    public ClashUIItem ClashUIItem { get; set; }\n    public SystemProxyItem SystemProxyItem { get; set; }\n    public WebDavItem WebDavItem { get; set; }\n    public CheckUpdateItem CheckUpdateItem { get; set; }\n    public Fragment4RayItem? Fragment4RayItem { get; set; }\n    public List<InItem> Inbound { get; set; }\n    public List<KeyEventItem> GlobalHotkeys { get; set; }\n    public List<CoreTypeItem> CoreTypeItem { get; set; }\n    public SimpleDNSItem SimpleDNSItem { get; set; }\n\n    #endregion other entities\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ConfigItems.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class CoreBasicItem\n{\n    public bool LogEnabled { get; set; }\n\n    public string Loglevel { get; set; }\n\n    public bool MuxEnabled { get; set; }\n\n    public bool DefAllowInsecure { get; set; }\n\n    public string DefFingerprint { get; set; }\n\n    public string DefUserAgent { get; set; }\n\n    public bool EnableFragment { get; set; }\n\n    public bool EnableCacheFile4Sbox { get; set; } = true;\n}\n\n[Serializable]\npublic class InItem\n{\n    public int LocalPort { get; set; }\n    public string Protocol { get; set; }\n    public bool UdpEnabled { get; set; }\n    public bool SniffingEnabled { get; set; } = true;\n    public List<string>? DestOverride { get; set; } = [\"http\", \"tls\"];\n    public bool RouteOnly { get; set; }\n    public bool AllowLANConn { get; set; }\n    public bool NewPort4LAN { get; set; }\n    public string User { get; set; }\n    public string Pass { get; set; }\n    public bool SecondLocalPortEnabled { get; set; }\n}\n\n[Serializable]\npublic class KcpItem\n{\n    public int Mtu { get; set; }\n\n    public int Tti { get; set; }\n\n    public int UplinkCapacity { get; set; }\n\n    public int DownlinkCapacity { get; set; }\n\n    public bool Congestion { get; set; }\n\n    public int ReadBufferSize { get; set; }\n\n    public int WriteBufferSize { get; set; }\n}\n\n[Serializable]\npublic class GrpcItem\n{\n    public int? IdleTimeout { get; set; }\n    public int? HealthCheckTimeout { get; set; }\n    public bool? PermitWithoutStream { get; set; }\n    public int? InitialWindowsSize { get; set; }\n}\n\n[Serializable]\npublic class GUIItem\n{\n    public bool AutoRun { get; set; }\n    public bool EnableStatistics { get; set; }\n    public bool DisplayRealTimeSpeed { get; set; }\n    public bool KeepOlderDedupl { get; set; }\n    public int AutoUpdateInterval { get; set; }\n    public int TrayMenuServersLimit { get; set; } = 20;\n    public bool EnableHWA { get; set; } = false;\n    public bool EnableLog { get; set; } = true;\n}\n\n[Serializable]\npublic class MsgUIItem\n{\n    public string? MainMsgFilter { get; set; }\n    public bool? AutoRefresh { get; set; }\n}\n\n[Serializable]\npublic class UIItem\n{\n    public bool EnableAutoAdjustMainLvColWidth { get; set; }\n    public int MainGirdHeight1 { get; set; }\n    public int MainGirdHeight2 { get; set; }\n    public EGirdOrientation MainGirdOrientation { get; set; } = EGirdOrientation.Vertical;\n    public string? ColorPrimaryName { get; set; }\n    public string? CurrentTheme { get; set; }\n    public string CurrentLanguage { get; set; }\n    public string CurrentFontFamily { get; set; }\n    public int CurrentFontSize { get; set; }\n    public bool EnableDragDropSort { get; set; }\n    public bool DoubleClick2Activate { get; set; }\n    public bool AutoHideStartup { get; set; }\n    public bool Hide2TrayWhenClose { get; set; }\n    public bool MacOSShowInDock { get; set; }\n    public List<ColumnItem> MainColumnItem { get; set; }\n    public List<WindowSizeItem> WindowSizeItem { get; set; }\n}\n\n[Serializable]\npublic class ConstItem\n{\n    public string? SubConvertUrl { get; set; }\n    public string? GeoSourceUrl { get; set; }\n    public string? SrsSourceUrl { get; set; }\n    public string? RouteRulesTemplateSourceUrl { get; set; }\n}\n\n[Serializable]\npublic class KeyEventItem\n{\n    public EGlobalHotkey EGlobalHotkey { get; set; }\n\n    public bool Alt { get; set; }\n\n    public bool Control { get; set; }\n\n    public bool Shift { get; set; }\n\n    public int? KeyCode { get; set; }\n}\n\n[Serializable]\npublic class CoreTypeItem\n{\n    public EConfigType ConfigType { get; set; }\n\n    public ECoreType CoreType { get; set; }\n}\n\n[Serializable]\npublic class TunModeItem\n{\n    public bool EnableTun { get; set; }\n    public bool AutoRoute { get; set; } = true;\n    public bool StrictRoute { get; set; } = true;\n    public string Stack { get; set; }\n    public int Mtu { get; set; }\n    public bool EnableIPv6Address { get; set; }\n}\n\n[Serializable]\npublic class SpeedTestItem\n{\n    public int SpeedTestTimeout { get; set; }\n    public string SpeedTestUrl { get; set; }\n    public string SpeedPingTestUrl { get; set; }\n    public int MixedConcurrencyCount { get; set; }\n    public string IPAPIUrl { get; set; }\n}\n\n[Serializable]\npublic class RoutingBasicItem\n{\n    public string DomainStrategy { get; set; }\n    public string DomainStrategy4Singbox { get; set; }\n    public string RoutingIndexId { get; set; }\n}\n\n[Serializable]\npublic class ColumnItem\n{\n    public string Name { get; set; }\n    public int Width { get; set; }\n    public int Index { get; set; }\n}\n\n[Serializable]\npublic class Mux4RayItem\n{\n    public int? Concurrency { get; set; }\n    public int? XudpConcurrency { get; set; }\n    public string? XudpProxyUDP443 { get; set; }\n}\n\n[Serializable]\npublic class Mux4SboxItem\n{\n    public string Protocol { get; set; }\n    public int MaxConnections { get; set; }\n    public bool? Padding { get; set; }\n}\n\n[Serializable]\npublic class HysteriaItem\n{\n    public int UpMbps { get; set; }\n    public int DownMbps { get; set; }\n    public int HopInterval { get; set; } = 30;\n}\n\n[Serializable]\npublic class ClashUIItem\n{\n    public ERuleMode RuleMode { get; set; }\n    public bool EnableIPv6 { get; set; }\n    public bool EnableMixinContent { get; set; }\n    public int ProxiesSorting { get; set; }\n    public bool ProxiesAutoRefresh { get; set; }\n    public int ProxiesAutoDelayTestInterval { get; set; } = 10;\n    public bool ConnectionsAutoRefresh { get; set; }\n    public int ConnectionsRefreshInterval { get; set; } = 2;\n    public List<ColumnItem> ConnectionsColumnItem { get; set; }\n}\n\n[Serializable]\npublic class SystemProxyItem\n{\n    public ESysProxyType SysProxyType { get; set; }\n    public string SystemProxyExceptions { get; set; }\n    public bool NotProxyLocalAddress { get; set; } = true;\n    public string SystemProxyAdvancedProtocol { get; set; }\n    public string? CustomSystemProxyPacPath { get; set; }\n    public string? CustomSystemProxyScriptPath { get; set; }\n}\n\n[Serializable]\npublic class WebDavItem\n{\n    public string? Url { get; set; }\n    public string? UserName { get; set; }\n    public string? Password { get; set; }\n    public string? DirName { get; set; }\n}\n\n[Serializable]\npublic class CheckUpdateItem\n{\n    public bool CheckPreReleaseUpdate { get; set; }\n    public List<string>? SelectedCoreTypes { get; set; }\n}\n\n[Serializable]\npublic class Fragment4RayItem\n{\n    public string? Packets { get; set; }\n    public string? Length { get; set; }\n    public string? Interval { get; set; }\n}\n\n[Serializable]\npublic class WindowSizeItem\n{\n    public string TypeName { get; set; }\n    public int Width { get; set; }\n    public int Height { get; set; }\n}\n\n[Serializable]\npublic class SimpleDNSItem\n{\n    public bool? UseSystemHosts { get; set; }\n    public bool? AddCommonHosts { get; set; }\n    public bool? FakeIP { get; set; }\n    public bool? GlobalFakeIp { get; set; }\n    public bool? BlockBindingQuery { get; set; }\n    public string? DirectDNS { get; set; }\n    public string? RemoteDNS { get; set; }\n    public string? BootstrapDNS { get; set; }\n    public string? Strategy4Freedom { get; set; }\n    public string? Strategy4Proxy { get; set; }\n    public bool? ServeStale { get; set; }\n    public bool? ParallelQuery { get; set; }\n    public string? Hosts { get; set; }\n    public string? DirectExpectedIPs { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/CoreConfigContext.cs",
    "content": "namespace ServiceLib.Models;\n\npublic record CoreConfigContext\n{\n    public required ProfileItem Node { get; init; }\n    public required ECoreType RunCoreType { get; init; }\n    public RoutingItem? RoutingItem { get; init; }\n    public DNSItem? RawDnsItem { get; init; }\n    public SimpleDNSItem SimpleDnsItem { get; init; } = new();\n    public Dictionary<string, ProfileItem> AllProxiesMap { get; init; } = new();\n    public Config AppConfig { get; init; } = new();\n    public FullConfigTemplateItem? FullConfigTemplate { get; init; } = new();\n\n    // Test ServerTestItem Map\n    public Dictionary<string, string> ServerTestItemMap { get; init; } = new();\n\n    // TUN Compatibility\n    public bool IsTunEnabled { get; init; } = false;\n    public HashSet<string> ProtectDomainList { get; init; } = new();\n    // -> tun inbound --(if routing proxy)--> relay outbound\n    // -> proxy core (relay inbound --> proxy outbound --(dialerProxy)--> protect outbound)\n    // -> protect inbound -> direct proxy outbound data -> internet\n    public int TunProtectSsPort { get; init; } = 0;\n    public int ProxyRelaySsPort { get; init; } = 0;\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/CoreInfo.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class CoreInfo\n{\n    public ECoreType CoreType { get; set; }\n    public List<string>? CoreExes { get; set; }\n    public string? Arguments { get; set; }\n    public string? Url { get; set; }\n    public string? ReleaseApiUrl { get; set; }\n    public string? DownloadUrlWin64 { get; set; }\n    public string? DownloadUrlWinArm64 { get; set; }\n    public string? DownloadUrlLinux64 { get; set; }\n    public string? DownloadUrlLinuxArm64 { get; set; }\n    public string? DownloadUrlOSX64 { get; set; }\n    public string? DownloadUrlOSXArm64 { get; set; }\n    public string? Match { get; set; }\n    public string? VersionArg { get; set; }\n    public bool AbsolutePath { get; set; }\n    public IDictionary<string, string?> Environment { get; set; } = new Dictionary<string, string?>();\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/DNSItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class DNSItem\n{\n    [PrimaryKey]\n    public string Id { get; set; }\n\n    public string Remarks { get; set; }\n    public bool Enabled { get; set; } = false;\n    public ECoreType CoreType { get; set; }\n    public bool UseSystemHosts { get; set; }\n    public string? NormalDNS { get; set; }\n    public string? TunDNS { get; set; }\n    public string? DomainStrategy4Freedom { get; set; }\n    public string? DomainDNSAddress { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/FullConfigTemplateItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class FullConfigTemplateItem\n{\n    [PrimaryKey]\n    public string Id { get; set; }\n\n    public string Remarks { get; set; }\n    public bool Enabled { get; set; } = false;\n    public ECoreType CoreType { get; set; }\n    public string? Config { get; set; }\n    public string? TunConfig { get; set; }\n    public bool? AddProxyOnly { get; set; } = false;\n    public string? ProxyDetour { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/GitHubRelease.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class GitHubReleaseAsset\n{\n    [JsonPropertyName(\"url\")] public string? Url { get; set; }\n\n    [JsonPropertyName(\"id\")] public int Id { get; set; }\n\n    [JsonPropertyName(\"node_id\")] public string? NodeId { get; set; }\n\n    [JsonPropertyName(\"name\")] public string? Name { get; set; }\n\n    [JsonPropertyName(\"label\")] public object Label { get; set; }\n\n    [JsonPropertyName(\"content_type\")] public string? ContentType { get; set; }\n\n    [JsonPropertyName(\"state\")] public string? State { get; set; }\n\n    [JsonPropertyName(\"size\")] public int Size { get; set; }\n\n    [JsonPropertyName(\"download_count\")] public int DownloadCount { get; set; }\n\n    [JsonPropertyName(\"created_at\")] public DateTime CreatedAt { get; set; }\n\n    [JsonPropertyName(\"updated_at\")] public DateTime UpdatedAt { get; set; }\n\n    [JsonPropertyName(\"browser_download_url\")] public string? BrowserDownloadUrl { get; set; }\n}\n\npublic class GitHubRelease\n{\n    [JsonPropertyName(\"url\")] public string? Url { get; set; }\n\n    [JsonPropertyName(\"assets_url\")] public string? AssetsUrl { get; set; }\n\n    [JsonPropertyName(\"upload_url\")] public string? UploadUrl { get; set; }\n\n    [JsonPropertyName(\"html_url\")] public string? HtmlUrl { get; set; }\n\n    [JsonPropertyName(\"id\")] public int Id { get; set; }\n\n    [JsonPropertyName(\"node_id\")] public string? NodeId { get; set; }\n\n    [JsonPropertyName(\"tag_name\")] public string? TagName { get; set; }\n\n    [JsonPropertyName(\"target_commitish\")] public string? TargetCommitish { get; set; }\n\n    [JsonPropertyName(\"name\")] public string? Name { get; set; }\n\n    [JsonPropertyName(\"draft\")] public bool Draft { get; set; }\n\n    [JsonPropertyName(\"prerelease\")] public bool Prerelease { get; set; }\n\n    [JsonPropertyName(\"created_at\")] public DateTime CreatedAt { get; set; }\n\n    [JsonPropertyName(\"published_at\")] public DateTime PublishedAt { get; set; }\n\n    [JsonPropertyName(\"assets\")] public List<GitHubReleaseAsset> Assets { get; set; }\n\n    [JsonPropertyName(\"tarball_url\")] public string? TarballUrl { get; set; }\n\n    [JsonPropertyName(\"zipball_url\")] public string? ZipballUrl { get; set; }\n\n    [JsonPropertyName(\"body\")] public string? Body { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/IPAPIInfo.cs",
    "content": "namespace ServiceLib.Models;\n\ninternal class IPAPIInfo\n{\n    public string? ip { get; set; }\n    public string? clientIp { get; set; }\n    public string? ip_addr { get; set; }\n    public string? query { get; set; }\n    public string? country { get; set; }\n    public string? country_name { get; set; }\n    public string? country_code { get; set; }\n    public string? countryCode { get; set; }\n    public LocationInfo? location { get; set; }\n}\n\npublic class LocationInfo\n{\n    public string? country_code { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ProfileExItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class ProfileExItem\n{\n    [PrimaryKey]\n    public string IndexId { get; set; }\n\n    public int Delay { get; set; }\n    public decimal Speed { get; set; }\n    public int Sort { get; set; }\n    public string? Message { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ProfileGroupItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Obsolete(\"Use ProtocolExtraItem instead.\")]\n[Serializable]\npublic class ProfileGroupItem\n{\n    [PrimaryKey]\n    public string IndexId { get; set; }\n\n    public string ChildItems { get; set; }\n\n    public string? SubChildItems { get; set; }\n\n    public string? Filter { get; set; }\n\n    public EMultipleLoad MultipleLoad { get; set; } = EMultipleLoad.LeastPing;\n\n    public bool NotHasChild()\n    {\n        return string.IsNullOrWhiteSpace(ChildItems) && string.IsNullOrWhiteSpace(SubChildItems);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ProfileItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class ProfileItem\n{\n    private ProtocolExtraItem? _protocolExtraCache;\n\n    public ProfileItem()\n    {\n        IndexId = string.Empty;\n        ConfigType = EConfigType.VMess;\n        ConfigVersion = 3;\n        Subid = string.Empty;\n        Address = string.Empty;\n        Port = 0;\n        Password = string.Empty;\n        Username = string.Empty;\n        Network = string.Empty;\n        Remarks = string.Empty;\n        HeaderType = string.Empty;\n        RequestHost = string.Empty;\n        Path = string.Empty;\n        StreamSecurity = string.Empty;\n        AllowInsecure = string.Empty;\n    }\n\n    #region function\n\n    public string GetSummary()\n    {\n        var summary = $\"[{ConfigType.ToString()}] \";\n        if (IsComplex())\n        {\n            summary += $\"[{CoreType.ToString()}]{Remarks}\";\n        }\n        else\n        {\n            var arrAddr = Address.Contains(':') ? Address.Split(':') : Address.Split('.');\n            var addr = arrAddr.Length switch\n            {\n                > 2 => $\"{arrAddr.First()}***{arrAddr.Last()}\",\n                > 1 => $\"***{arrAddr.Last()}\",\n                _ => Address\n            };\n            summary += $\"{Remarks}({addr}:{Port})\";\n        }\n        return summary;\n    }\n\n    public List<string>? GetAlpn()\n    {\n        return Alpn.IsNullOrEmpty() ? null : Utils.String2List(Alpn);\n    }\n\n    public string GetNetwork()\n    {\n        if (Network.IsNullOrEmpty() || !Global.Networks.Contains(Network))\n        {\n            return Global.DefaultNetwork;\n        }\n        return Network.TrimEx();\n    }\n\n    public bool IsComplex()\n    {\n        return ConfigType.IsComplexType();\n    }\n\n    public bool IsValid()\n    {\n        if (IsComplex())\n        {\n            return true;\n        }\n\n        if (Address.IsNullOrEmpty() || Port is <= 0 or >= 65536)\n        {\n            return false;\n        }\n\n        switch (ConfigType)\n        {\n            case EConfigType.VMess:\n                if (Password.IsNullOrEmpty() || !Utils.IsGuidByParse(Password))\n                {\n                    return false;\n                }\n\n                break;\n\n            case EConfigType.VLESS:\n                if (Password.IsNullOrEmpty() || (!Utils.IsGuidByParse(Password) && Password.Length > 30))\n                {\n                    return false;\n                }\n\n                if (!Global.Flows.Contains(GetProtocolExtra().Flow ?? string.Empty))\n                {\n                    return false;\n                }\n\n                break;\n\n            case EConfigType.Shadowsocks:\n                if (Password.IsNullOrEmpty())\n                {\n                    return false;\n                }\n\n                if (string.IsNullOrEmpty(GetProtocolExtra().SsMethod)\n                    || !Global.SsSecuritiesInSingbox.Contains(GetProtocolExtra().SsMethod))\n                {\n                    return false;\n                }\n\n                break;\n        }\n\n        if ((ConfigType is EConfigType.VLESS or EConfigType.Trojan)\n            && StreamSecurity == Global.StreamSecurityReality\n            && PublicKey.IsNullOrEmpty())\n        {\n            return false;\n        }\n\n        return true;\n    }\n\n    public void SetProtocolExtra(ProtocolExtraItem extraItem)\n    {\n        _protocolExtraCache = extraItem;\n        ProtoExtra = JsonUtils.Serialize(extraItem, false);\n    }\n\n    public void SetProtocolExtra()\n    {\n        ProtoExtra = JsonUtils.Serialize(_protocolExtraCache, false);\n    }\n\n    public ProtocolExtraItem GetProtocolExtra()\n    {\n        return _protocolExtraCache ??= JsonUtils.Deserialize<ProtocolExtraItem>(ProtoExtra) ?? new ProtocolExtraItem();\n    }\n\n    #endregion function\n\n    [PrimaryKey]\n    public string IndexId { get; set; }\n\n    public EConfigType ConfigType { get; set; }\n    public ECoreType? CoreType { get; set; }\n    public int ConfigVersion { get; set; }\n    public string Subid { get; set; }\n    public bool IsSub { get; set; } = true;\n    public int? PreSocksPort { get; set; }\n    public bool DisplayLog { get; set; } = true;\n    public string Remarks { get; set; }\n    public string Address { get; set; }\n    public int Port { get; set; }\n    public string Password { get; set; }\n    public string Username { get; set; }\n    public string Network { get; set; }\n    public string HeaderType { get; set; }\n    public string RequestHost { get; set; }\n    public string Path { get; set; }\n    public string StreamSecurity { get; set; }\n    public string AllowInsecure { get; set; }\n    public string Sni { get; set; }\n    public string Alpn { get; set; } = string.Empty;\n    public string Fingerprint { get; set; }\n    public string PublicKey { get; set; }\n    public string ShortId { get; set; }\n    public string SpiderX { get; set; }\n    public string Mldsa65Verify { get; set; }\n    public string Extra { get; set; }\n    public bool? MuxEnabled { get; set; }\n    public string Cert { get; set; }\n    public string CertSha { get; set; }\n    public string EchConfigList { get; set; }\n    public string EchForceQuery { get; set; }\n    public string Finalmask { get; set; }\n\n    public string ProtoExtra { get; set; }\n\n    [Obsolete(\"Use ProtocolExtraItem.Ports instead.\")]\n    public string Ports { get; set; }\n\n    [Obsolete(\"Use ProtocolExtraItem.AlterId instead.\")]\n    public int AlterId { get; set; }\n\n    [Obsolete(\"Use ProtocolExtraItem.Flow instead.\")]\n    public string Flow { get; set; }\n\n    [Obsolete(\"Use ProfileItem.Password instead.\")]\n    public string Id { get; set; }\n\n    [Obsolete(\"Use ProtocolExtraItem.xxx instead.\")]\n    public string Security { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ProfileItemModel.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class ProfileItemModel : ReactiveObject\n{\n    public bool IsActive { get; set; }\n    public string IndexId { get; set; }\n    public EConfigType ConfigType { get; set; }\n    public string Remarks { get; set; }\n    public string Address { get; set; }\n    public int Port { get; set; }\n    public string Network { get; set; }\n    public string StreamSecurity { get; set; }\n    public string Subid { get; set; }\n    public string SubRemarks { get; set; }\n    public int Sort { get; set; }\n\n    [Reactive]\n    public int Delay { get; set; }\n\n    public decimal Speed { get; set; }\n\n    [Reactive]\n    public string DelayVal { get; set; }\n\n    [Reactive]\n    public string SpeedVal { get; set; }\n\n    [Reactive]\n    public string TodayUp { get; set; }\n\n    [Reactive]\n    public string TodayDown { get; set; }\n\n    [Reactive]\n    public string TotalUp { get; set; }\n\n    [Reactive]\n    public string TotalDown { get; set; }\n\n    public string GetSummary()\n    {\n        var summary = $\"[{ConfigType}] {Remarks}\";\n        if (!ConfigType.IsComplexType())\n        {\n            summary += $\"({Address}:{Port})\";\n        }\n\n        return summary;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ProtocolExtraItem.cs",
    "content": "namespace ServiceLib.Models;\n\npublic record ProtocolExtraItem\n{\n    // vmess\n    public string? AlterId { get; init; }\n    public string? VmessSecurity { get; init; }\n\n    // vless\n    public string? Flow { get; init; }\n    public string? VlessEncryption { get; init; }\n    //public string? VisionSeed { get; init; }\n\n    // shadowsocks\n    //public string? PluginArgs { get; init; }\n    public string? SsMethod { get; init; }\n\n    // wireguard\n    public string? WgPublicKey { get; init; }\n    public string? WgPresharedKey { get; init; }\n    public string? WgInterfaceAddress { get; init; }\n    public string? WgReserved { get; init; }\n    public int? WgMtu { get; init; }\n\n    // hysteria2\n    public string? SalamanderPass { get; init; }\n    public int? UpMbps { get; init; }\n    public int? DownMbps { get; init; }\n    public string? Ports { get; init; }\n    public string? HopInterval { get; init; }\n\n    // group profile\n    public string? GroupType { get; init; }\n    public string? ChildItems { get; init; }\n    public string? SubChildItems { get; init; }\n    public string? Filter { get; init; }\n    public EMultipleLoad? MultipleLoad { get; init; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/RetResult.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class RetResult\n{\n    public bool Success { get; set; }\n    public string? Msg { get; set; }\n    public object? Data { get; set; }\n\n    public RetResult(bool success = false)\n    {\n        Success = success;\n    }\n\n    public RetResult(bool success, string? msg)\n    {\n        Success = success;\n        Msg = msg;\n    }\n\n    public RetResult(bool success, string? msg, object? data)\n    {\n        Success = success;\n        Msg = msg;\n        Data = data;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/RoutingItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class RoutingItem\n{\n    [PrimaryKey]\n    public string Id { get; set; }\n\n    public string Remarks { get; set; }\n    public string Url { get; set; }\n    public string RuleSet { get; set; }\n    public int RuleNum { get; set; }\n    public bool Enabled { get; set; } = true;\n    public bool Locked { get; set; }\n    public string CustomIcon { get; set; }\n    public string CustomRulesetPath4Singbox { get; set; }\n    public string DomainStrategy { get; set; }\n    public string DomainStrategy4Singbox { get; set; }\n    public int Sort { get; set; }\n    public bool IsActive { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/RoutingItemModel.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class RoutingItemModel : RoutingItem\n{\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/RoutingTemplate.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class RoutingTemplate\n{\n    public string Version { get; set; }\n    public RoutingItem[] RoutingItems { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/RulesItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class RulesItem\n{\n    public string Id { get; set; }\n    public string? Type { get; set; }\n    public string? Port { get; set; }\n    public string? Network { get; set; }\n    public List<string>? InboundTag { get; set; }\n    public string? OutboundTag { get; set; }\n    public List<string>? Ip { get; set; }\n    public List<string>? Domain { get; set; }\n    public List<string>? Protocol { get; set; }\n    public List<string>? Process { get; set; }\n    public bool Enabled { get; set; } = true;\n    public string? Remarks { get; set; }\n    public ERuleType? RuleType { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/RulesItemModel.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class RulesItemModel : RulesItem\n{\n    public string InboundTags { get; set; }\n    public string Ips { get; set; }\n    public string Domains { get; set; }\n    public string Protocols { get; set; }\n    public string RuleTypeName { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/SemanticVersion.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class SemanticVersion\n{\n    private readonly int major;\n    private readonly int minor;\n    private readonly int patch;\n    private readonly string version;\n\n    public SemanticVersion(int major, int minor, int patch)\n    {\n        this.major = major;\n        this.minor = minor;\n        this.patch = patch;\n        version = $\"{major}.{minor}.{patch}\";\n    }\n\n    public SemanticVersion(string? version)\n    {\n        try\n        {\n            if (string.IsNullOrEmpty(version))\n            {\n                major = 0;\n                minor = 0;\n                patch = 0;\n                return;\n            }\n            this.version = version.RemovePrefix('v');\n\n            var parts = this.version.Split('.');\n            if (parts.Length == 2)\n            {\n                major = int.Parse(parts.First());\n                minor = int.Parse(parts.Last());\n                patch = 0;\n            }\n            else if (parts.Length is 3 or 4)\n            {\n                major = int.Parse(parts[0]);\n                minor = int.Parse(parts[1]);\n                patch = int.Parse(parts[2]);\n            }\n            else\n            {\n                throw new ArgumentException(\"Invalid version string\");\n            }\n        }\n        catch\n        {\n            major = 0;\n            minor = 0;\n            patch = 0;\n        }\n    }\n\n    public override bool Equals(object? obj)\n    {\n        if (obj is SemanticVersion other)\n        {\n            return major == other.major && minor == other.minor && patch == other.patch;\n        }\n        else\n        {\n            return false;\n        }\n    }\n\n    public override int GetHashCode()\n    {\n        return major.GetHashCode() ^ minor.GetHashCode() ^ patch.GetHashCode();\n    }\n\n    /// <summary>\n    /// Use ToVersionString(string? prefix) instead if possible.\n    /// </summary>\n    /// <returns>major.minor.patch</returns>\n    public override string ToString()\n    {\n        return version;\n    }\n\n    public string ToVersionString(string? prefix = null)\n    {\n        if (prefix == null)\n        {\n            return version;\n        }\n        else\n        {\n            return $\"{prefix}{version}\";\n        }\n    }\n\n    public static bool operator ==(SemanticVersion v1, SemanticVersion v2)\n    { return v1.Equals(v2); }\n\n    public static bool operator !=(SemanticVersion v1, SemanticVersion v2)\n    { return !v1.Equals(v2); }\n\n    public static bool operator >=(SemanticVersion v1, SemanticVersion v2)\n    { return v1.GreaterEquals(v2); }\n\n    public static bool operator <=(SemanticVersion v1, SemanticVersion v2)\n    { return v1.LessEquals(v2); }\n\n    #region Private\n\n    private bool GreaterEquals(SemanticVersion other)\n    {\n        if (major < other.major)\n        {\n            return false;\n        }\n        else if (major > other.major)\n        {\n            return true;\n        }\n        else\n        {\n            if (minor < other.minor)\n            {\n                return false;\n            }\n            else if (minor > other.minor)\n            {\n                return true;\n            }\n            else\n            {\n                if (patch < other.patch)\n                {\n                    return false;\n                }\n                else if (patch > other.patch)\n                {\n                    return true;\n                }\n                else\n                {\n                    return true;\n                }\n            }\n        }\n    }\n\n    private bool LessEquals(SemanticVersion other)\n    {\n        if (major < other.major)\n        {\n            return true;\n        }\n        else if (major > other.major)\n        {\n            return false;\n        }\n        else\n        {\n            if (minor < other.minor)\n            {\n                return true;\n            }\n            else if (minor > other.minor)\n            {\n                return false;\n            }\n            else\n            {\n                if (patch < other.patch)\n                {\n                    return true;\n                }\n                else if (patch > other.patch)\n                {\n                    return false;\n                }\n                else\n                {\n                    return true;\n                }\n            }\n        }\n    }\n\n    #endregion Private\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ServerSpeedItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class ServerSpeedItem : ServerStatItem\n{\n    public long ProxyUp { get; set; }\n\n    public long ProxyDown { get; set; }\n\n    public long DirectUp { get; set; }\n\n    public long DirectDown { get; set; }\n}\n\n[Serializable]\npublic class TrafficItem\n{\n    public ulong Up { get; set; }\n\n    public ulong Down { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ServerStatItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class ServerStatItem\n{\n    [PrimaryKey]\n    public string IndexId { get; set; }\n\n    public long TotalUp { get; set; }\n\n    public long TotalDown { get; set; }\n\n    public long TodayUp { get; set; }\n\n    public long TodayDown { get; set; }\n\n    public long DateNow { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/ServerTestItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class ServerTestItem\n{\n    public string? IndexId { get; set; }\n    public string? Address { get; set; }\n    public int Port { get; set; }\n    public EConfigType ConfigType { get; set; }\n    public bool AllowTest { get; set; }\n    public int QueueNum { get; set; }\n    public ProfileItem Profile { get; set; }\n    public ECoreType CoreType { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/SingboxConfig.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class SingboxConfig\n{\n    public Log4Sbox log { get; set; }\n    public Dns4Sbox? dns { get; set; }\n    public List<Inbound4Sbox> inbounds { get; set; }\n    public List<Outbound4Sbox> outbounds { get; set; }\n    public List<Endpoints4Sbox>? endpoints { get; set; }\n    public Route4Sbox route { get; set; }\n    public Experimental4Sbox? experimental { get; set; }\n}\n\npublic class Log4Sbox\n{\n    public bool? disabled { get; set; }\n    public string level { get; set; }\n    public string output { get; set; }\n    public bool? timestamp { get; set; }\n}\n\npublic class Dns4Sbox\n{\n    public List<Server4Sbox> servers { get; set; }\n    public List<Rule4Sbox> rules { get; set; }\n    public string? final { get; set; }\n    public string? strategy { get; set; }\n    public bool? disable_cache { get; set; }\n    public bool? disable_expire { get; set; }\n    public bool? independent_cache { get; set; }\n    public int? cache_capacity { get; set; }\n    public bool? reverse_mapping { get; set; }\n    public string? client_subnet { get; set; }\n}\n\npublic class Route4Sbox\n{\n    public Rule4Sbox? default_domain_resolver { get; set; } // or string\n    public bool? auto_detect_interface { get; set; }\n    public List<Rule4Sbox> rules { get; set; }\n    public List<Ruleset4Sbox>? rule_set { get; set; }\n    public string? final { get; set; }\n}\n\n[Serializable]\npublic class Rule4Sbox\n{\n    public string? outbound { get; set; }\n    public string? server { get; set; }\n    public bool? disable_cache { get; set; }\n    public string? type { get; set; }\n    public string? mode { get; set; }\n    public bool? ip_is_private { get; set; }\n    public string? client_subnet { get; set; }\n    public int? rewrite_ttl { get; set; }\n    public bool? invert { get; set; }\n    public string? clash_mode { get; set; }\n    public List<string>? inbound { get; set; }\n    public List<string>? protocol { get; set; }\n    public List<string>? network { get; set; }\n    public List<int>? port { get; set; }\n    public List<string>? port_range { get; set; }\n    public List<string>? geosite { get; set; }\n    public List<string>? domain { get; set; }\n    public List<string>? domain_suffix { get; set; }\n    public List<string>? domain_keyword { get; set; }\n    public List<string>? domain_regex { get; set; }\n    public List<string>? geoip { get; set; }\n    public List<string>? ip_cidr { get; set; }\n    public List<string>? source_ip_cidr { get; set; }\n    public List<string>? process_name { get; set; }\n    public List<string>? process_path { get; set; }\n    public List<string>? rule_set { get; set; }\n    public List<Rule4Sbox>? rules { get; set; }\n    public string? action { get; set; }\n    public string? strategy { get; set; }\n    public List<string>? sniffer { get; set; }\n    public string? rcode { get; set; }\n    public List<int>? query_type { get; set; }\n    public List<string>? answer { get; set; }\n    public List<string>? ns { get; set; }\n    public List<string>? extra { get; set; }\n    public string? method { get; set; }\n    public bool? no_drop { get; set; }\n    public bool? source_ip_is_private { get; set; }\n    public bool? ip_accept_any { get; set; }\n    public int? source_port { get; set; }\n    public List<string>? source_port_range { get; set; }\n    public List<string>? network_type { get; set; }\n    public bool? network_is_expensive { get; set; }\n    public bool? network_is_constrained { get; set; }\n    public List<string>? wifi_ssid { get; set; }\n    public List<string>? wifi_bssid { get; set; }\n    public bool? rule_set_ip_cidr_match_source { get; set; }\n    public bool? rule_set_ip_cidr_accept_empty { get; set; }\n}\n\n[Serializable]\npublic class Inbound4Sbox\n{\n    public string type { get; set; }\n    public string tag { get; set; }\n    public string listen { get; set; }\n    public int? listen_port { get; set; }\n    public string interface_name { get; set; }\n    public List<string>? address { get; set; }\n    public int? mtu { get; set; }\n    public bool? auto_route { get; set; }\n    public bool? strict_route { get; set; }\n    public bool? endpoint_independent_nat { get; set; }\n    public string? stack { get; set; }\n    public List<User4Sbox> users { get; set; }\n}\n\npublic class User4Sbox\n{\n    public string username { get; set; }\n    public string password { get; set; }\n}\n\npublic class Outbound4Sbox : BaseServer4Sbox\n{\n    public string? server { get; set; }\n    public int? server_port { get; set; }\n    public List<string>? server_ports { get; set; }\n    public string? uuid { get; set; }\n    public string? security { get; set; }\n    public int? alter_id { get; set; }\n    public string? flow { get; set; }\n    public string? hop_interval { get; set; }\n    public int? up_mbps { get; set; }\n    public int? down_mbps { get; set; }\n    public string? auth_str { get; set; }\n    public int? recv_window_conn { get; set; }\n    public int? recv_window { get; set; }\n    public bool? disable_mtu_discovery { get; set; }\n    public string? method { get; set; }\n    public string? username { get; set; }\n    public string? password { get; set; }\n    public string? congestion_control { get; set; }\n    public string? version { get; set; }\n    public string? network { get; set; }\n    public string? packet_encoding { get; set; }\n    public string? plugin { get; set; }\n    public string? plugin_opts { get; set; }\n    public List<string>? outbounds { get; set; }\n    public bool? interrupt_exist_connections { get; set; }\n    public int? tolerance { get; set; }\n}\n\npublic class Endpoints4Sbox : BaseServer4Sbox\n{\n    public bool? system { get; set; }\n    public string? name { get; set; }\n    public int? mtu { get; set; }\n    public List<string> address { get; set; }\n    public string private_key { get; set; }\n    public int? listen_port { get; set; }\n    public string? udp_timeout { get; set; }\n    public int? workers { get; set; }\n    public List<Peer4Sbox> peers { get; set; }\n}\n\npublic class Peer4Sbox\n{\n    public string address { get; set; }\n    public int port { get; set; }\n    public string public_key { get; set; }\n    public string? pre_shared_key { get; set; }\n    public List<string> allowed_ips { get; set; }\n    public int? persistent_keepalive_interval { get; set; }\n    public List<int> reserved { get; set; }\n}\n\npublic class Tls4Sbox\n{\n    public bool enabled { get; set; }\n    public string? server_name { get; set; }\n    public bool? insecure { get; set; }\n    public List<string>? alpn { get; set; }\n    public Utls4Sbox? utls { get; set; }\n    public Reality4Sbox? reality { get; set; }\n    public bool? fragment { get; set; }\n    public string? fragment_fallback_delay { get; set; }\n    public bool? record_fragment { get; set; }\n    public List<string>? certificate { get; set; }\n    public Ech4Sbox? ech { get; set; }\n}\n\npublic class Ech4Sbox\n{\n    public bool enabled { get; set; }\n    public List<string>? config { get; set; }\n    public string? query_server_name { get; set; }\n}\n\npublic class Multiplex4Sbox\n{\n    public bool enabled { get; set; }\n    public string protocol { get; set; }\n    public int max_connections { get; set; }\n    public bool? padding { get; set; }\n}\n\npublic class Utls4Sbox\n{\n    public bool enabled { get; set; }\n    public string fingerprint { get; set; }\n}\n\npublic class Reality4Sbox\n{\n    public bool enabled { get; set; }\n    public string public_key { get; set; }\n    public string short_id { get; set; }\n}\n\npublic class Transport4Sbox\n{\n    public string? type { get; set; }\n    public object? host { get; set; }\n    public string? path { get; set; }\n    public Headers4Sbox? headers { get; set; }\n\n    public string? service_name { get; set; }\n    public string? idle_timeout { get; set; }\n    public string? ping_timeout { get; set; }\n    public bool? permit_without_stream { get; set; }\n    public int? max_early_data { get; set; }\n    public string? early_data_header_name { get; set; }\n}\n\npublic class Headers4Sbox\n{\n    public string? Host { get; set; }\n}\n\npublic class HyObfs4Sbox\n{\n    public string? type { get; set; }\n    public string? password { get; set; }\n}\n\npublic class Server4Sbox : BaseServer4Sbox\n{\n    public string? inet4_range { get; set; }\n    public string? inet6_range { get; set; }\n    public string? client_subnet { get; set; }\n    public string? server { get; set; }\n    public new string? domain_resolver { get; set; }\n    [JsonPropertyName(\"interface\")] public string? Interface { get; set; }\n    public int? server_port { get; set; }\n    public string? path { get; set; }\n    public Headers4Sbox? headers { get; set; }\n\n    // public List<string>? path { get; set; } // hosts\n    public Dictionary<string, List<string>>? predefined { get; set; }\n\n    // Deprecated in sing-box 1.12.0 , kept for backward compatibility\n    public string? address { get; set; }\n\n    public string? address_resolver { get; set; }\n    public string? address_strategy { get; set; }\n    public string? strategy { get; set; }\n    // Deprecated End\n}\n\npublic class Experimental4Sbox\n{\n    public CacheFile4Sbox? cache_file { get; set; }\n    public V2ray_Api4Sbox? v2ray_api { get; set; }\n    public Clash_Api4Sbox? clash_api { get; set; }\n}\n\npublic class V2ray_Api4Sbox\n{\n    public string listen { get; set; }\n    public Stats4Sbox stats { get; set; }\n}\n\npublic class Clash_Api4Sbox\n{\n    public string? external_controller { get; set; }\n    public bool? store_selected { get; set; }\n}\n\npublic class Stats4Sbox\n{\n    public bool enabled { get; set; }\n    public List<string>? inbounds { get; set; }\n    public List<string>? outbounds { get; set; }\n    public List<string>? users { get; set; }\n}\n\npublic class CacheFile4Sbox\n{\n    public bool enabled { get; set; }\n    public string? path { get; set; }\n    public string? cache_id { get; set; }\n    public bool? store_fakeip { get; set; }\n}\n\npublic class Ruleset4Sbox\n{\n    public string? tag { get; set; }\n    public string? type { get; set; }\n    public string? format { get; set; }\n    public string? path { get; set; }\n    public string? url { get; set; }\n    public string? download_detour { get; set; }\n    public string? update_interval { get; set; }\n}\n\npublic abstract class DialFields4Sbox\n{\n    public string? detour { get; set; }\n    public string? bind_interface { get; set; }\n    public string? inet4_bind_address { get; set; }\n    public string? inet6_bind_address { get; set; }\n    public int? routing_mark { get; set; }\n    public bool? reuse_addr { get; set; }\n    public string? netns { get; set; }\n    public string? connect_timeout { get; set; }\n    public bool? tcp_fast_open { get; set; }\n    public bool? tcp_multi_path { get; set; }\n    public bool? udp_fragment { get; set; }\n    public Rule4Sbox? domain_resolver { get; set; } // or string\n    public string? network_strategy { get; set; }\n    public List<string>? network_type { get; set; }\n    public List<string>? fallback_network_type { get; set; }\n    public string? fallback_delay { get; set; }\n    public Tls4Sbox? tls { get; set; }\n    public Multiplex4Sbox? multiplex { get; set; }\n    public Transport4Sbox? transport { get; set; }\n    public HyObfs4Sbox? obfs { get; set; }\n}\n\npublic abstract class BaseServer4Sbox : DialFields4Sbox\n{\n    public string type { get; set; }\n    public string tag { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/SpeedTestResult.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class SpeedTestResult\n{\n    public string? IndexId { get; set; }\n\n    public string? Delay { get; set; }\n\n    public string? Speed { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/SsSIP008.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class SsSIP008\n{\n    public List<SsServer>? servers { get; set; }\n}\n\n[Serializable]\npublic class SsServer\n{\n    public string? remarks { get; set; }\n    public string? server { get; set; }\n    public string? server_port { get; set; }\n    public string? method { get; set; }\n    public string? password { get; set; }\n    public string? plugin { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/SubItem.cs",
    "content": "namespace ServiceLib.Models;\n\n[Serializable]\npublic class SubItem\n{\n    [PrimaryKey]\n    public string Id { get; set; }\n\n    public string Remarks { get; set; }\n\n    public string Url { get; set; }\n\n    public string MoreUrl { get; set; }\n\n    public bool Enabled { get; set; } = true;\n\n    public string UserAgent { get; set; } = string.Empty;\n\n    public int Sort { get; set; }\n\n    public string? Filter { get; set; }\n\n    public int AutoUpdateInterval { get; set; }\n\n    public long UpdateTime { get; set; }\n\n    public string? ConvertTarget { get; set; }\n\n    public string? PrevProfile { get; set; }\n\n    public string? NextProfile { get; set; }\n\n    public int? PreSocksPort { get; set; }\n\n    public string? Memo { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/UpdateResult.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class UpdateResult\n{\n    public bool Success { get; set; }\n    public string? Msg { get; set; }\n    public SemanticVersion? Version { get; set; }\n    public string? Url { get; set; }\n\n    public UpdateResult(bool success, string? msg)\n    {\n        Success = success;\n        Msg = msg;\n    }\n\n    public UpdateResult(bool success, SemanticVersion? version)\n    {\n        Success = success;\n        Version = version;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/V2rayConfig.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class V2rayConfig\n{\n    public Log4Ray log { get; set; }\n    public object dns { get; set; }\n    public List<Inbounds4Ray> inbounds { get; set; }\n    public List<Outbounds4Ray> outbounds { get; set; }\n    public Routing4Ray routing { get; set; }\n    public Metrics4Ray? metrics { get; set; }\n    public Policy4Ray? policy { get; set; }\n    public Stats4Ray? stats { get; set; }\n    public Observatory4Ray? observatory { get; set; }\n    public BurstObservatory4Ray? burstObservatory { get; set; }\n    public string? remarks { get; set; }\n}\n\npublic class Stats4Ray\n{ }\n\npublic class Metrics4Ray\n{\n    public string tag { get; set; }\n}\n\npublic class Policy4Ray\n{\n    public SystemPolicy4Ray system { get; set; }\n}\n\npublic class SystemPolicy4Ray\n{\n    public bool statsOutboundUplink { get; set; }\n    public bool statsOutboundDownlink { get; set; }\n}\n\npublic class Log4Ray\n{\n    public string? access { get; set; }\n\n    public string? error { get; set; }\n\n    public string? loglevel { get; set; }\n}\n\npublic class Inbounds4Ray\n{\n    public string tag { get; set; }\n\n    public int port { get; set; }\n\n    public string listen { get; set; }\n\n    public string protocol { get; set; }\n\n    public Sniffing4Ray sniffing { get; set; }\n\n    public Inboundsettings4Ray settings { get; set; }\n}\n\npublic class Inboundsettings4Ray\n{\n    public string? auth { get; set; }\n\n    public bool? udp { get; set; }\n\n    public string? ip { get; set; }\n\n    public string? address { get; set; }\n\n    public List<UsersItem4Ray>? clients { get; set; }\n\n    public string? decryption { get; set; }\n\n    public bool? allowTransparent { get; set; }\n\n    public List<AccountsItem4Ray>? accounts { get; set; }\n}\n\npublic class UsersItem4Ray\n{\n    public string? id { get; set; }\n\n    public int? alterId { get; set; }\n\n    public string? email { get; set; }\n\n    public string? security { get; set; }\n\n    public string? encryption { get; set; }\n\n    public string? flow { get; set; }\n}\n\npublic class Sniffing4Ray\n{\n    public bool enabled { get; set; }\n    public List<string>? destOverride { get; set; }\n    public bool routeOnly { get; set; }\n}\n\npublic class Outbounds4Ray\n{\n    public string tag { get; set; }\n\n    public string protocol { get; set; }\n\n    public string? targetStrategy { get; set; }\n\n    public Outboundsettings4Ray settings { get; set; }\n\n    public StreamSettings4Ray streamSettings { get; set; }\n\n    public Mux4Ray mux { get; set; }\n}\n\npublic class Outboundsettings4Ray\n{\n    public List<VnextItem4Ray>? vnext { get; set; }\n\n    public List<ServersItem4Ray>? servers { get; set; }\n\n    public Response4Ray? response { get; set; }\n\n    public string domainStrategy { get; set; }\n\n    public int? userLevel { get; set; }\n\n    public FragmentItem4Ray? fragment { get; set; }\n\n    public string? secretKey { get; set; }\n\n    public Object? address { get; set; }\n    public int? port { get; set; }\n\n    public List<WireguardPeer4Ray>? peers { get; set; }\n\n    public bool? noKernelTun { get; set; }\n\n    public int? mtu { get; set; }\n\n    public List<int>? reserved { get; set; }\n\n    public int? workers { get; set; }\n\n    public int? version { get; set; }\n}\n\npublic class WireguardPeer4Ray\n{\n    public string endpoint { get; set; }\n    public string publicKey { get; set; }\n}\n\npublic class VnextItem4Ray\n{\n    public string address { get; set; }\n\n    public int port { get; set; }\n\n    public List<UsersItem4Ray> users { get; set; }\n}\n\npublic class ServersItem4Ray\n{\n    public string email { get; set; }\n\n    public string address { get; set; }\n\n    public string? method { get; set; }\n\n    public bool? ota { get; set; }\n\n    public string? password { get; set; }\n\n    public int port { get; set; }\n\n    public int? level { get; set; }\n\n    public string flow { get; set; }\n\n    public List<SocksUsersItem4Ray> users { get; set; }\n}\n\npublic class SocksUsersItem4Ray\n{\n    public string user { get; set; }\n\n    public string pass { get; set; }\n\n    public int? level { get; set; }\n}\n\npublic class Mux4Ray\n{\n    public bool enabled { get; set; }\n    public int? concurrency { get; set; }\n    public int? xudpConcurrency { get; set; }\n    public string? xudpProxyUDP443 { get; set; }\n}\n\npublic class Response4Ray\n{\n    public string type { get; set; }\n}\n\npublic class Dns4Ray\n{\n    public Dictionary<string, object>? hosts { get; set; }\n    public List<object> servers { get; set; }\n    public bool? serveStale { get; set; }\n    public bool? enableParallelQuery { get; set; }\n    public string? tag { get; set; }\n}\n\npublic class DnsServer4Ray\n{\n    public string? address { get; set; }\n    public int? port { get; set; }\n    public List<string>? domains { get; set; }\n    public bool? skipFallback { get; set; }\n    public List<string>? expectedIPs { get; set; }\n    public string? tag { get; set; }\n}\n\npublic class Routing4Ray\n{\n    public string domainStrategy { get; set; }\n\n    public List<RulesItem4Ray> rules { get; set; }\n\n    public List<BalancersItem4Ray>? balancers { get; set; }\n}\n\n[Serializable]\npublic class RulesItem4Ray\n{\n    public string? type { get; set; }\n\n    public string? port { get; set; }\n    public string? network { get; set; }\n\n    public List<string>? inboundTag { get; set; }\n\n    public string? outboundTag { get; set; }\n\n    public string? balancerTag { get; set; }\n\n    public List<string>? ip { get; set; }\n\n    public List<string>? domain { get; set; }\n\n    public List<string>? protocol { get; set; }\n\n    public List<string>? process { get; set; }\n}\n\npublic class BalancersItem4Ray\n{\n    public List<string>? selector { get; set; }\n    public BalancersStrategy4Ray? strategy { get; set; }\n    public string? tag { get; set; }\n}\n\npublic class BalancersStrategy4Ray\n{\n    public string? type { get; set; }\n    public BalancersStrategySettings4Ray? settings { get; set; }\n}\n\npublic class BalancersStrategySettings4Ray\n{\n    public int? expected { get; set; }\n    public string? maxRTT { get; set; }\n    public float? tolerance { get; set; }\n    public List<string>? baselines { get; set; }\n    public List<BalancersStrategySettingsCosts4Ray>? costs { get; set; }\n}\n\npublic class BalancersStrategySettingsCosts4Ray\n{\n    public bool? regexp { get; set; }\n    public string? match { get; set; }\n    public float? value { get; set; }\n}\n\npublic class Observatory4Ray\n{\n    public List<string>? subjectSelector { get; set; }\n    public string? probeUrl { get; set; }\n    public string? probeInterval { get; set; }\n    public bool? enableConcurrency { get; set; }\n}\n\npublic class BurstObservatory4Ray\n{\n    public List<string>? subjectSelector { get; set; }\n    public BurstObservatoryPingConfig4Ray? pingConfig { get; set; }\n}\n\npublic class BurstObservatoryPingConfig4Ray\n{\n    public string? destination { get; set; }\n    public string? connectivity { get; set; }\n    public string? interval { get; set; }\n    public int? sampling { get; set; }\n    public string? timeout { get; set; }\n}\n\npublic class StreamSettings4Ray\n{\n    public string network { get; set; }\n\n    public string security { get; set; }\n\n    public TlsSettings4Ray? tlsSettings { get; set; }\n\n    public TcpSettings4Ray? tcpSettings { get; set; }\n\n    public KcpSettings4Ray? kcpSettings { get; set; }\n\n    public WsSettings4Ray? wsSettings { get; set; }\n\n    public HttpupgradeSettings4Ray? httpupgradeSettings { get; set; }\n\n    public XhttpSettings4Ray? xhttpSettings { get; set; }\n\n    public HttpSettings4Ray? httpSettings { get; set; }\n\n    public QuicSettings4Ray? quicSettings { get; set; }\n\n    public TlsSettings4Ray? realitySettings { get; set; }\n\n    public GrpcSettings4Ray? grpcSettings { get; set; }\n\n    public HysteriaSettings4Ray? hysteriaSettings { get; set; }\n\n    public Finalmask4Ray? finalmask { get; set; }\n\n    public Sockopt4Ray? sockopt { get; set; }\n}\n\npublic class TlsSettings4Ray\n{\n    public bool? allowInsecure { get; set; }\n\n    public string? serverName { get; set; }\n\n    public List<string>? alpn { get; set; }\n\n    public string? fingerprint { get; set; }\n\n    public bool? show { get; set; }\n    public string? publicKey { get; set; }\n    public string? shortId { get; set; }\n    public string? spiderX { get; set; }\n    public string? mldsa65Verify { get; set; }\n    public List<CertificateSettings4Ray>? certificates { get; set; }\n    public string? pinnedPeerCertSha256 { get; set; }\n    public bool? disableSystemRoot { get; set; }\n    public string? echConfigList { get; set; }\n    public string? echForceQuery { get; set; }\n    public Sockopt4Ray? echSockopt { get; set; }\n}\n\npublic class CertificateSettings4Ray\n{\n    public List<string>? certificate { get; set; }\n    public string? usage { get; set; }\n}\n\npublic class TcpSettings4Ray\n{\n    public Header4Ray header { get; set; }\n}\n\npublic class Header4Ray\n{\n    public string type { get; set; }\n\n    public object request { get; set; }\n\n    public object response { get; set; }\n}\n\npublic class KcpSettings4Ray\n{\n    public int mtu { get; set; }\n\n    public int tti { get; set; }\n\n    public int uplinkCapacity { get; set; }\n\n    public int downlinkCapacity { get; set; }\n\n    public bool congestion { get; set; }\n\n    public int readBufferSize { get; set; }\n\n    public int writeBufferSize { get; set; }\n}\n\npublic class WsSettings4Ray\n{\n    public string? path { get; set; }\n    public string? host { get; set; }\n\n    public Headers4Ray headers { get; set; }\n}\n\npublic class Headers4Ray\n{\n    [JsonPropertyName(\"User-Agent\")]\n    public string UserAgent { get; set; }\n}\n\npublic class HttpupgradeSettings4Ray\n{\n    public string? path { get; set; }\n\n    public string? host { get; set; }\n}\n\npublic class XhttpSettings4Ray\n{\n    public string? path { get; set; }\n    public string? host { get; set; }\n    public string? mode { get; set; }\n    public object? extra { get; set; }\n}\n\npublic class HttpSettings4Ray\n{\n    public string? path { get; set; }\n\n    public List<string>? host { get; set; }\n}\n\npublic class QuicSettings4Ray\n{\n    public string security { get; set; }\n\n    public string key { get; set; }\n\n    public Header4Ray header { get; set; }\n}\n\npublic class GrpcSettings4Ray\n{\n    public string? authority { get; set; }\n    public string? serviceName { get; set; }\n    public bool multiMode { get; set; }\n    public int? idle_timeout { get; set; }\n    public int? health_check_timeout { get; set; }\n    public bool? permit_without_stream { get; set; }\n    public int? initial_windows_size { get; set; }\n}\n\npublic class HysteriaSettings4Ray\n{\n    public int version { get; set; }\n    public string? auth { get; set; }\n    public string? up { get; set; }\n    public string? down { get; set; }\n    public HysteriaUdpHop4Ray? udphop { get; set; }\n}\n\npublic class HysteriaUdpHop4Ray\n{\n    public string? port { get; set; }\n    public string? interval { get; set; }\n}\n\npublic class Finalmask4Ray\n{\n    public List<Mask4Ray>? tcp { get; set; }\n    public List<Mask4Ray>? udp { get; set; }\n}\n\npublic class Mask4Ray\n{\n    public string type { get; set; }\n    public object? settings { get; set; }\n}\n\npublic class MaskSettings4Ray\n{\n    public string? password { get; set; }\n    public string? domain { get; set; }\n}\n\npublic class AccountsItem4Ray\n{\n    public string user { get; set; }\n\n    public string pass { get; set; }\n}\n\npublic class Sockopt4Ray\n{\n    public string? dialerProxy { get; set; }\n}\n\npublic class FragmentItem4Ray\n{\n    public string? packets { get; set; }\n    public string? length { get; set; }\n    public string? interval { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/V2rayMetricsVars.cs",
    "content": "using System.Collections;\n\nnamespace ServiceLib.Models;\n\ninternal class V2rayMetricsVars\n{\n    public V2rayMetricsVarsStats? stats { get; set; }\n}\n\npublic class V2rayMetricsVarsStats\n{\n    public Hashtable? outbound { get; set; }\n}\n\npublic class V2rayMetricsVarsLink\n{\n    public long downlink { get; set; }\n    public long uplink { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/V2rayTcpRequest.cs",
    "content": "namespace ServiceLib.Models;\n\npublic class V2rayTcpRequest\n{\n    /// <summary>\n    ///\n    /// </summary>\n    public RequestHeaders headers { get; set; }\n}\n\npublic class RequestHeaders\n{\n    /// <summary>\n    ///\n    /// </summary>\n    public List<string> Host { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Models/VmessQRCode.cs",
    "content": "namespace ServiceLib.Models;\n\n/// <summary>\n/// https://github.com/2dust/v2rayN/wiki/\n/// </summary>\n[Serializable]\npublic class VmessQRCode\n{\n    [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]\n    public int v { get; set; } = 2;\n\n    public string ps { get; set; } = string.Empty;\n\n    public string add { get; set; } = string.Empty;\n\n    [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]\n    public int port { get; set; } = 0;\n\n    public string id { get; set; } = string.Empty;\n\n    [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]\n    public int aid { get; set; } = 0;\n\n    public string scy { get; set; } = string.Empty;\n\n    public string net { get; set; } = string.Empty;\n\n    public string type { get; set; } = string.Empty;\n\n    public string host { get; set; } = string.Empty;\n\n    public string path { get; set; } = string.Empty;\n\n    public string tls { get; set; } = string.Empty;\n\n    public string sni { get; set; } = string.Empty;\n\n    public string alpn { get; set; } = string.Empty;\n\n    public string fp { get; set; } = string.Empty;\n\n    public string insecure { get; set; } = string.Empty;\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace ServiceLib.Resx {\n    using System;\n    \n    \n    /// <summary>\n    ///   一个强类型的资源类，用于查找本地化的字符串等。\n    /// </summary>\n    // 此类是由 StronglyTypedResourceBuilder\n    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。\n    // 若要添加或移除成员，请编辑 .ResX 文件，然后重新运行 ResGen\n    // (以 /str 作为命令选项)，或重新生成 VS 项目。\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"18.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    public class ResUI {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal ResUI() {\n        }\n        \n        /// <summary>\n        ///   返回此类使用的缓存的 ResourceManager 实例。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        public static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"ServiceLib.Resx.ResUI\", typeof(ResUI).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   重写当前线程的 CurrentUICulture 属性，对\n        ///   使用此强类型资源类的所有资源查找执行重写。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        public static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Do you want to append rules? Choose yes to append, no to replace. 的本地化字符串。\n        /// </summary>\n        public static string AddBatchRoutingRulesYesNo {\n            get {\n                return ResourceManager.GetString(\"AddBatchRoutingRulesYesNo\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 All 的本地化字符串。\n        /// </summary>\n        public static string AllGroupServers {\n            get {\n                return ResourceManager.GetString(\"AllGroupServers\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Export share link to clipboard successfully 的本地化字符串。\n        /// </summary>\n        public static string BatchExportURLSuccessfully {\n            get {\n                return ResourceManager.GetString(\"BatchExportURLSuccessfully\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Certificate not set 的本地化字符串。\n        /// </summary>\n        public static string CertNotSet {\n            get {\n                return ResourceManager.GetString(\"CertNotSet\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Certificate set 的本地化字符串。\n        /// </summary>\n        public static string CertSet {\n            get {\n                return ResourceManager.GetString(\"CertSet\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please check the Configuration settings first. 的本地化字符串。\n        /// </summary>\n        public static string CheckServerSettings {\n            get {\n                return ResourceManager.GetString(\"CheckServerSettings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Invalid configuration format. 的本地化字符串。\n        /// </summary>\n        public static string ConfigurationFormatIncorrect {\n            get {\n                return ResourceManager.GetString(\"ConfigurationFormatIncorrect\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Host filter 的本地化字符串。\n        /// </summary>\n        public static string ConnectionsHostFilterTitle {\n            get {\n                return ResourceManager.GetString(\"ConnectionsHostFilterTitle\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Note that custom configuration relies entirely on your own configuration and does not work with all settings. If you want to use the system proxy, please modify the listening port manually. 的本地化字符串。\n        /// </summary>\n        public static string CustomServerTips {\n            get {\n                return ResourceManager.GetString(\"CustomServerTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Downloading... 的本地化字符串。\n        /// </summary>\n        public static string Downloading {\n            get {\n                return ResourceManager.GetString(\"Downloading\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to convert configuration file 的本地化字符串。\n        /// </summary>\n        public static string FailedConversionConfiguration {\n            get {\n                return ResourceManager.GetString(\"FailedConversionConfiguration\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to generate default configuration file 的本地化字符串。\n        /// </summary>\n        public static string FailedGenDefaultConfiguration {\n            get {\n                return ResourceManager.GetString(\"FailedGenDefaultConfiguration\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to get the default configuration 的本地化字符串。\n        /// </summary>\n        public static string FailedGetDefaultConfiguration {\n            get {\n                return ResourceManager.GetString(\"FailedGetDefaultConfiguration\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to import custom configuration Configuration 的本地化字符串。\n        /// </summary>\n        public static string FailedImportedCustomServer {\n            get {\n                return ResourceManager.GetString(\"FailedImportedCustomServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to read configuration file 的本地化字符串。\n        /// </summary>\n        public static string FailedReadConfiguration {\n            get {\n                return ResourceManager.GetString(\"FailedReadConfiguration\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to run Core, please check the prompt information 的本地化字符串。\n        /// </summary>\n        public static string FailedToRunCore {\n            get {\n                return ResourceManager.GetString(\"FailedToRunCore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please fill in the correct config template 的本地化字符串。\n        /// </summary>\n        public static string FillCorrectConfigTemplateText {\n            get {\n                return ResourceManager.GetString(\"FillCorrectConfigTemplateText\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please fill in the correct custom DNS 的本地化字符串。\n        /// </summary>\n        public static string FillCorrectDNSText {\n            get {\n                return ResourceManager.GetString(\"FillCorrectDNSText\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please enter the correct port format. 的本地化字符串。\n        /// </summary>\n        public static string FillCorrectServerPort {\n            get {\n                return ResourceManager.GetString(\"FillCorrectServerPort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please enter the local listening port. 的本地化字符串。\n        /// </summary>\n        public static string FillLocalListeningPort {\n            get {\n                return ResourceManager.GetString(\"FillLocalListeningPort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please enter the password. 的本地化字符串。\n        /// </summary>\n        public static string FillPassword {\n            get {\n                return ResourceManager.GetString(\"FillPassword\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please enter the address. 的本地化字符串。\n        /// </summary>\n        public static string FillServerAddress {\n            get {\n                return ResourceManager.GetString(\"FillServerAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please browse to import Configuration configuration 的本地化字符串。\n        /// </summary>\n        public static string FillServerAddressCustom {\n            get {\n                return ResourceManager.GetString(\"FillServerAddressCustom\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please enter the user ID. 的本地化字符串。\n        /// </summary>\n        public static string FillUUID {\n            get {\n                return ResourceManager.GetString(\"FillUUID\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Transport 的本地化字符串。\n        /// </summary>\n        public static string GbTransport {\n            get {\n                return ResourceManager.GetString(\"GbTransport\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 This is not the correct configuration, please check 的本地化字符串。\n        /// </summary>\n        public static string Incorrectconfiguration {\n            get {\n                return ResourceManager.GetString(\"Incorrectconfiguration\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Initial Configuration 的本地化字符串。\n        /// </summary>\n        public static string InitialConfiguration {\n            get {\n                return ResourceManager.GetString(\"InitialConfiguration\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please do not use the insecure HTTP protocol subscription address 的本地化字符串。\n        /// </summary>\n        public static string InsecureUrlProtocol {\n            get {\n                return ResourceManager.GetString(\"InsecureUrlProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Invalid address (URL) 的本地化字符串。\n        /// </summary>\n        public static string InvalidUrlTip {\n            get {\n                return ResourceManager.GetString(\"InvalidUrlTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 {0} {1} already up to date. 的本地化字符串。\n        /// </summary>\n        public static string IsLatestCore {\n            get {\n                return ResourceManager.GetString(\"IsLatestCore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 {0} {1} already up to date. 的本地化字符串。\n        /// </summary>\n        public static string IsLatestN {\n            get {\n                return ResourceManager.GetString(\"IsLatestN\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 LAN 的本地化字符串。\n        /// </summary>\n        public static string LabLAN {\n            get {\n                return ResourceManager.GetString(\"LabLAN\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Local 的本地化字符串。\n        /// </summary>\n        public static string LabLocal {\n            get {\n                return ResourceManager.GetString(\"LabLocal\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Invalid backup file 的本地化字符串。\n        /// </summary>\n        public static string LocalRestoreInvalidZipTips {\n            get {\n                return ResourceManager.GetString(\"LocalRestoreInvalidZipTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Address 的本地化字符串。\n        /// </summary>\n        public static string LvAddress {\n            get {\n                return ResourceManager.GetString(\"LvAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Automatic update interval (minutes) 的本地化字符串。\n        /// </summary>\n        public static string LvAutoUpdateInterval {\n            get {\n                return ResourceManager.GetString(\"LvAutoUpdateInterval\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Convert target type 的本地化字符串。\n        /// </summary>\n        public static string LvConvertTarget {\n            get {\n                return ResourceManager.GetString(\"LvConvertTarget\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please leave blank if no conversion is required 的本地化字符串。\n        /// </summary>\n        public static string LvConvertTargetTip {\n            get {\n                return ResourceManager.GetString(\"LvConvertTargetTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Count 的本地化字符串。\n        /// </summary>\n        public static string LvCount {\n            get {\n                return ResourceManager.GetString(\"LvCount\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Custom icon 的本地化字符串。\n        /// </summary>\n        public static string LvCustomIcon {\n            get {\n                return ResourceManager.GetString(\"LvCustomIcon\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Customize the rule-set of sing-box 的本地化字符串。\n        /// </summary>\n        public static string LvCustomRulesetPath4Singbox {\n            get {\n                return ResourceManager.GetString(\"LvCustomRulesetPath4Singbox\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable update 的本地化字符串。\n        /// </summary>\n        public static string LvEnabled {\n            get {\n                return ResourceManager.GetString(\"LvEnabled\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Security 的本地化字符串。\n        /// </summary>\n        public static string LvEncryptionMethod {\n            get {\n                return ResourceManager.GetString(\"LvEncryptionMethod\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remarks regular filter 的本地化字符串。\n        /// </summary>\n        public static string LvFilter {\n            get {\n                return ResourceManager.GetString(\"LvFilter\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remarks Memo 的本地化字符串。\n        /// </summary>\n        public static string LvMemo {\n            get {\n                return ResourceManager.GetString(\"LvMemo\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 More URLs, separated by commas; Subscription conversion will be invalid 的本地化字符串。\n        /// </summary>\n        public static string LvMoreUrl {\n            get {\n                return ResourceManager.GetString(\"LvMoreUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Next proxy remarks 的本地化字符串。\n        /// </summary>\n        public static string LvNextProfile {\n            get {\n                return ResourceManager.GetString(\"LvNextProfile\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Port 的本地化字符串。\n        /// </summary>\n        public static string LvPort {\n            get {\n                return ResourceManager.GetString(\"LvPort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Previous proxy remarks 的本地化字符串。\n        /// </summary>\n        public static string LvPrevProfile {\n            get {\n                return ResourceManager.GetString(\"LvPrevProfile\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please make sure the Configuration remarks exist and are unique 的本地化字符串。\n        /// </summary>\n        public static string LvPrevProfileTip {\n            get {\n                return ResourceManager.GetString(\"LvPrevProfileTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remarks 的本地化字符串。\n        /// </summary>\n        public static string LvRemarks {\n            get {\n                return ResourceManager.GetString(\"LvRemarks\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Type 的本地化字符串。\n        /// </summary>\n        public static string LvServiceType {\n            get {\n                return ResourceManager.GetString(\"LvServiceType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Sort 的本地化字符串。\n        /// </summary>\n        public static string LvSort {\n            get {\n                return ResourceManager.GetString(\"LvSort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subs group 的本地化字符串。\n        /// </summary>\n        public static string LvSubscription {\n            get {\n                return ResourceManager.GetString(\"LvSubscription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Delay (ms) 的本地化字符串。\n        /// </summary>\n        public static string LvTestDelay {\n            get {\n                return ResourceManager.GetString(\"LvTestDelay\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Speed (MB/s) 的本地化字符串。\n        /// </summary>\n        public static string LvTestSpeed {\n            get {\n                return ResourceManager.GetString(\"LvTestSpeed\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 TLS 的本地化字符串。\n        /// </summary>\n        public static string LvTLS {\n            get {\n                return ResourceManager.GetString(\"LvTLS\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Download traffic today 的本地化字符串。\n        /// </summary>\n        public static string LvTodayDownloadDataAmount {\n            get {\n                return ResourceManager.GetString(\"LvTodayDownloadDataAmount\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Upload traffic today 的本地化字符串。\n        /// </summary>\n        public static string LvTodayUploadDataAmount {\n            get {\n                return ResourceManager.GetString(\"LvTodayUploadDataAmount\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Total download traffic 的本地化字符串。\n        /// </summary>\n        public static string LvTotalDownloadDataAmount {\n            get {\n                return ResourceManager.GetString(\"LvTotalDownloadDataAmount\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Total upload traffic 的本地化字符串。\n        /// </summary>\n        public static string LvTotalUploadDataAmount {\n            get {\n                return ResourceManager.GetString(\"LvTotalUploadDataAmount\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Transport 的本地化字符串。\n        /// </summary>\n        public static string LvTransportProtocol {\n            get {\n                return ResourceManager.GetString(\"LvTransportProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 URL (optional) 的本地化字符串。\n        /// </summary>\n        public static string LvUrl {\n            get {\n                return ResourceManager.GetString(\"LvUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 User Agent 的本地化字符串。\n        /// </summary>\n        public static string LvUserAgent {\n            get {\n                return ResourceManager.GetString(\"LvUserAgent\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 WebDAV Check 的本地化字符串。\n        /// </summary>\n        public static string LvWebDavCheck {\n            get {\n                return ResourceManager.GetString(\"LvWebDavCheck\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remote folder name (optional) 的本地化字符串。\n        /// </summary>\n        public static string LvWebDavDirName {\n            get {\n                return ResourceManager.GetString(\"LvWebDavDirName\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 WebDAV Password 的本地化字符串。\n        /// </summary>\n        public static string LvWebDavPassword {\n            get {\n                return ResourceManager.GetString(\"LvWebDavPassword\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 WebDAV URL 的本地化字符串。\n        /// </summary>\n        public static string LvWebDavUrl {\n            get {\n                return ResourceManager.GetString(\"LvWebDavUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 WebDAV User Name 的本地化字符串。\n        /// </summary>\n        public static string LvWebDavUserName {\n            get {\n                return ResourceManager.GetString(\"LvWebDavUserName\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [Anytls] 的本地化字符串。\n        /// </summary>\n        public static string menuAddAnytlsServer {\n            get {\n                return ResourceManager.GetString(\"menuAddAnytlsServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add Child  的本地化字符串。\n        /// </summary>\n        public static string menuAddChildServer {\n            get {\n                return ResourceManager.GetString(\"menuAddChildServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add a custom configuration 的本地化字符串。\n        /// </summary>\n        public static string menuAddCustomServer {\n            get {\n                return ResourceManager.GetString(\"menuAddCustomServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [HTTP] 的本地化字符串。\n        /// </summary>\n        public static string menuAddHttpServer {\n            get {\n                return ResourceManager.GetString(\"menuAddHttpServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [Hysteria2]  的本地化字符串。\n        /// </summary>\n        public static string menuAddHysteria2Server {\n            get {\n                return ResourceManager.GetString(\"menuAddHysteria2Server\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add Policy Group  的本地化字符串。\n        /// </summary>\n        public static string menuAddPolicyGroupServer {\n            get {\n                return ResourceManager.GetString(\"menuAddPolicyGroupServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add Proxy Chain 的本地化字符串。\n        /// </summary>\n        public static string menuAddProxyChainServer {\n            get {\n                return ResourceManager.GetString(\"menuAddProxyChainServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Import Share Links from clipboard 的本地化字符串。\n        /// </summary>\n        public static string menuAddServerViaClipboard {\n            get {\n                return ResourceManager.GetString(\"menuAddServerViaClipboard\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Scan QR code in the image 的本地化字符串。\n        /// </summary>\n        public static string menuAddServerViaImage {\n            get {\n                return ResourceManager.GetString(\"menuAddServerViaImage\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Scan QR code on the screen 的本地化字符串。\n        /// </summary>\n        public static string menuAddServerViaScan {\n            get {\n                return ResourceManager.GetString(\"menuAddServerViaScan\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [Shadowsocks]  的本地化字符串。\n        /// </summary>\n        public static string menuAddShadowsocksServer {\n            get {\n                return ResourceManager.GetString(\"menuAddShadowsocksServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [SOCKS]  的本地化字符串。\n        /// </summary>\n        public static string menuAddSocksServer {\n            get {\n                return ResourceManager.GetString(\"menuAddSocksServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [Trojan]  的本地化字符串。\n        /// </summary>\n        public static string menuAddTrojanServer {\n            get {\n                return ResourceManager.GetString(\"menuAddTrojanServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [TUIC]  的本地化字符串。\n        /// </summary>\n        public static string menuAddTuicServer {\n            get {\n                return ResourceManager.GetString(\"menuAddTuicServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [VLESS]  的本地化字符串。\n        /// </summary>\n        public static string menuAddVlessServer {\n            get {\n                return ResourceManager.GetString(\"menuAddVlessServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [VMess]  的本地化字符串。\n        /// </summary>\n        public static string menuAddVmessServer {\n            get {\n                return ResourceManager.GetString(\"menuAddVmessServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add [WireGuard]  的本地化字符串。\n        /// </summary>\n        public static string menuAddWireguardServer {\n            get {\n                return ResourceManager.GetString(\"menuAddWireguardServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 All configurations 的本地化字符串。\n        /// </summary>\n        public static string menuAllServers {\n            get {\n                return ResourceManager.GetString(\"menuAllServers\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Backup and Restore 的本地化字符串。\n        /// </summary>\n        public static string menuBackupAndRestore {\n            get {\n                return ResourceManager.GetString(\"menuBackupAndRestore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Check Update 的本地化字符串。\n        /// </summary>\n        public static string menuCheckUpdate {\n            get {\n                return ResourceManager.GetString(\"menuCheckUpdate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Clear all service statistics 的本地化字符串。\n        /// </summary>\n        public static string menuClearServerStatistics {\n            get {\n                return ResourceManager.GetString(\"menuClearServerStatistics\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Close 的本地化字符串。\n        /// </summary>\n        public static string menuClose {\n            get {\n                return ResourceManager.GetString(\"menuClose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Close Connection 的本地化字符串。\n        /// </summary>\n        public static string menuConnectionClose {\n            get {\n                return ResourceManager.GetString(\"menuConnectionClose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Close All Connections 的本地化字符串。\n        /// </summary>\n        public static string menuConnectionCloseAll {\n            get {\n                return ResourceManager.GetString(\"menuConnectionCloseAll\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Copy proxy command to clipboard 的本地化字符串。\n        /// </summary>\n        public static string menuCopyProxyCmdToClipboard {\n            get {\n                return ResourceManager.GetString(\"menuCopyProxyCmdToClipboard\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Clone selected 的本地化字符串。\n        /// </summary>\n        public static string menuCopyServer {\n            get {\n                return ResourceManager.GetString(\"menuCopyServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 DNS Settings 的本地化字符串。\n        /// </summary>\n        public static string menuDNSSetting {\n            get {\n                return ResourceManager.GetString(\"menuDNSSetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Edit  的本地化字符串。\n        /// </summary>\n        public static string menuEditServer {\n            get {\n                return ResourceManager.GetString(\"menuEditServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Exit 的本地化字符串。\n        /// </summary>\n        public static string menuExit {\n            get {\n                return ResourceManager.GetString(\"menuExit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Are you sure you want to exit? 的本地化字符串。\n        /// </summary>\n        public static string menuExitTips {\n            get {\n                return ResourceManager.GetString(\"menuExitTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Export selected for complete configuration 的本地化字符串。\n        /// </summary>\n        public static string menuExport2ClientConfig {\n            get {\n                return ResourceManager.GetString(\"menuExport2ClientConfig\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Export selected for complete configuration to clipboard 的本地化字符串。\n        /// </summary>\n        public static string menuExport2ClientConfigClipboard {\n            get {\n                return ResourceManager.GetString(\"menuExport2ClientConfigClipboard\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Export Share Link to Clipboard 的本地化字符串。\n        /// </summary>\n        public static string menuExport2ShareUrl {\n            get {\n                return ResourceManager.GetString(\"menuExport2ShareUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Export Base64-encoded Share Links to Clipboard 的本地化字符串。\n        /// </summary>\n        public static string menuExport2ShareUrlBase64 {\n            get {\n                return ResourceManager.GetString(\"menuExport2ShareUrlBase64\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Export 的本地化字符串。\n        /// </summary>\n        public static string menuExportConfig {\n            get {\n                return ResourceManager.GetString(\"menuExportConfig\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Test real delay 的本地化字符串。\n        /// </summary>\n        public static string menuFastRealPing {\n            get {\n                return ResourceManager.GetString(\"menuFastRealPing\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Full Config Template Setting 的本地化字符串。\n        /// </summary>\n        public static string menuFullConfigTemplate {\n            get {\n                return ResourceManager.GetString(\"menuFullConfigTemplate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Generate Policy Group 的本地化字符串。\n        /// </summary>\n        public static string menuGenGroupServer {\n            get {\n                return ResourceManager.GetString(\"menuGenGroupServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Group by Region 的本地化字符串。\n        /// </summary>\n        public static string menuGenRegionGroup {\n            get {\n                return ResourceManager.GetString(\"menuGenRegionGroup\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Global Hotkey Setting 的本地化字符串。\n        /// </summary>\n        public static string menuGlobalHotkeySetting {\n            get {\n                return ResourceManager.GetString(\"menuGlobalHotkeySetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Help 的本地化字符串。\n        /// </summary>\n        public static string menuHelp {\n            get {\n                return ResourceManager.GetString(\"menuHelp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Import Rules From Clipboard 的本地化字符串。\n        /// </summary>\n        public static string menuImportRulesFromClipboard {\n            get {\n                return ResourceManager.GetString(\"menuImportRulesFromClipboard\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Import Rules From File 的本地化字符串。\n        /// </summary>\n        public static string menuImportRulesFromFile {\n            get {\n                return ResourceManager.GetString(\"menuImportRulesFromFile\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Import Rules From Subscription URL 的本地化字符串。\n        /// </summary>\n        public static string menuImportRulesFromUrl {\n            get {\n                return ResourceManager.GetString(\"menuImportRulesFromUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Backup to local 的本地化字符串。\n        /// </summary>\n        public static string menuLocalBackup {\n            get {\n                return ResourceManager.GetString(\"menuLocalBackup\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Local 的本地化字符串。\n        /// </summary>\n        public static string menuLocalBackupAndRestore {\n            get {\n                return ResourceManager.GetString(\"menuLocalBackupAndRestore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Restore from local 的本地化字符串。\n        /// </summary>\n        public static string menuLocalRestore {\n            get {\n                return ResourceManager.GetString(\"menuLocalRestore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 One-click multi-test latency and speed (Ctrl+E) 的本地化字符串。\n        /// </summary>\n        public static string menuMixedTestServer {\n            get {\n                return ResourceManager.GetString(\"menuMixedTestServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Direct 的本地化字符串。\n        /// </summary>\n        public static string menuModeDirect {\n            get {\n                return ResourceManager.GetString(\"menuModeDirect\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Global 的本地化字符串。\n        /// </summary>\n        public static string menuModeGlobal {\n            get {\n                return ResourceManager.GetString(\"menuModeGlobal\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Do not change 的本地化字符串。\n        /// </summary>\n        public static string menuModeNothing {\n            get {\n                return ResourceManager.GetString(\"menuModeNothing\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rule 的本地化字符串。\n        /// </summary>\n        public static string menuModeRule {\n            get {\n                return ResourceManager.GetString(\"menuModeRule\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move to bottom 的本地化字符串。\n        /// </summary>\n        public static string menuMoveBottom {\n            get {\n                return ResourceManager.GetString(\"menuMoveBottom\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Down 的本地化字符串。\n        /// </summary>\n        public static string menuMoveDown {\n            get {\n                return ResourceManager.GetString(\"menuMoveDown\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move up and down 的本地化字符串。\n        /// </summary>\n        public static string menuMoveTo {\n            get {\n                return ResourceManager.GetString(\"menuMoveTo\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move to group 的本地化字符串。\n        /// </summary>\n        public static string menuMoveToGroup {\n            get {\n                return ResourceManager.GetString(\"menuMoveToGroup\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Move to top 的本地化字符串。\n        /// </summary>\n        public static string menuMoveTop {\n            get {\n                return ResourceManager.GetString(\"menuMoveTop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Up 的本地化字符串。\n        /// </summary>\n        public static string menuMoveUp {\n            get {\n                return ResourceManager.GetString(\"menuMoveUp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Clear all 的本地化字符串。\n        /// </summary>\n        public static string menuMsgViewClear {\n            get {\n                return ResourceManager.GetString(\"menuMsgViewClear\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Copy 的本地化字符串。\n        /// </summary>\n        public static string menuMsgViewCopy {\n            get {\n                return ResourceManager.GetString(\"menuMsgViewCopy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Copy all 的本地化字符串。\n        /// </summary>\n        public static string menuMsgViewCopyAll {\n            get {\n                return ResourceManager.GetString(\"menuMsgViewCopyAll\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Select all 的本地化字符串。\n        /// </summary>\n        public static string menuMsgViewSelectAll {\n            get {\n                return ResourceManager.GetString(\"menuMsgViewSelectAll\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Open the storage location 的本地化字符串。\n        /// </summary>\n        public static string menuOpenTheFileLocation {\n            get {\n                return ResourceManager.GetString(\"menuOpenTheFileLocation\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Option Setting 的本地化字符串。\n        /// </summary>\n        public static string menuOptionSetting {\n            get {\n                return ResourceManager.GetString(\"menuOptionSetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auto column width adjustment 的本地化字符串。\n        /// </summary>\n        public static string menuProfileAutofitColumnWidth {\n            get {\n                return ResourceManager.GetString(\"menuProfileAutofitColumnWidth\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Promotion 的本地化字符串。\n        /// </summary>\n        public static string menuPromotion {\n            get {\n                return ResourceManager.GetString(\"menuPromotion\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Latency Test 的本地化字符串。\n        /// </summary>\n        public static string menuProxiesDelaytest {\n            get {\n                return ResourceManager.GetString(\"menuProxiesDelaytest\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Part Node Latency Test 的本地化字符串。\n        /// </summary>\n        public static string menuProxiesDelaytestPart {\n            get {\n                return ResourceManager.GetString(\"menuProxiesDelaytestPart\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Refresh Proxies 的本地化字符串。\n        /// </summary>\n        public static string menuProxiesReload {\n            get {\n                return ResourceManager.GetString(\"menuProxiesReload\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Select active node 的本地化字符串。\n        /// </summary>\n        public static string menuProxiesSelectActivity {\n            get {\n                return ResourceManager.GetString(\"menuProxiesSelectActivity\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Test real delay 的本地化字符串。\n        /// </summary>\n        public static string menuRealPingServer {\n            get {\n                return ResourceManager.GetString(\"menuRealPingServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Restart as Administrator 的本地化字符串。\n        /// </summary>\n        public static string menuRebootAsAdmin {\n            get {\n                return ResourceManager.GetString(\"menuRebootAsAdmin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Regional presets setting 的本地化字符串。\n        /// </summary>\n        public static string menuRegionalPresets {\n            get {\n                return ResourceManager.GetString(\"menuRegionalPresets\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Default 的本地化字符串。\n        /// </summary>\n        public static string menuRegionalPresetsDefault {\n            get {\n                return ResourceManager.GetString(\"menuRegionalPresetsDefault\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Iran 的本地化字符串。\n        /// </summary>\n        public static string menuRegionalPresetsIran {\n            get {\n                return ResourceManager.GetString(\"menuRegionalPresetsIran\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Russia 的本地化字符串。\n        /// </summary>\n        public static string menuRegionalPresetsRussia {\n            get {\n                return ResourceManager.GetString(\"menuRegionalPresetsRussia\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Reload 的本地化字符串。\n        /// </summary>\n        public static string menuReload {\n            get {\n                return ResourceManager.GetString(\"menuReload\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Backup to remote (WebDAV) 的本地化字符串。\n        /// </summary>\n        public static string menuRemoteBackup {\n            get {\n                return ResourceManager.GetString(\"menuRemoteBackup\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remote (WebDAV) 的本地化字符串。\n        /// </summary>\n        public static string menuRemoteBackupAndRestore {\n            get {\n                return ResourceManager.GetString(\"menuRemoteBackupAndRestore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Restore from remote (WebDAV) 的本地化字符串。\n        /// </summary>\n        public static string menuRemoteRestore {\n            get {\n                return ResourceManager.GetString(\"menuRemoteRestore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remove Child  的本地化字符串。\n        /// </summary>\n        public static string menuRemoveChildServer {\n            get {\n                return ResourceManager.GetString(\"menuRemoveChildServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remove duplicate 的本地化字符串。\n        /// </summary>\n        public static string menuRemoveDuplicateServer {\n            get {\n                return ResourceManager.GetString(\"menuRemoveDuplicateServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remove invalid by test results 的本地化字符串。\n        /// </summary>\n        public static string menuRemoveInvalidServerResult {\n            get {\n                return ResourceManager.GetString(\"menuRemoveInvalidServerResult\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remove selected 的本地化字符串。\n        /// </summary>\n        public static string menuRemoveServer {\n            get {\n                return ResourceManager.GetString(\"menuRemoveServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing 的本地化字符串。\n        /// </summary>\n        public static string menuRouting {\n            get {\n                return ResourceManager.GetString(\"menuRouting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add 的本地化字符串。\n        /// </summary>\n        public static string menuRoutingAdvancedAdd {\n            get {\n                return ResourceManager.GetString(\"menuRoutingAdvancedAdd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Import Rules 的本地化字符串。\n        /// </summary>\n        public static string menuRoutingAdvancedImportRules {\n            get {\n                return ResourceManager.GetString(\"menuRoutingAdvancedImportRules\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remove selected 的本地化字符串。\n        /// </summary>\n        public static string menuRoutingAdvancedRemove {\n            get {\n                return ResourceManager.GetString(\"menuRoutingAdvancedRemove\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set as active rule 的本地化字符串。\n        /// </summary>\n        public static string menuRoutingAdvancedSetDefault {\n            get {\n                return ResourceManager.GetString(\"menuRoutingAdvancedSetDefault\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing Rule Details Setting 的本地化字符串。\n        /// </summary>\n        public static string menuRoutingRuleDetailsSetting {\n            get {\n                return ResourceManager.GetString(\"menuRoutingRuleDetailsSetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rule Settings 的本地化字符串。\n        /// </summary>\n        public static string menuRoutingRuleSetting {\n            get {\n                return ResourceManager.GetString(\"menuRoutingRuleSetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing Setting 的本地化字符串。\n        /// </summary>\n        public static string menuRoutingSetting {\n            get {\n                return ResourceManager.GetString(\"menuRoutingSetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add Rule 的本地化字符串。\n        /// </summary>\n        public static string menuRuleAdd {\n            get {\n                return ResourceManager.GetString(\"menuRuleAdd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Export Selected Rules 的本地化字符串。\n        /// </summary>\n        public static string menuRuleExportSelected {\n            get {\n                return ResourceManager.GetString(\"menuRuleExportSelected\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rule List 的本地化字符串。\n        /// </summary>\n        public static string menuRuleList {\n            get {\n                return ResourceManager.GetString(\"menuRuleList\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rule mode 的本地化字符串。\n        /// </summary>\n        public static string menuRulemode {\n            get {\n                return ResourceManager.GetString(\"menuRulemode\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remove Rule 的本地化字符串。\n        /// </summary>\n        public static string menuRuleRemove {\n            get {\n                return ResourceManager.GetString(\"menuRuleRemove\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Select all 的本地化字符串。\n        /// </summary>\n        public static string menuSelectAll {\n            get {\n                return ResourceManager.GetString(\"menuSelectAll\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Configuration item 1, Auto add from subscription group 的本地化字符串。\n        /// </summary>\n        public static string menuServerList {\n            get {\n                return ResourceManager.GetString(\"menuServerList\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Configuration Item 2, Select and add from self-built 的本地化字符串。\n        /// </summary>\n        public static string menuServerList2 {\n            get {\n                return ResourceManager.GetString(\"menuServerList2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Configuration item preview 的本地化字符串。\n        /// </summary>\n        public static string menuServerListPreview {\n            get {\n                return ResourceManager.GetString(\"menuServerListPreview\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Configuration 的本地化字符串。\n        /// </summary>\n        public static string menuServers {\n            get {\n                return ResourceManager.GetString(\"menuServers\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set as active 的本地化字符串。\n        /// </summary>\n        public static string menuSetDefaultServer {\n            get {\n                return ResourceManager.GetString(\"menuSetDefaultServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Settings 的本地化字符串。\n        /// </summary>\n        public static string menuSetting {\n            get {\n                return ResourceManager.GetString(\"menuSetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Share 的本地化字符串。\n        /// </summary>\n        public static string menuShareServer {\n            get {\n                return ResourceManager.GetString(\"menuShareServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Show or hide the main window 的本地化字符串。\n        /// </summary>\n        public static string menuShowOrHideMainWindow {\n            get {\n                return ResourceManager.GetString(\"menuShowOrHideMainWindow\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Sort by test result 的本地化字符串。\n        /// </summary>\n        public static string menuSortServerResult {\n            get {\n                return ResourceManager.GetString(\"menuSortServerResult\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Test download speed 的本地化字符串。\n        /// </summary>\n        public static string menuSpeedServer {\n            get {\n                return ResourceManager.GetString(\"menuSpeedServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add 的本地化字符串。\n        /// </summary>\n        public static string menuSubAdd {\n            get {\n                return ResourceManager.GetString(\"menuSubAdd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Delete 的本地化字符串。\n        /// </summary>\n        public static string menuSubDelete {\n            get {\n                return ResourceManager.GetString(\"menuSubDelete\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Edit 的本地化字符串。\n        /// </summary>\n        public static string menuSubEdit {\n            get {\n                return ResourceManager.GetString(\"menuSubEdit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Update current subscription without proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSubGroupUpdate {\n            get {\n                return ResourceManager.GetString(\"menuSubGroupUpdate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Update current subscription with proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSubGroupUpdateViaProxy {\n            get {\n                return ResourceManager.GetString(\"menuSubGroupUpdateViaProxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subscription Group 的本地化字符串。\n        /// </summary>\n        public static string menuSubscription {\n            get {\n                return ResourceManager.GetString(\"menuSubscription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subscription group settings 的本地化字符串。\n        /// </summary>\n        public static string menuSubSetting {\n            get {\n                return ResourceManager.GetString(\"menuSubSetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Share 的本地化字符串。\n        /// </summary>\n        public static string menuSubShare {\n            get {\n                return ResourceManager.GetString(\"menuSubShare\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Update subscriptions without proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSubUpdate {\n            get {\n                return ResourceManager.GetString(\"menuSubUpdate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Update subscriptions with proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSubUpdateViaProxy {\n            get {\n                return ResourceManager.GetString(\"menuSubUpdateViaProxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 System proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSystemproxy {\n            get {\n                return ResourceManager.GetString(\"menuSystemproxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Clear system proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSystemProxyClear {\n            get {\n                return ResourceManager.GetString(\"menuSystemProxyClear\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Do not change system proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSystemProxyNothing {\n            get {\n                return ResourceManager.GetString(\"menuSystemProxyNothing\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 PAC mode 的本地化字符串。\n        /// </summary>\n        public static string menuSystemProxyPac {\n            get {\n                return ResourceManager.GetString(\"menuSystemProxyPac\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set system proxy 的本地化字符串。\n        /// </summary>\n        public static string menuSystemProxySet {\n            get {\n                return ResourceManager.GetString(\"menuSystemProxySet\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Test tcping 的本地化字符串。\n        /// </summary>\n        public static string menuTcpingServer {\n            get {\n                return ResourceManager.GetString(\"menuTcpingServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 By test result 的本地化字符串。\n        /// </summary>\n        public static string menuTestServerResult {\n            get {\n                return ResourceManager.GetString(\"menuTestServerResult\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 {0} Website 的本地化字符串。\n        /// </summary>\n        public static string menuWebsiteItem {\n            get {\n                return ResourceManager.GetString(\"menuWebsiteItem\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Core &apos;{0}&apos; does not support network type &apos;{1}&apos; 的本地化字符串。\n        /// </summary>\n        public static string MsgCoreNotSupportNetwork {\n            get {\n                return ResourceManager.GetString(\"MsgCoreNotSupportNetwork\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Core &apos;{0}&apos; does not support protocol &apos;{1}&apos; 的本地化字符串。\n        /// </summary>\n        public static string MsgCoreNotSupportProtocol {\n            get {\n                return ResourceManager.GetString(\"MsgCoreNotSupportProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Core &apos;{0}&apos; does not support protocol &apos;{1}&apos; when using transport &apos;{2}&apos; 的本地化字符串。\n        /// </summary>\n        public static string MsgCoreNotSupportProtocolTransport {\n            get {\n                return ResourceManager.GetString(\"MsgCoreNotSupportProtocolTransport\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Downloaded GeoFile: {0} successfully 的本地化字符串。\n        /// </summary>\n        public static string MsgDownloadGeoFileSuccessfully {\n            get {\n                return ResourceManager.GetString(\"MsgDownloadGeoFileSuccessfully\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Downloaded Core successfully 的本地化字符串。\n        /// </summary>\n        public static string MsgDownloadV2rayCoreSuccessfully {\n            get {\n                return ResourceManager.GetString(\"MsgDownloadV2rayCoreSuccessfully\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Failed to import subscription content 的本地化字符串。\n        /// </summary>\n        public static string MsgFailedImportSubscription {\n            get {\n                return ResourceManager.GetString(\"MsgFailedImportSubscription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Filter, supports regular expressions 的本地化字符串。\n        /// </summary>\n        public static string MsgFilterTitle {\n            get {\n                return ResourceManager.GetString(\"MsgFilterTitle\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Got subscription content successfully 的本地化字符串。\n        /// </summary>\n        public static string MsgGetSubscriptionSuccessfully {\n            get {\n                return ResourceManager.GetString(\"MsgGetSubscriptionSuccessfully\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Group {0} child group node {1} error: {2}. Skipping this node. 的本地化字符串。\n        /// </summary>\n        public static string MsgGroupChildGroupNodeError {\n            get {\n                return ResourceManager.GetString(\"MsgGroupChildGroupNodeError\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Group {0} child group node {1} warning: {2} 的本地化字符串。\n        /// </summary>\n        public static string MsgGroupChildGroupNodeWarning {\n            get {\n                return ResourceManager.GetString(\"MsgGroupChildGroupNodeWarning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Group {0} child node {1} error: {2}. Skipping this node. 的本地化字符串。\n        /// </summary>\n        public static string MsgGroupChildNodeError {\n            get {\n                return ResourceManager.GetString(\"MsgGroupChildNodeError\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Group {0} child node {1} warning: {2} 的本地化字符串。\n        /// </summary>\n        public static string MsgGroupChildNodeWarning {\n            get {\n                return ResourceManager.GetString(\"MsgGroupChildNodeWarning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Group {0} has a cycle dependency on child node {1}. Skipping this node. 的本地化字符串。\n        /// </summary>\n        public static string MsgGroupCycleDependency {\n            get {\n                return ResourceManager.GetString(\"MsgGroupCycleDependency\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Group {0} has no valid child node. 的本地化字符串。\n        /// </summary>\n        public static string MsgGroupNoValidChildNode {\n            get {\n                return ResourceManager.GetString(\"MsgGroupNoValidChildNode\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Information 的本地化字符串。\n        /// </summary>\n        public static string MsgInformationTitle {\n            get {\n                return ResourceManager.GetString(\"MsgInformationTitle\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 The {0} property is invalid, please check 的本地化字符串。\n        /// </summary>\n        public static string MsgInvalidProperty {\n            get {\n                return ResourceManager.GetString(\"MsgInvalidProperty\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please enter the URL 的本地化字符串。\n        /// </summary>\n        public static string MsgNeedUrl {\n            get {\n                return ResourceManager.GetString(\"MsgNeedUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Not support protocol &apos;{0}&apos; 的本地化字符串。\n        /// </summary>\n        public static string MsgNotSupportProtocol {\n            get {\n                return ResourceManager.GetString(\"MsgNotSupportProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 No valid subscriptions set 的本地化字符串。\n        /// </summary>\n        public static string MsgNoValidSubscription {\n            get {\n                return ResourceManager.GetString(\"MsgNoValidSubscription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Resolved {0} successfully 的本地化字符串。\n        /// </summary>\n        public static string MsgParsingSuccessfully {\n            get {\n                return ResourceManager.GetString(\"MsgParsingSuccessfully\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing rule {0} has an empty outbound tag. Fallback to proxy node only. 的本地化字符串。\n        /// </summary>\n        public static string MsgRoutingRuleEmptyOutboundTag {\n            get {\n                return ResourceManager.GetString(\"MsgRoutingRuleEmptyOutboundTag\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing rule {0} outbound node {1} error: {2}. Fallback to proxy node only. 的本地化字符串。\n        /// </summary>\n        public static string MsgRoutingRuleOutboundNodeError {\n            get {\n                return ResourceManager.GetString(\"MsgRoutingRuleOutboundNodeError\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing rule {0} outbound node {1} not found. Fallback to proxy node only. 的本地化字符串。\n        /// </summary>\n        public static string MsgRoutingRuleOutboundNodeNotFound {\n            get {\n                return ResourceManager.GetString(\"MsgRoutingRuleOutboundNodeNotFound\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing rule {0} outbound node {1} warning: {2} 的本地化字符串。\n        /// </summary>\n        public static string MsgRoutingRuleOutboundNodeWarning {\n            get {\n                return ResourceManager.GetString(\"MsgRoutingRuleOutboundNodeWarning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Filter, press Enter to execute 的本地化字符串。\n        /// </summary>\n        public static string MsgServerTitle {\n            get {\n                return ResourceManager.GetString(\"MsgServerTitle\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Updates are not enabled, skip this subscription 的本地化字符串。\n        /// </summary>\n        public static string MsgSkipSubscriptionUpdate {\n            get {\n                return ResourceManager.GetString(\"MsgSkipSubscriptionUpdate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Started getting subscriptions 的本地化字符串。\n        /// </summary>\n        public static string MsgStartGettingSubscriptions {\n            get {\n                return ResourceManager.GetString(\"MsgStartGettingSubscriptions\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Start parsing and processing subscription content 的本地化字符串。\n        /// </summary>\n        public static string MsgStartParsingSubscription {\n            get {\n                return ResourceManager.GetString(\"MsgStartParsingSubscription\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Started updating {0}... 的本地化字符串。\n        /// </summary>\n        public static string MsgStartUpdating {\n            get {\n                return ResourceManager.GetString(\"MsgStartUpdating\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Invalid subscription content 的本地化字符串。\n        /// </summary>\n        public static string MsgSubscriptionDecodingFailed {\n            get {\n                return ResourceManager.GetString(\"MsgSubscriptionDecodingFailed\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subscription next proxy {0} not found. Skipping. 的本地化字符串。\n        /// </summary>\n        public static string MsgSubscriptionNextProfileNotFound {\n            get {\n                return ResourceManager.GetString(\"MsgSubscriptionNextProfileNotFound\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subscription previous proxy {0} not found. Skipping. 的本地化字符串。\n        /// </summary>\n        public static string MsgSubscriptionPrevProfileNotFound {\n            get {\n                return ResourceManager.GetString(\"MsgSubscriptionPrevProfileNotFound\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Unpacking... 的本地化字符串。\n        /// </summary>\n        public static string MsgUnpacking {\n            get {\n                return ResourceManager.GetString(\"MsgUnpacking\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subscription update ended 的本地化字符串。\n        /// </summary>\n        public static string MsgUpdateSubscriptionEnd {\n            get {\n                return ResourceManager.GetString(\"MsgUpdateSubscriptionEnd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subscription update started 的本地化字符串。\n        /// </summary>\n        public static string MsgUpdateSubscriptionStart {\n            get {\n                return ResourceManager.GetString(\"MsgUpdateSubscriptionStart\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Updated Core successfully 的本地化字符串。\n        /// </summary>\n        public static string MsgUpdateV2rayCoreSuccessfully {\n            get {\n                return ResourceManager.GetString(\"MsgUpdateV2rayCoreSuccessfully\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Updated Core successfully! Restarting service... 的本地化字符串。\n        /// </summary>\n        public static string MsgUpdateV2rayCoreSuccessfullyMore {\n            get {\n                return ResourceManager.GetString(\"MsgUpdateV2rayCoreSuccessfullyMore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Successful operation. Click the settings menu to reboot the app. 的本地化字符串。\n        /// </summary>\n        public static string NeedRebootTips {\n            get {\n                return ResourceManager.GetString(\"NeedRebootTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Non-VMess or SS protocol 的本地化字符串。\n        /// </summary>\n        public static string NonvmessOrssProtocol {\n            get {\n                return ResourceManager.GetString(\"NonvmessOrssProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 The Core file (file name: {1}) was not found under the folder ({0}), please download and put it in the folder, download address: {2} 的本地化字符串。\n        /// </summary>\n        public static string NotFoundCore {\n            get {\n                return ResourceManager.GetString(\"NotFoundCore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Not run as Admin 的本地化字符串。\n        /// </summary>\n        public static string NotRunAsAdmin {\n            get {\n                return ResourceManager.GetString(\"NotRunAsAdmin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Scan completed, no valid QR code found 的本地化字符串。\n        /// </summary>\n        public static string NoValidQRcodeFound {\n            get {\n                return ResourceManager.GetString(\"NoValidQRcodeFound\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Operation failed, please check and retry 的本地化字符串。\n        /// </summary>\n        public static string OperationFailed {\n            get {\n                return ResourceManager.GetString(\"OperationFailed\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Operation successful 的本地化字符串。\n        /// </summary>\n        public static string OperationSuccess {\n            get {\n                return ResourceManager.GetString(\"OperationSuccess\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please Add At Least One Configuration 的本地化字符串。\n        /// </summary>\n        public static string PleaseAddAtLeastOneServer {\n            get {\n                return ResourceManager.GetString(\"PleaseAddAtLeastOneServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please fill Remarks 的本地化字符串。\n        /// </summary>\n        public static string PleaseFillRemarks {\n            get {\n                return ResourceManager.GetString(\"PleaseFillRemarks\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please select the encryption method 的本地化字符串。\n        /// </summary>\n        public static string PleaseSelectEncryption {\n            get {\n                return ResourceManager.GetString(\"PleaseSelectEncryption\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please select a protocol 的本地化字符串。\n        /// </summary>\n        public static string PleaseSelectProtocol {\n            get {\n                return ResourceManager.GetString(\"PleaseSelectProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please select rules 的本地化字符串。\n        /// </summary>\n        public static string PleaseSelectRules {\n            get {\n                return ResourceManager.GetString(\"PleaseSelectRules\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please select the Configuration first 的本地化字符串。\n        /// </summary>\n        public static string PleaseSelectServer {\n            get {\n                return ResourceManager.GetString(\"PleaseSelectServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Global hotkey {0} registration failed, reason: {1} 的本地化字符串。\n        /// </summary>\n        public static string RegisterGlobalHotkeyFailed {\n            get {\n                return ResourceManager.GetString(\"RegisterGlobalHotkeyFailed\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Global hotkey {0} registered successfully 的本地化字符串。\n        /// </summary>\n        public static string RegisterGlobalHotkeySuccessfully {\n            get {\n                return ResourceManager.GetString(\"RegisterGlobalHotkeySuccessfully\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Configurations deduplication completed. Old: {0}, New: {1}. 的本地化字符串。\n        /// </summary>\n        public static string RemoveDuplicateServerResult {\n            get {\n                return ResourceManager.GetString(\"RemoveDuplicateServerResult\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Removed {0} invalid test results. 的本地化字符串。\n        /// </summary>\n        public static string RemoveInvalidServerResultTip {\n            get {\n                return ResourceManager.GetString(\"RemoveInvalidServerResultTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Are you sure you want to remove the rules? 的本地化字符串。\n        /// </summary>\n        public static string RemoveRules {\n            get {\n                return ResourceManager.GetString(\"RemoveRules\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Are you sure you want to remove? 的本地化字符串。\n        /// </summary>\n        public static string RemoveServer {\n            get {\n                return ResourceManager.GetString(\"RemoveServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 {0}, one of the required fields. 的本地化字符串。\n        /// </summary>\n        public static string RoutingRuleDetailRequiredTips {\n            get {\n                return ResourceManager.GetString(\"RoutingRuleDetailRequiredTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Run as Admin 的本地化字符串。\n        /// </summary>\n        public static string RunAsAdmin {\n            get {\n                return ResourceManager.GetString(\"RunAsAdmin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 The client configuration file is saved at: {0} 的本地化字符串。\n        /// </summary>\n        public static string SaveClientConfigurationIn {\n            get {\n                return ResourceManager.GetString(\"SaveClientConfigurationIn\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please set a valid domain 的本地化字符串。\n        /// </summary>\n        public static string ServerNameMustBeValidDomain {\n            get {\n                return ResourceManager.GetString(\"ServerNameMustBeValidDomain\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 {0} : {1}/s↑ | {2}/s↓ 的本地化字符串。\n        /// </summary>\n        public static string SpeedDisplayText {\n            get {\n                return ResourceManager.GetString(\"SpeedDisplayText\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Testing... 的本地化字符串。\n        /// </summary>\n        public static string Speedtesting {\n            get {\n                return ResourceManager.GetString(\"Speedtesting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Test completed 的本地化字符串。\n        /// </summary>\n        public static string SpeedtestingCompleted {\n            get {\n                return ResourceManager.GetString(\"SpeedtestingCompleted\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Press ESC to terminate the test 的本地化字符串。\n        /// </summary>\n        public static string SpeedtestingPressEscToExit {\n            get {\n                return ResourceManager.GetString(\"SpeedtestingPressEscToExit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Skip test 的本地化字符串。\n        /// </summary>\n        public static string SpeedtestingSkip {\n            get {\n                return ResourceManager.GetString(\"SpeedtestingSkip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Test terminating... 的本地化字符串。\n        /// </summary>\n        public static string SpeedtestingStop {\n            get {\n                return ResourceManager.GetString(\"SpeedtestingStop\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Starting retesting failed parts, {0} remaining. Press ESC to terminate... 的本地化字符串。\n        /// </summary>\n        public static string SpeedtestingTestFailedPart {\n            get {\n                return ResourceManager.GetString(\"SpeedtestingTestFailedPart\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Waiting... 的本地化字符串。\n        /// </summary>\n        public static string SpeedtestingWait {\n            get {\n                return ResourceManager.GetString(\"SpeedtestingWait\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Starting service ({0})... 的本地化字符串。\n        /// </summary>\n        public static string StartService {\n            get {\n                return ResourceManager.GetString(\"StartService\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 For group please leave blank here 的本地化字符串。\n        /// </summary>\n        public static string SubUrlTips {\n            get {\n                return ResourceManager.GetString(\"SubUrlTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Configuration successful. {0} 的本地化字符串。\n        /// </summary>\n        public static string SuccessfulConfiguration {\n            get {\n                return ResourceManager.GetString(\"SuccessfulConfiguration\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Custom configuration Configuration imported successfully 的本地化字符串。\n        /// </summary>\n        public static string SuccessfullyImportedCustomServer {\n            get {\n                return ResourceManager.GetString(\"SuccessfullyImportedCustomServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 {0} Configurations have been imported from clipboard 的本地化字符串。\n        /// </summary>\n        public static string SuccessfullyImportedServerViaClipboard {\n            get {\n                return ResourceManager.GetString(\"SuccessfullyImportedServerViaClipboard\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Successfully scanned and imported the shared link 的本地化字符串。\n        /// </summary>\n        public static string SuccessfullyImportedServerViaScan {\n            get {\n                return ResourceManager.GetString(\"SuccessfullyImportedServerViaScan\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Incorrect password, please try again. 的本地化字符串。\n        /// </summary>\n        public static string SudoIncorrectPasswordTip {\n            get {\n                return ResourceManager.GetString(\"SudoIncorrectPasswordTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add Common DNS Hosts 的本地化字符串。\n        /// </summary>\n        public static string TbAddCommonDNSHosts {\n            get {\n                return ResourceManager.GetString(\"TbAddCommonDNSHosts\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Do Not Add Non-Proxy Protocol Outbound 的本地化字符串。\n        /// </summary>\n        public static string TbAddProxyProtocolOutboundOnly {\n            get {\n                return ResourceManager.GetString(\"TbAddProxyProtocolOutboundOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Address 的本地化字符串。\n        /// </summary>\n        public static string TbAddress {\n            get {\n                return ResourceManager.GetString(\"TbAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Allow Insecure 的本地化字符串。\n        /// </summary>\n        public static string TbAllowInsecure {\n            get {\n                return ResourceManager.GetString(\"TbAllowInsecure\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 ALPN 的本地化字符串。\n        /// </summary>\n        public static string TbAlpn {\n            get {\n                return ResourceManager.GetString(\"TbAlpn\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Alter ID 的本地化字符串。\n        /// </summary>\n        public static string TbAlterId {\n            get {\n                return ResourceManager.GetString(\"TbAlterId\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auto refresh 的本地化字符串。\n        /// </summary>\n        public static string TbAutoRefresh {\n            get {\n                return ResourceManager.GetString(\"TbAutoRefresh\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auto scroll to end 的本地化字符串。\n        /// </summary>\n        public static string TbAutoScrollToEnd {\n            get {\n                return ResourceManager.GetString(\"TbAutoScrollToEnd\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Domain, IP, process are auto-sorted when saving 的本地化字符串。\n        /// </summary>\n        public static string TbAutoSort {\n            get {\n                return ResourceManager.GetString(\"TbAutoSort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Block SVCB and HTTPS Queries 的本地化字符串。\n        /// </summary>\n        public static string TbBlockSVCBHTTPSQueries {\n            get {\n                return ResourceManager.GetString(\"TbBlockSVCBHTTPSQueries\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Block ECH and HTTP/3 availability checks when enabled 的本地化字符串。\n        /// </summary>\n        public static string TbBlockSVCBHTTPSQueriesTips {\n            get {\n                return ResourceManager.GetString(\"TbBlockSVCBHTTPSQueriesTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Bootstrap DNS 的本地化字符串。\n        /// </summary>\n        public static string TbBootstrapDNS {\n            get {\n                return ResourceManager.GetString(\"TbBootstrapDNS\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Resolve DNS server domains, requires IP 的本地化字符串。\n        /// </summary>\n        public static string TbBootstrapDNSTips {\n            get {\n                return ResourceManager.GetString(\"TbBootstrapDNSTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Browse 的本地化字符串。\n        /// </summary>\n        public static string TbBrowse {\n            get {\n                return ResourceManager.GetString(\"TbBrowse\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Cancel 的本地化字符串。\n        /// </summary>\n        public static string TbCancel {\n            get {\n                return ResourceManager.GetString(\"TbCancel\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Certificate Pinning 的本地化字符串。\n        /// </summary>\n        public static string TbCertPinning {\n            get {\n                return ResourceManager.GetString(\"TbCertPinning\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Pinned certificate (fill in either one)\n        ///When specified, the certificate will be pinned, and &quot;Allow Insecure&quot; will be disabled.\n        ///\n        ///The &quot;Get Certificate&quot; action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA. 的本地化字符串。\n        /// </summary>\n        public static string TbCertPinningTips {\n            get {\n                return ResourceManager.GetString(\"TbCertPinningTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Certificate fingerprint (SHA-256) 的本地化字符串。\n        /// </summary>\n        public static string TbCertSha256Tips {\n            get {\n                return ResourceManager.GetString(\"TbCertSha256Tips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Clear system proxy 的本地化字符串。\n        /// </summary>\n        public static string TbClearSystemProxy {\n            get {\n                return ResourceManager.GetString(\"TbClearSystemProxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Policy Group 的本地化字符串。\n        /// </summary>\n        public static string TbConfigTypePolicyGroup {\n            get {\n                return ResourceManager.GetString(\"TbConfigTypePolicyGroup\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Proxy Chain 的本地化字符串。\n        /// </summary>\n        public static string TbConfigTypeProxyChain {\n            get {\n                return ResourceManager.GetString(\"TbConfigTypeProxyChain\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Confirm 的本地化字符串。\n        /// </summary>\n        public static string TbConfirm {\n            get {\n                return ResourceManager.GetString(\"TbConfirm\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Connections 的本地化字符串。\n        /// </summary>\n        public static string TbConnections {\n            get {\n                return ResourceManager.GetString(\"TbConnections\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Core Type 的本地化字符串。\n        /// </summary>\n        public static string TbCoreType {\n            get {\n                return ResourceManager.GetString(\"TbCoreType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable Custom DNS 的本地化字符串。\n        /// </summary>\n        public static string TbCustomDNSEnable {\n            get {\n                return ResourceManager.GetString(\"TbCustomDNSEnable\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Custom DNS Enabled, This Page&apos;s Settings Invalid 的本地化字符串。\n        /// </summary>\n        public static string TbCustomDNSEnabledPageInvalid {\n            get {\n                return ResourceManager.GetString(\"TbCustomDNSEnabledPageInvalid\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 V2ray Custom DNS 的本地化字符串。\n        /// </summary>\n        public static string TbCustomDnsRay {\n            get {\n                return ResourceManager.GetString(\"TbCustomDnsRay\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 sing-box Custom DNS 的本地化字符串。\n        /// </summary>\n        public static string TbCustomDnsSingbox {\n            get {\n                return ResourceManager.GetString(\"TbCustomDnsSingbox\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Direct Target Resolution Strategy 的本地化字符串。\n        /// </summary>\n        public static string TbDirectResolveStrategy {\n            get {\n                return ResourceManager.GetString(\"TbDirectResolveStrategy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 If unset or &quot;AsIs&quot;, DNS resolution uses the system DNS; otherwise, the internal DNS module is used. 的本地化字符串。\n        /// </summary>\n        public static string TbDirectResolveStrategyTips {\n            get {\n                return ResourceManager.GetString(\"TbDirectResolveStrategyTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Display GUI 的本地化字符串。\n        /// </summary>\n        public static string TbDisplayGUI {\n            get {\n                return ResourceManager.GetString(\"TbDisplayGUI\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Display Log 的本地化字符串。\n        /// </summary>\n        public static string TbDisplayLog {\n            get {\n                return ResourceManager.GetString(\"TbDisplayLog\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 DNS Hosts: (&quot;domain1 ip1 ip2&quot; per line) 的本地化字符串。\n        /// </summary>\n        public static string TbDNSHostsConfig {\n            get {\n                return ResourceManager.GetString(\"TbDNSHostsConfig\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Supports DNS Object; Click to view documentation 的本地化字符串。\n        /// </summary>\n        public static string TbDnsObjectDoc {\n            get {\n                return ResourceManager.GetString(\"TbDnsObjectDoc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please fill in DNS Structure, Click to view the document 的本地化字符串。\n        /// </summary>\n        public static string TbDnsSingboxObjectDoc {\n            get {\n                return ResourceManager.GetString(\"TbDnsSingboxObjectDoc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Domain strategy 的本地化字符串。\n        /// </summary>\n        public static string TbdomainStrategy {\n            get {\n                return ResourceManager.GetString(\"TbdomainStrategy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 sing-box domain strategy 的本地化字符串。\n        /// </summary>\n        public static string TbdomainStrategy4Singbox {\n            get {\n                return ResourceManager.GetString(\"TbdomainStrategy4Singbox\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Domestic DNS 的本地化字符串。\n        /// </summary>\n        public static string TbDomesticDNS {\n            get {\n                return ResourceManager.GetString(\"TbDomesticDNS\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 By default, invoked only during routing for resolution 的本地化字符串。\n        /// </summary>\n        public static string TbDomesticDNSTips {\n            get {\n                return ResourceManager.GetString(\"TbDomesticDNSTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 EchConfigList 的本地化字符串。\n        /// </summary>\n        public static string TbEchConfigList {\n            get {\n                return ResourceManager.GetString(\"TbEchConfigList\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 EchForceQuery 的本地化字符串。\n        /// </summary>\n        public static string TbEchForceQuery {\n            get {\n                return ResourceManager.GetString(\"TbEchForceQuery\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Edit 的本地化字符串。\n        /// </summary>\n        public static string TbEdit {\n            get {\n                return ResourceManager.GetString(\"TbEdit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable Tun 的本地化字符串。\n        /// </summary>\n        public static string TbEnableTunAs {\n            get {\n                return ResourceManager.GetString(\"TbEnableTunAs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 FakeIP 的本地化字符串。\n        /// </summary>\n        public static string TbFakeIP {\n            get {\n                return ResourceManager.GetString(\"TbFakeIP\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Applies globally by default, with built-in FakeIP filtering (sing-box only). 的本地化字符串。\n        /// </summary>\n        public static string TbFakeIPTips {\n            get {\n                return ResourceManager.GetString(\"TbFakeIPTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Fallback 的本地化字符串。\n        /// </summary>\n        public static string TbFallback {\n            get {\n                return ResourceManager.GetString(\"TbFallback\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Fetch Certificate 的本地化字符串。\n        /// </summary>\n        public static string TbFetchCert {\n            get {\n                return ResourceManager.GetString(\"TbFetchCert\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Fetch Certificate Chain 的本地化字符串。\n        /// </summary>\n        public static string TbFetchCertChain {\n            get {\n                return ResourceManager.GetString(\"TbFetchCertChain\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Finalmask 的本地化字符串。\n        /// </summary>\n        public static string TbFinalmask {\n            get {\n                return ResourceManager.GetString(\"TbFinalmask\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Fingerprint 的本地化字符串。\n        /// </summary>\n        public static string TbFingerprint {\n            get {\n                return ResourceManager.GetString(\"TbFingerprint\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Flow 的本地化字符串。\n        /// </summary>\n        public static string TbFlow5 {\n            get {\n                return ResourceManager.GetString(\"TbFlow5\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Full certificate (chain), PEM format 的本地化字符串。\n        /// </summary>\n        public static string TbFullCertTips {\n            get {\n                return ResourceManager.GetString(\"TbFullCertTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core&apos;s basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you. 的本地化字符串。\n        /// </summary>\n        public static string TbFullConfigTemplateDesc {\n            get {\n                return ResourceManager.GetString(\"TbFullConfigTemplateDesc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable Full Config Template 的本地化字符串。\n        /// </summary>\n        public static string TbFullConfigTemplateEnable {\n            get {\n                return ResourceManager.GetString(\"TbFullConfigTemplateEnable\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Global Hotkey Settings 的本地化字符串。\n        /// </summary>\n        public static string TbGlobalHotkeySetting {\n            get {\n                return ResourceManager.GetString(\"TbGlobalHotkeySetting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set directly by pressing the keyboard; takes effect after restart 的本地化字符串。\n        /// </summary>\n        public static string TbGlobalHotkeySettingTip {\n            get {\n                return ResourceManager.GetString(\"TbGlobalHotkeySettingTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Generate 的本地化字符串。\n        /// </summary>\n        public static string TbGUID {\n            get {\n                return ResourceManager.GetString(\"TbGUID\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Camouflage type 的本地化字符串。\n        /// </summary>\n        public static string TbHeaderType {\n            get {\n                return ResourceManager.GetString(\"TbHeaderType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Congestion control 的本地化字符串。\n        /// </summary>\n        public static string TbHeaderType8 {\n            get {\n                return ResourceManager.GetString(\"TbHeaderType8\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Port hopping interval 的本地化字符串。\n        /// </summary>\n        public static string TbHopInt7 {\n            get {\n                return ResourceManager.GetString(\"TbHopInt7\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 UUID(id) 的本地化字符串。\n        /// </summary>\n        public static string TbId {\n            get {\n                return ResourceManager.GetString(\"TbId\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Password 的本地化字符串。\n        /// </summary>\n        public static string TbId3 {\n            get {\n                return ResourceManager.GetString(\"TbId3\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Password(Optional) 的本地化字符串。\n        /// </summary>\n        public static string TbId4 {\n            get {\n                return ResourceManager.GetString(\"TbId4\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 UUID(id) 的本地化字符串。\n        /// </summary>\n        public static string TbId5 {\n            get {\n                return ResourceManager.GetString(\"TbId5\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Most Stable 的本地化字符串。\n        /// </summary>\n        public static string TbLeastLoad {\n            get {\n                return ResourceManager.GetString(\"TbLeastLoad\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Lowest Latency 的本地化字符串。\n        /// </summary>\n        public static string TbLeastPing {\n            get {\n                return ResourceManager.GetString(\"TbLeastPing\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Address (IPv4, IPv6) 的本地化字符串。\n        /// </summary>\n        public static string TbLocalAddress {\n            get {\n                return ResourceManager.GetString(\"TbLocalAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Mldsa65Verify 的本地化字符串。\n        /// </summary>\n        public static string TbMldsa65Verify {\n            get {\n                return ResourceManager.GetString(\"TbMldsa65Verify\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Transport protocol(network) 的本地化字符串。\n        /// </summary>\n        public static string TbNetwork {\n            get {\n                return ResourceManager.GetString(\"TbNetwork\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Do not change system proxy 的本地化字符串。\n        /// </summary>\n        public static string TbNotChangeSystemProxy {\n            get {\n                return ResourceManager.GetString(\"TbNotChangeSystemProxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Parallel Query 的本地化字符串。\n        /// </summary>\n        public static string TbParallelQuery {\n            get {\n                return ResourceManager.GetString(\"TbParallelQuery\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Path 的本地化字符串。\n        /// </summary>\n        public static string TbPath {\n            get {\n                return ResourceManager.GetString(\"TbPath\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 obfs password 的本地化字符串。\n        /// </summary>\n        public static string TbPath7 {\n            get {\n                return ResourceManager.GetString(\"TbPath7\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auto add filtered configuration from subscription groups 的本地化字符串。\n        /// </summary>\n        public static string TbPolicyGroupSubChildTip {\n            get {\n                return ResourceManager.GetString(\"TbPolicyGroupSubChildTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Policy Group Type 的本地化字符串。\n        /// </summary>\n        public static string TbPolicyGroupType {\n            get {\n                return ResourceManager.GetString(\"TbPolicyGroupType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Port 的本地化字符串。\n        /// </summary>\n        public static string TbPort {\n            get {\n                return ResourceManager.GetString(\"TbPort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Configuration port range 的本地化字符串。\n        /// </summary>\n        public static string TbPorts7 {\n            get {\n                return ResourceManager.GetString(\"TbPorts7\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Will cover the port, separate with commas (,) 的本地化字符串。\n        /// </summary>\n        public static string TbPorts7Tips {\n            get {\n                return ResourceManager.GetString(\"TbPorts7Tips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Socks port 的本地化字符串。\n        /// </summary>\n        public static string TbPreSocksPort {\n            get {\n                return ResourceManager.GetString(\"TbPreSocksPort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Custom config socks port 的本地化字符串。\n        /// </summary>\n        public static string TbPreSocksPort4Sub {\n            get {\n                return ResourceManager.GetString(\"TbPreSocksPort4Sub\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Private Key 的本地化字符串。\n        /// </summary>\n        public static string TbPrivateKey {\n            get {\n                return ResourceManager.GetString(\"TbPrivateKey\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Proxies 的本地化字符串。\n        /// </summary>\n        public static string TbProxies {\n            get {\n                return ResourceManager.GetString(\"TbProxies\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Public Key 的本地化字符串。\n        /// </summary>\n        public static string TbPublicKey {\n            get {\n                return ResourceManager.GetString(\"TbPublicKey\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Random 的本地化字符串。\n        /// </summary>\n        public static string TbRandom {\n            get {\n                return ResourceManager.GetString(\"TbRandom\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 v2ray Full Config Template 的本地化字符串。\n        /// </summary>\n        public static string TbRayFullConfigTemplate {\n            get {\n                return ResourceManager.GetString(\"TbRayFullConfigTemplate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document 的本地化字符串。\n        /// </summary>\n        public static string TbRayFullConfigTemplateDesc {\n            get {\n                return ResourceManager.GetString(\"TbRayFullConfigTemplateDesc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Alias (remarks) 的本地化字符串。\n        /// </summary>\n        public static string TbRemarks {\n            get {\n                return ResourceManager.GetString(\"TbRemarks\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Remote DNS 的本地化字符串。\n        /// </summary>\n        public static string TbRemoteDNS {\n            get {\n                return ResourceManager.GetString(\"TbRemoteDNS\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 By default, invoked only during routing for resolution; ensure the remote server can reach this DNS 的本地化字符串。\n        /// </summary>\n        public static string TbRemoteDNSTips {\n            get {\n                return ResourceManager.GetString(\"TbRemoteDNSTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Proxy Target Resolution Strategy 的本地化字符串。\n        /// </summary>\n        public static string TbRemoteResolveStrategy {\n            get {\n                return ResourceManager.GetString(\"TbRemoteResolveStrategy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 If unset or &quot;AsIs&quot;, DNS resolution is performed by the remote server&apos;s DNS; otherwise, the internal DNS module is used. 的本地化字符串。\n        /// </summary>\n        public static string TbRemoteResolveStrategyTips {\n            get {\n                return ResourceManager.GetString(\"TbRemoteResolveStrategyTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Camouflage domain(host) 的本地化字符串。\n        /// </summary>\n        public static string TbRequestHost {\n            get {\n                return ResourceManager.GetString(\"TbRequestHost\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Reserved (2,3,4) 的本地化字符串。\n        /// </summary>\n        public static string TbReserved {\n            get {\n                return ResourceManager.GetString(\"TbReserved\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Reset 的本地化字符串。\n        /// </summary>\n        public static string TbReset {\n            get {\n                return ResourceManager.GetString(\"TbReset\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Round Robin 的本地化字符串。\n        /// </summary>\n        public static string TbRoundRobin {\n            get {\n                return ResourceManager.GetString(\"TbRoundRobin\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 socks: local port, socks2: second local port, socks3: LAN port 的本地化字符串。\n        /// </summary>\n        public static string TbRoutingInboundTagTips {\n            get {\n                return ResourceManager.GetString(\"TbRoutingInboundTagTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Domain 的本地化字符串。\n        /// </summary>\n        public static string TbRoutingRuleDomain {\n            get {\n                return ResourceManager.GetString(\"TbRoutingRuleDomain\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 IP or IP CIDR 的本地化字符串。\n        /// </summary>\n        public static string TbRoutingRuleIP {\n            get {\n                return ResourceManager.GetString(\"TbRoutingRuleIP\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Process (Linux/Windows) 的本地化字符串。\n        /// </summary>\n        public static string TbRoutingRuleProcess {\n            get {\n                return ResourceManager.GetString(\"TbRoutingRuleProcess\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Pre-defined Rule Set List 的本地化字符串。\n        /// </summary>\n        public static string TbRoutingTabRuleList {\n            get {\n                return ResourceManager.GetString(\"TbRoutingTabRuleList\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *Separate rules by commas (,); For a literal comma use &lt;COMMA&gt;; Prefix # to ignore a rule 的本地化字符串。\n        /// </summary>\n        public static string TbRoutingTips {\n            get {\n                return ResourceManager.GetString(\"TbRoutingTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 (Domain or IP or Proc Name) and Port and Protocol and Inbound Tag =&gt; Outbound Tag 的本地化字符串。\n        /// </summary>\n        public static string TbRuleMatchingTips {\n            get {\n                return ResourceManager.GetString(\"TbRuleMatchingTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rule object Doc 的本地化字符串。\n        /// </summary>\n        public static string TbRuleobjectDoc {\n            get {\n                return ResourceManager.GetString(\"TbRuleobjectDoc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Can fill in the configuration remarks, please make sure it exist and are unique 的本地化字符串。\n        /// </summary>\n        public static string TbRuleOutboundTagTip {\n            get {\n                return ResourceManager.GetString(\"TbRuleOutboundTagTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Rule Type 的本地化字符串。\n        /// </summary>\n        public static string TbRuleType {\n            get {\n                return ResourceManager.GetString(\"TbRuleType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 You can set separate rules for Routing and DNS, or select &quot;ALL&quot; to apply to both 的本地化字符串。\n        /// </summary>\n        public static string TbRuleTypeTips {\n            get {\n                return ResourceManager.GetString(\"TbRuleTypeTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 sing-box Full Config Template 的本地化字符串。\n        /// </summary>\n        public static string TbSBFullConfigTemplate {\n            get {\n                return ResourceManager.GetString(\"TbSBFullConfigTemplate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Add Outbound and Endpoint Config Only, Click to view the document 的本地化字符串。\n        /// </summary>\n        public static string TbSBFullConfigTemplateDesc {\n            get {\n                return ResourceManager.GetString(\"TbSBFullConfigTemplateDesc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Encryption method (security) 的本地化字符串。\n        /// </summary>\n        public static string TbSecurity {\n            get {\n                return ResourceManager.GetString(\"TbSecurity\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Encryption 的本地化字符串。\n        /// </summary>\n        public static string TbSecurity3 {\n            get {\n                return ResourceManager.GetString(\"TbSecurity3\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 User(Optional) 的本地化字符串。\n        /// </summary>\n        public static string TbSecurity4 {\n            get {\n                return ResourceManager.GetString(\"TbSecurity4\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Encryption 的本地化字符串。\n        /// </summary>\n        public static string TbSecurity5 {\n            get {\n                return ResourceManager.GetString(\"TbSecurity5\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Select Profile 的本地化字符串。\n        /// </summary>\n        public static string TbSelectProfile {\n            get {\n                return ResourceManager.GetString(\"TbSelectProfile\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Serve Stale 的本地化字符串。\n        /// </summary>\n        public static string TbServeStale {\n            get {\n                return ResourceManager.GetString(\"TbServeStale\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set system proxy 的本地化字符串。\n        /// </summary>\n        public static string TbSetSystemProxy {\n            get {\n                return ResourceManager.GetString(\"TbSetSystemProxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Click to import default DNS config 的本地化字符串。\n        /// </summary>\n        public static string TbSettingDnsImportDefConfig {\n            get {\n                return ResourceManager.GetString(\"TbSettingDnsImportDefConfig\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Advanced proxy settings, protocol selection (optional) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsAdvancedProtocol {\n            get {\n                return ResourceManager.GetString(\"TbSettingsAdvancedProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Allow connections from the LAN 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsAllowLAN {\n            get {\n                return ResourceManager.GetString(\"TbSettingsAllowLAN\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auto hide on startup 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsAutoHideStartup {\n            get {\n                return ResourceManager.GetString(\"TbSettingsAutoHideStartup\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Automatic update interval for Geo files (hours) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsAutoUpdateInterval {\n            get {\n                return ResourceManager.GetString(\"TbSettingsAutoUpdateInterval\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Users in China region can ignore this item 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsChinaUserTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsChinaUserTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Color 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsColor {\n            get {\n                return ResourceManager.GetString(\"TbSettingsColor\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Core: basic settings 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCore {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCore\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Core: KCP settings 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCoreKcp {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCoreKcp\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Core Type settings 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCoreType {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCoreType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Font family (requires restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCurrentFontFamily {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCurrentFontFamily\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Install the font to the system, select or fill in the font name, restart the settings 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCurrentFontFamilyLinuxTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCurrentFontFamilyLinuxTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Copy the font TTF/TTC file to the directory gui Fonts; Reopen the settings window 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCurrentFontFamilyTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCurrentFontFamilyTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Custom PAC file path 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCustomSystemProxyPacPath {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCustomSystemProxyPacPath\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Custom system proxy script file path 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsCustomSystemProxyScriptPath {\n            get {\n                return ResourceManager.GetString(\"TbSettingsCustomSystemProxyScriptPath\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Allow Insecure 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDefAllowInsecure {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDefAllowInsecure\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Default TLS fingerprint 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDefFingerprint {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDefFingerprint\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 User-Agent 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDefUserAgent {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDefUserAgent\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 This parameter is valid only for tcp/http and ws 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDefUserAgentTips {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDefUserAgentTips\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Sniffing type 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDestOverride {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDestOverride\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Display real-time speed (requires restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDisplayRealTimeSpeed {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDisplayRealTimeSpeed\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Outbound DNS address 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDomainDNSAddress {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDomainDNSAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Outbound Freedom domain Strategy 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDomainStrategy4Freedom {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDomainStrategy4Freedom\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Default domain strategy for outbound 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDomainStrategy4Out {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDomainStrategy4Out\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Double-clicking Configuration makes it active 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsDoubleClick2Activate {\n            get {\n                return ResourceManager.GetString(\"TbSettingsDoubleClick2Activate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Automatically adjust column width after subscription update 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsEnableAutoAdjustMainLvColWidth {\n            get {\n                return ResourceManager.GetString(\"TbSettingsEnableAutoAdjustMainLvColWidth\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable cache file for sing-box (ruleset files) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsEnableCacheFile4Sbox {\n            get {\n                return ResourceManager.GetString(\"TbSettingsEnableCacheFile4Sbox\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Check for pre-release updates 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsEnableCheckPreReleaseUpdate {\n            get {\n                return ResourceManager.GetString(\"TbSettingsEnableCheckPreReleaseUpdate\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable sorting Configurations by drag-n-drop (requires restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsEnableDragDropSort {\n            get {\n                return ResourceManager.GetString(\"TbSettingsEnableDragDropSort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable fragment 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsEnableFragment {\n            get {\n                return ResourceManager.GetString(\"TbSettingsEnableFragment\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable hardware acceleration (requires restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsEnableHWA {\n            get {\n                return ResourceManager.GetString(\"TbSettingsEnableHWA\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable IPv6 Address 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsEnableIPv6Address {\n            get {\n                return ResourceManager.GetString(\"TbSettingsEnableIPv6Address\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Exception 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsException {\n            get {\n                return ResourceManager.GetString(\"TbSettingsException\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Exclusions: Do not use proxy server for addresses beginning with the following. Use semicolon (;) to separate entries. 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsExceptionTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsExceptionTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Exclusions: Do not use proxy server for the following addresses. Use comma (,) to separate entries. 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsExceptionTip2 {\n            get {\n                return ResourceManager.GetString(\"TbSettingsExceptionTip2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Font Size 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsFontSize {\n            get {\n                return ResourceManager.GetString(\"TbSettingsFontSize\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Geo files source (optional) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsGeoFilesSource {\n            get {\n                return ResourceManager.GetString(\"TbSettingsGeoFilesSource\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Hide to tray when closing the window 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsHide2TrayWhenClose {\n            get {\n                return ResourceManager.GetString(\"TbSettingsHide2TrayWhenClose\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 If the system does not have a tray function, please do not enable it 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsHide2TrayWhenCloseTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsHide2TrayWhenCloseTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Hysteria Max bandwidth (Up/Down) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsHysteriaBandwidth {\n            get {\n                return ResourceManager.GetString(\"TbSettingsHysteriaBandwidth\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Current connection info test URL 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsIPAPIUrl {\n            get {\n                return ResourceManager.GetString(\"TbSettingsIPAPIUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Keep older entries when de-duplicating 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsKeepOlderDedupl {\n            get {\n                return ResourceManager.GetString(\"TbSettingsKeepOlderDedupl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Language (Restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsLanguage {\n            get {\n                return ResourceManager.GetString(\"TbSettingsLanguage\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 System sudo password 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsLinuxSudoPassword {\n            get {\n                return ResourceManager.GetString(\"TbSettingsLinuxSudoPassword\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 The password will be validated via the command line. If a validation error causes the application to malfunction, please restart the application. The password will not be stored and must be entered again after each restart. 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsLinuxSudoPasswordTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsLinuxSudoPasswordTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable Log 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsLogEnabled {\n            get {\n                return ResourceManager.GetString(\"TbSettingsLogEnabled\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable logging to file 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsLogEnabledToFile {\n            get {\n                return ResourceManager.GetString(\"TbSettingsLogEnabledToFile\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Log Level 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsLogLevel {\n            get {\n                return ResourceManager.GetString(\"TbSettingsLogLevel\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 macOS displays this in the Dock (requires restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsMacOSShowInDock {\n            get {\n                return ResourceManager.GetString(\"TbSettingsMacOSShowInDock\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Main layout orientation (requires restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsMainGirdOrientation {\n            get {\n                return ResourceManager.GetString(\"TbSettingsMainGirdOrientation\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 The number of concurrent tests during multi-test 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsMixedConcurrencyCount {\n            get {\n                return ResourceManager.GetString(\"TbSettingsMixedConcurrencyCount\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 sing-box Mux Protocol 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsMux4SboxProtocol {\n            get {\n                return ResourceManager.GetString(\"TbSettingsMux4SboxProtocol\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Turn on Mux Multiplexing 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsMuxEnabled {\n            get {\n                return ResourceManager.GetString(\"TbSettingsMuxEnabled\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 v2rayN settings 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsN {\n            get {\n                return ResourceManager.GetString(\"TbSettingsN\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 New Port for LAN 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsNewPort4LAN {\n            get {\n                return ResourceManager.GetString(\"TbSettingsNewPort4LAN\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Do not use proxy servers for local (intranet) addresses 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsNotProxyLocalAddress {\n            get {\n                return ResourceManager.GetString(\"TbSettingsNotProxyLocalAddress\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auth pass 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsPass {\n            get {\n                return ResourceManager.GetString(\"TbSettingsPass\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Custom DNS (multiple, separated by commas (,)) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsRemoteDNS {\n            get {\n                return ResourceManager.GetString(\"TbSettingsRemoteDNS\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Route Only 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsRouteOnly {\n            get {\n                return ResourceManager.GetString(\"TbSettingsRouteOnly\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing rules source (optional) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsRoutingRulesSource {\n            get {\n                return ResourceManager.GetString(\"TbSettingsRoutingRulesSource\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable second mixed port 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSecondLocalPortEnabled {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSecondLocalPortEnabled\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set Win10 UWP Loopback 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSetUWP {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSetUWP\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Turn on Sniffing 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSniffingEnabled {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSniffingEnabled\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Mixed Port 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSocksPort {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSocksPort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Pac port = +3; Xray API port = +4; mihomo API port = +5; 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSocksPortTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSocksPortTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Speed Ping Test URL 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSpeedPingTestUrl {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSpeedPingTestUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Speed Test Single Timeout Value 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSpeedTestTimeout {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSpeedTestTimeout\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Speed Test URL 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSpeedTestUrl {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSpeedTestUrl\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 sing-box ruleset files source (optional) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSrsFilesSource {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSrsFilesSource\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Start on boot 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsStartBoot {\n            get {\n                return ResourceManager.GetString(\"TbSettingsStartBoot\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set this with admin privileges, get admin privileges after startup 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsStartBootTip {\n            get {\n                return ResourceManager.GetString(\"TbSettingsStartBootTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable traffic statistics (requires restart) 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsStatistics {\n            get {\n                return ResourceManager.GetString(\"TbSettingsStatistics\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Subscription conversion URL 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSubConvert {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSubConvert\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 System proxy settings 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsSystemproxy {\n            get {\n                return ResourceManager.GetString(\"TbSettingsSystemproxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Theme 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsTheme {\n            get {\n                return ResourceManager.GetString(\"TbSettingsTheme\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Tray right-click menu display limit 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsTrayMenuServersLimit {\n            get {\n                return ResourceManager.GetString(\"TbSettingsTrayMenuServersLimit\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auto Route 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsTunAutoRoute {\n            get {\n                return ResourceManager.GetString(\"TbSettingsTunAutoRoute\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Tun Mode settings 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsTunMode {\n            get {\n                return ResourceManager.GetString(\"TbSettingsTunMode\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 MTU 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsTunMtu {\n            get {\n                return ResourceManager.GetString(\"TbSettingsTunMtu\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Stack 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsTunStack {\n            get {\n                return ResourceManager.GetString(\"TbSettingsTunStack\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Strict Route 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsTunStrictRoute {\n            get {\n                return ResourceManager.GetString(\"TbSettingsTunStrictRoute\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Enable UDP 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsUdpEnabled {\n            get {\n                return ResourceManager.GetString(\"TbSettingsUdpEnabled\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Auth user 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsUser {\n            get {\n                return ResourceManager.GetString(\"TbSettingsUser\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Use System Hosts 的本地化字符串。\n        /// </summary>\n        public static string TbSettingsUseSystemHosts {\n            get {\n                return ResourceManager.GetString(\"TbSettingsUseSystemHosts\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Set Upstream Proxy Tag 的本地化字符串。\n        /// </summary>\n        public static string TbSetUpstreamProxyDetour {\n            get {\n                return ResourceManager.GetString(\"TbSetUpstreamProxyDetour\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Short Id 的本地化字符串。\n        /// </summary>\n        public static string TbShortId {\n            get {\n                return ResourceManager.GetString(\"TbShortId\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 SNI 的本地化字符串。\n        /// </summary>\n        public static string TbSNI {\n            get {\n                return ResourceManager.GetString(\"TbSNI\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Sorting 的本地化字符串。\n        /// </summary>\n        public static string TbSorting {\n            get {\n                return ResourceManager.GetString(\"TbSorting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Chain 的本地化字符串。\n        /// </summary>\n        public static string TbSortingChain {\n            get {\n                return ResourceManager.GetString(\"TbSortingChain\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Default 的本地化字符串。\n        /// </summary>\n        public static string TbSortingDefault {\n            get {\n                return ResourceManager.GetString(\"TbSortingDefault\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Delay 的本地化字符串。\n        /// </summary>\n        public static string TbSortingDelay {\n            get {\n                return ResourceManager.GetString(\"TbSortingDelay\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Download Speed 的本地化字符串。\n        /// </summary>\n        public static string TbSortingDownSpeed {\n            get {\n                return ResourceManager.GetString(\"TbSortingDownSpeed\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Download Traffic 的本地化字符串。\n        /// </summary>\n        public static string TbSortingDownTraffic {\n            get {\n                return ResourceManager.GetString(\"TbSortingDownTraffic\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Host 的本地化字符串。\n        /// </summary>\n        public static string TbSortingHost {\n            get {\n                return ResourceManager.GetString(\"TbSortingHost\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Name 的本地化字符串。\n        /// </summary>\n        public static string TbSortingName {\n            get {\n                return ResourceManager.GetString(\"TbSortingName\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Network 的本地化字符串。\n        /// </summary>\n        public static string TbSortingNetwork {\n            get {\n                return ResourceManager.GetString(\"TbSortingNetwork\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Time 的本地化字符串。\n        /// </summary>\n        public static string TbSortingTime {\n            get {\n                return ResourceManager.GetString(\"TbSortingTime\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Type 的本地化字符串。\n        /// </summary>\n        public static string TbSortingType {\n            get {\n                return ResourceManager.GetString(\"TbSortingType\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Upload Speed 的本地化字符串。\n        /// </summary>\n        public static string TbSortingUpSpeed {\n            get {\n                return ResourceManager.GetString(\"TbSortingUpSpeed\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Upload Traffic 的本地化字符串。\n        /// </summary>\n        public static string TbSortingUpTraffic {\n            get {\n                return ResourceManager.GetString(\"TbSortingUpTraffic\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Spider X 的本地化字符串。\n        /// </summary>\n        public static string TbSpiderX {\n            get {\n                return ResourceManager.GetString(\"TbSpiderX\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 TLS 的本地化字符串。\n        /// </summary>\n        public static string TbStreamSecurity {\n            get {\n                return ResourceManager.GetString(\"TbStreamSecurity\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 PAC mode 的本地化字符串。\n        /// </summary>\n        public static string TbSystemProxyPac {\n            get {\n                return ResourceManager.GetString(\"TbSystemProxyPac\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Validate Regional Domain IPs 的本地化字符串。\n        /// </summary>\n        public static string TbValidateDirectExpectedIPs {\n            get {\n                return ResourceManager.GetString(\"TbValidateDirectExpectedIPs\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs 的本地化字符串。\n        /// </summary>\n        public static string TbValidateDirectExpectedIPsDesc {\n            get {\n                return ResourceManager.GetString(\"TbValidateDirectExpectedIPsDesc\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 The delay: {0} ms, {1} 的本地化字符串。\n        /// </summary>\n        public static string TestMeOutput {\n            get {\n                return ResourceManager.GetString(\"TestMeOutput\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Advanced DNS Settings 的本地化字符串。\n        /// </summary>\n        public static string ThAdvancedDNSSettings {\n            get {\n                return ResourceManager.GetString(\"ThAdvancedDNSSettings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Basic DNS Settings 的本地化字符串。\n        /// </summary>\n        public static string ThBasicDNSSettings {\n            get {\n                return ResourceManager.GetString(\"ThBasicDNSSettings\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Active 的本地化字符串。\n        /// </summary>\n        public static string TipActiveServer {\n            get {\n                return ResourceManager.GetString(\"TipActiveServer\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Routing setting has changed 的本地化字符串。\n        /// </summary>\n        public static string TipChangeRouting {\n            get {\n                return ResourceManager.GetString(\"TipChangeRouting\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 System proxy setting has changed 的本地化字符串。\n        /// </summary>\n        public static string TipChangeSystemProxy {\n            get {\n                return ResourceManager.GetString(\"TipChangeSystemProxy\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Please turn off when there is an abnormal disconnection 的本地化字符串。\n        /// </summary>\n        public static string TipDisplayLog {\n            get {\n                return ResourceManager.GetString(\"TipDisplayLog\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *Default value tcp 的本地化字符串。\n        /// </summary>\n        public static string TipNetwork {\n            get {\n                return ResourceManager.GetString(\"TipNetwork\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 * After setting this value, a socks service will be started using Xray/sing-box(Tun) to provide functions such as speed display 的本地化字符串。\n        /// </summary>\n        public static string TipPreSocksPort {\n            get {\n                return ResourceManager.GetString(\"TipPreSocksPort\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 XHTTP Extra raw JSON, format: { XHTTP Object } 的本地化字符串。\n        /// </summary>\n        public static string TransportExtraTip {\n            get {\n                return ResourceManager.GetString(\"TransportExtraTip\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *tcp camouflage type 的本地化字符串。\n        /// </summary>\n        public static string TransportHeaderTypeTip1 {\n            get {\n                return ResourceManager.GetString(\"TransportHeaderTypeTip1\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *kcp camouflage type 的本地化字符串。\n        /// </summary>\n        public static string TransportHeaderTypeTip2 {\n            get {\n                return ResourceManager.GetString(\"TransportHeaderTypeTip2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *QUIC camouflage type 的本地化字符串。\n        /// </summary>\n        public static string TransportHeaderTypeTip3 {\n            get {\n                return ResourceManager.GetString(\"TransportHeaderTypeTip3\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *grpc mode 的本地化字符串。\n        /// </summary>\n        public static string TransportHeaderTypeTip4 {\n            get {\n                return ResourceManager.GetString(\"TransportHeaderTypeTip4\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *xhttp mode 的本地化字符串。\n        /// </summary>\n        public static string TransportHeaderTypeTip5 {\n            get {\n                return ResourceManager.GetString(\"TransportHeaderTypeTip5\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *ws/http upgrade/xhttp path 的本地化字符串。\n        /// </summary>\n        public static string TransportPathTip1 {\n            get {\n                return ResourceManager.GetString(\"TransportPathTip1\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *h2 path 的本地化字符串。\n        /// </summary>\n        public static string TransportPathTip2 {\n            get {\n                return ResourceManager.GetString(\"TransportPathTip2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *QUIC key/KCP seed 的本地化字符串。\n        /// </summary>\n        public static string TransportPathTip3 {\n            get {\n                return ResourceManager.GetString(\"TransportPathTip3\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *grpc service name 的本地化字符串。\n        /// </summary>\n        public static string TransportPathTip4 {\n            get {\n                return ResourceManager.GetString(\"TransportPathTip4\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *kcp seed 的本地化字符串。\n        /// </summary>\n        public static string TransportPathTip5 {\n            get {\n                return ResourceManager.GetString(\"TransportPathTip5\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *http host separated by commas (,) 的本地化字符串。\n        /// </summary>\n        public static string TransportRequestHostTip1 {\n            get {\n                return ResourceManager.GetString(\"TransportRequestHostTip1\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *ws/http upgrade/xhttp host 的本地化字符串。\n        /// </summary>\n        public static string TransportRequestHostTip2 {\n            get {\n                return ResourceManager.GetString(\"TransportRequestHostTip2\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *h2 host separated by commas (,) 的本地化字符串。\n        /// </summary>\n        public static string TransportRequestHostTip3 {\n            get {\n                return ResourceManager.GetString(\"TransportRequestHostTip3\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *QUIC security 的本地化字符串。\n        /// </summary>\n        public static string TransportRequestHostTip4 {\n            get {\n                return ResourceManager.GetString(\"TransportRequestHostTip4\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 *grpc Authority 的本地化字符串。\n        /// </summary>\n        public static string TransportRequestHostTip5 {\n            get {\n                return ResourceManager.GetString(\"TransportRequestHostTip5\", resourceCulture);\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似 Upgrade App does not exist 的本地化字符串。\n        /// </summary>\n        public static string UpgradeAppNotExistTip {\n            get {\n                return ResourceManager.GetString(\"UpgradeAppNotExistTip\", resourceCulture);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BatchExportURLSuccessfully\" xml:space=\"preserve\">\n    <value>ارسال دسته ای آدرس اینترنتی اشتراک گذاری به کلیپ بورد با موفقیت.</value>\n  </data>\n  <data name=\"CheckServerSettings\" xml:space=\"preserve\">\n    <value>لطفا ابتدا تنظیمات سرور را بررسی کنید</value>\n  </data>\n  <data name=\"ConfigurationFormatIncorrect\" xml:space=\"preserve\">\n    <value>فرمت پیکربندی نادرست است</value>\n  </data>\n  <data name=\"CustomServerTips\" xml:space=\"preserve\">\n    <value>توجه داشته باشید که پیکربندی سفارشی کاملاً به پیکربندی خود شما بستگی دارد و با همه تنظیمات کار نمی کند. اگر می خواهید از پروکسی سیستم استفاده کنید، لطفاً پورت درحال شنود را به صورت دستی تغییر دهید.</value>\n  </data>\n  <data name=\"Downloading\" xml:space=\"preserve\">\n    <value>درحال دانلود...</value>\n  </data>\n  <data name=\"FailedConversionConfiguration\" xml:space=\"preserve\">\n    <value>تبدیل فایل پیکربندی انجام نشد</value>\n  </data>\n  <data name=\"FailedGenDefaultConfiguration\" xml:space=\"preserve\">\n    <value>فایل پیکربندی پیش فرض ایجاد نشد</value>\n  </data>\n  <data name=\"FailedGetDefaultConfiguration\" xml:space=\"preserve\">\n    <value>پیکربندی پیش فرض دریافت نشد</value>\n  </data>\n  <data name=\"FailedImportedCustomServer\" xml:space=\"preserve\">\n    <value>سرور پیکربندی سفارشی وارد نشد</value>\n  </data>\n  <data name=\"FailedReadConfiguration\" xml:space=\"preserve\">\n    <value>فایل پیکربندی خوانده نشد</value>\n  </data>\n  <data name=\"FillCorrectServerPort\" xml:space=\"preserve\">\n    <value>لطفا فرمت صحیح پورت سرور را وارد کنید.</value>\n  </data>\n  <data name=\"FillLocalListeningPort\" xml:space=\"preserve\">\n    <value>لطفاً پورت گوش دادن محلی را وارد کنید.</value>\n  </data>\n  <data name=\"FillPassword\" xml:space=\"preserve\">\n    <value>لطفا رمز عبور را وارد کنید.</value>\n  </data>\n  <data name=\"FillServerAddress\" xml:space=\"preserve\">\n    <value>لطفا آدرس سرور را وارد کنید.</value>\n  </data>\n  <data name=\"FillUUID\" xml:space=\"preserve\">\n    <value>لطفا شناسه کاربری را وارد کنید.</value>\n  </data>\n  <data name=\"Incorrectconfiguration\" xml:space=\"preserve\">\n    <value>این پیکربندی صحیحی نیست، لطفا بررسی کنید.</value>\n  </data>\n  <data name=\"InitialConfiguration\" xml:space=\"preserve\">\n    <value>پیکربندی اولیه</value>\n  </data>\n  <data name=\"IsLatestCore\" xml:space=\"preserve\">\n    <value>{0} {1} در حال حاضر به روز است.</value>\n  </data>\n  <data name=\"IsLatestN\" xml:space=\"preserve\">\n    <value>{0} {1} در حال حاضر به روز است.</value>\n  </data>\n  <data name=\"LvAddress\" xml:space=\"preserve\">\n    <value>آدرس</value>\n  </data>\n  <data name=\"LvEncryptionMethod\" xml:space=\"preserve\">\n    <value>امنیت</value>\n  </data>\n  <data name=\"LvPort\" xml:space=\"preserve\">\n    <value>پورت</value>\n  </data>\n  <data name=\"LvServiceType\" xml:space=\"preserve\">\n    <value>نوع</value>\n  </data>\n  <data name=\"LvSubscription\" xml:space=\"preserve\">\n    <value>گروه فرعی</value>\n  </data>\n  <data name=\"LvTodayDownloadDataAmount\" xml:space=\"preserve\">\n    <value> ترافیک دانلود امروز</value>\n  </data>\n  <data name=\"LvTodayUploadDataAmount\" xml:space=\"preserve\">\n    <value> ترافیک اپلود امروز</value>\n  </data>\n  <data name=\"LvTotalDownloadDataAmount\" xml:space=\"preserve\">\n    <value>کل ترافیک دانلود</value>\n  </data>\n  <data name=\"LvTotalUploadDataAmount\" xml:space=\"preserve\">\n    <value>کل ترافیک آپلود</value>\n  </data>\n  <data name=\"LvTransportProtocol\" xml:space=\"preserve\">\n    <value>جابجایی</value>\n  </data>\n  <data name=\"MsgDownloadV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>هسته با موفقیت دانلود شد</value>\n  </data>\n  <data name=\"MsgFailedImportSubscription\" xml:space=\"preserve\">\n    <value>محتوای اشتراک با موفقیت وارد نشد</value>\n  </data>\n  <data name=\"MsgGetSubscriptionSuccessfully\" xml:space=\"preserve\">\n    <value>محتوای اشتراک با موفقیت دریافت شد</value>\n  </data>\n  <data name=\"MsgNoValidSubscription\" xml:space=\"preserve\">\n    <value>هیچ اشتراک معتبری تنظیم نشده است</value>\n  </data>\n  <data name=\"MsgParsingSuccessfully\" xml:space=\"preserve\">\n    <value>{0} با موفقیت حل شد</value>\n  </data>\n  <data name=\"MsgStartGettingSubscriptions\" xml:space=\"preserve\">\n    <value>شروع به دریافت اشتراک کرد</value>\n  </data>\n  <data name=\"MsgStartUpdating\" xml:space=\"preserve\">\n    <value>شروع به‌روزرسانی {0}...</value>\n  </data>\n  <data name=\"MsgSubscriptionDecodingFailed\" xml:space=\"preserve\">\n    <value>محتوای اشتراک نامعتبر است</value>\n  </data>\n  <data name=\"MsgUnpacking\" xml:space=\"preserve\">\n    <value>باز کردن بسته بندی...</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionEnd\" xml:space=\"preserve\">\n    <value>بروزرسانی اشتراک به پایان رسید</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionStart\" xml:space=\"preserve\">\n    <value>بروزرسانی اشتراک شروع شد</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>هسته با موفقیت بروزرسانی شد</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfullyMore\" xml:space=\"preserve\">\n    <value>هسته با موفقیت بروزرسانی شد! راه اندازی مجدد سرویس...</value>\n  </data>\n  <data name=\"NonvmessOrssProtocol\" xml:space=\"preserve\">\n    <value>پروتکل غیر VMess یا ss</value>\n  </data>\n  <data name=\"NotFoundCore\" xml:space=\"preserve\">\n    <value>فایل Core (نام فایل: {1}) در زیر پوشه ({0}) یافت نشد، لطفاً آن را دانلود کرده و در پوشه قرار دهید، آدرس دانلود: {2}</value>\n  </data>\n  <data name=\"NoValidQRcodeFound\" xml:space=\"preserve\">\n    <value>اسکن کامل شد، QRcode معتبری یافت نشد</value>\n  </data>\n  <data name=\"OperationFailed\" xml:space=\"preserve\">\n    <value> عملیات انجام نشد، لطفا بررسی کنید و دوباره امتحان کنید</value>\n  </data>\n  <data name=\"PleaseFillRemarks\" xml:space=\"preserve\">\n    <value>لطفا ملاحظات را پر کنید</value>\n  </data>\n  <data name=\"PleaseSelectEncryption\" xml:space=\"preserve\">\n    <value>لطفاً روش رمزگذاری را انتخاب کنید</value>\n  </data>\n  <data name=\"PleaseSelectProtocol\" xml:space=\"preserve\">\n    <value>لطفا یک پروتکل انتخاب کنید</value>\n  </data>\n  <data name=\"PleaseSelectServer\" xml:space=\"preserve\">\n    <value>لطفا ابتدا سرور را انتخاب کنید</value>\n  </data>\n  <data name=\"RemoveDuplicateServerResult\" xml:space=\"preserve\">\n    <value>حذف مجدد سرورها تکمیل شد. قدیمی: {0}، جدید: {1}.</value>\n  </data>\n  <data name=\"RemoveServer\" xml:space=\"preserve\">\n    <value>آیا مطمئن هستید که می خواهید سرور را حذف کنید؟</value>\n  </data>\n  <data name=\"SaveClientConfigurationIn\" xml:space=\"preserve\">\n    <value>فایل پیکربندی کلاینت در این آدرس ذخیره می شود: {0}</value>\n  </data>\n  <data name=\"StartService\" xml:space=\"preserve\">\n    <value>شروع سرویس ({0})...</value>\n  </data>\n  <data name=\"SuccessfulConfiguration\" xml:space=\"preserve\">\n    <value>پیکربندی با موفقیت انجام شد{0}</value>\n  </data>\n  <data name=\"SuccessfullyImportedCustomServer\" xml:space=\"preserve\">\n    <value>سرور پیکربندی سفارشی با موفقیت وارد شد.</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaClipboard\" xml:space=\"preserve\">\n    <value>{0} سرورها از کلیپ بورد وارد شده اند.</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaScan\" xml:space=\"preserve\">\n    <value>آدرس اینترنتی با موفقیت اسکن و وارد شد</value>\n  </data>\n  <data name=\"TestMeOutput\" xml:space=\"preserve\">\n    <value>پینگ سرویس فعلی: {0} ms, {1}</value>\n  </data>\n  <data name=\"OperationSuccess\" xml:space=\"preserve\">\n    <value>عملیات با موفقیت انجام شد</value>\n  </data>\n  <data name=\"PleaseSelectRules\" xml:space=\"preserve\">\n    <value>لطفا قوانین را انتخاب کنید</value>\n  </data>\n  <data name=\"RemoveRules\" xml:space=\"preserve\">\n    <value>آیا مطمئن هستید که می خواهید قوانین را حذف کنید؟</value>\n  </data>\n  <data name=\"RoutingRuleDetailRequiredTips\" xml:space=\"preserve\">\n    <value>{0}، یکی از فیلدهای الزامی است.</value>\n  </data>\n  <data name=\"LvRemarks\" xml:space=\"preserve\">\n    <value>ملاحظات</value>\n  </data>\n  <data name=\"LvUrl\" xml:space=\"preserve\">\n    <value>آدرس اینترنتی (اختیاری)</value>\n  </data>\n  <data name=\"LvCount\" xml:space=\"preserve\">\n    <value>شمارش</value>\n  </data>\n  <data name=\"MsgNeedUrl\" xml:space=\"preserve\">\n    <value>لطفا آدرس (آدرس اینترنتی) را وارد کنید</value>\n  </data>\n  <data name=\"AddBatchRoutingRulesYesNo\" xml:space=\"preserve\">\n    <value>آآیا می خواهید قوانین را اضافه کنید؟ بله برای افزودن، نه برای جایگزینی را انتخاب کنید.</value>\n  </data>\n  <data name=\"MsgDownloadGeoFileSuccessfully\" xml:space=\"preserve\">\n    <value>GeoFile بارگیری شد: {0} با موفقیت</value>\n  </data>\n  <data name=\"MsgInformationTitle\" xml:space=\"preserve\">\n    <value>اطلاعات</value>\n  </data>\n  <data name=\"LvCustomIcon\" xml:space=\"preserve\">\n    <value>نماد سفارشی</value>\n  </data>\n  <data name=\"FillCorrectDNSText\" xml:space=\"preserve\">\n    <value>لطفاً DNS سفارشی صحیح را پر کنید</value>\n  </data>\n  <data name=\"TransportPathTip1\" xml:space=\"preserve\">\n    <value>* مسیر ws</value>\n  </data>\n  <data name=\"TransportPathTip2\" xml:space=\"preserve\">\n    <value>* مسیر h2</value>\n  </data>\n  <data name=\"TransportPathTip3\" xml:space=\"preserve\">\n    <value>*QUIC key/Kcp seed</value>\n  </data>\n  <data name=\"TransportPathTip4\" xml:space=\"preserve\">\n    <value>*grpc serviceName</value>\n  </data>\n  <data name=\"TransportRequestHostTip1\" xml:space=\"preserve\">\n    <value>*هاست http جدا شده با کاما (،)</value>\n  </data>\n  <data name=\"TransportRequestHostTip2\" xml:space=\"preserve\">\n    <value>*هاست ws</value>\n  </data>\n  <data name=\"TransportRequestHostTip3\" xml:space=\"preserve\">\n    <value>*هاست h2 با کاما (،) جدا شده است</value>\n  </data>\n  <data name=\"TransportRequestHostTip4\" xml:space=\"preserve\">\n    <value>*QUIC securty</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip1\" xml:space=\"preserve\">\n    <value>*tcp camouflage type</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip2\" xml:space=\"preserve\">\n    <value>*kcp camouflage type</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip3\" xml:space=\"preserve\">\n    <value>*QUIC camouflage type</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip4\" xml:space=\"preserve\">\n    <value>*حالت grpc</value>\n  </data>\n  <data name=\"LvTLS\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TransportPathTip5\" xml:space=\"preserve\">\n    <value>*Kcp seed</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeyFailed\" xml:space=\"preserve\">\n    <value>ثبت کلید جهانی {0} انجام نشد، دلیل: {1}</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeySuccessfully\" xml:space=\"preserve\">\n    <value>کلید میانبر جهانی {0} با موفقیت ثبت شد</value>\n  </data>\n  <data name=\"AllGroupServers\" xml:space=\"preserve\">\n    <value>همه سرورها</value>\n  </data>\n  <data name=\"FillServerAddressCustom\" xml:space=\"preserve\">\n    <value>لطفاً برای وارد کردن پیکربندی سرور مرور کنید</value>\n  </data>\n  <data name=\"Speedtesting\" xml:space=\"preserve\">\n    <value>درحال تست کردن...</value>\n  </data>\n  <data name=\"LabLAN\" xml:space=\"preserve\">\n    <value>شبکه محلی</value>\n  </data>\n  <data name=\"LabLocal\" xml:space=\"preserve\">\n    <value>محلی</value>\n  </data>\n  <data name=\"MsgServerTitle\" xml:space=\"preserve\">\n    <value>فیلتر سرورها</value>\n  </data>\n  <data name=\"menuCheckUpdate\" xml:space=\"preserve\">\n    <value>بررسی بروزرسانی</value>\n  </data>\n  <data name=\"menuClose\" xml:space=\"preserve\">\n    <value>بستن</value>\n  </data>\n  <data name=\"menuExit\" xml:space=\"preserve\">\n    <value>خروج</value>\n  </data>\n  <data name=\"menuGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>تنظیم کلید میانبر کلی</value>\n  </data>\n  <data name=\"menuHelp\" xml:space=\"preserve\">\n    <value>کمک</value>\n  </data>\n  <data name=\"menuOptionSetting\" xml:space=\"preserve\">\n    <value>تنظیمات پارامتر</value>\n  </data>\n  <data name=\"menuPromotion\" xml:space=\"preserve\">\n    <value>ترفیع</value>\n  </data>\n  <data name=\"menuReload\" xml:space=\"preserve\">\n    <value>بارگذاری مجدد</value>\n  </data>\n  <data name=\"menuRoutingSetting\" xml:space=\"preserve\">\n    <value>تنظیم مسیریابی</value>\n  </data>\n  <data name=\"menuServers\" xml:space=\"preserve\">\n    <value>سرورها</value>\n  </data>\n  <data name=\"menuSetting\" xml:space=\"preserve\">\n    <value>تنظیمات</value>\n  </data>\n  <data name=\"menuSubGroupUpdate\" xml:space=\"preserve\">\n    <value>اشتراک فعلی را بدون پروکسی به روز شود</value>\n  </data>\n  <data name=\"menuSubGroupUpdateViaProxy\" xml:space=\"preserve\">\n    <value>اشتراک فعلی را با پروکسی به روز شود</value>\n  </data>\n  <data name=\"menuSubscription\" xml:space=\"preserve\">\n    <value>گروه اشتراک</value>\n  </data>\n  <data name=\"menuSubSetting\" xml:space=\"preserve\">\n    <value>تنظیم گروه اشتراک</value>\n  </data>\n  <data name=\"menuSubUpdate\" xml:space=\"preserve\">\n    <value>اشتراک را بدون پروکسی به روز شود</value>\n  </data>\n  <data name=\"menuSubUpdateViaProxy\" xml:space=\"preserve\">\n    <value>اشتراک را با پروکسی به روز شود</value>\n  </data>\n  <data name=\"menuSystemproxy\" xml:space=\"preserve\">\n    <value>پروکسی سیستم</value>\n  </data>\n  <data name=\"menuSystemProxyClear\" xml:space=\"preserve\">\n    <value>پاک کردن پروکسی سیستم</value>\n  </data>\n  <data name=\"menuSystemProxyNothing\" xml:space=\"preserve\">\n    <value>پروکسی سیستم تغییر نکند</value>\n  </data>\n  <data name=\"menuSystemProxyPac\" xml:space=\"preserve\">\n    <value>حالت Pac</value>\n  </data>\n  <data name=\"menuSystemProxySet\" xml:space=\"preserve\">\n    <value>تنظیم پراکسی سیستم</value>\n  </data>\n  <data name=\"TbSettingsColor\" xml:space=\"preserve\">\n    <value>رنگ</value>\n  </data>\n  <data name=\"TbSettingsLanguage\" xml:space=\"preserve\">\n    <value>زبان</value>\n  </data>\n  <data name=\"menuAddServerViaClipboard\" xml:space=\"preserve\">\n    <value>وارد کردن URL انبوه از کلیپ بورد</value>\n  </data>\n  <data name=\"menuAddServerViaScan\" xml:space=\"preserve\">\n    <value>اسکن کد QR روی صفحه</value>\n  </data>\n  <data name=\"menuCopyServer\" xml:space=\"preserve\">\n    <value>سرور انتخاب شده را شبیه سازی کنید</value>\n  </data>\n  <data name=\"menuRemoveDuplicateServer\" xml:space=\"preserve\">\n    <value>سرورهای تکراری را حذف کنید</value>\n  </data>\n  <data name=\"menuRemoveServer\" xml:space=\"preserve\">\n    <value>حذف سرورهای انتخابی</value>\n  </data>\n  <data name=\"menuSetDefaultServer\" xml:space=\"preserve\">\n    <value>به عنوان سرور فعال تنظیم کنید</value>\n  </data>\n  <data name=\"menuClearServerStatistics\" xml:space=\"preserve\">\n    <value>تمام آمار خدمات را پاک کنید</value>\n  </data>\n  <data name=\"menuRealPingServer\" xml:space=\"preserve\">\n    <value>آزمایش سرورها با تاخیر واقعی</value>\n  </data>\n  <data name=\"menuSortServerResult\" xml:space=\"preserve\">\n    <value>مرتب سازی بر اساس نتیجه تست</value>\n  </data>\n  <data name=\"menuSpeedServer\" xml:space=\"preserve\">\n    <value>تست سرعت دانلود سرورها</value>\n  </data>\n  <data name=\"menuTcpingServer\" xml:space=\"preserve\">\n    <value>تست سرورها با tcping</value>\n  </data>\n  <data name=\"menuExport2ClientConfig\" xml:space=\"preserve\">\n    <value>سرور انتخابی را برای پیکربندی کلاینت صادر کنید</value>\n  </data>\n  <data name=\"menuExport2ShareUrl\" xml:space=\"preserve\">\n    <value>URL های اشتراک گذاری را به کلیپ بورد صادر کنید</value>\n  </data>\n  <data name=\"menuAddCustomServer\" xml:space=\"preserve\">\n    <value>یک سرور پیکربندی سفارشی اضافه شود</value>\n  </data>\n  <data name=\"menuAddShadowsocksServer\" xml:space=\"preserve\">\n    <value>سرور [شادوساکس] را اضافه کنید</value>\n  </data>\n  <data name=\"menuAddSocksServer\" xml:space=\"preserve\">\n    <value>سرور [ساکس] را اضافه کنید</value>\n  </data>\n  <data name=\"menuAddTrojanServer\" xml:space=\"preserve\">\n    <value>سرور [تروجان] را اضافه کنید</value>\n  </data>\n  <data name=\"menuAddVlessServer\" xml:space=\"preserve\">\n    <value>سرور [VLESS] را اضافه کنید</value>\n  </data>\n  <data name=\"menuAddVmessServer\" xml:space=\"preserve\">\n    <value>سرور [VMess] را اضافه کنید</value>\n  </data>\n  <data name=\"menuSelectAll\" xml:space=\"preserve\">\n    <value>انتخاب همه</value>\n  </data>\n  <data name=\"menuMsgViewClear\" xml:space=\"preserve\">\n    <value>همه را پاک کن</value>\n  </data>\n  <data name=\"menuMsgViewCopy\" xml:space=\"preserve\">\n    <value>کپی</value>\n  </data>\n  <data name=\"menuMsgViewCopyAll\" xml:space=\"preserve\">\n    <value>کپی همه</value>\n  </data>\n  <data name=\"menuMsgViewSelectAll\" xml:space=\"preserve\">\n    <value>انتخاب همه</value>\n  </data>\n  <data name=\"menuSubAdd\" xml:space=\"preserve\">\n    <value>اضافه کردن</value>\n  </data>\n  <data name=\"menuSubDelete\" xml:space=\"preserve\">\n    <value>حذف</value>\n  </data>\n  <data name=\"menuSubEdit\" xml:space=\"preserve\">\n    <value>ویرایش</value>\n  </data>\n  <data name=\"menuSubShare\" xml:space=\"preserve\">\n    <value>اشتراک</value>\n  </data>\n  <data name=\"LvEnabled\" xml:space=\"preserve\">\n    <value>به روز رسانی فعال شد</value>\n  </data>\n  <data name=\"LvSort\" xml:space=\"preserve\">\n    <value>مرتب سازی</value>\n  </data>\n  <data name=\"LvUserAgent\" xml:space=\"preserve\">\n    <value>عامل کاربر</value>\n  </data>\n  <data name=\"TbCancel\" xml:space=\"preserve\">\n    <value>لغو</value>\n  </data>\n  <data name=\"TbConfirm\" xml:space=\"preserve\">\n    <value>تایید</value>\n  </data>\n  <data name=\"GbTransport\" xml:space=\"preserve\">\n    <value>انتقال</value>\n  </data>\n  <data name=\"TbAddress\" xml:space=\"preserve\">\n    <value>آدرس</value>\n  </data>\n  <data name=\"TbAllowInsecure\" xml:space=\"preserve\">\n    <value>اعطای مجوز ناامن</value>\n  </data>\n  <data name=\"TbAlpn\" xml:space=\"preserve\">\n    <value>Alpn</value>\n  </data>\n  <data name=\"TbAlterId\" xml:space=\"preserve\">\n    <value>AlterId</value>\n  </data>\n  <data name=\"TbFingerprint\" xml:space=\"preserve\">\n    <value>اثرانگشت</value>\n  </data>\n  <data name=\"TbHeaderType\" xml:space=\"preserve\">\n    <value>نوع Camouflage</value>\n  </data>\n  <data name=\"TbId\" xml:space=\"preserve\">\n    <value>UUID(id)</value>\n  </data>\n  <data name=\"TbNetwork\" xml:space=\"preserve\">\n    <value>پروتکل جابجایی (شبکه)</value>\n  </data>\n  <data name=\"TbPath\" xml:space=\"preserve\">\n    <value>مسیر</value>\n  </data>\n  <data name=\"TbPort\" xml:space=\"preserve\">\n    <value>پورت</value>\n  </data>\n  <data name=\"TbRemarks\" xml:space=\"preserve\">\n    <value>نام مستعار (ملاحظات)</value>\n  </data>\n  <data name=\"TbRequestHost\" xml:space=\"preserve\">\n    <value>Camouflage domain(host)</value>\n  </data>\n  <data name=\"TbSecurity\" xml:space=\"preserve\">\n    <value>روش رمزگذاری (امنیتی)</value>\n  </data>\n  <data name=\"TbSNI\" xml:space=\"preserve\">\n    <value>SNI</value>\n  </data>\n  <data name=\"TbStreamSecurity\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TipNetwork\" xml:space=\"preserve\">\n    <value>*مقدار پیش فرض tcp</value>\n  </data>\n  <data name=\"TbCoreType\" xml:space=\"preserve\">\n    <value>نوع هسته</value>\n  </data>\n  <data name=\"TbFlow5\" xml:space=\"preserve\">\n    <value>جریان</value>\n  </data>\n  <data name=\"TbGUID\" xml:space=\"preserve\">\n    <value>ساختن</value>\n  </data>\n  <data name=\"TbId3\" xml:space=\"preserve\">\n    <value>رمزعبور</value>\n  </data>\n  <data name=\"TbId4\" xml:space=\"preserve\">\n    <value>رمز عبور (اختیاری)</value>\n  </data>\n  <data name=\"TbId5\" xml:space=\"preserve\">\n    <value>UUID(id)</value>\n  </data>\n  <data name=\"TbSecurity3\" xml:space=\"preserve\">\n    <value>رمزگذاری</value>\n  </data>\n  <data name=\"TbSecurity4\" xml:space=\"preserve\">\n    <value>کاربر (اختیاری)</value>\n  </data>\n  <data name=\"TbSecurity5\" xml:space=\"preserve\">\n    <value>رمزگذاری</value>\n  </data>\n  <data name=\"TbPreSocksPort\" xml:space=\"preserve\">\n    <value>txtPreSocksPort</value>\n  </data>\n  <data name=\"TipPreSocksPort\" xml:space=\"preserve\">\n    <value>* پس از تنظیم این مقدار، یک سرویس جوراب با استفاده از Xray/sing-box (Tun) برای ارائه عملکردهایی مانند نمایش سرعت شروع می شود.</value>\n  </data>\n  <data name=\"TbBrowse\" xml:space=\"preserve\">\n    <value>مرور کردن</value>\n  </data>\n  <data name=\"TbEdit\" xml:space=\"preserve\">\n    <value>ویرایش</value>\n  </data>\n  <data name=\"TbSettingsAdvancedProtocol\" xml:space=\"preserve\">\n    <value>تنظیمات پیشرفته پروکسی، انتخاب پروتکل (اختیاری)</value>\n  </data>\n  <data name=\"TbSettingsAllowLAN\" xml:space=\"preserve\">\n    <value>اتصالات از LAN را مجاز کنید</value>\n  </data>\n  <data name=\"TbSettingsAutoHideStartup\" xml:space=\"preserve\">\n    <value>مخفی کردن خودکار هنگام راه اندازی</value>\n  </data>\n  <data name=\"TbSettingsAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>فاصله به روز رسانی خودکار برای فایل های Geo (ساعت)</value>\n  </data>\n  <data name=\"TbSettingsCore\" xml:space=\"preserve\">\n    <value>هسته: تنظیمات اولیه</value>\n  </data>\n  <data name=\"TbCustomDnsRay\" xml:space=\"preserve\">\n    <value>V2ray Custom DNS</value>\n  </data>\n  <data name=\"TbSettingsCoreKcp\" xml:space=\"preserve\">\n    <value>هسته: تنظیمات KCP</value>\n  </data>\n  <data name=\"TbSettingsCoreType\" xml:space=\"preserve\">\n    <value>تنظیمات CoreType</value>\n  </data>\n  <data name=\"TbSettingsDefAllowInsecure\" xml:space=\"preserve\">\n    <value>اعطای مجوز ناامن</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Freedom\" xml:space=\"preserve\">\n    <value>Outbound Freedom domainStrategy</value>\n  </data>\n  <data name=\"TbSettingsEnableAutoAdjustMainLvColWidth\" xml:space=\"preserve\">\n    <value>پس از به‌روزرسانی اشتراک، عرض ستون به صورت خودکار تنظیم شود</value>\n  </data>\n  <data name=\"TbSettingsEnableCheckPreReleaseUpdate\" xml:space=\"preserve\">\n    <value>به روز رسانی های پیش از انتشار را بررسی شود</value>\n  </data>\n  <data name=\"TbSettingsException\" xml:space=\"preserve\">\n    <value>استثنا</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip\" xml:space=\"preserve\">\n    <value>استثناها: از سرور پروکسی برای آدرس هایی که با موارد زیر شروع می شوند استفاده نکنید. برای جدا کردن ورودی ها از نقطه ویرگول (;) استفاده کنید.</value>\n  </data>\n  <data name=\"TbSettingsDisplayRealTimeSpeed\" xml:space=\"preserve\">\n    <value>نمایش سرعت واقعی (نیاز به راه اندازی مجدد)</value>\n  </data>\n  <data name=\"TbSettingsKeepOlderDedupl\" xml:space=\"preserve\">\n    <value>ورودی‌های قدیمی‌تر را هنگام حذف کپی نگه دارید</value>\n  </data>\n  <data name=\"TbSettingsLogEnabled\" xml:space=\"preserve\">\n    <value>ثبت گزارش های محلی</value>\n  </data>\n  <data name=\"TbSettingsLogLevel\" xml:space=\"preserve\">\n    <value>سطح ثبت رویداد</value>\n  </data>\n  <data name=\"TbSettingsMuxEnabled\" xml:space=\"preserve\">\n    <value>فعال کردن Mux Multiplexing</value>\n  </data>\n  <data name=\"TbSettingsN\" xml:space=\"preserve\">\n    <value>تنظیمات v2rayN</value>\n  </data>\n  <data name=\"TbSettingsPass\" xml:space=\"preserve\">\n    <value>مجوز احراز هویت</value>\n  </data>\n  <data name=\"TbSettingsRemoteDNS\" xml:space=\"preserve\">\n    <value>سفارشی DNS (multiple, separated by commas (,))</value>\n  </data>\n  <data name=\"TbSettingsSetUWP\" xml:space=\"preserve\">\n    <value>تنظیم کردن Win10 UWP Loopback</value>\n  </data>\n  <data name=\"TbSettingsSniffingEnabled\" xml:space=\"preserve\">\n    <value>فعال کردن Sniffing</value>\n  </data>\n  <data name=\"TbSettingsSocksPort\" xml:space=\"preserve\">\n    <value>پورت Mixed</value>\n  </data>\n  <data name=\"TbSettingsStartBoot\" xml:space=\"preserve\">\n    <value>درهنگام راه ائدازی شروع شود</value>\n  </data>\n  <data name=\"TbSettingsStatistics\" xml:space=\"preserve\">\n    <value>فعال کردن آمار ترافیک (نیاز به راه اندازی مجدد)</value>\n  </data>\n  <data name=\"TbSettingsSubConvert\" xml:space=\"preserve\">\n    <value>آدرس اینترنتی تبدیل اشتراک</value>\n  </data>\n  <data name=\"TbSettingsSystemproxy\" xml:space=\"preserve\">\n    <value>تنظیمات پراکسی سیستم</value>\n  </data>\n  <data name=\"TbSettingsTrayMenuServersLimit\" xml:space=\"preserve\">\n    <value>محدودیت نمایش سرورهای منوی سینی کلیک راست</value>\n  </data>\n  <data name=\"TbSettingsUdpEnabled\" xml:space=\"preserve\">\n    <value>فعال سازی UDP</value>\n  </data>\n  <data name=\"TbSettingsUser\" xml:space=\"preserve\">\n    <value>تایید کاربر</value>\n  </data>\n  <data name=\"TbClearSystemProxy\" xml:space=\"preserve\">\n    <value>پاک کردن پروکسی سیستم</value>\n  </data>\n  <data name=\"TbDisplayGUI\" xml:space=\"preserve\">\n    <value>نمایش رابط کاربری گرافیکی</value>\n  </data>\n  <data name=\"TbGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>تنظیم کلید میانبر جهانی</value>\n  </data>\n  <data name=\"TbGlobalHotkeySettingTip\" xml:space=\"preserve\">\n    <value>مستقیماً با فشار دادن صفحه کلید تنظیم کنید. پس از راه اندازی مجدد اعمال می شود</value>\n  </data>\n  <data name=\"TbNotChangeSystemProxy\" xml:space=\"preserve\">\n    <value>پروکسی سیستم را تغییر ندهید</value>\n  </data>\n  <data name=\"TbReset\" xml:space=\"preserve\">\n    <value>بازنشانی</value>\n  </data>\n  <data name=\"TbSetSystemProxy\" xml:space=\"preserve\">\n    <value>تنظیم پراکسی سیستم</value>\n  </data>\n  <data name=\"TbSystemProxyPac\" xml:space=\"preserve\">\n    <value>حالت Pac</value>\n  </data>\n  <data name=\"menuShareServer\" xml:space=\"preserve\">\n    <value>اشتراک گذاری سرور(Ctrl+F)</value>\n  </data>\n  <data name=\"menuRouting\" xml:space=\"preserve\">\n    <value>مسیریابی</value>\n  </data>\n  <data name=\"NotRunAsAdmin\" xml:space=\"preserve\">\n    <value>به عنوان ادمین اجرا نمی شود</value>\n  </data>\n  <data name=\"RunAsAdmin\" xml:space=\"preserve\">\n    <value>اجرا به عنوان ادمین</value>\n  </data>\n  <data name=\"menuMoveBottom\" xml:space=\"preserve\">\n    <value>به پایین حرکت شود(B)</value>\n  </data>\n  <data name=\"menuMoveDown\" xml:space=\"preserve\">\n    <value>پایین</value>\n  </data>\n  <data name=\"menuMoveTop\" xml:space=\"preserve\">\n    <value>حرکت به بالا</value>\n  </data>\n  <data name=\"menuMoveUp\" xml:space=\"preserve\">\n    <value>بالا</value>\n  </data>\n  <data name=\"MsgFilterTitle\" xml:space=\"preserve\">\n    <value>فیلتر، از عبارات منظم پشتیبانی می کند</value>\n  </data>\n  <data name=\"menuWebsiteItem\" xml:space=\"preserve\">\n    <value>{0} وب سایت</value>\n  </data>\n  <data name=\"menuRoutingAdvancedAdd\" xml:space=\"preserve\">\n    <value>اضافه کردن</value>\n  </data>\n  <data name=\"menuRoutingAdvancedImportRules\" xml:space=\"preserve\">\n    <value>وارد کردن مجموعه قوانین</value>\n  </data>\n  <data name=\"menuRoutingAdvancedRemove\" xml:space=\"preserve\">\n    <value>حذف انتخاب شده</value>\n  </data>\n  <data name=\"menuRoutingAdvancedSetDefault\" xml:space=\"preserve\">\n    <value>تنظیم کردن به عنوان قانون فعال</value>\n  </data>\n  <data name=\"TbdomainStrategy\" xml:space=\"preserve\">\n    <value>استراتژی دامنه</value>\n  </data>\n  <data name=\"TbRoutingTabRuleList\" xml:space=\"preserve\">\n    <value>لیست مجموعه قوانین از پیش تعریف شده</value>\n  </data>\n  <data name=\"TbRoutingTips\" xml:space=\"preserve\">\n    <value>*قوانین را با کاما (,) جدا کنید. برای کاما به معنای واقعی کلمه از &lt;COMMA&gt;; پیشوند # برای نادیده گرفتن یک قانون</value>\n  </data>\n  <data name=\"menuImportRulesFromClipboard\" xml:space=\"preserve\">\n    <value>وارد کردن قوانین از کلیپ بورد</value>\n  </data>\n  <data name=\"menuImportRulesFromFile\" xml:space=\"preserve\">\n    <value>وارد کردن قوانین از فایل</value>\n  </data>\n  <data name=\"menuImportRulesFromUrl\" xml:space=\"preserve\">\n    <value>وارد کردن قوانین از آدرس اینترنتی Sub</value>\n  </data>\n  <data name=\"menuRoutingRuleSetting\" xml:space=\"preserve\">\n    <value>تنظیم قانون</value>\n  </data>\n  <data name=\"menuRuleAdd\" xml:space=\"preserve\">\n    <value>اضافه کردن قانون</value>\n  </data>\n  <data name=\"menuRuleExportSelected\" xml:space=\"preserve\">\n    <value>صادر کردن قوانین انتخاب شده</value>\n  </data>\n  <data name=\"menuRuleList\" xml:space=\"preserve\">\n    <value>فهرست قوانین</value>\n  </data>\n  <data name=\"menuRuleRemove\" xml:space=\"preserve\">\n    <value>حذف قوانین</value>\n  </data>\n  <data name=\"menuRoutingRuleDetailsSetting\" xml:space=\"preserve\">\n    <value>تنظیم جزئیات قانون مسیریابی</value>\n  </data>\n  <data name=\"TbAutoSort\" xml:space=\"preserve\">\n    <value>دامنه و آی پی در هنگام ذخیره به طور خودکار مرتب می شوند</value>\n  </data>\n  <data name=\"TbRuleobjectDoc\" xml:space=\"preserve\">\n    <value>مستندات شی قانون</value>\n  </data>\n  <data name=\"TbDnsObjectDoc\" xml:space=\"preserve\">\n    <value>پشتیبانی از DnsObject. برای مشاهده مستندات کلیک کنید</value>\n  </data>\n  <data name=\"SubUrlTips\" xml:space=\"preserve\">\n    <value>گروه لطفا اینجا را خالی بگذارید</value>\n  </data>\n  <data name=\"TipChangeRouting\" xml:space=\"preserve\">\n    <value>تنظیمات مسیریابی تغییر کرده است</value>\n  </data>\n  <data name=\"TipChangeSystemProxy\" xml:space=\"preserve\">\n    <value>تنظیمات پراکسی سیستم تغییر کرده است</value>\n  </data>\n  <data name=\"TbSettingsRouteOnly\" xml:space=\"preserve\">\n    <value>فقط مسیر</value>\n  </data>\n  <data name=\"TbSettingsNotProxyLocalAddress\" xml:space=\"preserve\">\n    <value>از سرورهای پروکسی برای آدرس های محلی (اینترانت) استفاده نکنید</value>\n  </data>\n  <data name=\"menuMixedTestServer\" xml:space=\"preserve\">\n    <value>تاخیر و سرعت تست با یک کلیک (Ctrl+E)</value>\n  </data>\n  <data name=\"LvTestDelay\" xml:space=\"preserve\">\n    <value>تاخیر (میلی‌ثانیه)</value>\n  </data>\n  <data name=\"LvTestSpeed\" xml:space=\"preserve\">\n    <value>سرعت (MB/s)</value>\n  </data>\n  <data name=\"FailedToRunCore\" xml:space=\"preserve\">\n    <value>Core اجرا نشد، لطفاً گزارش را ببینید</value>\n  </data>\n  <data name=\"LvFilter\" xml:space=\"preserve\">\n    <value>Remarks regular filter</value>\n  </data>\n  <data name=\"TbDisplayLog\" xml:space=\"preserve\">\n    <value>نمایش گزارش</value>\n  </data>\n  <data name=\"TbEnableTunAs\" xml:space=\"preserve\">\n    <value>فعال سازی Tun</value>\n  </data>\n  <data name=\"TbSettingsNewPort4LAN\" xml:space=\"preserve\">\n    <value>پورت جدید برای LAN</value>\n  </data>\n  <data name=\"TbSettingsTunMode\" xml:space=\"preserve\">\n    <value>تنظیمات TunMode</value>\n  </data>\n  <data name=\"menuMoveToGroup\" xml:space=\"preserve\">\n    <value>انتقال به گروه</value>\n  </data>\n  <data name=\"TbSettingsEnableDragDropSort\" xml:space=\"preserve\">\n    <value>فعال کردن مرتب‌سازی سرورها با کشیدن و رها کردن (نیاز به راه‌اندازی مجدد)</value>\n  </data>\n  <data name=\"TbAutoRefresh\" xml:space=\"preserve\">\n    <value>بازخوانی خودکار</value>\n  </data>\n  <data name=\"SpeedtestingSkip\" xml:space=\"preserve\">\n    <value>رد شدن از آزمون</value>\n  </data>\n  <data name=\"menuEditServer\" xml:space=\"preserve\">\n    <value>ویرایش سرور</value>\n  </data>\n  <data name=\"TbSettingsDoubleClick2Activate\" xml:space=\"preserve\">\n    <value>دوبار کلیک کردن سرور باعث فعال شدن آن می شود</value>\n  </data>\n  <data name=\"SpeedtestingCompleted\" xml:space=\"preserve\">\n    <value>تست تکمیل شد</value>\n  </data>\n  <data name=\"TbSettingsDefFingerprint\" xml:space=\"preserve\">\n    <value>اثر انگشت tls پیش فرض</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgent\" xml:space=\"preserve\">\n    <value>User-Agent</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgentTips\" xml:space=\"preserve\">\n    <value>این پارامتر فقط برای tcp/http و ws معتبر است</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamily\" xml:space=\"preserve\">\n    <value>FontFamily (نیاز به راه اندازی مجدد)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyTip\" xml:space=\"preserve\">\n    <value>فایل TTF/TTC فونت را در دایرکتوری guiFonts کپی کنید. پنجره تنظیمات را دوباره باز کنید</value>\n  </data>\n  <data name=\"TbSettingsSocksPortTip\" xml:space=\"preserve\">\n    <value>پورت Pac = +3; پورت Xray API = +4; پورت mihomo API = +5;</value>\n  </data>\n  <data name=\"TbSettingsStartBootTip\" xml:space=\"preserve\">\n    <value>این را با امتیازات ادمین تنظیم کنید، پس از راه اندازی، امتیازات مدیر را دریافت کنید</value>\n  </data>\n  <data name=\"TbSettingsFontSize\" xml:space=\"preserve\">\n    <value>اندازه فونت</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestTimeout\" xml:space=\"preserve\">\n    <value>یمقدار تاخیر تست سرعت منفرد</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestUrl\" xml:space=\"preserve\">\n    <value>/آدرس اینترنتی SpeedTest</value>\n  </data>\n  <data name=\"menuMoveTo\" xml:space=\"preserve\">\n    <value>بالا و پایین حرکت کنید</value>\n  </data>\n  <data name=\"TbPublicKey\" xml:space=\"preserve\">\n    <value>PublicKey</value>\n  </data>\n  <data name=\"TbShortId\" xml:space=\"preserve\">\n    <value>ShortId</value>\n  </data>\n  <data name=\"TbSpiderX\" xml:space=\"preserve\">\n    <value>SpiderX</value>\n  </data>\n  <data name=\"TbSettingsEnableHWA\" xml:space=\"preserve\">\n    <value>فعال‌ سازی شتاب‌ دهنده سخت‌ افزاری (نیاز به راه‌اندازی مجدد)</value>\n  </data>\n  <data name=\"SpeedtestingWait\" xml:space=\"preserve\">\n    <value>در انتظار آزمایش...</value>\n  </data>\n  <data name=\"SpeedtestingPressEscToExit\" xml:space=\"preserve\">\n    <value>برای پایان دادن به ESC فشار دهید</value>\n  </data>\n  <data name=\"TipDisplayLog\" xml:space=\"preserve\">\n    <value>لطفاً در صورت قطع غیرعادی آن را خاموش کنید</value>\n  </data>\n  <data name=\"MsgSkipSubscriptionUpdate\" xml:space=\"preserve\">\n    <value>به روز رسانی ها فعال نیستند، از این اشتراک رد شوید</value>\n  </data>\n  <data name=\"menuRebootAsAdmin\" xml:space=\"preserve\">\n    <value>به عنوان مدیر راه اندازی مجدد</value>\n  </data>\n  <data name=\"LvMoreUrl\" xml:space=\"preserve\">\n    <value>نشانی‌های وب بیشتر که با کاما از هم جدا شده‌اند. تبدیل اشتراک نامعتبر خواهد بود</value>\n  </data>\n  <data name=\"SpeedDisplayText\" xml:space=\"preserve\">\n    <value>{0} : {1}/s↑ | {2}/s↓</value>\n  </data>\n  <data name=\"LvAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>فاصله به روز رسانی خودکار (دقیقه)</value>\n  </data>\n  <data name=\"TbSettingsLogEnabledToFile\" xml:space=\"preserve\">\n    <value>فعال کردن ورود به فایل</value>\n  </data>\n  <data name=\"LvConvertTarget\" xml:space=\"preserve\">\n    <value>تبدیل نوع هدف</value>\n  </data>\n  <data name=\"LvConvertTargetTip\" xml:space=\"preserve\">\n    <value>اگر نیازی به تبدیل نیست، لطفاً خالی بگذارید</value>\n  </data>\n  <data name=\"menuDNSSetting\" xml:space=\"preserve\">\n    <value>تنظیمات DNS</value>\n  </data>\n  <data name=\"TbCustomDnsSingbox\" xml:space=\"preserve\">\n    <value>sing-box Custom DNS</value>\n  </data>\n  <data name=\"TbDnsSingboxObjectDoc\" xml:space=\"preserve\">\n    <value>لطفا ساختار DNS را پر کنید، برای مشاهده سند کلیک کنید</value>\n  </data>\n  <data name=\"TbSettingDnsImportDefConfig\" xml:space=\"preserve\">\n    <value>برای وارد کردن تنظیمات پیش‌فرض DNS کلیک کنید</value>\n  </data>\n  <data name=\"TbdomainStrategy4Singbox\" xml:space=\"preserve\">\n    <value>استراتژی دامنه sing-box</value>\n  </data>\n  <data name=\"TbSettingsMux4SboxProtocol\" xml:space=\"preserve\">\n    <value>پروتکل sing-box Mux</value>\n  </data>\n  <data name=\"TbRoutingRuleProcess\" xml:space=\"preserve\">\n    <value>Process (Linux/Windows)</value>\n  </data>\n  <data name=\"TbRoutingRuleIP\" xml:space=\"preserve\">\n    <value>IP or IP CIDR</value>\n  </data>\n  <data name=\"TbRoutingRuleDomain\" xml:space=\"preserve\">\n    <value>دامنه</value>\n  </data>\n  <data name=\"menuAddHysteria2Server\" xml:space=\"preserve\">\n    <value>Add [Hysteria2] server</value>\n  </data>\n  <data name=\"TbSettingsHysteriaBandwidth\" xml:space=\"preserve\">\n    <value>حداکتر پهنای باند هیستریا (آپلود/دانلود)</value>\n  </data>\n  <data name=\"TbSettingsUseSystemHosts\" xml:space=\"preserve\">\n    <value>استفاده کردن از System Hosts</value>\n  </data>\n  <data name=\"menuAddTuicServer\" xml:space=\"preserve\">\n    <value>افزودن سرور [TUIC]</value>\n  </data>\n  <data name=\"TbHeaderType8\" xml:space=\"preserve\">\n    <value>کنترل تراکم</value>\n  </data>\n  <data name=\"LvPrevProfile\" xml:space=\"preserve\">\n    <value>نام مستعار پروکسی قبلی</value>\n  </data>\n  <data name=\"LvNextProfile\" xml:space=\"preserve\">\n    <value>نام مستعار پروکسی بعدی</value>\n  </data>\n  <data name=\"LvPrevProfileTip\" xml:space=\"preserve\">\n    <value>لطفاً مطمئن شوید که ملاحظات وجود دارند و منحصر به فرد هستند</value>\n  </data>\n  <data name=\"TbSettingsTunAutoRoute\" xml:space=\"preserve\">\n    <value>مسیریابی خودکار</value>\n  </data>\n  <data name=\"TbSettingsTunStrictRoute\" xml:space=\"preserve\">\n    <value>مسیریابی سخت‌گیرانه</value>\n  </data>\n  <data name=\"TbSettingsTunStack\" xml:space=\"preserve\">\n    <value>پشته شبکه</value>\n  </data>\n  <data name=\"TbSettingsTunMtu\" xml:space=\"preserve\">\n    <value>MTU</value>\n  </data>\n  <data name=\"TbSettingsEnableIPv6Address\" xml:space=\"preserve\">\n    <value>فعال سازی آدرس IPv6</value>\n  </data>\n  <data name=\"menuAddWireguardServer\" xml:space=\"preserve\">\n    <value>افزودن سرور [WireGuard]</value>\n  </data>\n  <data name=\"TbPrivateKey\" xml:space=\"preserve\">\n    <value>کلید خصوصی</value>\n  </data>\n  <data name=\"TbReserved\" xml:space=\"preserve\">\n    <value>Reserved (2,3,4)</value>\n  </data>\n  <data name=\"TbLocalAddress\" xml:space=\"preserve\">\n    <value>آدرس (IPv4, IPv6)</value>\n  </data>\n  <data name=\"TbPath7\" xml:space=\"preserve\">\n    <value>پسورد obfs</value>\n  </data>\n  <data name=\"TbRuleMatchingTips\" xml:space=\"preserve\">\n    <value>(Domain or IP or ProcName) and Port and Protocol and InboundTag =&gt; OutboundTag</value>\n  </data>\n  <data name=\"TbAutoScrollToEnd\" xml:space=\"preserve\">\n    <value>خودکار ScrollToEnd</value>\n  </data>\n  <data name=\"TbSettingsSpeedPingTestUrl\" xml:space=\"preserve\">\n    <value>آدرس اینترنتی تست پینگ سرعت</value>\n  </data>\n  <data name=\"SpeedtestingStop\" xml:space=\"preserve\">\n    <value>پایان تست...</value>\n  </data>\n  <data name=\"TransportRequestHostTip5\" xml:space=\"preserve\">\n    <value>*grpc Authority</value>\n  </data>\n  <data name=\"menuAddHttpServer\" xml:space=\"preserve\">\n    <value>افزودن سرور [HTTP]</value>\n  </data>\n  <data name=\"TbSettingsEnableFragment\" xml:space=\"preserve\">\n    <value>فعال کردن فرگمنت</value>\n  </data>\n  <data name=\"TbSettingsEnableCacheFile4Sbox\" xml:space=\"preserve\">\n    <value>فعال کردن کش فایل مجموعه قوانین برای sing-box</value>\n  </data>\n  <data name=\"LvCustomRulesetPath4Singbox\" xml:space=\"preserve\">\n    <value>سفارش سازی مجموعه قوانین sing box</value>\n  </data>\n  <data name=\"NeedRebootTips\" xml:space=\"preserve\">\n    <value>عملکرد موفقیت آمیز بود، روی منوی تنظیمات کلیک کنید تا برنامه راه اندازی مجدد شود.</value>\n  </data>\n  <data name=\"menuOpenTheFileLocation\" xml:space=\"preserve\">\n    <value>باز کردن محل ذخیره سازی</value>\n  </data>\n  <data name=\"TbSorting\" xml:space=\"preserve\">\n    <value>مرتب سازی</value>\n  </data>\n  <data name=\"TbSortingChain\" xml:space=\"preserve\">\n    <value>Chain</value>\n  </data>\n  <data name=\"TbSortingDefault\" xml:space=\"preserve\">\n    <value>پیش فرض</value>\n  </data>\n  <data name=\"TbSortingDelay\" xml:space=\"preserve\">\n    <value>تاخیر</value>\n  </data>\n  <data name=\"TbSortingDownSpeed\" xml:space=\"preserve\">\n    <value>سرعت دانلود</value>\n  </data>\n  <data name=\"TbSortingDownTraffic\" xml:space=\"preserve\">\n    <value>ترافیک دانلود</value>\n  </data>\n  <data name=\"TbSortingHost\" xml:space=\"preserve\">\n    <value>هاست</value>\n  </data>\n  <data name=\"TbSortingName\" xml:space=\"preserve\">\n    <value>نام</value>\n  </data>\n  <data name=\"TbSortingNetwork\" xml:space=\"preserve\">\n    <value>شبکه</value>\n  </data>\n  <data name=\"TbSortingTime\" xml:space=\"preserve\">\n    <value>زمان</value>\n  </data>\n  <data name=\"TbSortingType\" xml:space=\"preserve\">\n    <value>نوع</value>\n  </data>\n  <data name=\"TbSortingUpSpeed\" xml:space=\"preserve\">\n    <value>سرعت اپلود</value>\n  </data>\n  <data name=\"TbSortingUpTraffic\" xml:space=\"preserve\">\n    <value>ترافیک آپلود</value>\n  </data>\n  <data name=\"TbConnections\" xml:space=\"preserve\">\n    <value>اتصالات</value>\n  </data>\n  <data name=\"menuConnectionClose\" xml:space=\"preserve\">\n    <value>بستن اتصال</value>\n  </data>\n  <data name=\"menuConnectionCloseAll\" xml:space=\"preserve\">\n    <value>تمام اتصالات را ببندید</value>\n  </data>\n  <data name=\"TbProxies\" xml:space=\"preserve\">\n    <value>پروکسی</value>\n  </data>\n  <data name=\"menuRulemode\" xml:space=\"preserve\">\n    <value>نوع قانون</value>\n  </data>\n  <data name=\"menuModeDirect\" xml:space=\"preserve\">\n    <value>مستقیم</value>\n  </data>\n  <data name=\"menuModeGlobal\" xml:space=\"preserve\">\n    <value>جهانی</value>\n  </data>\n  <data name=\"menuModeNothing\" xml:space=\"preserve\">\n    <value>تغییر نده</value>\n  </data>\n  <data name=\"menuModeRule\" xml:space=\"preserve\">\n    <value>قانون</value>\n  </data>\n  <data name=\"menuProxiesDelaytest\" xml:space=\"preserve\">\n    <value>تست تأخیر</value>\n  </data>\n  <data name=\"menuProxiesDelaytestPart\" xml:space=\"preserve\">\n    <value>تست تاخیر قسمت گره (نقطه اتصال)</value>\n  </data>\n  <data name=\"menuProxiesReload\" xml:space=\"preserve\">\n    <value>تازه سازی پروکسی ها</value>\n  </data>\n  <data name=\"menuProxiesSelectActivity\" xml:space=\"preserve\">\n    <value>انتخاب گره فعال</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Out\" xml:space=\"preserve\">\n    <value>استراتژی دامنه پیش فرض برای خروجی</value>\n  </data>\n  <data name=\"TbSettingsMainGirdOrientation\" xml:space=\"preserve\">\n    <value>جهت چیدمان اصلی (نیاز به راه اندازی مجدد)</value>\n  </data>\n  <data name=\"TbSettingsDomainDNSAddress\" xml:space=\"preserve\">\n    <value>آدرس DNS خروجی</value>\n  </data>\n  <data name=\"menuProfileAutofitColumnWidth\" xml:space=\"preserve\">\n    <value>تنظیم خودکار عرض ستون</value>\n  </data>\n  <data name=\"menuExport2ShareUrlBase64\" xml:space=\"preserve\">\n    <value>صادر کردن پیوندهای اشتراک گذاری کدگذاری شده با Base64 به کلیپ بورد</value>\n  </data>\n  <data name=\"menuExport2ClientConfigClipboard\" xml:space=\"preserve\">\n    <value>صادر کردن سرور انتخاب شده برای پیکربندی کامل به کلیپ بورد</value>\n  </data>\n  <data name=\"menuShowOrHideMainWindow\" xml:space=\"preserve\">\n    <value>نمایش یا پنهان کردن پنجره اصلی</value>\n  </data>\n  <data name=\"TbPreSocksPort4Sub\" xml:space=\"preserve\">\n    <value>پیکربندی سفارشی ساکس پورت</value>\n  </data>\n  <data name=\"menuBackupAndRestore\" xml:space=\"preserve\">\n    <value>پشتیبان گیری و بازیابی</value>\n  </data>\n  <data name=\"menuLocalBackup\" xml:space=\"preserve\">\n    <value>پشتیبان گیری به محلی</value>\n  </data>\n  <data name=\"menuLocalRestore\" xml:space=\"preserve\">\n    <value>بازیابی از محلی</value>\n  </data>\n  <data name=\"menuRemoteBackup\" xml:space=\"preserve\">\n    <value>پشتیبان گیری از راه دور (WebDAV)</value>\n  </data>\n  <data name=\"menuRemoteRestore\" xml:space=\"preserve\">\n    <value>بازیابی از راه دور (WebDAV)</value>\n  </data>\n  <data name=\"menuLocalBackupAndRestore\" xml:space=\"preserve\">\n    <value>محلی</value>\n  </data>\n  <data name=\"menuRemoteBackupAndRestore\" xml:space=\"preserve\">\n    <value>از راه دور (WebDAV)</value>\n  </data>\n  <data name=\"LvWebDavUrl\" xml:space=\"preserve\">\n    <value>آدرس اینترنتی WebDav</value>\n  </data>\n  <data name=\"LvWebDavUserName\" xml:space=\"preserve\">\n    <value>نام کاربری WebDav</value>\n  </data>\n  <data name=\"LvWebDavPassword\" xml:space=\"preserve\">\n    <value>پسورد WebDav</value>\n  </data>\n  <data name=\"LvWebDavCheck\" xml:space=\"preserve\">\n    <value>چک کردن WebDav</value>\n  </data>\n  <data name=\"LvWebDavDirName\" xml:space=\"preserve\">\n    <value>نام پوشه راه دور (اختیاری)</value>\n  </data>\n  <data name=\"LocalRestoreInvalidZipTips\" xml:space=\"preserve\">\n    <value>فایل پشتیبان نامعتبر است</value>\n  </data>\n  <data name=\"ConnectionsHostFilterTitle\" xml:space=\"preserve\">\n    <value>فیلتر هسته</value>\n  </data>\n  <data name=\"TipActiveServer\" xml:space=\"preserve\">\n    <value>فعال سازی</value>\n  </data>\n  <data name=\"TbSettingsGeoFilesSource\" xml:space=\"preserve\">\n    <value>منبع فایل های جغرافیایی (اختیاری)</value>\n  </data>\n  <data name=\"TbSettingsSrsFilesSource\" xml:space=\"preserve\">\n    <value>منبع فایل های مجموعه قوانین sing-box (اختیاری)</value>\n  </data>\n  <data name=\"UpgradeAppNotExistTip\" xml:space=\"preserve\">\n    <value>برنامه ارتقا وجود ندارد</value>\n  </data>\n  <data name=\"TbSettingsRoutingRulesSource\" xml:space=\"preserve\">\n    <value>منبع قوانین مسیریابی (اختیاری)</value>\n  </data>\n  <data name=\"menuRegionalPresets\" xml:space=\"preserve\">\n    <value>تنظیمات از پیش تعیین شده منطقه ای</value>\n  </data>\n  <data name=\"menuRegionalPresetsDefault\" xml:space=\"preserve\">\n    <value>پیش فرض</value>\n  </data>\n  <data name=\"menuRegionalPresetsRussia\" xml:space=\"preserve\">\n    <value>روسیه</value>\n  </data>\n  <data name=\"menuRegionalPresetsIran\" xml:space=\"preserve\">\n    <value>ایران</value>\n  </data>\n  <data name=\"TbSettingsChinaUserTip\" xml:space=\"preserve\">\n    <value>کاربران در منطقه چین می توانند این مورد را نادیده بگیرند</value>\n  </data>\n  <data name=\"menuAddServerViaImage\" xml:space=\"preserve\">\n    <value>اسکن کردن QRcode موجود در تصویر</value>\n  </data>\n  <data name=\"InvalidUrlTip\" xml:space=\"preserve\">\n    <value>آدرس نامعتبر (آدرس اینترنتی)</value>\n  </data>\n  <data name=\"InsecureUrlProtocol\" xml:space=\"preserve\">\n    <value>لطفاً از آدرس اشتراک پروتکل HTTP ناامن استفاده نکنید</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyLinuxTip\" xml:space=\"preserve\">\n    <value>فونت را روی سیستم نصب کنید و تنظیمات را مجددا راه اندازی کنید</value>\n  </data>\n  <data name=\"menuExitTips\" xml:space=\"preserve\">\n    <value>آیا مطمئن هستید که خارج می شوید؟</value>\n  </data>\n  <data name=\"LvMemo\" xml:space=\"preserve\">\n    <value>یادداشت ملاحظات</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPassword\" xml:space=\"preserve\">\n    <value>رمز عبور sudo سیستم</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPasswordTip\" xml:space=\"preserve\">\n    <value>The password will be validated via the command line. If a validation error causes the application to malfunction, please restart the application. The password will not be stored and must be entered again after each restart.</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip5\" xml:space=\"preserve\">\n    <value>*حالت xhttp</value>\n  </data>\n  <data name=\"TransportExtraTip\" xml:space=\"preserve\">\n    <value>جیسون خام XHTTP Extra, فرمت: { XHTTPObject }</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenClose\" xml:space=\"preserve\">\n    <value>هنگام بستن پنجره در سینی پنهان شوید</value>\n  </data>\n  <data name=\"TbSettingsMixedConcurrencyCount\" xml:space=\"preserve\">\n    <value>تعداد همزمان در طول چند آزمون</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip2\" xml:space=\"preserve\">\n    <value>موارد استثنا: از سرور پروکسی برای آدرس های زیر استفاده نکنید. برای جدا کردن ورودی ها از کاما (،) استفاده کنید.</value>\n  </data>\n  <data name=\"TbSettingsDestOverride\" xml:space=\"preserve\">\n    <value>نوع Sniffing</value>\n  </data>\n  <data name=\"TbSettingsSecondLocalPortEnabled\" xml:space=\"preserve\">\n    <value>فعال کردن دومین پورت ترکیبی</value>\n  </data>\n  <data name=\"TbRoutingInboundTagTips\" xml:space=\"preserve\">\n    <value>socks:پورت محلی، socks2: پورت دوم محلی، socks3: پورت LAN</value>\n  </data>\n  <data name=\"TbSettingsTheme\" xml:space=\"preserve\">\n    <value>تم</value>\n  </data>\n  <data name=\"menuCopyProxyCmdToClipboard\" xml:space=\"preserve\">\n    <value>کپی کردن دستور پروکسی در کلیپ بورد</value>\n  </data>\n  <data name=\"SpeedtestingTestFailedPart\" xml:space=\"preserve\">\n    <value>شروع آزمایش مجدد قطعات ناموفق، {0} باقی مانده است. برای خاتمه ESC را فشار دهید...</value>\n  </data>\n  <data name=\"menuTestServerResult\" xml:space=\"preserve\">\n    <value>با نتیجه آزمایش</value>\n  </data>\n  <data name=\"menuRemoveInvalidServerResult\" xml:space=\"preserve\">\n    <value>حذف نامعتبر با نتایج آزمایش</value>\n  </data>\n  <data name=\"RemoveInvalidServerResultTip\" xml:space=\"preserve\">\n    <value>{0} نتایج آزمایش نامعتبر حذف شد.</value>\n  </data>\n  <data name=\"TbPorts7\" xml:space=\"preserve\">\n    <value>محدوده پورت سرور</value>\n  </data>\n  <data name=\"TbPorts7Tips\" xml:space=\"preserve\">\n    <value>مخفی و پورت می شود، با کاما (،) جدا می شود</value>\n  </data>\n  <data name=\"menuExportConfig\" xml:space=\"preserve\">\n    <value>صادر کردن سرور</value>\n  </data>\n  <data name=\"TbSettingsIPAPIUrl\" xml:space=\"preserve\">\n    <value>URL آزمایش اطلاعات اتصال فعلی</value>\n  </data>\n  <data name=\"TbRuleOutboundTagTip\" xml:space=\"preserve\">\n    <value>Can fill in the configuration remarks, please make sure it exist and are unique</value>\n  </data>\n  <data name=\"SudoIncorrectPasswordTip\" xml:space=\"preserve\">\n    <value>Incorrect password, please try again.</value>\n  </data>\n  <data name=\"TbMldsa65Verify\" xml:space=\"preserve\">\n    <value>Mldsa65Verify</value>\n  </data>\n  <data name=\"menuAddAnytlsServer\" xml:space=\"preserve\">\n    <value>Add [Anytls] Configuration</value>\n  </data>\n  <data name=\"TbRemoteDNS\" xml:space=\"preserve\">\n    <value>Remote DNS</value>\n  </data>\n  <data name=\"TbDomesticDNS\" xml:space=\"preserve\">\n    <value>Domestic DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategy\" xml:space=\"preserve\">\n    <value>Direct Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategy\" xml:space=\"preserve\">\n    <value>Proxy Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbAddCommonDNSHosts\" xml:space=\"preserve\">\n    <value>Add Common DNS Hosts</value>\n  </data>\n  <data name=\"TbFakeIP\" xml:space=\"preserve\">\n    <value>FakeIP</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueries\" xml:space=\"preserve\">\n    <value>Block SVCB and HTTPS Queries</value>\n  </data>\n  <data name=\"TbDNSHostsConfig\" xml:space=\"preserve\">\n    <value>DNS Hosts: (\"domain1 ip1 ip2\" per line)</value>\n  </data>\n  <data name=\"ThBasicDNSSettings\" xml:space=\"preserve\">\n    <value>Basic DNS Settings</value>\n  </data>\n  <data name=\"ThAdvancedDNSSettings\" xml:space=\"preserve\">\n    <value>Advanced DNS Settings</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPs\" xml:space=\"preserve\">\n    <value>Validate Regional Domain IPs</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPsDesc\" xml:space=\"preserve\">\n    <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs</value>\n  </data>\n  <data name=\"TbCustomDNSEnable\" xml:space=\"preserve\">\n    <value>Enable Custom DNS</value>\n  </data>\n  <data name=\"TbCustomDNSEnabledPageInvalid\" xml:space=\"preserve\">\n    <value>Custom DNS Enabled, This Page's Settings Invalid</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueriesTips\" xml:space=\"preserve\">\n    <value>Block ECH and HTTP/3 availability checks when enabled</value>\n  </data>\n  <data name=\"FillCorrectConfigTemplateText\" xml:space=\"preserve\">\n    <value>Please fill in the correct config template</value>\n  </data>\n  <data name=\"menuFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Full Config Template Setting</value>\n  </data>\n  <data name=\"TbFullConfigTemplateEnable\" xml:space=\"preserve\">\n    <value>Enable Full Config Template</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplate\" xml:space=\"preserve\">\n    <value>v2ray Full Config Template</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>\n  </data>\n  <data name=\"TbAddProxyProtocolOutboundOnly\" xml:space=\"preserve\">\n    <value>Do Not Add Non-Proxy Protocol Outbound</value>\n  </data>\n  <data name=\"TbSetUpstreamProxyDetour\" xml:space=\"preserve\">\n    <value>Set Upstream Proxy Tag</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplate\" xml:space=\"preserve\">\n    <value>sing-box Full Config Template</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Add Outbound and Endpoint Config Only, Click to view the document</value>\n  </data>\n  <data name=\"TbFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>\n  </data>\n  <data name=\"MsgStartParsingSubscription\" xml:space=\"preserve\">\n    <value>Start parsing and processing subscription content</value>\n  </data>\n  <data name=\"TbSelectProfile\" xml:space=\"preserve\">\n    <value>Select Profile</value>\n  </data>\n  <data name=\"TbFakeIPTips\" xml:space=\"preserve\">\n    <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value>\n  </data>\n  <data name=\"PleaseAddAtLeastOneServer\" xml:space=\"preserve\">\n    <value>Please Add At Least One Configuration</value>\n  </data>\n  <data name=\"TbConfigTypePolicyGroup\" xml:space=\"preserve\">\n    <value>Policy Group</value>\n  </data>\n  <data name=\"TbConfigTypeProxyChain\" xml:space=\"preserve\">\n    <value>Proxy Chain</value>\n  </data>\n  <data name=\"TbLeastPing\" xml:space=\"preserve\">\n    <value>Lowest Latency</value>\n  </data>\n  <data name=\"TbRandom\" xml:space=\"preserve\">\n    <value>Random</value>\n  </data>\n  <data name=\"TbRoundRobin\" xml:space=\"preserve\">\n    <value>Round Robin</value>\n  </data>\n  <data name=\"TbLeastLoad\" xml:space=\"preserve\">\n    <value>Most Stable</value>\n  </data>\n  <data name=\"TbPolicyGroupType\" xml:space=\"preserve\">\n    <value>Policy Group Type</value>\n  </data>\n  <data name=\"menuAddPolicyGroupServer\" xml:space=\"preserve\">\n    <value>Add Policy Group Configuration</value>\n  </data>\n  <data name=\"menuAddProxyChainServer\" xml:space=\"preserve\">\n    <value>Add Proxy Chain Configuration</value>\n  </data>\n  <data name=\"menuAddChildServer\" xml:space=\"preserve\">\n    <value>Add Child Configuration</value>\n  </data>\n  <data name=\"menuRemoveChildServer\" xml:space=\"preserve\">\n    <value>Remove Child Configuration</value>\n  </data>\n  <data name=\"menuServerList\" xml:space=\"preserve\">\n    <value>Configuration item 1, Auto add from subscription group</value>\n  </data>\n  <data name=\"TbFallback\" xml:space=\"preserve\">\n    <value>Fallback</value>\n  </data>\n  <data name=\"MsgCoreNotSupportNetwork\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support network type '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocolTransport\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}' when using transport '{2}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}'</value>\n  </data>\n  <data name=\"MsgInvalidProperty\" xml:space=\"preserve\">\n    <value>The {0} property is invalid, please check</value>\n  </data>\n  <data name=\"MsgNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Not support protocol '{0}'</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenCloseTip\" xml:space=\"preserve\">\n    <value>If the system does not have a tray function, please do not enable it</value>\n  </data>\n  <data name=\"TbRuleType\" xml:space=\"preserve\">\n    <value>Rule Type</value>\n  </data>\n  <data name=\"TbRuleTypeTips\" xml:space=\"preserve\">\n    <value>You can set separate rules for Routing and DNS, or select \"ALL\" to apply to both</value>\n  </data>\n  <data name=\"TbBootstrapDNS\" xml:space=\"preserve\">\n    <value>Bootstrap DNS</value>\n  </data>\n  <data name=\"TbBootstrapDNSTips\" xml:space=\"preserve\">\n    <value>Resolve DNS server domains, requires IP</value>\n  </data>\n  <data name=\"menuFastRealPing\" xml:space=\"preserve\">\n    <value>Test real delay</value>\n  </data>\n  <data name=\"TbPolicyGroupSubChildTip\" xml:space=\"preserve\">\n    <value>Auto add filtered configuration from subscription groups</value>\n  </data>\n  <data name=\"TbCertPinning\" xml:space=\"preserve\">\n    <value>Certificate Pinning</value>\n  </data>\n  <data name=\"TbCertPinningTips\" xml:space=\"preserve\">\n    <value>Server Certificate (PEM format, optional)\nWhen specified, the certificate will be pinned, and \"Allow Insecure\" will be disabled.\n\nThe \"Get Certificate\" action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA.</value>\n  </data>\n  <data name=\"TbFetchCert\" xml:space=\"preserve\">\n    <value>Fetch Certificate</value>\n  </data>\n  <data name=\"TbFetchCertChain\" xml:space=\"preserve\">\n    <value>Fetch Certificate Chain</value>\n  </data>\n  <data name=\"ServerNameMustBeValidDomain\" xml:space=\"preserve\">\n    <value>Please set a valid domain</value>\n  </data>\n  <data name=\"CertNotSet\" xml:space=\"preserve\">\n    <value>Certificate not set</value>\n  </data>\n  <data name=\"CertSet\" xml:space=\"preserve\">\n    <value>Certificate set</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyPacPath\" xml:space=\"preserve\">\n    <value>Custom PAC file path</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyScriptPath\" xml:space=\"preserve\">\n    <value>Custom system proxy script file path</value>\n  </data>\n  <data name=\"TbSettingsMacOSShowInDock\" xml:space=\"preserve\">\n    <value>macOS displays this in the Dock (requires restart)</value>\n  </data>\n  <data name=\"menuServerList2\" xml:space=\"preserve\">\n    <value>Configuration Item 2, Select and add from self-built</value>\n  </data>\n  <data name=\"TbEchConfigList\" xml:space=\"preserve\">\n    <value>EchConfigList</value>\n  </data>\n  <data name=\"TbEchForceQuery\" xml:space=\"preserve\">\n    <value>EchForceQuery</value>\n  </data>\n  <data name=\"TbFullCertTips\" xml:space=\"preserve\">\n    <value>Full certificate (chain), PEM format</value>\n  </data>\n  <data name=\"TbCertSha256Tips\" xml:space=\"preserve\">\n    <value>Certificate fingerprint (SHA-256)</value>\n  </data>\n  <data name=\"TbServeStale\" xml:space=\"preserve\">\n    <value>Serve Stale</value>\n  </data>\n  <data name=\"TbParallelQuery\" xml:space=\"preserve\">\n    <value>Parallel Query</value>\n  </data>\n  <data name=\"TbDomesticDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution</value>\n  </data>\n  <data name=\"TbRemoteDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution; ensure the remote server can reach this DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution uses the system DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbHopInt7\" xml:space=\"preserve\">\n    <value>Port hopping interval</value>\n  </data>\n  <data name=\"menuServerListPreview\" xml:space=\"preserve\">\n    <value>Configuration item preview</value>\n  </data>\n  <data name=\"TbFinalmask\" xml:space=\"preserve\">\n    <value>Finalmask</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeWarning\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeError\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} error: {2}. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgGroupCycleDependency\" xml:space=\"preserve\">\n    <value>Group {0} has a cycle dependency on child node {1}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupNoValidChildNode\" xml:space=\"preserve\">\n    <value>Group {0} has no valid child node.</value>\n  </data>\n  <data name=\"MsgRoutingRuleEmptyOutboundTag\" xml:space=\"preserve\">\n    <value>Routing rule {0} has an empty outbound tag. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeNotFound\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} not found. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgSubscriptionPrevProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription previous proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"MsgSubscriptionNextProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription next proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"menuGenGroupServer\" xml:space=\"preserve\">\n    <value>Generate Policy Group</value>\n  </data>\n  <data name=\"menuAllServers\" xml:space=\"preserve\">\n    <value>All configurations</value>\n  </data>\n  <data name=\"menuGenRegionGroup\" xml:space=\"preserve\">\n    <value>Group by Region</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.fr.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BatchExportURLSuccessfully\" xml:space=\"preserve\">\n    <value>Lien de partage exporté vers le presse-papiers avec succès</value>\n  </data>\n  <data name=\"CheckServerSettings\" xml:space=\"preserve\">\n    <value>Veuillez vérifier d’abord la config</value>\n  </data>\n  <data name=\"ConfigurationFormatIncorrect\" xml:space=\"preserve\">\n    <value>Format de configuration incorrect</value>\n  </data>\n  <data name=\"CustomServerTips\" xml:space=\"preserve\">\n    <value>Attention : la configuration personnalisée dépend entièrement de vos paramètres et peut ne pas activer toutes les fonctions. Pour utiliser le proxy système, changez le port d’écoute manuellement.</value>\n  </data>\n  <data name=\"Downloading\" xml:space=\"preserve\">\n    <value>Téléchargement commencé...</value>\n  </data>\n  <data name=\"FailedConversionConfiguration\" xml:space=\"preserve\">\n    <value>Échec de la conversion de la configuration</value>\n  </data>\n  <data name=\"FailedGenDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Échec de la génération du fichier de configuration par défaut</value>\n  </data>\n  <data name=\"FailedGetDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Échec de l’obtention de la configuration par défaut</value>\n  </data>\n  <data name=\"FailedImportedCustomServer\" xml:space=\"preserve\">\n    <value>Échec de l’importation de la configuration personnalisée</value>\n  </data>\n  <data name=\"FailedReadConfiguration\" xml:space=\"preserve\">\n    <value>Échec de la lecture de la configuration</value>\n  </data>\n  <data name=\"FillCorrectServerPort\" xml:space=\"preserve\">\n    <value>Veuillez saisir un port au format correct</value>\n  </data>\n  <data name=\"FillLocalListeningPort\" xml:space=\"preserve\">\n    <value>Veuillez saisir le port d’écoute local</value>\n  </data>\n  <data name=\"FillPassword\" xml:space=\"preserve\">\n    <value>Veuillez saisir le mot de passe</value>\n  </data>\n  <data name=\"FillServerAddress\" xml:space=\"preserve\">\n    <value>Veuillez saisir l’adresse</value>\n  </data>\n  <data name=\"FillUUID\" xml:space=\"preserve\">\n    <value>Veuillez saisir l’ID utilisateur</value>\n  </data>\n  <data name=\"Incorrectconfiguration\" xml:space=\"preserve\">\n    <value>Configuration incorrecte, veuillez vérifier</value>\n  </data>\n  <data name=\"InitialConfiguration\" xml:space=\"preserve\">\n    <value>Initialiser la configuration</value>\n  </data>\n  <data name=\"IsLatestCore\" xml:space=\"preserve\">\n    <value>{0} {1} est déjà à jour.</value>\n  </data>\n  <data name=\"IsLatestN\" xml:space=\"preserve\">\n    <value>{0} {1} est déjà à jour.</value>\n  </data>\n  <data name=\"LvAddress\" xml:space=\"preserve\">\n    <value>Adresse</value>\n  </data>\n  <data name=\"LvEncryptionMethod\" xml:space=\"preserve\">\n    <value>Méthode de chiffrement</value>\n  </data>\n  <data name=\"LvPort\" xml:space=\"preserve\">\n    <value>Port</value>\n  </data>\n  <data name=\"LvServiceType\" xml:space=\"preserve\">\n    <value>Type</value>\n  </data>\n  <data name=\"LvSubscription\" xml:space=\"preserve\">\n    <value>Grp abonn.</value>\n  </data>\n  <data name=\"LvTodayDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Téléchargement du jour</value>\n  </data>\n  <data name=\"LvTodayUploadDataAmount\" xml:space=\"preserve\">\n    <value>Téléversement du jour</value>\n  </data>\n  <data name=\"LvTotalDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Total téléchargé</value>\n  </data>\n  <data name=\"LvTotalUploadDataAmount\" xml:space=\"preserve\">\n    <value>Total téléversé</value>\n  </data>\n  <data name=\"LvTransportProtocol\" xml:space=\"preserve\">\n    <value>Protoc. Transp.</value>\n  </data>\n  <data name=\"MsgDownloadV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>Téléchargement du Core réussi</value>\n  </data>\n  <data name=\"MsgFailedImportSubscription\" xml:space=\"preserve\">\n    <value>Échec de l’importation du contenu d’abonnement</value>\n  </data>\n  <data name=\"MsgGetSubscriptionSuccessfully\" xml:space=\"preserve\">\n    <value>Contenu d’abonnement récupéré avec succès</value>\n  </data>\n  <data name=\"MsgNoValidSubscription\" xml:space=\"preserve\">\n    <value>Aucun abonnement valide défini</value>\n  </data>\n  <data name=\"MsgParsingSuccessfully\" xml:space=\"preserve\">\n    <value>Analyse de {0} réussie</value>\n  </data>\n  <data name=\"MsgStartGettingSubscriptions\" xml:space=\"preserve\">\n    <value>Début de la récupération du contenu d’abonnement</value>\n  </data>\n  <data name=\"MsgStartUpdating\" xml:space=\"preserve\">\n    <value>Début de la mise à jour de {0}...</value>\n  </data>\n  <data name=\"MsgSubscriptionDecodingFailed\" xml:space=\"preserve\">\n    <value>Contenu d’abonnement invalide</value>\n  </data>\n  <data name=\"MsgUnpacking\" xml:space=\"preserve\">\n    <value>Décompression en cours......</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionEnd\" xml:space=\"preserve\">\n    <value>Fin de la mise à jour des abonnements</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionStart\" xml:space=\"preserve\">\n    <value>Début de la mise à jour des abonnements</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>Mise à jour du Core réussie</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfullyMore\" xml:space=\"preserve\">\n    <value>Mise à jour du Core réussie ! Redémarrage du service...</value>\n  </data>\n  <data name=\"NonvmessOrssProtocol\" xml:space=\"preserve\">\n    <value>Protocole non VMess ni SS</value>\n  </data>\n  <data name=\"NotFoundCore\" xml:space=\"preserve\">\n    <value>Fichier Core introuvable dans le dossier ({0}) (nom de fichier : {1}). Veuillez le télécharger puis le placer dans le dossier. Adresse de téléchargement : {2}</value>\n  </data>\n  <data name=\"NoValidQRcodeFound\" xml:space=\"preserve\">\n    <value>Analyse terminée, aucun QR code valide trouvé</value>\n  </data>\n  <data name=\"OperationFailed\" xml:space=\"preserve\">\n    <value>Échec de l’opération, veuillez vérifier et réessayer</value>\n  </data>\n  <data name=\"PleaseFillRemarks\" xml:space=\"preserve\">\n    <value>Veuillez saisir un alias</value>\n  </data>\n  <data name=\"PleaseSelectEncryption\" xml:space=\"preserve\">\n    <value>Veuillez sélectionner une méthode de chiffrement</value>\n  </data>\n  <data name=\"PleaseSelectProtocol\" xml:space=\"preserve\">\n    <value>Veuillez sélectionner un protocole</value>\n  </data>\n  <data name=\"PleaseSelectServer\" xml:space=\"preserve\">\n    <value>Sélectionnez d’abord une configuration</value>\n  </data>\n  <data name=\"RemoveDuplicateServerResult\" xml:space=\"preserve\">\n    <value>Déduplication des configurations terminée. Quantité initiale : {0}, quantité actuelle : {1}.</value>\n  </data>\n  <data name=\"RemoveServer\" xml:space=\"preserve\">\n    <value>Confirmer la suppression ?</value>\n  </data>\n  <data name=\"SaveClientConfigurationIn\" xml:space=\"preserve\">\n    <value>Le fichier de configuration client est enregistré dans : {0}</value>\n  </data>\n  <data name=\"StartService\" xml:space=\"preserve\">\n    <value>Démarrage du service ({0})...</value>\n  </data>\n  <data name=\"SuccessfulConfiguration\" xml:space=\"preserve\">\n    <value>Configuration réussie. {0}</value>\n  </data>\n  <data name=\"SuccessfullyImportedCustomServer\" xml:space=\"preserve\">\n    <value>Configuration personnalisée importée avec succès</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaClipboard\" xml:space=\"preserve\">\n    <value>{0} configurations importées depuis le presse-papiers</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaScan\" xml:space=\"preserve\">\n    <value>Lien de partage importé par analyse avec succès</value>\n  </data>\n  <data name=\"TestMeOutput\" xml:space=\"preserve\">\n    <value>Latence actuelle : {0} ms, {1}</value>\n  </data>\n  <data name=\"OperationSuccess\" xml:space=\"preserve\">\n    <value>Opération réussie</value>\n  </data>\n  <data name=\"PleaseSelectRules\" xml:space=\"preserve\">\n    <value>Veuillez d’abord sélectionner une règle</value>\n  </data>\n  <data name=\"RemoveRules\" xml:space=\"preserve\">\n    <value>Confirmer la suppression de la règle ?</value>\n  </data>\n  <data name=\"RoutingRuleDetailRequiredTips\" xml:space=\"preserve\">\n    <value>{0}, au moins un champ est obligatoire.</value>\n  </data>\n  <data name=\"LvRemarks\" xml:space=\"preserve\">\n    <value>Alias</value>\n  </data>\n  <data name=\"LvUrl\" xml:space=\"preserve\">\n    <value>Adresse optionnelle (URL)</value>\n  </data>\n  <data name=\"LvCount\" xml:space=\"preserve\">\n    <value>Quantité</value>\n  </data>\n  <data name=\"MsgNeedUrl\" xml:space=\"preserve\">\n    <value>Veuillez saisir l’URL</value>\n  </data>\n  <data name=\"AddBatchRoutingRulesYesNo\" xml:space=\"preserve\">\n    <value>Ajouter les règles ? Choisir \"Oui\" pour ajouter, \"Non\" pour tout remplacer.</value>\n  </data>\n  <data name=\"MsgDownloadGeoFileSuccessfully\" xml:space=\"preserve\">\n    <value>Téléchargement du fichier Geo : {0} réussi</value>\n  </data>\n  <data name=\"MsgInformationTitle\" xml:space=\"preserve\">\n    <value>Information</value>\n  </data>\n  <data name=\"LvCustomIcon\" xml:space=\"preserve\">\n    <value>Icône personnalisée</value>\n  </data>\n  <data name=\"FillCorrectDNSText\" xml:space=\"preserve\">\n    <value>Veuillez saisir un DNS personnalisé valide</value>\n  </data>\n  <data name=\"TransportPathTip1\" xml:space=\"preserve\">\n    <value>*chemin ws/httpupgrade/xhttp</value>\n  </data>\n  <data name=\"TransportPathTip2\" xml:space=\"preserve\">\n    <value>*chemin h2</value>\n  </data>\n  <data name=\"TransportPathTip3\" xml:space=\"preserve\">\n    <value>*clé de chiffrement QUIC</value>\n  </data>\n  <data name=\"TransportPathTip4\" xml:space=\"preserve\">\n    <value>*nom de service gRPC</value>\n  </data>\n  <data name=\"TransportRequestHostTip1\" xml:space=\"preserve\">\n    <value>*hôte http, séparés par des virgules (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip2\" xml:space=\"preserve\">\n    <value>*hôte ws/httpupgrade/xhttp</value>\n  </data>\n  <data name=\"TransportRequestHostTip3\" xml:space=\"preserve\">\n    <value>*hôte h2, séparés par des virgules (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip4\" xml:space=\"preserve\">\n    <value>*méthode de chiffrement QUIC</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip1\" xml:space=\"preserve\">\n    <value>*type de camouflage tcp</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip2\" xml:space=\"preserve\">\n    <value>*type de camouflage kcp</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip3\" xml:space=\"preserve\">\n    <value>*type de camouflage QUIC</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip4\" xml:space=\"preserve\">\n    <value>*mode gRPC</value>\n  </data>\n  <data name=\"LvTLS\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TransportPathTip5\" xml:space=\"preserve\">\n    <value>*graine Kcp</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeyFailed\" xml:space=\"preserve\">\n    <value>Échec de l’enregistrement du raccourci global {0}, raison : {1}</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeySuccessfully\" xml:space=\"preserve\">\n    <value>Raccourci global {0} enregistré avec succès</value>\n  </data>\n  <data name=\"AllGroupServers\" xml:space=\"preserve\">\n    <value>Tous</value>\n  </data>\n  <data name=\"FillServerAddressCustom\" xml:space=\"preserve\">\n    <value>Parcourir pour importer la configuration</value>\n  </data>\n  <data name=\"Speedtesting\" xml:space=\"preserve\">\n    <value>Test en cours...</value>\n  </data>\n  <data name=\"LabLAN\" xml:space=\"preserve\">\n    <value>Réseau local</value>\n  </data>\n  <data name=\"LabLocal\" xml:space=\"preserve\">\n    <value>Local</value>\n  </data>\n  <data name=\"MsgServerTitle\" xml:space=\"preserve\">\n    <value>Filtre : Entrée pour exécuter</value>\n  </data>\n  <data name=\"menuCheckUpdate\" xml:space=\"preserve\">\n    <value>Rechercher mises à jour</value>\n  </data>\n  <data name=\"menuClose\" xml:space=\"preserve\">\n    <value>Fermer</value>\n  </data>\n  <data name=\"menuExit\" xml:space=\"preserve\">\n    <value>Quitter</value>\n  </data>\n  <data name=\"menuGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Paramètres des raccourcis globaux</value>\n  </data>\n  <data name=\"menuHelp\" xml:space=\"preserve\">\n    <value>Aide</value>\n  </data>\n  <data name=\"menuOptionSetting\" xml:space=\"preserve\">\n    <value>Paramètres config</value>\n  </data>\n  <data name=\"menuPromotion\" xml:space=\"preserve\">\n    <value>Promotion</value>\n  </data>\n  <data name=\"menuReload\" xml:space=\"preserve\">\n    <value>Redémarrer</value>\n  </data>\n  <data name=\"menuRoutingSetting\" xml:space=\"preserve\">\n    <value>Paramètres de routage</value>\n  </data>\n  <data name=\"menuServers\" xml:space=\"preserve\">\n    <value>Fichiers de config</value>\n  </data>\n  <data name=\"menuSetting\" xml:space=\"preserve\">\n    <value>Paramètres</value>\n  </data>\n  <data name=\"menuSubGroupUpdate\" xml:space=\"preserve\">\n    <value>Mettre à jour l’abonnement actuel (sans proxy)</value>\n  </data>\n  <data name=\"menuSubGroupUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Mettre à jour l’abonnement actuel (via le proxy)</value>\n  </data>\n  <data name=\"menuSubscription\" xml:space=\"preserve\">\n    <value>Groupe abonnements</value>\n  </data>\n  <data name=\"menuSubSetting\" xml:space=\"preserve\">\n    <value>Paramètres des groupes d’abonnement</value>\n  </data>\n  <data name=\"menuSubUpdate\" xml:space=\"preserve\">\n    <value>Mettre à jour tous les abonnements (sans proxy)</value>\n  </data>\n  <data name=\"menuSubUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Mettre à jour tous les abonnements (via le proxy)</value>\n  </data>\n  <data name=\"menuSystemproxy\" xml:space=\"preserve\">\n    <value>Proxy système</value>\n  </data>\n  <data name=\"menuSystemProxyClear\" xml:space=\"preserve\">\n    <value>Effacer le proxy système</value>\n  </data>\n  <data name=\"menuSystemProxyNothing\" xml:space=\"preserve\">\n    <value>Ne pas modifier le proxy système</value>\n  </data>\n  <data name=\"menuSystemProxyPac\" xml:space=\"preserve\">\n    <value>Mode PAC</value>\n  </data>\n  <data name=\"menuSystemProxySet\" xml:space=\"preserve\">\n    <value>Configuration auto proxy système</value>\n  </data>\n  <data name=\"TbSettingsColor\" xml:space=\"preserve\">\n    <value>Couleur</value>\n  </data>\n  <data name=\"TbSettingsLanguage\" xml:space=\"preserve\">\n    <value>Langue (redémarrage requis)</value>\n  </data>\n  <data name=\"menuAddServerViaClipboard\" xml:space=\"preserve\">\n    <value>Importer liens depuis le presse-papiers</value>\n  </data>\n  <data name=\"menuAddServerViaScan\" xml:space=\"preserve\">\n    <value>Scanner le QR code à l’écran</value>\n  </data>\n  <data name=\"menuCopyServer\" xml:space=\"preserve\">\n    <value>Cloner la sélection</value>\n  </data>\n  <data name=\"menuRemoveDuplicateServer\" xml:space=\"preserve\">\n    <value>Supprimer les doublons</value>\n  </data>\n  <data name=\"menuRemoveServer\" xml:space=\"preserve\">\n    <value>Supprimer la sélection (multi-sélection)</value>\n  </data>\n  <data name=\"menuSetDefaultServer\" xml:space=\"preserve\">\n    <value>Définir comme actif (Entrée)</value>\n  </data>\n  <data name=\"menuClearServerStatistics\" xml:space=\"preserve\">\n    <value>Effacer toutes les statistiques de service</value>\n  </data>\n  <data name=\"menuRealPingServer\" xml:space=\"preserve\">\n    <value>Tester la latence de connexion réelle (multi-sélect)</value>\n  </data>\n  <data name=\"menuSortServerResult\" xml:space=\"preserve\">\n    <value>Trier selon les résultats de test</value>\n  </data>\n  <data name=\"menuSpeedServer\" xml:space=\"preserve\">\n    <value>Tester la vitesse (multi-sélection)</value>\n  </data>\n  <data name=\"menuTcpingServer\" xml:space=\"preserve\">\n    <value>Tester la latence Tcping (multi-sélection)</value>\n  </data>\n  <data name=\"menuExport2ClientConfig\" xml:space=\"preserve\">\n    <value>Exporter la configuration complète sélectionnée</value>\n  </data>\n  <data name=\"menuExport2ShareUrl\" xml:space=\"preserve\">\n    <value>Exporter les liens de partage vers le presse-papiers (multi-sélection)</value>\n  </data>\n  <data name=\"menuAddCustomServer\" xml:space=\"preserve\">\n    <value>Ajouter une configuration personnalisée</value>\n  </data>\n  <data name=\"menuAddShadowsocksServer\" xml:space=\"preserve\">\n    <value>Ajouter [Shadowsocks]</value>\n  </data>\n  <data name=\"menuAddSocksServer\" xml:space=\"preserve\">\n    <value>Ajouter [SOCKS]</value>\n  </data>\n  <data name=\"menuAddTrojanServer\" xml:space=\"preserve\">\n    <value>Ajouter [Trojan]</value>\n  </data>\n  <data name=\"menuAddVlessServer\" xml:space=\"preserve\">\n    <value>Ajouter [VLESS]</value>\n  </data>\n  <data name=\"menuAddVmessServer\" xml:space=\"preserve\">\n    <value>Ajouter [VMess]</value>\n  </data>\n  <data name=\"menuSelectAll\" xml:space=\"preserve\">\n    <value>Tout sélectionner</value>\n  </data>\n  <data name=\"menuMsgViewClear\" xml:space=\"preserve\">\n    <value>Tout effacer</value>\n  </data>\n  <data name=\"menuMsgViewCopy\" xml:space=\"preserve\">\n    <value>Copier</value>\n  </data>\n  <data name=\"menuMsgViewCopyAll\" xml:space=\"preserve\">\n    <value>Tout copier</value>\n  </data>\n  <data name=\"menuMsgViewSelectAll\" xml:space=\"preserve\">\n    <value>Tout sélect</value>\n  </data>\n  <data name=\"menuSubAdd\" xml:space=\"preserve\">\n    <value>Ajouter</value>\n  </data>\n  <data name=\"menuSubDelete\" xml:space=\"preserve\">\n    <value>Supprimer</value>\n  </data>\n  <data name=\"menuSubEdit\" xml:space=\"preserve\">\n    <value>Éditer</value>\n  </data>\n  <data name=\"menuSubShare\" xml:space=\"preserve\">\n    <value>Partager</value>\n  </data>\n  <data name=\"LvEnabled\" xml:space=\"preserve\">\n    <value>Activer MAJ</value>\n  </data>\n  <data name=\"LvSort\" xml:space=\"preserve\">\n    <value>Tri</value>\n  </data>\n  <data name=\"LvUserAgent\" xml:space=\"preserve\">\n    <value>User-Agent (optionnel)</value>\n  </data>\n  <data name=\"TbCancel\" xml:space=\"preserve\">\n    <value>Annuler</value>\n  </data>\n  <data name=\"TbConfirm\" xml:space=\"preserve\">\n    <value>OK</value>\n  </data>\n  <data name=\"GbTransport\" xml:space=\"preserve\">\n    <value>Méthode de transport sous-jacente (transport)</value>\n  </data>\n  <data name=\"TbAddress\" xml:space=\"preserve\">\n    <value>Adresse (address)</value>\n  </data>\n  <data name=\"TbAllowInsecure\" xml:space=\"preserve\">\n    <value>Ignorer la vérification du certificat (allowInsecure)</value>\n  </data>\n  <data name=\"TbAlpn\" xml:space=\"preserve\">\n    <value>ALPN</value>\n  </data>\n  <data name=\"TbAlterId\" xml:space=\"preserve\">\n    <value>ID supplémentaire (alterId)</value>\n  </data>\n  <data name=\"TbFingerprint\" xml:space=\"preserve\">\n    <value>Empreinte</value>\n  </data>\n  <data name=\"TbHeaderType\" xml:space=\"preserve\">\n    <value>Type de camouflage (type)</value>\n  </data>\n  <data name=\"TbId\" xml:space=\"preserve\">\n    <value>ID utilisateur (id)</value>\n  </data>\n  <data name=\"TbNetwork\" xml:space=\"preserve\">\n    <value>Protocole (network)</value>\n  </data>\n  <data name=\"TbPath\" xml:space=\"preserve\">\n    <value>Chemin (path)</value>\n  </data>\n  <data name=\"TbPort\" xml:space=\"preserve\">\n    <value>Port (port)</value>\n  </data>\n  <data name=\"TbRemarks\" xml:space=\"preserve\">\n    <value>Alias (remarks)</value>\n  </data>\n  <data name=\"TbRequestHost\" xml:space=\"preserve\">\n    <value>Domaine de camouflage (host)</value>\n  </data>\n  <data name=\"TbSecurity\" xml:space=\"preserve\">\n    <value>Méthode de chiffrement (security)</value>\n  </data>\n  <data name=\"TbSNI\" xml:space=\"preserve\">\n    <value>SNI</value>\n  </data>\n  <data name=\"TbStreamSecurity\" xml:space=\"preserve\">\n    <value>Sécurité couche transport (TLS)</value>\n  </data>\n  <data name=\"TipNetwork\" xml:space=\"preserve\">\n    <value>*tcp par défaut ; un mauvais choix bloque la connexion</value>\n  </data>\n  <data name=\"TbCoreType\" xml:space=\"preserve\">\n    <value>Type de Core</value>\n  </data>\n  <data name=\"TbFlow5\" xml:space=\"preserve\">\n    <value>Contrôle de flux (flow)</value>\n  </data>\n  <data name=\"TbGUID\" xml:space=\"preserve\">\n    <value>Générer</value>\n  </data>\n  <data name=\"TbId3\" xml:space=\"preserve\">\n    <value>Mot de passe (password)</value>\n  </data>\n  <data name=\"TbId4\" xml:space=\"preserve\">\n    <value>Mot de passe (optionnel)</value>\n  </data>\n  <data name=\"TbId5\" xml:space=\"preserve\">\n    <value>ID utilisateur (id)</value>\n  </data>\n  <data name=\"TbSecurity3\" xml:space=\"preserve\">\n    <value>Mode chiffrement (encryption)</value>\n  </data>\n  <data name=\"TbSecurity4\" xml:space=\"preserve\">\n    <value>Nom d’utilisateur (optionnel)</value>\n  </data>\n  <data name=\"TbSecurity5\" xml:space=\"preserve\">\n    <value>Mode chiffrement (encryption)</value>\n  </data>\n  <data name=\"TbPreSocksPort\" xml:space=\"preserve\">\n    <value>Port Socks</value>\n  </data>\n  <data name=\"TipPreSocksPort\" xml:space=\"preserve\">\n    <value>*Valeur du port Socks (config perso, optionnelle). Si défini, Xray/sing-box (Tun) démarre un service Socks en amont supplémentaire pour fournir le routage sélectif et l’affichage de la vitesse.</value>\n  </data>\n  <data name=\"TbBrowse\" xml:space=\"preserve\">\n    <value>Parcourir</value>\n  </data>\n  <data name=\"TbEdit\" xml:space=\"preserve\">\n    <value>Éditer</value>\n  </data>\n  <data name=\"TbSettingsAdvancedProtocol\" xml:space=\"preserve\">\n    <value>Paramètres avancés du proxy, choix du protocole (optionnel)</value>\n  </data>\n  <data name=\"TbSettingsAllowLAN\" xml:space=\"preserve\">\n    <value>Autoriser les connexions depuis le LAN</value>\n  </data>\n  <data name=\"TbSettingsAutoHideStartup\" xml:space=\"preserve\">\n    <value>Masquer la fenêtre au démarrage</value>\n  </data>\n  <data name=\"TbSettingsAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Intervalle de mise à jour auto des fichiers Geo (heures)</value>\n  </data>\n  <data name=\"TbSettingsCore\" xml:space=\"preserve\">\n    <value>Core : paramètres de base</value>\n  </data>\n  <data name=\"TbCustomDnsRay\" xml:space=\"preserve\">\n    <value>DNS personnalisé v2ray</value>\n  </data>\n  <data name=\"TbSettingsCoreKcp\" xml:space=\"preserve\">\n    <value>Core : paramètres KCP</value>\n  </data>\n  <data name=\"TbSettingsCoreType\" xml:space=\"preserve\">\n    <value>Paramètres du type de Core</value>\n  </data>\n  <data name=\"TbSettingsDefAllowInsecure\" xml:space=\"preserve\">\n    <value>Ignorer la vérif. du certificat (Dangereux)</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Freedom\" xml:space=\"preserve\">\n    <value>domainStrategy de Freedom (sortant)</value>\n  </data>\n  <data name=\"TbSettingsEnableAutoAdjustMainLvColWidth\" xml:space=\"preserve\">\n    <value>Auto-ajuster la largeur des colonnes après maj. abonnements</value>\n  </data>\n  <data name=\"TbSettingsEnableCheckPreReleaseUpdate\" xml:space=\"preserve\">\n    <value>Vérifier les mises à jour pré-version (à activer avec prudence)</value>\n  </data>\n  <data name=\"TbSettingsException\" xml:space=\"preserve\">\n    <value>Exceptions</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip\" xml:space=\"preserve\">\n    <value>Exceptions : pour les adresses commençant par les caractères ci-dessous, ne pas utiliser le proxy. Séparez par des points-virgules (;).</value>\n  </data>\n  <data name=\"TbSettingsDisplayRealTimeSpeed\" xml:space=\"preserve\">\n    <value>Afficher la vitesse en temps réel (redémarrage requis)</value>\n  </data>\n  <data name=\"TbSettingsKeepOlderDedupl\" xml:space=\"preserve\">\n    <value>À la déduplication, garder l’élément au plus petit numéro</value>\n  </data>\n  <data name=\"TbSettingsLogEnabled\" xml:space=\"preserve\">\n    <value>Activer les journaux</value>\n  </data>\n  <data name=\"TbSettingsLogLevel\" xml:space=\"preserve\">\n    <value>Niveau de journalisation</value>\n  </data>\n  <data name=\"TbSettingsMuxEnabled\" xml:space=\"preserve\">\n    <value>Activer Mux multiplex</value>\n  </data>\n  <data name=\"TbSettingsN\" xml:space=\"preserve\">\n    <value>Paramètres v2rayN</value>\n  </data>\n  <data name=\"TbSettingsPass\" xml:space=\"preserve\">\n    <value>Mot de passe d’authentification</value>\n  </data>\n  <data name=\"TbSettingsRemoteDNS\" xml:space=\"preserve\">\n    <value>DNS perso (plusieurs configurables, séparés par virgules)</value>\n  </data>\n  <data name=\"TbSettingsSetUWP\" xml:space=\"preserve\">\n    <value>Lever la restriction de proxy en boucle locale pour les applications Win10 UWP</value>\n  </data>\n  <data name=\"TbSettingsSniffingEnabled\" xml:space=\"preserve\">\n    <value>Activer le sniffing de trafic</value>\n  </data>\n  <data name=\"TbSettingsSocksPort\" xml:space=\"preserve\">\n    <value>Port d’écoute mixte local</value>\n  </data>\n  <data name=\"TbSettingsStartBoot\" xml:space=\"preserve\">\n    <value>Lancer au démarrage (peut échouer)</value>\n  </data>\n  <data name=\"TbSettingsStatistics\" xml:space=\"preserve\">\n    <value>Activer les statistiques de trafic (redémarrage requis)</value>\n  </data>\n  <data name=\"TbSettingsSubConvert\" xml:space=\"preserve\">\n    <value>URL de conversion d’abonnement (optionnel)</value>\n  </data>\n  <data name=\"TbSettingsSystemproxy\" xml:space=\"preserve\">\n    <value>Paramètres du proxy système</value>\n  </data>\n  <data name=\"TbSettingsTrayMenuServersLimit\" xml:space=\"preserve\">\n    <value>Limite du nombre de configurations affichées dans le menu du plateau</value>\n  </data>\n  <data name=\"TbSettingsUdpEnabled\" xml:space=\"preserve\">\n    <value>Activer l’UDP</value>\n  </data>\n  <data name=\"TbSettingsUser\" xml:space=\"preserve\">\n    <value>Nom d’utilisateur d’authentification</value>\n  </data>\n  <data name=\"TbClearSystemProxy\" xml:space=\"preserve\">\n    <value>Effacer le proxy système</value>\n  </data>\n  <data name=\"TbDisplayGUI\" xml:space=\"preserve\">\n    <value>Afficher l’interface principale</value>\n  </data>\n  <data name=\"TbGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Paramètres des raccourcis globaux</value>\n  </data>\n  <data name=\"TbGlobalHotkeySettingTip\" xml:space=\"preserve\">\n    <value>Appuyez directement sur les touches pour définir ; prendra effet après redémarrage</value>\n  </data>\n  <data name=\"TbNotChangeSystemProxy\" xml:space=\"preserve\">\n    <value>Ne pas modifier le proxy système</value>\n  </data>\n  <data name=\"TbReset\" xml:space=\"preserve\">\n    <value>Réinitialiser</value>\n  </data>\n  <data name=\"TbSetSystemProxy\" xml:space=\"preserve\">\n    <value>Configurer automatiquement le proxy système</value>\n  </data>\n  <data name=\"TbSystemProxyPac\" xml:space=\"preserve\">\n    <value>Mode PAC</value>\n  </data>\n  <data name=\"menuShareServer\" xml:space=\"preserve\">\n    <value>Partager</value>\n  </data>\n  <data name=\"menuRouting\" xml:space=\"preserve\">\n    <value>Routage</value>\n  </data>\n  <data name=\"NotRunAsAdmin\" xml:space=\"preserve\">\n    <value>Exécuter sans droits administrateur</value>\n  </data>\n  <data name=\"RunAsAdmin\" xml:space=\"preserve\">\n    <value>Exécuter en tant qu’administrateur</value>\n  </data>\n  <data name=\"menuMoveBottom\" xml:space=\"preserve\">\n    <value>Déplacer tout en bas</value>\n  </data>\n  <data name=\"menuMoveDown\" xml:space=\"preserve\">\n    <value>Descendre</value>\n  </data>\n  <data name=\"menuMoveTop\" xml:space=\"preserve\">\n    <value>Déplacer tout en haut</value>\n  </data>\n  <data name=\"menuMoveUp\" xml:space=\"preserve\">\n    <value>Monter</value>\n  </data>\n  <data name=\"MsgFilterTitle\" xml:space=\"preserve\">\n    <value>Filtre (regex pris en charge)</value>\n  </data>\n  <data name=\"menuWebsiteItem\" xml:space=\"preserve\">\n    <value>Site officiel de {0}</value>\n  </data>\n  <data name=\"menuRoutingAdvancedAdd\" xml:space=\"preserve\">\n    <value>Ajouter un jeu de règles</value>\n  </data>\n  <data name=\"menuRoutingAdvancedImportRules\" xml:space=\"preserve\">\n    <value>Importer 1-clic du jeu de règles</value>\n  </data>\n  <data name=\"menuRoutingAdvancedRemove\" xml:space=\"preserve\">\n    <value>Suppr. règles sélectionnées</value>\n  </data>\n  <data name=\"menuRoutingAdvancedSetDefault\" xml:space=\"preserve\">\n    <value>Définir comme règles actives (Entrée)</value>\n  </data>\n  <data name=\"TbdomainStrategy\" xml:space=\"preserve\">\n    <value>Stratégie résolution domaine</value>\n  </data>\n  <data name=\"TbRoutingTabRuleList\" xml:space=\"preserve\">\n    <value>Liste des jeux de règles prédef.</value>\n  </data>\n  <data name=\"TbRoutingTips\" xml:space=\"preserve\">\n    <value>*Règles de routage définies, séparées par des virgules (,); remplacez la virgule dans les expressions régulières par &lt;COMMA&gt;</value>\n  </data>\n  <data name=\"menuImportRulesFromClipboard\" xml:space=\"preserve\">\n    <value>Importer règles du presse-papiers</value>\n  </data>\n  <data name=\"menuImportRulesFromFile\" xml:space=\"preserve\">\n    <value>Importer règles depuis fichier</value>\n  </data>\n  <data name=\"menuImportRulesFromUrl\" xml:space=\"preserve\">\n    <value>Importer depuis URL d’abonnement</value>\n  </data>\n  <data name=\"menuRoutingRuleSetting\" xml:space=\"preserve\">\n    <value>Paramètres du jeu de règles</value>\n  </data>\n  <data name=\"menuRuleAdd\" xml:space=\"preserve\">\n    <value>Ajouter une règle</value>\n  </data>\n  <data name=\"menuRuleExportSelected\" xml:space=\"preserve\">\n    <value>Exporter les règles sélectionnées vers le presse-papiers</value>\n  </data>\n  <data name=\"menuRuleList\" xml:space=\"preserve\">\n    <value>Liste des règles</value>\n  </data>\n  <data name=\"menuRuleRemove\" xml:space=\"preserve\">\n    <value>Supprimer les règles sélectionnées</value>\n  </data>\n  <data name=\"menuRoutingRuleDetailsSetting\" xml:space=\"preserve\">\n    <value>Paramètres détaillés des règles de routage</value>\n  </data>\n  <data name=\"TbAutoSort\" xml:space=\"preserve\">\n    <value>Tri automatique par domaine, IP et nom de processus lors de l’enregistrement</value>\n  </data>\n  <data name=\"TbRuleobjectDoc\" xml:space=\"preserve\">\n    <value>Documentation détaillée des règles</value>\n  </data>\n  <data name=\"TbDnsObjectDoc\" xml:space=\"preserve\">\n    <value>Saisie DnsObject prise en charge (format JSON), cliquer pour doc</value>\n  </data>\n  <data name=\"SubUrlTips\" xml:space=\"preserve\">\n    <value>Laissez vide pour les groupes ordinaires</value>\n  </data>\n  <data name=\"TipChangeRouting\" xml:space=\"preserve\">\n    <value>Paramètres de routage modifiés</value>\n  </data>\n  <data name=\"TipChangeSystemProxy\" xml:space=\"preserve\">\n    <value>Paramètres du proxy système modifiés</value>\n  </data>\n  <data name=\"TbSettingsRouteOnly\" xml:space=\"preserve\">\n    <value>Routage uniquement (routeOnly)</value>\n  </data>\n  <data name=\"TbSettingsNotProxyLocalAddress\" xml:space=\"preserve\">\n    <value>Ne pas utiliser le proxy pour les adresses locales (Intranet)</value>\n  </data>\n  <data name=\"menuMixedTestServer\" xml:space=\"preserve\">\n    <value>Tester latence et vitesse multithread en un clic (Ctrl+E)</value>\n  </data>\n  <data name=\"LvTestDelay\" xml:space=\"preserve\">\n    <value>Latence (ms)</value>\n  </data>\n  <data name=\"LvTestSpeed\" xml:space=\"preserve\">\n    <value>Vitesse (Mo/s)</value>\n  </data>\n  <data name=\"FailedToRunCore\" xml:space=\"preserve\">\n    <value>Échec d’exécution du Core, veuillez consulter les messages</value>\n  </data>\n  <data name=\"LvFilter\" xml:space=\"preserve\">\n    <value>Filtrage par alias (regex)</value>\n  </data>\n  <data name=\"TbDisplayLog\" xml:space=\"preserve\">\n    <value>Afficher les logs</value>\n  </data>\n  <data name=\"TbEnableTunAs\" xml:space=\"preserve\">\n    <value>Activer Tun</value>\n  </data>\n  <data name=\"TbSettingsNewPort4LAN\" xml:space=\"preserve\">\n    <value>Ouvrir un nouveau port pour le LAN</value>\n  </data>\n  <data name=\"TbSettingsTunMode\" xml:space=\"preserve\">\n    <value>Paramètres du mode Tun</value>\n  </data>\n  <data name=\"menuMoveToGroup\" xml:space=\"preserve\">\n    <value>Déplacer vers un groupe d’abonnement</value>\n  </data>\n  <data name=\"TbSettingsEnableDragDropSort\" xml:space=\"preserve\">\n    <value>Activer le tri par glisser-déposer des configurations (redémarrage requis)</value>\n  </data>\n  <data name=\"TbAutoRefresh\" xml:space=\"preserve\">\n    <value>Actualisation automatique</value>\n  </data>\n  <data name=\"SpeedtestingSkip\" xml:space=\"preserve\">\n    <value>Ignorer le test</value>\n  </data>\n  <data name=\"menuEditServer\" xml:space=\"preserve\">\n    <value>Éditer</value>\n  </data>\n  <data name=\"TbSettingsDoubleClick2Activate\" xml:space=\"preserve\">\n    <value>Double-cliquer sur l’interface principale pour activer</value>\n  </data>\n  <data name=\"SpeedtestingCompleted\" xml:space=\"preserve\">\n    <value>Test terminé</value>\n  </data>\n  <data name=\"TbSettingsDefFingerprint\" xml:space=\"preserve\">\n    <value>Empreinte TLS par défaut (fingerprint)</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgent\" xml:space=\"preserve\">\n    <value>Agent utilisateur (User-Agent)</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgentTips\" xml:space=\"preserve\">\n    <value>Valable uniquement pour les protocoles tcp/http et ws</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamily\" xml:space=\"preserve\">\n    <value>Police actuelle (redémarrage requis)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyTip\" xml:space=\"preserve\">\n    <value>Copiez les fichiers de police TTF/TTC dans le dossier guiFonts, effet après redémarrage</value>\n  </data>\n  <data name=\"TbSettingsSocksPortTip\" xml:space=\"preserve\">\n    <value>Port PAC = +3 ; port API Xray = +4 ; port API mihomo = +5 ;</value>\n  </data>\n  <data name=\"TbSettingsStartBootTip\" xml:space=\"preserve\">\n    <value>Définir cette option avec des privilèges administrateur pour obtenir les droits admin au démarrage</value>\n  </data>\n  <data name=\"TbSettingsFontSize\" xml:space=\"preserve\">\n    <value>Taille de police</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestTimeout\" xml:space=\"preserve\">\n    <value>Valeur délai d'expiration test vitesse unique</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestUrl\" xml:space=\"preserve\">\n    <value>URL du fichier de test de vitesse</value>\n  </data>\n  <data name=\"menuMoveTo\" xml:space=\"preserve\">\n    <value>Déplacer vers haut/bas</value>\n  </data>\n  <data name=\"TbPublicKey\" xml:space=\"preserve\">\n    <value>PublicKey</value>\n  </data>\n  <data name=\"TbShortId\" xml:space=\"preserve\">\n    <value>ShortId</value>\n  </data>\n  <data name=\"TbSpiderX\" xml:space=\"preserve\">\n    <value>SpiderX</value>\n  </data>\n  <data name=\"TbSettingsEnableHWA\" xml:space=\"preserve\">\n    <value>Activer l’accélération matérielle (redémarrage requis)</value>\n  </data>\n  <data name=\"SpeedtestingWait\" xml:space=\"preserve\">\n    <value>En attente du test...</value>\n  </data>\n  <data name=\"SpeedtestingPressEscToExit\" xml:space=\"preserve\">\n    <value>Appuyer sur Échap pour arrêter</value>\n  </data>\n  <data name=\"TipDisplayLog\" xml:space=\"preserve\">\n    <value>Désactiver cette option si coupure anormale</value>\n  </data>\n  <data name=\"MsgSkipSubscriptionUpdate\" xml:space=\"preserve\">\n    <value>Mise à jour désactivée, abonnement ignoré</value>\n  </data>\n  <data name=\"menuRebootAsAdmin\" xml:space=\"preserve\">\n    <value>Redémarrer en tant qu’administrateur</value>\n  </data>\n  <data name=\"LvMoreUrl\" xml:space=\"preserve\">\n    <value>Adresses suppl. (URL), séparées par des virgules ; la conversion d’abonnement sera désactivée</value>\n  </data>\n  <data name=\"LvAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Intervalle maj. auto (min)</value>\n  </data>\n  <data name=\"TbSettingsLogEnabledToFile\" xml:space=\"preserve\">\n    <value>Activer l’enregistrement des journaux dans un fichier</value>\n  </data>\n  <data name=\"LvConvertTarget\" xml:space=\"preserve\">\n    <value>Type cible conv. d’abonnement</value>\n  </data>\n  <data name=\"LvConvertTargetTip\" xml:space=\"preserve\">\n    <value>Laisser vide si aucune conversion n’est nécessaire</value>\n  </data>\n  <data name=\"menuDNSSetting\" xml:space=\"preserve\">\n    <value>Paramètres DNS</value>\n  </data>\n  <data name=\"TbCustomDnsSingbox\" xml:space=\"preserve\">\n    <value>DNS personnalisé sing-box</value>\n  </data>\n  <data name=\"TbDnsSingboxObjectDoc\" xml:space=\"preserve\">\n    <value>Saisissez la structure JSON DNS ; cliquez pour voir la doc.</value>\n  </data>\n  <data name=\"TbSettingDnsImportDefConfig\" xml:space=\"preserve\">\n    <value>Cliquez pour importer la config DNS par défaut</value>\n  </data>\n  <data name=\"TbdomainStrategy4Singbox\" xml:space=\"preserve\">\n    <value>Stratégie résolution domaine (sing-box)</value>\n  </data>\n  <data name=\"TbSettingsMux4SboxProtocol\" xml:space=\"preserve\">\n    <value>Protocole de multiplexage Mux (sing-box)</value>\n  </data>\n  <data name=\"TbRoutingRuleProcess\" xml:space=\"preserve\">\n    <value>Process (Linux/Windows)</value>\n  </data>\n  <data name=\"TbRoutingRuleIP\" xml:space=\"preserve\">\n    <value>IP ou IP CIDR</value>\n  </data>\n  <data name=\"TbRoutingRuleDomain\" xml:space=\"preserve\">\n    <value>Domaine</value>\n  </data>\n  <data name=\"menuAddHysteria2Server\" xml:space=\"preserve\">\n    <value>Ajouter [Hysteria2]</value>\n  </data>\n  <data name=\"TbSettingsHysteriaBandwidth\" xml:space=\"preserve\">\n    <value>Bande passante maximale Hysteria (Up/Down)</value>\n  </data>\n  <data name=\"TbSettingsUseSystemHosts\" xml:space=\"preserve\">\n    <value>Utiliser les hosts du système</value>\n  </data>\n  <data name=\"menuAddTuicServer\" xml:space=\"preserve\">\n    <value>Ajouter [TUIC]</value>\n  </data>\n  <data name=\"TbHeaderType8\" xml:space=\"preserve\">\n    <value>Algo contrôle congestion</value>\n  </data>\n  <data name=\"LvPrevProfile\" xml:space=\"preserve\">\n    <value>Alias de config du proxy amont</value>\n  </data>\n  <data name=\"LvNextProfile\" xml:space=\"preserve\">\n    <value>Alias de config du proxy aval</value>\n  </data>\n  <data name=\"LvPrevProfileTip\" xml:space=\"preserve\">\n    <value>Assurez-vous que l’alias config existe et est unique</value>\n  </data>\n  <data name=\"TbSettingsTunAutoRoute\" xml:space=\"preserve\">\n    <value>Routage automatique</value>\n  </data>\n  <data name=\"TbSettingsTunStrictRoute\" xml:space=\"preserve\">\n    <value>Routage strict</value>\n  </data>\n  <data name=\"TbSettingsTunStack\" xml:space=\"preserve\">\n    <value>Pile de protocoles</value>\n  </data>\n  <data name=\"TbSettingsTunMtu\" xml:space=\"preserve\">\n    <value>MTU</value>\n  </data>\n  <data name=\"TbSettingsEnableIPv6Address\" xml:space=\"preserve\">\n    <value>Activer IPv6</value>\n  </data>\n  <data name=\"menuAddWireguardServer\" xml:space=\"preserve\">\n    <value>Ajouter [WireGuard]</value>\n  </data>\n  <data name=\"TbPrivateKey\" xml:space=\"preserve\">\n    <value>PrivateKey</value>\n  </data>\n  <data name=\"TbReserved\" xml:space=\"preserve\">\n    <value>Reserved (2,3,4)</value>\n  </data>\n  <data name=\"TbLocalAddress\" xml:space=\"preserve\">\n    <value>Address (IPv4,IPv6)</value>\n  </data>\n  <data name=\"TbPath7\" xml:space=\"preserve\">\n    <value>Mot de passe d’obfuscation (obfs password)</value>\n  </data>\n  <data name=\"TbRuleMatchingTips\" xml:space=\"preserve\">\n    <value>(Domaine ou IP ou nom de processus) avec Port et Protocole et InboundTag =&gt; OutboundTag</value>\n  </data>\n  <data name=\"TbAutoScrollToEnd\" xml:space=\"preserve\">\n    <value>Défilement automatique vers la fin</value>\n  </data>\n  <data name=\"TbSettingsSpeedPingTestUrl\" xml:space=\"preserve\">\n    <value>Adresse de test de connexion réelle</value>\n  </data>\n  <data name=\"SpeedtestingStop\" xml:space=\"preserve\">\n    <value>Arrêt du test en cours...</value>\n  </data>\n  <data name=\"TransportRequestHostTip5\" xml:space=\"preserve\">\n    <value>*Autorité gRPC</value>\n  </data>\n  <data name=\"menuAddHttpServer\" xml:space=\"preserve\">\n    <value>Ajouter [HTTP]</value>\n  </data>\n  <data name=\"TbSettingsEnableFragment\" xml:space=\"preserve\">\n    <value>Activer le fragmentation (Fragment)</value>\n  </data>\n  <data name=\"TbSettingsEnableCacheFile4Sbox\" xml:space=\"preserve\">\n    <value>Activer le fichier de cache de sing-box (fichiers règles)</value>\n  </data>\n  <data name=\"LvCustomRulesetPath4Singbox\" xml:space=\"preserve\">\n    <value>Set de règles sing-box perso</value>\n  </data>\n  <data name=\"NeedRebootTips\" xml:space=\"preserve\">\n    <value>Opération réussie. Veuillez redémarrer l’app via le menu Paramètres.</value>\n  </data>\n  <data name=\"menuOpenTheFileLocation\" xml:space=\"preserve\">\n    <value>Ouvrir l’emplacement du fichier</value>\n  </data>\n  <data name=\"TbSorting\" xml:space=\"preserve\">\n    <value>Tri</value>\n  </data>\n  <data name=\"TbSortingChain\" xml:space=\"preserve\">\n    <value>Chaîne de routage</value>\n  </data>\n  <data name=\"TbSortingDefault\" xml:space=\"preserve\">\n    <value>Par défaut</value>\n  </data>\n  <data name=\"TbSortingDelay\" xml:space=\"preserve\">\n    <value>Latence</value>\n  </data>\n  <data name=\"TbSortingDownSpeed\" xml:space=\"preserve\">\n    <value>Vitesse de téléchargement</value>\n  </data>\n  <data name=\"TbSortingDownTraffic\" xml:space=\"preserve\">\n    <value>Trafic téléchargé</value>\n  </data>\n  <data name=\"TbSortingHost\" xml:space=\"preserve\">\n    <value>Hôte</value>\n  </data>\n  <data name=\"TbSortingName\" xml:space=\"preserve\">\n    <value>Nom</value>\n  </data>\n  <data name=\"TbSortingNetwork\" xml:space=\"preserve\">\n    <value>Réseau</value>\n  </data>\n  <data name=\"TbSortingTime\" xml:space=\"preserve\">\n    <value>Heure</value>\n  </data>\n  <data name=\"TbSortingType\" xml:space=\"preserve\">\n    <value>Type</value>\n  </data>\n  <data name=\"TbSortingUpSpeed\" xml:space=\"preserve\">\n    <value>Vitesse d’envoi</value>\n  </data>\n  <data name=\"TbSortingUpTraffic\" xml:space=\"preserve\">\n    <value>Trafic envoyé</value>\n  </data>\n  <data name=\"TbConnections\" xml:space=\"preserve\">\n    <value>Connexions en cours</value>\n  </data>\n  <data name=\"menuConnectionClose\" xml:space=\"preserve\">\n    <value>Fermer la connexion</value>\n  </data>\n  <data name=\"menuConnectionCloseAll\" xml:space=\"preserve\">\n    <value>Fermer toutes les connexions</value>\n  </data>\n  <data name=\"TbProxies\" xml:space=\"preserve\">\n    <value>Proxies actuels</value>\n  </data>\n  <data name=\"menuRulemode\" xml:space=\"preserve\">\n    <value>Mode règle</value>\n  </data>\n  <data name=\"menuModeDirect\" xml:space=\"preserve\">\n    <value>Direct</value>\n  </data>\n  <data name=\"menuModeGlobal\" xml:space=\"preserve\">\n    <value>Global</value>\n  </data>\n  <data name=\"menuModeNothing\" xml:space=\"preserve\">\n    <value>Suivre la configuration d’origine</value>\n  </data>\n  <data name=\"menuModeRule\" xml:space=\"preserve\">\n    <value>Règle</value>\n  </data>\n  <data name=\"menuProxiesDelaytest\" xml:space=\"preserve\">\n    <value>Test de latence</value>\n  </data>\n  <data name=\"menuProxiesDelaytestPart\" xml:space=\"preserve\">\n    <value>Test de latence partiel actuel</value>\n  </data>\n  <data name=\"menuProxiesReload\" xml:space=\"preserve\">\n    <value>Actualiser</value>\n  </data>\n  <data name=\"menuProxiesSelectActivity\" xml:space=\"preserve\">\n    <value>Définir comme actif (Entrée)</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Out\" xml:space=\"preserve\">\n    <value>Stratégie de résolution par défaut des sortants</value>\n  </data>\n  <data name=\"TbSettingsMainGirdOrientation\" xml:space=\"preserve\">\n    <value>Orientation mise en page principale (redémarrage requis)</value>\n  </data>\n  <data name=\"TbSettingsDomainDNSAddress\" xml:space=\"preserve\">\n    <value>Adresse de résolution de domaine pour sortants</value>\n  </data>\n  <data name=\"menuProfileAutofitColumnWidth\" xml:space=\"preserve\">\n    <value>Ajuster auto. la largeur des colonnes</value>\n  </data>\n  <data name=\"menuExport2ShareUrlBase64\" xml:space=\"preserve\">\n    <value>Exporter les liens de partage en Base64 vers le presse-papiers (multi-sélection)</value>\n  </data>\n  <data name=\"menuExport2ClientConfigClipboard\" xml:space=\"preserve\">\n    <value>Exporter la configuration complète sélectionnée vers le presse-papiers</value>\n  </data>\n  <data name=\"menuShowOrHideMainWindow\" xml:space=\"preserve\">\n    <value>Afficher ou masquer l’interface principale</value>\n  </data>\n  <data name=\"TbPreSocksPort4Sub\" xml:space=\"preserve\">\n    <value>Port Socks config personnalisée</value>\n  </data>\n  <data name=\"menuBackupAndRestore\" xml:space=\"preserve\">\n    <value>Sauvegarder et restaurer</value>\n  </data>\n  <data name=\"menuLocalBackup\" xml:space=\"preserve\">\n    <value>Sauvegarder localement</value>\n  </data>\n  <data name=\"menuLocalRestore\" xml:space=\"preserve\">\n    <value>Restaurer localement</value>\n  </data>\n  <data name=\"menuRemoteBackup\" xml:space=\"preserve\">\n    <value>Sauvegarder à distance (WebDAV)</value>\n  </data>\n  <data name=\"menuRemoteRestore\" xml:space=\"preserve\">\n    <value>Restaurer à distance (WebDAV)</value>\n  </data>\n  <data name=\"menuLocalBackupAndRestore\" xml:space=\"preserve\">\n    <value>Local</value>\n  </data>\n  <data name=\"menuRemoteBackupAndRestore\" xml:space=\"preserve\">\n    <value>Distant (WebDAV)</value>\n  </data>\n  <data name=\"LvWebDavUrl\" xml:space=\"preserve\">\n    <value>Adresse du serveur WebDAV</value>\n  </data>\n  <data name=\"LvWebDavUserName\" xml:space=\"preserve\">\n    <value>Compte WebDAV</value>\n  </data>\n  <data name=\"LvWebDavPassword\" xml:space=\"preserve\">\n    <value>Mot de passe WebDAV</value>\n  </data>\n  <data name=\"LvWebDavCheck\" xml:space=\"preserve\">\n    <value>Vérification de disponibilité WebDAV</value>\n  </data>\n  <data name=\"LvWebDavDirName\" xml:space=\"preserve\">\n    <value>Nom du dossier distant (optionnel)</value>\n  </data>\n  <data name=\"LocalRestoreInvalidZipTips\" xml:space=\"preserve\">\n    <value>Fichier de sauvegarde invalide</value>\n  </data>\n  <data name=\"ConnectionsHostFilterTitle\" xml:space=\"preserve\">\n    <value>Filtre d’hôte</value>\n  </data>\n  <data name=\"TipActiveServer\" xml:space=\"preserve\">\n    <value>Actif</value>\n  </data>\n  <data name=\"TbSettingsGeoFilesSource\" xml:space=\"preserve\">\n    <value>Source des fichiers Geo (optionnel)</value>\n  </data>\n  <data name=\"TbSettingsSrsFilesSource\" xml:space=\"preserve\">\n    <value>Source des fichiers de jeux de règles sing-box (optionnel)</value>\n  </data>\n  <data name=\"UpgradeAppNotExistTip\" xml:space=\"preserve\">\n    <value>L’application d’outil de mise à niveau est introuvable</value>\n  </data>\n  <data name=\"TbSettingsRoutingRulesSource\" xml:space=\"preserve\">\n    <value>Source des jeux de règles de routage (optionnel)</value>\n  </data>\n  <data name=\"menuRegionalPresets\" xml:space=\"preserve\">\n    <value>Réglages régionaux prédéfinis</value>\n  </data>\n  <data name=\"menuRegionalPresetsDefault\" xml:space=\"preserve\">\n    <value>Région par défaut</value>\n  </data>\n  <data name=\"menuRegionalPresetsRussia\" xml:space=\"preserve\">\n    <value>Russie</value>\n  </data>\n  <data name=\"menuRegionalPresetsIran\" xml:space=\"preserve\">\n    <value>Iran</value>\n  </data>\n  <data name=\"TbSettingsChinaUserTip\" xml:space=\"preserve\">\n    <value>Les utilisateurs de Chine peuvent ignorer</value>\n  </data>\n  <data name=\"menuAddServerViaImage\" xml:space=\"preserve\">\n    <value>Scanner le QR code dans l’image</value>\n  </data>\n  <data name=\"InvalidUrlTip\" xml:space=\"preserve\">\n    <value>Adresse (URL) invalide</value>\n  </data>\n  <data name=\"InsecureUrlProtocol\" xml:space=\"preserve\">\n    <value>N’utilisez pas d’adresse d’abonnement HTTP non sécurisée</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyLinuxTip\" xml:space=\"preserve\">\n    <value>Installer la police sur le système, choisir ou saisir son nom, effet après redémarrage</value>\n  </data>\n  <data name=\"menuExitTips\" xml:space=\"preserve\">\n    <value>Voulez-vous vraiment quitter ?</value>\n  </data>\n  <data name=\"LvMemo\" xml:space=\"preserve\">\n    <value>Mémo</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPassword\" xml:space=\"preserve\">\n    <value>Mot de passe sudo système</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPasswordTip\" xml:space=\"preserve\">\n    <value>Le mot de passe sera vérifié en ligne de commande. En cas d’échec ou de dysfonctionnement, redémarrez l’application. Il n’est pas stocké et doit être saisi à chaque redémarrage.</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip5\" xml:space=\"preserve\">\n    <value>*Mode XHTTP</value>\n  </data>\n  <data name=\"TransportExtraTip\" xml:space=\"preserve\">\n    <value>JSON brut XHTTP Extra, format : { XHTTPObject }</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenClose\" xml:space=\"preserve\">\n    <value>Masquer dans la barre d’état à la fermeture de la fenêtre</value>\n  </data>\n  <data name=\"TbSettingsMixedConcurrencyCount\" xml:space=\"preserve\">\n    <value>Niveau de concurrence lors des tests multithread</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip2\" xml:space=\"preserve\">\n    <value>Exceptions : ne pas utiliser le proxy pour ces adresses, séparées par des virgules (,).</value>\n  </data>\n  <data name=\"TbSettingsDestOverride\" xml:space=\"preserve\">\n    <value>Type de détection de trafic</value>\n  </data>\n  <data name=\"TbSettingsSecondLocalPortEnabled\" xml:space=\"preserve\">\n    <value>Activer un second port d’écoute local</value>\n  </data>\n  <data name=\"TbRoutingInboundTagTips\" xml:space=\"preserve\">\n    <value>Socks : port local ; Socks2 : deuxième port local ; Socks3 : port LAN</value>\n  </data>\n  <data name=\"TbSettingsTheme\" xml:space=\"preserve\">\n    <value>Thème</value>\n  </data>\n  <data name=\"menuCopyProxyCmdToClipboard\" xml:space=\"preserve\">\n    <value>Copier la cmd proxy terminal dans le presse-papiers</value>\n  </data>\n  <data name=\"SpeedtestingTestFailedPart\" xml:space=\"preserve\">\n    <value>Recommencer le test des éléments échoués, {0} restants. Appuyez sur Échap pour arrêter...</value>\n  </data>\n  <data name=\"menuTestServerResult\" xml:space=\"preserve\">\n    <value>Selon le résultat des tests</value>\n  </data>\n  <data name=\"menuRemoveInvalidServerResult\" xml:space=\"preserve\">\n    <value>Supprimer les éléments invalides selon résultats tests</value>\n  </data>\n  <data name=\"RemoveInvalidServerResultTip\" xml:space=\"preserve\">\n    <value>{0} résultats de test invalides supprimés.</value>\n  </data>\n  <data name=\"TbPorts7\" xml:space=\"preserve\">\n    <value>Plage de ports sautés</value>\n  </data>\n  <data name=\"TbPorts7Tips\" xml:space=\"preserve\">\n    <value>Écrase le port ; pour plusieurs groupes, séparer par virgules (,)</value>\n  </data>\n  <data name=\"menuExportConfig\" xml:space=\"preserve\">\n    <value>Exporter</value>\n  </data>\n  <data name=\"TbSettingsIPAPIUrl\" xml:space=\"preserve\">\n    <value>Adresse de test d’informations de connexion actuelles</value>\n  </data>\n  <data name=\"TbRuleOutboundTagTip\" xml:space=\"preserve\">\n    <value>Vous pouvez saisir un alias de configuration ; assurez-vous qu’il existe et qu’il est unique</value>\n  </data>\n  <data name=\"SudoIncorrectPasswordTip\" xml:space=\"preserve\">\n    <value>Mot de passe incorrect, veuillez réessayer.</value>\n  </data>\n  <data name=\"TbMldsa65Verify\" xml:space=\"preserve\">\n    <value>Mldsa65Verify</value>\n  </data>\n  <data name=\"menuAddAnytlsServer\" xml:space=\"preserve\">\n    <value>Ajouter [Anytls]</value>\n  </data>\n  <data name=\"TbRemoteDNS\" xml:space=\"preserve\">\n    <value>DNS distant</value>\n  </data>\n  <data name=\"TbDomesticDNS\" xml:space=\"preserve\">\n    <value>DNS direct</value>\n  </data>\n  <data name=\"TbDirectResolveStrategy\" xml:space=\"preserve\">\n    <value>Direct Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategy\" xml:space=\"preserve\">\n    <value>Proxy Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbAddCommonDNSHosts\" xml:space=\"preserve\">\n    <value>Ajouter des hôtes DNS courants</value>\n  </data>\n  <data name=\"TbFakeIP\" xml:space=\"preserve\">\n    <value>FakeIP</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueries\" xml:space=\"preserve\">\n    <value>Bloquer les requêtes SVCB et HTTPS</value>\n  </data>\n  <data name=\"TbDNSHostsConfig\" xml:space=\"preserve\">\n    <value>Hôtes DNS : (« domaine1 ip1 ip2 » une ligne par entrée)</value>\n  </data>\n  <data name=\"ThBasicDNSSettings\" xml:space=\"preserve\">\n    <value>Paramètres DNS de base</value>\n  </data>\n  <data name=\"ThAdvancedDNSSettings\" xml:space=\"preserve\">\n    <value>Paramètres DNS avancés</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPs\" xml:space=\"preserve\">\n    <value>Valider les IP des domaines de la région concernée</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPsDesc\" xml:space=\"preserve\">\n    <value>Après config, les IP renvoyées des domaines régionaux (ex. geosite:cn - geoip:cn) seront vérifiées ; seules les IP attendues seront retournées.</value>\n  </data>\n  <data name=\"TbCustomDNSEnable\" xml:space=\"preserve\">\n    <value>Activer le DNS personnalisé</value>\n  </data>\n  <data name=\"TbCustomDNSEnabledPageInvalid\" xml:space=\"preserve\">\n    <value>DNS personnalisé activé ; la configuration de cette page sera ignorée</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueriesTips\" xml:space=\"preserve\">\n    <value>Une fois activé, bloque les requêtes ECH et de disponibilité HTTP/3</value>\n  </data>\n  <data name=\"FillCorrectConfigTemplateText\" xml:space=\"preserve\">\n    <value>Veuillez saisir un modèle de configuration valide</value>\n  </data>\n  <data name=\"menuFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Paramètres du modèle de config complet</value>\n  </data>\n  <data name=\"TbFullConfigTemplateEnable\" xml:space=\"preserve\">\n    <value>Activer le modèle de config. complet</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Modèle de configuration complet v2ray</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Ajoute seulement la config sortante, routing.balancers et routing.rules.outboundTag. Voir la doc.</value>\n  </data>\n  <data name=\"TbAddProxyProtocolOutboundOnly\" xml:space=\"preserve\">\n    <value>N’ajoutez pas de sorties pour protocoles non-proxy.</value>\n  </data>\n  <data name=\"TbSetUpstreamProxyDetour\" xml:space=\"preserve\">\n    <value>Définir le tag de proxy amont</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Modèle de configuration complet sing-box</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Ajoute uniquement la configuration des sortants et des endpoints ; cliquer pour voir la documentation</value>\n  </data>\n  <data name=\"TbFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Cette fonction s’adresse aux utilisateurs avancés et aux besoins spécifiques. Une fois activée, les paramètres de base du Core, du DNS et du routage sont ignorés. Vous devez vous assurer que la configuration des ports du proxy système, des statistiques de trafic, etc., est correcte — tout est à votre charge.</value>\n  </data>\n  <data name=\"MsgStartParsingSubscription\" xml:space=\"preserve\">\n    <value>Début de l’analyse et du traitement du contenu d’abonnement</value>\n  </data>\n  <data name=\"TbSelectProfile\" xml:space=\"preserve\">\n    <value>Choisir une config.</value>\n  </data>\n  <data name=\"TbFakeIPTips\" xml:space=\"preserve\">\n    <value>Actif globalement par défaut, avec filtre FakeIP intégré ; ne fonctionne que dans sing-box</value>\n  </data>\n  <data name=\"PleaseAddAtLeastOneServer\" xml:space=\"preserve\">\n    <value>Veuillez ajouter au moins une configuration</value>\n  </data>\n  <data name=\"TbConfigTypePolicyGroup\" xml:space=\"preserve\">\n    <value>Groupe de stratégie</value>\n  </data>\n  <data name=\"TbConfigTypeProxyChain\" xml:space=\"preserve\">\n    <value>Chaîne de proxy</value>\n  </data>\n  <data name=\"TbLeastPing\" xml:space=\"preserve\">\n    <value>Latence minimale</value>\n  </data>\n  <data name=\"TbRandom\" xml:space=\"preserve\">\n    <value>Aléatoire</value>\n  </data>\n  <data name=\"TbRoundRobin\" xml:space=\"preserve\">\n    <value>Round Robin</value>\n  </data>\n  <data name=\"TbLeastLoad\" xml:space=\"preserve\">\n    <value>Le plus stable</value>\n  </data>\n  <data name=\"TbPolicyGroupType\" xml:space=\"preserve\">\n    <value>Type de groupe de stratégie</value>\n  </data>\n  <data name=\"menuAddPolicyGroupServer\" xml:space=\"preserve\">\n    <value>Ajouter un groupe de stratégie</value>\n  </data>\n  <data name=\"menuAddProxyChainServer\" xml:space=\"preserve\">\n    <value>Ajouter une chaîne de proxy</value>\n  </data>\n  <data name=\"menuAddChildServer\" xml:space=\"preserve\">\n    <value>Ajouter une sous-configuration</value>\n  </data>\n  <data name=\"menuRemoveChildServer\" xml:space=\"preserve\">\n    <value>Supprimer une sous-configuration</value>\n  </data>\n  <data name=\"menuServerList\" xml:space=\"preserve\">\n    <value>Configuration item 1, Auto add from subscription group</value>\n  </data>\n  <data name=\"TbFallback\" xml:space=\"preserve\">\n    <value>Basculement (failover)</value>\n  </data>\n  <data name=\"MsgCoreNotSupportNetwork\" xml:space=\"preserve\">\n    <value>Le cœur « {0} » ne prend pas en charge le type de réseau « {1} »</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocolTransport\" xml:space=\"preserve\">\n    <value>Le cœur « {0} » ne prend pas en charge le protocole « {1} » avec le mode de transport « {2} »</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Le cœur « {0} » ne prend pas en charge le protocole « {1} »</value>\n  </data>\n  <data name=\"MsgInvalidProperty\" xml:space=\"preserve\">\n    <value>La propriété {0} est invalide, veuillez vérifier</value>\n  </data>\n  <data name=\"MsgNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Protocole « {0} » non pris en charge</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenCloseTip\" xml:space=\"preserve\">\n    <value>Si le système n’a pas de zone de notif., n’activez pas cette option</value>\n  </data>\n  <data name=\"TbRuleType\" xml:space=\"preserve\">\n    <value>Type de règle</value>\n  </data>\n  <data name=\"TbRuleTypeTips\" xml:space=\"preserve\">\n    <value>Des règles peuvent être définies séparément pour Routing et DNS ; ALL les applique aux deux</value>\n  </data>\n  <data name=\"TbBootstrapDNS\" xml:space=\"preserve\">\n    <value>DNS d’amorçage</value>\n  </data>\n  <data name=\"TbBootstrapDNSTips\" xml:space=\"preserve\">\n    <value>Résoudre le nom du serveur DNS ; doit être spécifié en IP</value>\n  </data>\n  <data name=\"menuFastRealPing\" xml:space=\"preserve\">\n    <value>Test 1-clic de latence réelle</value>\n  </data>\n  <data name=\"TbPolicyGroupSubChildTip\" xml:space=\"preserve\">\n    <value>Ajout auto des configs filtrées depuis les groupes d’abonnement</value>\n  </data>\n  <data name=\"TbCertPinning\" xml:space=\"preserve\">\n    <value>Certificate Pinning</value>\n  </data>\n  <data name=\"TbCertPinningTips\" xml:space=\"preserve\">\n    <value>Pinned certificate (fill in either one)\nWhen specified, the certificate will be pinned, and \"Allow Insecure\" will be disabled.\n\nThe \"Get Certificate\" action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA.</value>\n  </data>\n  <data name=\"TbFetchCert\" xml:space=\"preserve\">\n    <value>Obtenir le certificat</value>\n  </data>\n  <data name=\"TbFetchCertChain\" xml:space=\"preserve\">\n    <value>Obtenir la chaîne de certificats</value>\n  </data>\n  <data name=\"ServerNameMustBeValidDomain\" xml:space=\"preserve\">\n    <value>Veuillez définir un domaine valide</value>\n  </data>\n  <data name=\"CertNotSet\" xml:space=\"preserve\">\n    <value>Certificat non configuré</value>\n  </data>\n  <data name=\"CertSet\" xml:space=\"preserve\">\n    <value>Certificat configuré </value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyPacPath\" xml:space=\"preserve\">\n    <value>Chemin fichier PAC personnalisé</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyScriptPath\" xml:space=\"preserve\">\n    <value>Chemin script proxy système personnalisé</value>\n  </data>\n  <data name=\"TbSettingsMacOSShowInDock\" xml:space=\"preserve\">\n    <value>Afficher dans le Dock de macOS (redém. requis)</value>\n  </data>\n  <data name=\"menuServerList2\" xml:space=\"preserve\">\n    <value>Élément de config 2 : choisir et ajouter depuis self-hosted</value>\n  </data>\n  <data name=\"TbEchConfigList\" xml:space=\"preserve\">\n    <value>EchConfigList</value>\n  </data>\n  <data name=\"TbEchForceQuery\" xml:space=\"preserve\">\n    <value>EchForceQuery</value>\n  </data>\n  <data name=\"TbFullCertTips\" xml:space=\"preserve\">\n    <value>Certificat complet (chaîne), format PEM</value>\n  </data>\n  <data name=\"TbCertSha256Tips\" xml:space=\"preserve\">\n    <value>Empreinte du certificat (SHA-256)</value>\n  </data>\n  <data name=\"TbServeStale\" xml:space=\"preserve\">\n    <value>Cache optimiste</value>\n  </data>\n  <data name=\"TbParallelQuery\" xml:space=\"preserve\">\n    <value>Requête parallèle</value>\n  </data>\n  <data name=\"TbDomesticDNSTips\" xml:space=\"preserve\">\n    <value>Par défaut, utilisé uniquement lors du routage pour la résolution.</value>\n  </data>\n  <data name=\"TbRemoteDNSTips\" xml:space=\"preserve\">\n    <value>Par défaut, invoqué uniquement au routage pour la résolution. Vérifiez que le serveur distant peut joindre ce DNS.</value>\n  </data>\n  <data name=\"TbDirectResolveStrategyTips\" xml:space=\"preserve\">\n    <value>Si non défini ou « AsIs », le DNS système est utilisé ; sinon, le module DNS interne est utilisé.</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategyTips\" xml:space=\"preserve\">\n    <value>Si non défini ou « AsIs », la résolution DNS est assurée par le serveur distant ; sinon, le module DNS interne est utilisé.</value>\n  </data>\n  <data name=\"TbHopInt7\" xml:space=\"preserve\">\n    <value>Intervalle de saut de port</value>\n  </data>\n  <data name=\"menuServerListPreview\" xml:space=\"preserve\">\n    <value>Aperçu des sous-config</value>\n  </data>\n  <data name=\"TbFinalmask\" xml:space=\"preserve\">\n    <value>Finalmask</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeWarning\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeError\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} error: {2}. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgGroupCycleDependency\" xml:space=\"preserve\">\n    <value>Group {0} has a cycle dependency on child node {1}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupNoValidChildNode\" xml:space=\"preserve\">\n    <value>Group {0} has no valid child node.</value>\n  </data>\n  <data name=\"MsgRoutingRuleEmptyOutboundTag\" xml:space=\"preserve\">\n    <value>Routing rule {0} has an empty outbound tag. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeNotFound\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} not found. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgSubscriptionPrevProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription previous proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"MsgSubscriptionNextProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription next proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"menuGenGroupServer\" xml:space=\"preserve\">\n    <value>Generate Policy Group</value>\n  </data>\n  <data name=\"menuAllServers\" xml:space=\"preserve\">\n    <value>All configurations</value>\n  </data>\n  <data name=\"menuGenRegionGroup\" xml:space=\"preserve\">\n    <value>Group by Region</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.hu.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BatchExportURLSuccessfully\" xml:space=\"preserve\">\n    <value>Sikeresen exportálta a megosztási linket a vágólapra</value>\n  </data>\n  <data name=\"CheckServerSettings\" xml:space=\"preserve\">\n    <value>Kérjük, először ellenőrizze a konfigurációs beállításokat.</value>\n  </data>\n  <data name=\"ConfigurationFormatIncorrect\" xml:space=\"preserve\">\n    <value>Érvénytelen konfigurációs formátum.</value>\n  </data>\n  <data name=\"CustomServerTips\" xml:space=\"preserve\">\n    <value>Ne feledje, hogy az egyéni konfiguráció teljes mértékben a saját konfigurációjától függ, és nem működik minden beállítással. Ha a rendszerproxyt szeretné használni, kérjük, manuálisan módosítsa a figyelő portot.</value>\n  </data>\n  <data name=\"Downloading\" xml:space=\"preserve\">\n    <value>Letöltés...</value>\n  </data>\n  <data name=\"FailedConversionConfiguration\" xml:space=\"preserve\">\n    <value>Nem sikerült a konfigurációs fájl konvertálása</value>\n  </data>\n  <data name=\"FailedGenDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Nem sikerült az alapértelmezett konfigurációs fájl generálása</value>\n  </data>\n  <data name=\"FailedGetDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Nem sikerült lekérni az alapértelmezett konfigurációt</value>\n  </data>\n  <data name=\"FailedImportedCustomServer\" xml:space=\"preserve\">\n    <value>Nem sikerült importálni az egyéni konfigurációt</value>\n  </data>\n  <data name=\"FailedReadConfiguration\" xml:space=\"preserve\">\n    <value>Nem sikerült olvasni a konfigurációs fájlt</value>\n  </data>\n  <data name=\"FillCorrectServerPort\" xml:space=\"preserve\">\n    <value>Kérjük, adja meg a helyes port formátumot.</value>\n  </data>\n  <data name=\"FillLocalListeningPort\" xml:space=\"preserve\">\n    <value>Kérjük, adja meg a helyi figyelő portot.</value>\n  </data>\n  <data name=\"FillPassword\" xml:space=\"preserve\">\n    <value>Kérjük, adja meg a jelszót.</value>\n  </data>\n  <data name=\"FillServerAddress\" xml:space=\"preserve\">\n    <value>Kérjük, adja meg a címet.</value>\n  </data>\n  <data name=\"FillUUID\" xml:space=\"preserve\">\n    <value>Kérjük, adja meg a felhasználói azonosítót.</value>\n  </data>\n  <data name=\"Incorrectconfiguration\" xml:space=\"preserve\">\n    <value>Ez nem a megfelelő konfiguráció, kérjük, ellenőrizze</value>\n  </data>\n  <data name=\"InitialConfiguration\" xml:space=\"preserve\">\n    <value>Kezdeti konfiguráció</value>\n  </data>\n  <data name=\"IsLatestCore\" xml:space=\"preserve\">\n    <value>{0} {1} már naprakész.</value>\n  </data>\n  <data name=\"IsLatestN\" xml:space=\"preserve\">\n    <value>{0} {1} már naprakész.</value>\n  </data>\n  <data name=\"LvAddress\" xml:space=\"preserve\">\n    <value>Cím</value>\n  </data>\n  <data name=\"LvEncryptionMethod\" xml:space=\"preserve\">\n    <value>Biztonság</value>\n  </data>\n  <data name=\"LvPort\" xml:space=\"preserve\">\n    <value>Port</value>\n  </data>\n  <data name=\"LvServiceType\" xml:space=\"preserve\">\n    <value>Típus</value>\n  </data>\n  <data name=\"LvSubscription\" xml:space=\"preserve\">\n    <value>Előfizetés csoport</value>\n  </data>\n  <data name=\"LvTodayDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Mai letöltési forgalom</value>\n  </data>\n  <data name=\"LvTodayUploadDataAmount\" xml:space=\"preserve\">\n    <value>Mai feltöltési forgalom</value>\n  </data>\n  <data name=\"LvTotalDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Összes letöltési forgalom</value>\n  </data>\n  <data name=\"LvTotalUploadDataAmount\" xml:space=\"preserve\">\n    <value>Összes feltöltési forgalom</value>\n  </data>\n  <data name=\"LvTransportProtocol\" xml:space=\"preserve\">\n    <value>Szállítás</value>\n  </data>\n  <data name=\"MsgDownloadV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>A Core sikeresen letöltve</value>\n  </data>\n  <data name=\"MsgFailedImportSubscription\" xml:space=\"preserve\">\n    <value>Nem sikerült importálni az előfizetés tartalmát</value>\n  </data>\n  <data name=\"MsgGetSubscriptionSuccessfully\" xml:space=\"preserve\">\n    <value>Az előfizetés tartalma sikeresen lekérve</value>\n  </data>\n  <data name=\"MsgNoValidSubscription\" xml:space=\"preserve\">\n    <value>Nincs érvényes előfizetés beállítva</value>\n  </data>\n  <data name=\"MsgParsingSuccessfully\" xml:space=\"preserve\">\n    <value>Resolved {0} successfully</value>\n  </data>\n  <data name=\"MsgStartGettingSubscriptions\" xml:space=\"preserve\">\n    <value>Előfizetések lekérdezése elindult</value>\n  </data>\n  <data name=\"MsgStartUpdating\" xml:space=\"preserve\">\n    <value>Frissítés indítása: {0}...</value>\n  </data>\n  <data name=\"MsgSubscriptionDecodingFailed\" xml:space=\"preserve\">\n    <value>Érvénytelen előfizetés tartalom</value>\n  </data>\n  <data name=\"MsgUnpacking\" xml:space=\"preserve\">\n    <value>Kicsomagolás...</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionEnd\" xml:space=\"preserve\">\n    <value>Előfizetés frissítése befejeződött</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionStart\" xml:space=\"preserve\">\n    <value>Előfizetés frissítése elindult</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>A Core sikeresen frissítve</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfullyMore\" xml:space=\"preserve\">\n    <value>A Core sikeresen frissítve! Szolgáltatás újraindítása...</value>\n  </data>\n  <data name=\"NonvmessOrssProtocol\" xml:space=\"preserve\">\n    <value>Nem VMess vagy SS protokoll</value>\n  </data>\n  <data name=\"NotFoundCore\" xml:space=\"preserve\">\n    <value>A Core fájl (fájlnév: {1}) nem található a mappában ({0}), kérjük, töltse le és helyezze a mappába, letöltési cím: {2}</value>\n  </data>\n  <data name=\"NoValidQRcodeFound\" xml:space=\"preserve\">\n    <value>Szkennelés befejeződött, nem található érvényes QR kód</value>\n  </data>\n  <data name=\"OperationFailed\" xml:space=\"preserve\">\n    <value>Művelet sikertelen, kérjük, ellenőrizze és próbálja újra</value>\n  </data>\n  <data name=\"PleaseFillRemarks\" xml:space=\"preserve\">\n    <value>Kérjük, töltse ki a megjegyzéseket</value>\n  </data>\n  <data name=\"PleaseSelectEncryption\" xml:space=\"preserve\">\n    <value>Kérjük, válassza ki a titkosítási módszert</value>\n  </data>\n  <data name=\"PleaseSelectProtocol\" xml:space=\"preserve\">\n    <value>Kérjük, válassza ki a protokollt</value>\n  </data>\n  <data name=\"PleaseSelectServer\" xml:space=\"preserve\">\n    <value>Kérjük, először válassza ki a konfigurációt</value>\n  </data>\n  <data name=\"RemoveDuplicateServerResult\" xml:space=\"preserve\">\n    <value>Konfigurációk deduplikálása befejeződött. Régi: {0}, Új: {1}.</value>\n  </data>\n  <data name=\"RemoveServer\" xml:space=\"preserve\">\n    <value>Biztosan eltávolítja a konfigurációt?</value>\n  </data>\n  <data name=\"SaveClientConfigurationIn\" xml:space=\"preserve\">\n    <value>Az ügyfélkonfigurációs fájl mentése itt: {0}</value>\n  </data>\n  <data name=\"StartService\" xml:space=\"preserve\">\n    <value>Szolgáltatás indítása ({0})...</value>\n  </data>\n  <data name=\"SuccessfulConfiguration\" xml:space=\"preserve\">\n    <value>Konfiguráció sikeres. {0}</value>\n  </data>\n  <data name=\"SuccessfullyImportedCustomServer\" xml:space=\"preserve\">\n    <value>Egyéni konfiguráció sikeresen importálva</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaClipboard\" xml:space=\"preserve\">\n    <value>{0} konfiguráció importálva a vágólapról</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaScan\" xml:space=\"preserve\">\n    <value>Sikeresen beolvasta és importálta a megosztott linket</value>\n  </data>\n  <data name=\"TestMeOutput\" xml:space=\"preserve\">\n    <value>A késleltetés: {0} ms, {1}</value>\n  </data>\n  <data name=\"OperationSuccess\" xml:space=\"preserve\">\n    <value>Művelet sikeres</value>\n  </data>\n  <data name=\"PleaseSelectRules\" xml:space=\"preserve\">\n    <value>Kérjük, válasszon szabályokat</value>\n  </data>\n  <data name=\"RemoveRules\" xml:space=\"preserve\">\n    <value>Biztosan eltávolítja a szabályokat?</value>\n  </data>\n  <data name=\"RoutingRuleDetailRequiredTips\" xml:space=\"preserve\">\n    <value>{0}, az egyik kötelező mező.</value>\n  </data>\n  <data name=\"LvRemarks\" xml:space=\"preserve\">\n    <value>Megjegyzések</value>\n  </data>\n  <data name=\"LvUrl\" xml:space=\"preserve\">\n    <value>URL (opcionális)</value>\n  </data>\n  <data name=\"LvCount\" xml:space=\"preserve\">\n    <value>Darabszám</value>\n  </data>\n  <data name=\"MsgNeedUrl\" xml:space=\"preserve\">\n    <value>Kérjük, adja meg az URL-t</value>\n  </data>\n  <data name=\"AddBatchRoutingRulesYesNo\" xml:space=\"preserve\">\n    <value>Hozzá szeretne fűzni szabályokat? Igen a hozzáfűzéshez, nem a cseréhez.</value>\n  </data>\n  <data name=\"MsgDownloadGeoFileSuccessfully\" xml:space=\"preserve\">\n    <value>A GeoFile: {0} sikeresen letöltve</value>\n  </data>\n  <data name=\"MsgInformationTitle\" xml:space=\"preserve\">\n    <value>Információ</value>\n  </data>\n  <data name=\"LvCustomIcon\" xml:space=\"preserve\">\n    <value>Egyéni ikon</value>\n  </data>\n  <data name=\"FillCorrectDNSText\" xml:space=\"preserve\">\n    <value>Kérjük, töltse ki a helyes egyéni DNS-t</value>\n  </data>\n  <data name=\"TransportPathTip1\" xml:space=\"preserve\">\n    <value>*ws/http upgrade/xhttp elérési út</value>\n  </data>\n  <data name=\"TransportPathTip2\" xml:space=\"preserve\">\n    <value>*h2 elérési út</value>\n  </data>\n  <data name=\"TransportPathTip3\" xml:space=\"preserve\">\n    <value>*QUIC kulcs/KCP seed</value>\n  </data>\n  <data name=\"TransportPathTip4\" xml:space=\"preserve\">\n    <value>*grpc szolgáltatásnév</value>\n  </data>\n  <data name=\"TransportRequestHostTip1\" xml:space=\"preserve\">\n    <value>*http host vesszővel elválasztva (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip2\" xml:space=\"preserve\">\n    <value>*ws/http upgrade/xhttp host</value>\n  </data>\n  <data name=\"TransportRequestHostTip3\" xml:space=\"preserve\">\n    <value>*h2 host vesszővel elválasztva (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip4\" xml:space=\"preserve\">\n    <value>*QUIC biztonság</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip1\" xml:space=\"preserve\">\n    <value>*tcp álcázási típus</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip2\" xml:space=\"preserve\">\n    <value>*kcp álcázási típus</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip3\" xml:space=\"preserve\">\n    <value>*QUIC álcázási típus</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip4\" xml:space=\"preserve\">\n    <value>*grpc mód</value>\n  </data>\n  <data name=\"LvTLS\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TransportPathTip5\" xml:space=\"preserve\">\n    <value>*kcp seed</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeyFailed\" xml:space=\"preserve\">\n    <value>Globális gyorsbillentyű {0} regisztrációja sikertelen, ok: {1}</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeySuccessfully\" xml:space=\"preserve\">\n    <value>Globális gyorsbillentyű {0} sikeresen regisztrálva</value>\n  </data>\n  <data name=\"AllGroupServers\" xml:space=\"preserve\">\n    <value>Összes</value>\n  </data>\n  <data name=\"FillServerAddressCustom\" xml:space=\"preserve\">\n    <value>Kérjük, tallózzon a konfiguráció importálásához</value>\n  </data>\n  <data name=\"Speedtesting\" xml:space=\"preserve\">\n    <value>Tesztelés...</value>\n  </data>\n  <data name=\"LabLAN\" xml:space=\"preserve\">\n    <value>LAN</value>\n  </data>\n  <data name=\"LabLocal\" xml:space=\"preserve\">\n    <value>Helyi</value>\n  </data>\n  <data name=\"MsgServerTitle\" xml:space=\"preserve\">\n    <value>Konfigurációs szűrő, Enter billentyűvel végrehajtható</value>\n  </data>\n  <data name=\"menuCheckUpdate\" xml:space=\"preserve\">\n    <value>Frissítés ellenőrzése</value>\n  </data>\n  <data name=\"menuClose\" xml:space=\"preserve\">\n    <value>Bezárás</value>\n  </data>\n  <data name=\"menuExit\" xml:space=\"preserve\">\n    <value>Kilépés</value>\n  </data>\n  <data name=\"menuGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Globális gyorsbillentyű beállítás</value>\n  </data>\n  <data name=\"menuHelp\" xml:space=\"preserve\">\n    <value>Súgó</value>\n  </data>\n  <data name=\"menuOptionSetting\" xml:space=\"preserve\">\n    <value>Opció beállítás</value>\n  </data>\n  <data name=\"menuPromotion\" xml:space=\"preserve\">\n    <value>Promóció</value>\n  </data>\n  <data name=\"menuReload\" xml:space=\"preserve\">\n    <value>Újratöltés</value>\n  </data>\n  <data name=\"menuRoutingSetting\" xml:space=\"preserve\">\n    <value>Útválasztási beállítás</value>\n  </data>\n  <data name=\"menuServers\" xml:space=\"preserve\">\n    <value>Konfigurációk</value>\n  </data>\n  <data name=\"menuSetting\" xml:space=\"preserve\">\n    <value>Beállítások</value>\n  </data>\n  <data name=\"menuSubGroupUpdate\" xml:space=\"preserve\">\n    <value>Aktuális előfizetés frissítése proxy nélkül</value>\n  </data>\n  <data name=\"menuSubGroupUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Aktuális előfizetés frissítése proxyval</value>\n  </data>\n  <data name=\"menuSubscription\" xml:space=\"preserve\">\n    <value>Előfizetési csoport</value>\n  </data>\n  <data name=\"menuSubSetting\" xml:space=\"preserve\">\n    <value>Előfizetési csoport beállításai</value>\n  </data>\n  <data name=\"menuSubUpdate\" xml:space=\"preserve\">\n    <value>Előfizetések frissítése proxy nélkül</value>\n  </data>\n  <data name=\"menuSubUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Előfizetések frissítése proxyval</value>\n  </data>\n  <data name=\"menuSystemproxy\" xml:space=\"preserve\">\n    <value>Rendszerproxy</value>\n  </data>\n  <data name=\"menuSystemProxyClear\" xml:space=\"preserve\">\n    <value>Rendszerproxy törlése</value>\n  </data>\n  <data name=\"menuSystemProxyNothing\" xml:space=\"preserve\">\n    <value>Ne változtassa meg a rendszerproxyt</value>\n  </data>\n  <data name=\"menuSystemProxyPac\" xml:space=\"preserve\">\n    <value>PAC mód</value>\n  </data>\n  <data name=\"menuSystemProxySet\" xml:space=\"preserve\">\n    <value>Rendszerproxy beállítása</value>\n  </data>\n  <data name=\"TbSettingsColor\" xml:space=\"preserve\">\n    <value>Szín</value>\n  </data>\n  <data name=\"TbSettingsLanguage\" xml:space=\"preserve\">\n    <value>Nyelv (Újraindítás)</value>\n  </data>\n  <data name=\"menuAddServerViaClipboard\" xml:space=\"preserve\">\n    <value>Megosztási linkek importálása vágólapról</value>\n  </data>\n  <data name=\"menuAddServerViaScan\" xml:space=\"preserve\">\n    <value>QR kód beolvasása a képernyőről</value>\n  </data>\n  <data name=\"menuCopyServer\" xml:space=\"preserve\">\n    <value>Kijelölt konfiguráció klónozása</value>\n  </data>\n  <data name=\"menuRemoveDuplicateServer\" xml:space=\"preserve\">\n    <value>Ismétlődő konfigurációk eltávolítása</value>\n  </data>\n  <data name=\"menuRemoveServer\" xml:space=\"preserve\">\n    <value>Kijelölt konfigurációk eltávolítása</value>\n  </data>\n  <data name=\"menuSetDefaultServer\" xml:space=\"preserve\">\n    <value>Beállítás aktív konfigurációként</value>\n  </data>\n  <data name=\"menuClearServerStatistics\" xml:space=\"preserve\">\n    <value>Összes szolgáltatás statisztika törlése</value>\n  </data>\n  <data name=\"menuRealPingServer\" xml:space=\"preserve\">\n    <value>Konfigurációk valós késleltetésének tesztelése</value>\n  </data>\n  <data name=\"menuSortServerResult\" xml:space=\"preserve\">\n    <value>Rendezés teszteredmény szerint</value>\n  </data>\n  <data name=\"menuSpeedServer\" xml:space=\"preserve\">\n    <value>Konfigurációk letöltési sebességének tesztelése</value>\n  </data>\n  <data name=\"menuTcpingServer\" xml:space=\"preserve\">\n    <value>Konfigurációk tesztelése tcpinggel</value>\n  </data>\n  <data name=\"menuExport2ClientConfig\" xml:space=\"preserve\">\n    <value>Kijelölt konfiguráció exportálása teljes konfigurációként</value>\n  </data>\n  <data name=\"menuExport2ShareUrl\" xml:space=\"preserve\">\n    <value>Megosztási link exportálása vágólapra</value>\n  </data>\n  <data name=\"menuAddCustomServer\" xml:space=\"preserve\">\n    <value>Egyéni konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"menuAddShadowsocksServer\" xml:space=\"preserve\">\n    <value>[Shadowsocks] konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"menuAddSocksServer\" xml:space=\"preserve\">\n    <value>[SOCKS] konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"menuAddTrojanServer\" xml:space=\"preserve\">\n    <value>[Trojan] konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"menuAddVlessServer\" xml:space=\"preserve\">\n    <value>[VLESS] konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"menuAddVmessServer\" xml:space=\"preserve\">\n    <value>[VMess] konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"menuSelectAll\" xml:space=\"preserve\">\n    <value>Összes kijelölése</value>\n  </data>\n  <data name=\"menuMsgViewClear\" xml:space=\"preserve\">\n    <value>Összes törlése</value>\n  </data>\n  <data name=\"menuMsgViewCopy\" xml:space=\"preserve\">\n    <value>Másolás</value>\n  </data>\n  <data name=\"menuMsgViewCopyAll\" xml:space=\"preserve\">\n    <value>Összes másolása</value>\n  </data>\n  <data name=\"menuMsgViewSelectAll\" xml:space=\"preserve\">\n    <value>Összes kijelölése</value>\n  </data>\n  <data name=\"menuSubAdd\" xml:space=\"preserve\">\n    <value>Hozzáadás</value>\n  </data>\n  <data name=\"menuSubDelete\" xml:space=\"preserve\">\n    <value>Törlés</value>\n  </data>\n  <data name=\"menuSubEdit\" xml:space=\"preserve\">\n    <value>Szerkesztés</value>\n  </data>\n  <data name=\"menuSubShare\" xml:space=\"preserve\">\n    <value>Megosztás</value>\n  </data>\n  <data name=\"LvEnabled\" xml:space=\"preserve\">\n    <value>Frissítés engedélyezése</value>\n  </data>\n  <data name=\"LvSort\" xml:space=\"preserve\">\n    <value>Rendezés</value>\n  </data>\n  <data name=\"LvUserAgent\" xml:space=\"preserve\">\n    <value>User Agent</value>\n  </data>\n  <data name=\"TbCancel\" xml:space=\"preserve\">\n    <value>Mégsem</value>\n  </data>\n  <data name=\"TbConfirm\" xml:space=\"preserve\">\n    <value>Megerősítés</value>\n  </data>\n  <data name=\"GbTransport\" xml:space=\"preserve\">\n    <value>Szállítás</value>\n  </data>\n  <data name=\"TbAddress\" xml:space=\"preserve\">\n    <value>Cím</value>\n  </data>\n  <data name=\"TbAllowInsecure\" xml:space=\"preserve\">\n    <value>Nem biztonságos engedélyezése</value>\n  </data>\n  <data name=\"TbAlpn\" xml:space=\"preserve\">\n    <value>ALPN</value>\n  </data>\n  <data name=\"TbAlterId\" xml:space=\"preserve\">\n    <value>Alter ID</value>\n  </data>\n  <data name=\"TbFingerprint\" xml:space=\"preserve\">\n    <value>Ujjlenyomat</value>\n  </data>\n  <data name=\"TbHeaderType\" xml:space=\"preserve\">\n    <value>Álcázási típus</value>\n  </data>\n  <data name=\"TbId\" xml:space=\"preserve\">\n    <value>UUID(id)</value>\n  </data>\n  <data name=\"TbNetwork\" xml:space=\"preserve\">\n    <value>Szállítási protokoll(hálózat)</value>\n  </data>\n  <data name=\"TbPath\" xml:space=\"preserve\">\n    <value>Elérési út</value>\n  </data>\n  <data name=\"TbPort\" xml:space=\"preserve\">\n    <value>Port</value>\n  </data>\n  <data name=\"TbRemarks\" xml:space=\"preserve\">\n    <value>Alias (megjegyzések)</value>\n  </data>\n  <data name=\"TbRequestHost\" xml:space=\"preserve\">\n    <value>Álcázási tartomány(host)</value>\n  </data>\n  <data name=\"TbSecurity\" xml:space=\"preserve\">\n    <value>Titkosítási módszer (biztonság)</value>\n  </data>\n  <data name=\"TbSNI\" xml:space=\"preserve\">\n    <value>SNI</value>\n  </data>\n  <data name=\"TbStreamSecurity\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TipNetwork\" xml:space=\"preserve\">\n    <value>*Alapértelmezett érték tcp</value>\n  </data>\n  <data name=\"TbCoreType\" xml:space=\"preserve\">\n    <value>Core Típus</value>\n  </data>\n  <data name=\"TbFlow5\" xml:space=\"preserve\">\n    <value>Flow</value>\n  </data>\n  <data name=\"TbGUID\" xml:space=\"preserve\">\n    <value>Generálás</value>\n  </data>\n  <data name=\"TbId3\" xml:space=\"preserve\">\n    <value>Jelszó</value>\n  </data>\n  <data name=\"TbId4\" xml:space=\"preserve\">\n    <value>Jelszó(Opcionális)</value>\n  </data>\n  <data name=\"TbId5\" xml:space=\"preserve\">\n    <value>UUID(id)</value>\n  </data>\n  <data name=\"TbSecurity3\" xml:space=\"preserve\">\n    <value>Titkosítás</value>\n  </data>\n  <data name=\"TbSecurity4\" xml:space=\"preserve\">\n    <value>Felhasználó(Opcionális)</value>\n  </data>\n  <data name=\"TbSecurity5\" xml:space=\"preserve\">\n    <value>Titkosítás</value>\n  </data>\n  <data name=\"TbPreSocksPort\" xml:space=\"preserve\">\n    <value>Socks port</value>\n  </data>\n  <data name=\"TipPreSocksPort\" xml:space=\"preserve\">\n    <value>* A beállítás után egy socks szolgáltatás indul az Xray/sing-box(Tun) segítségével, hogy olyan funkciókat biztosítson, mint a sebességkijelzés</value>\n  </data>\n  <data name=\"TbBrowse\" xml:space=\"preserve\">\n    <value>Tallózás</value>\n  </data>\n  <data name=\"TbEdit\" xml:space=\"preserve\">\n    <value>Szerkesztés</value>\n  </data>\n  <data name=\"TbSettingsAdvancedProtocol\" xml:space=\"preserve\">\n    <value>Haladó proxy beállítások, protokoll kiválasztása (opcionális)</value>\n  </data>\n  <data name=\"TbSettingsAllowLAN\" xml:space=\"preserve\">\n    <value>Kapcsolatok engedélyezése a LAN-ról</value>\n  </data>\n  <data name=\"TbSettingsAutoHideStartup\" xml:space=\"preserve\">\n    <value>Automatikus elrejtés indításkor</value>\n  </data>\n  <data name=\"TbSettingsAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Geo fájlok automatikus frissítési intervalluma (órák)</value>\n  </data>\n  <data name=\"TbSettingsCore\" xml:space=\"preserve\">\n    <value>Core: alapbeállítások</value>\n  </data>\n  <data name=\"TbCustomDnsRay\" xml:space=\"preserve\">\n    <value>V2ray Custom DNS</value>\n  </data>\n  <data name=\"TbSettingsCoreKcp\" xml:space=\"preserve\">\n    <value>Core: KCP beállítások</value>\n  </data>\n  <data name=\"TbSettingsCoreType\" xml:space=\"preserve\">\n    <value>Core Típus beállítások</value>\n  </data>\n  <data name=\"TbSettingsDefAllowInsecure\" xml:space=\"preserve\">\n    <value>Nem biztonságos engedélyezése</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Freedom\" xml:space=\"preserve\">\n    <value>Kimenő Freedom tartomány stratégia</value>\n  </data>\n  <data name=\"TbSettingsEnableAutoAdjustMainLvColWidth\" xml:space=\"preserve\">\n    <value>Oszlopszélesség automatikus beállítása előfizetés frissítése után</value>\n  </data>\n  <data name=\"TbSettingsEnableCheckPreReleaseUpdate\" xml:space=\"preserve\">\n    <value>Előzetes kiadás frissítések ellenőrzése</value>\n  </data>\n  <data name=\"TbSettingsException\" xml:space=\"preserve\">\n    <value>Kivétel</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip\" xml:space=\"preserve\">\n    <value>Kivételek: Ne használjon proxy szervert a következő címmel kezdődő címekhez. Pontosvesszővel (;) válassza el a bejegyzéseket.</value>\n  </data>\n  <data name=\"TbSettingsDisplayRealTimeSpeed\" xml:space=\"preserve\">\n    <value>Valós idejű sebesség megjelenítése (újraindítást igényel)</value>\n  </data>\n  <data name=\"TbSettingsKeepOlderDedupl\" xml:space=\"preserve\">\n    <value>Régebbi bejegyzések megtartása deduplikáláskor</value>\n  </data>\n  <data name=\"TbSettingsLogEnabled\" xml:space=\"preserve\">\n    <value>Naplózás engedélyezése</value>\n  </data>\n  <data name=\"TbSettingsLogLevel\" xml:space=\"preserve\">\n    <value>Naplózási szint</value>\n  </data>\n  <data name=\"TbSettingsMuxEnabled\" xml:space=\"preserve\">\n    <value>Mux Multiplexing bekapcsolása</value>\n  </data>\n  <data name=\"TbSettingsN\" xml:space=\"preserve\">\n    <value>v2rayN beállítások</value>\n  </data>\n  <data name=\"TbSettingsPass\" xml:space=\"preserve\">\n    <value>Hitelesítési jelszó</value>\n  </data>\n  <data name=\"TbSettingsRemoteDNS\" xml:space=\"preserve\">\n    <value>Egyéni DNS (több, vesszővel (,) elválasztva)</value>\n  </data>\n  <data name=\"TbSettingsSetUWP\" xml:space=\"preserve\">\n    <value>Win10 UWP Loopback beállítása</value>\n  </data>\n  <data name=\"TbSettingsSniffingEnabled\" xml:space=\"preserve\">\n    <value>Sniffing bekapcsolása</value>\n  </data>\n  <data name=\"TbSettingsSocksPort\" xml:space=\"preserve\">\n    <value>Vegyes port</value>\n  </data>\n  <data name=\"TbSettingsStartBoot\" xml:space=\"preserve\">\n    <value>Indítás rendszerindításkor</value>\n  </data>\n  <data name=\"TbSettingsStatistics\" xml:space=\"preserve\">\n    <value>Forgalmi statisztikák engedélyezése (újraindítást igényel)</value>\n  </data>\n  <data name=\"TbSettingsSubConvert\" xml:space=\"preserve\">\n    <value>Előfizetés konverziós URL</value>\n  </data>\n  <data name=\"TbSettingsSystemproxy\" xml:space=\"preserve\">\n    <value>Rendszerproxy beállítások</value>\n  </data>\n  <data name=\"TbSettingsTrayMenuServersLimit\" xml:space=\"preserve\">\n    <value>Tálca jobb egérgombos menü konfigurációk megjelenítési limitje</value>\n  </data>\n  <data name=\"TbSettingsUdpEnabled\" xml:space=\"preserve\">\n    <value>UDP engedélyezése</value>\n  </data>\n  <data name=\"TbSettingsUser\" xml:space=\"preserve\">\n    <value>Hitelesítési felhasználó</value>\n  </data>\n  <data name=\"TbClearSystemProxy\" xml:space=\"preserve\">\n    <value>Rendszerproxy törlése</value>\n  </data>\n  <data name=\"TbDisplayGUI\" xml:space=\"preserve\">\n    <value>GUI megjelenítése</value>\n  </data>\n  <data name=\"TbGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Globális gyorsbillentyű beállítások</value>\n  </data>\n  <data name=\"TbGlobalHotkeySettingTip\" xml:space=\"preserve\">\n    <value>Közvetlenül beállítható billentyűnyomással; újraindítás után lép életbe</value>\n  </data>\n  <data name=\"TbNotChangeSystemProxy\" xml:space=\"preserve\">\n    <value>Ne változtassa meg a rendszerproxyt</value>\n  </data>\n  <data name=\"TbReset\" xml:space=\"preserve\">\n    <value>Visszaállítás</value>\n  </data>\n  <data name=\"TbSetSystemProxy\" xml:space=\"preserve\">\n    <value>Rendszerproxy beállítása</value>\n  </data>\n  <data name=\"TbSystemProxyPac\" xml:space=\"preserve\">\n    <value>PAC mód</value>\n  </data>\n  <data name=\"menuShareServer\" xml:space=\"preserve\">\n    <value>Konfiguráció megosztása</value>\n  </data>\n  <data name=\"menuRouting\" xml:space=\"preserve\">\n    <value>Útválasztás</value>\n  </data>\n  <data name=\"NotRunAsAdmin\" xml:space=\"preserve\">\n    <value>Nem rendszergazdaként fut</value>\n  </data>\n  <data name=\"RunAsAdmin\" xml:space=\"preserve\">\n    <value>Futtatás rendszergazdaként</value>\n  </data>\n  <data name=\"menuMoveBottom\" xml:space=\"preserve\">\n    <value>Mozgatás alulra</value>\n  </data>\n  <data name=\"menuMoveDown\" xml:space=\"preserve\">\n    <value>Le</value>\n  </data>\n  <data name=\"menuMoveTop\" xml:space=\"preserve\">\n    <value>Mozgatás felülre</value>\n  </data>\n  <data name=\"menuMoveUp\" xml:space=\"preserve\">\n    <value>Fel</value>\n  </data>\n  <data name=\"MsgFilterTitle\" xml:space=\"preserve\">\n    <value>Szűrő, támogatja a reguláris kifejezéseket</value>\n  </data>\n  <data name=\"menuWebsiteItem\" xml:space=\"preserve\">\n    <value>{0} Weboldal</value>\n  </data>\n  <data name=\"menuRoutingAdvancedAdd\" xml:space=\"preserve\">\n    <value>Hozzáadás</value>\n  </data>\n  <data name=\"menuRoutingAdvancedImportRules\" xml:space=\"preserve\">\n    <value>Szabályok importálása</value>\n  </data>\n  <data name=\"menuRoutingAdvancedRemove\" xml:space=\"preserve\">\n    <value>Kijelölt eltávolítása</value>\n  </data>\n  <data name=\"menuRoutingAdvancedSetDefault\" xml:space=\"preserve\">\n    <value>Beállítás aktív szabályként</value>\n  </data>\n  <data name=\"TbdomainStrategy\" xml:space=\"preserve\">\n    <value>Tartomány stratégia</value>\n  </data>\n  <data name=\"TbRoutingTabRuleList\" xml:space=\"preserve\">\n    <value>Előre definiált szabálykészlet lista</value>\n  </data>\n  <data name=\"TbRoutingTips\" xml:space=\"preserve\">\n    <value>*Szabályok elválasztása vesszővel (,); Szó szerinti vesszőhöz használja a &lt;COMMA&gt;-t; Előtag # a szabály figyelmen kívül hagyásához</value>\n  </data>\n  <data name=\"menuImportRulesFromClipboard\" xml:space=\"preserve\">\n    <value>Szabályok importálása vágólapról</value>\n  </data>\n  <data name=\"menuImportRulesFromFile\" xml:space=\"preserve\">\n    <value>Szabályok importálása fájlból</value>\n  </data>\n  <data name=\"menuImportRulesFromUrl\" xml:space=\"preserve\">\n    <value>Szabályok importálása előfizetési URL-ből</value>\n  </data>\n  <data name=\"menuRoutingRuleSetting\" xml:space=\"preserve\">\n    <value>Szabály beállítások</value>\n  </data>\n  <data name=\"menuRuleAdd\" xml:space=\"preserve\">\n    <value>Szabály hozzáadása</value>\n  </data>\n  <data name=\"menuRuleExportSelected\" xml:space=\"preserve\">\n    <value>Kijelölt szabályok exportálása</value>\n  </data>\n  <data name=\"menuRuleList\" xml:space=\"preserve\">\n    <value>Szabálylista</value>\n  </data>\n  <data name=\"menuRuleRemove\" xml:space=\"preserve\">\n    <value>Szabály eltávolítása</value>\n  </data>\n  <data name=\"menuRoutingRuleDetailsSetting\" xml:space=\"preserve\">\n    <value>Útválasztási szabály részleteinek beállítása</value>\n  </data>\n  <data name=\"TbAutoSort\" xml:space=\"preserve\">\n    <value>Tartomány, IP, folyamat automatikusan rendeződik mentéskor</value>\n  </data>\n  <data name=\"TbRuleobjectDoc\" xml:space=\"preserve\">\n    <value>Szabály objektum dokumentum</value>\n  </data>\n  <data name=\"TbDnsObjectDoc\" xml:space=\"preserve\">\n    <value>Támogatja a DNS objektumot; Kattintson a dokumentáció megtekintéséhez</value>\n  </data>\n  <data name=\"SubUrlTips\" xml:space=\"preserve\">\n    <value>Csoport esetén hagyja üresen</value>\n  </data>\n  <data name=\"TipChangeRouting\" xml:space=\"preserve\">\n    <value>Útválasztási beállítás megváltozott</value>\n  </data>\n  <data name=\"TipChangeSystemProxy\" xml:space=\"preserve\">\n    <value>Rendszerproxy beállítás megváltozott</value>\n  </data>\n  <data name=\"TbSettingsRouteOnly\" xml:space=\"preserve\">\n    <value>Csak útválasztás</value>\n  </data>\n  <data name=\"TbSettingsNotProxyLocalAddress\" xml:space=\"preserve\">\n    <value>Ne használjon proxy szervert helyi (intranet) címekhez</value>\n  </data>\n  <data name=\"menuMixedTestServer\" xml:space=\"preserve\">\n    <value>Egykattintásos többszörös késleltetés és sebesség teszt (Ctrl+E)</value>\n  </data>\n  <data name=\"LvTestDelay\" xml:space=\"preserve\">\n    <value>Késleltetés (ms)</value>\n  </data>\n  <data name=\"LvTestSpeed\" xml:space=\"preserve\">\n    <value>Sebesség (MB/s)</value>\n  </data>\n  <data name=\"FailedToRunCore\" xml:space=\"preserve\">\n    <value>Nem sikerült futtatni a Core-t, kérjük, ellenőrizze a prompt információt</value>\n  </data>\n  <data name=\"LvFilter\" xml:space=\"preserve\">\n    <value>Megjegyzések reguláris szűrője</value>\n  </data>\n  <data name=\"TbDisplayLog\" xml:space=\"preserve\">\n    <value>Napló megjelenítése</value>\n  </data>\n  <data name=\"TbEnableTunAs\" xml:space=\"preserve\">\n    <value>Tun engedélyezése</value>\n  </data>\n  <data name=\"TbSettingsNewPort4LAN\" xml:space=\"preserve\">\n    <value>Új port a LAN-hoz</value>\n  </data>\n  <data name=\"TbSettingsTunMode\" xml:space=\"preserve\">\n    <value>Tun mód beállítások</value>\n  </data>\n  <data name=\"menuMoveToGroup\" xml:space=\"preserve\">\n    <value>Mozgatás csoportba</value>\n  </data>\n  <data name=\"TbSettingsEnableDragDropSort\" xml:space=\"preserve\">\n    <value>Konfigurációk rendezésének engedélyezése húzással (újraindítást igényel)</value>\n  </data>\n  <data name=\"TbAutoRefresh\" xml:space=\"preserve\">\n    <value>Automatikus frissítés</value>\n  </data>\n  <data name=\"SpeedtestingSkip\" xml:space=\"preserve\">\n    <value>Teszt kihagyása</value>\n  </data>\n  <data name=\"menuEditServer\" xml:space=\"preserve\">\n    <value>Konfiguráció szerkesztése</value>\n  </data>\n  <data name=\"TbSettingsDoubleClick2Activate\" xml:space=\"preserve\">\n    <value>Dupla kattintás a konfigurációra aktiválja</value>\n  </data>\n  <data name=\"SpeedtestingCompleted\" xml:space=\"preserve\">\n    <value>Teszt befejeződött</value>\n  </data>\n  <data name=\"TbSettingsDefFingerprint\" xml:space=\"preserve\">\n    <value>Alapértelmezett TLS ujjlenyomat</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgent\" xml:space=\"preserve\">\n    <value>User-Agent</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgentTips\" xml:space=\"preserve\">\n    <value>Ez a paraméter csak tcp/http és ws esetén érvényes</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamily\" xml:space=\"preserve\">\n    <value>Betűtípus (újraindítást igényel)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyTip\" xml:space=\"preserve\">\n    <value>Másolja a TTF/TTC betűtípus fájlt a gui Fonts könyvtárba; Nyissa meg újra a beállítások ablakot</value>\n  </data>\n  <data name=\"TbSettingsSocksPortTip\" xml:space=\"preserve\">\n    <value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>\n  </data>\n  <data name=\"TbSettingsStartBootTip\" xml:space=\"preserve\">\n    <value>Rendszergazdai jogosultságokkal állítsa be, indítás után szerezzen rendszergazdai jogosultságokat</value>\n  </data>\n  <data name=\"TbSettingsFontSize\" xml:space=\"preserve\">\n    <value>Betűméret</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestTimeout\" xml:space=\"preserve\">\n    <value>Sebességteszt egyszeri időtúllépési érték</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestUrl\" xml:space=\"preserve\">\n    <value>Sebességteszt URL</value>\n  </data>\n  <data name=\"menuMoveTo\" xml:space=\"preserve\">\n    <value>Mozgatás fel és le</value>\n  </data>\n  <data name=\"TbPublicKey\" xml:space=\"preserve\">\n    <value>Nyilvános kulcs</value>\n  </data>\n  <data name=\"TbShortId\" xml:space=\"preserve\">\n    <value>Rövid azonosító</value>\n  </data>\n  <data name=\"TbSpiderX\" xml:space=\"preserve\">\n    <value>Spider X</value>\n  </data>\n  <data name=\"TbSettingsEnableHWA\" xml:space=\"preserve\">\n    <value>Hardveres gyorsítás engedélyezése (újraindítást igényel)</value>\n  </data>\n  <data name=\"SpeedtestingWait\" xml:space=\"preserve\">\n    <value>Tesztelésre vár...</value>\n  </data>\n  <data name=\"SpeedtestingPressEscToExit\" xml:space=\"preserve\">\n    <value>ESC megnyomásával megszakítható</value>\n  </data>\n  <data name=\"TipDisplayLog\" xml:space=\"preserve\">\n    <value>Kérjük, kapcsolja ki rendellenes megszakadás esetén</value>\n  </data>\n  <data name=\"MsgSkipSubscriptionUpdate\" xml:space=\"preserve\">\n    <value>A frissítések nincsenek engedélyezve, kihagyja ezt az előfizetést</value>\n  </data>\n  <data name=\"menuRebootAsAdmin\" xml:space=\"preserve\">\n    <value>Újraindítás rendszergazdaként</value>\n  </data>\n  <data name=\"LvMoreUrl\" xml:space=\"preserve\">\n    <value>További URL-ek, vesszővel elválasztva; Az előfizetés konverzió érvénytelen lesz</value>\n  </data>\n  <data name=\"SpeedDisplayText\" xml:space=\"preserve\">\n    <value>{0} : {1}/s↑ | {2}/s↓</value>\n  </data>\n  <data name=\"LvAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Automatikus frissítési intervallum (percek)</value>\n  </data>\n  <data name=\"TbSettingsLogEnabledToFile\" xml:space=\"preserve\">\n    <value>Naplózás engedélyezése fájlba</value>\n  </data>\n  <data name=\"LvConvertTarget\" xml:space=\"preserve\">\n    <value>Konverziós cél típus</value>\n  </data>\n  <data name=\"LvConvertTargetTip\" xml:space=\"preserve\">\n    <value>Kérjük, hagyja üresen, ha nincs szükség konverzióra</value>\n  </data>\n  <data name=\"menuDNSSetting\" xml:space=\"preserve\">\n    <value>DNS beállítások</value>\n  </data>\n  <data name=\"TbCustomDnsSingbox\" xml:space=\"preserve\">\n    <value>sing-box Custom DNS</value>\n  </data>\n  <data name=\"TbDnsSingboxObjectDoc\" xml:space=\"preserve\">\n    <value>Kérjük, töltse ki a DNS struktúrát, kattintson a dokumentum megtekintéséhez</value>\n  </data>\n  <data name=\"TbSettingDnsImportDefConfig\" xml:space=\"preserve\">\n    <value>Kattintson az alapértelmezett DNS konfiguráció importálásához</value>\n  </data>\n  <data name=\"TbdomainStrategy4Singbox\" xml:space=\"preserve\">\n    <value>sing-box tartomány stratégia</value>\n  </data>\n  <data name=\"TbSettingsMux4SboxProtocol\" xml:space=\"preserve\">\n    <value>sing-box Mux protokoll</value>\n  </data>\n  <data name=\"TbRoutingRuleProcess\" xml:space=\"preserve\">\n    <value>Process (Linux/Windows)</value>\n  </data>\n  <data name=\"TbRoutingRuleIP\" xml:space=\"preserve\">\n    <value>IP vagy IP CIDR</value>\n  </data>\n  <data name=\"TbRoutingRuleDomain\" xml:space=\"preserve\">\n    <value>Tartomány</value>\n  </data>\n  <data name=\"menuAddHysteria2Server\" xml:space=\"preserve\">\n    <value>Hysteria2 konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"TbSettingsHysteriaBandwidth\" xml:space=\"preserve\">\n    <value>Hysteria Max sávszélesség (Fel/Le)</value>\n  </data>\n  <data name=\"TbSettingsUseSystemHosts\" xml:space=\"preserve\">\n    <value>Rendszer Hosts használata</value>\n  </data>\n  <data name=\"menuAddTuicServer\" xml:space=\"preserve\">\n    <value>TUIC konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"TbHeaderType8\" xml:space=\"preserve\">\n    <value>Torlódásvezérlés</value>\n  </data>\n  <data name=\"LvPrevProfile\" xml:space=\"preserve\">\n    <value>Előző proxy konfiguráció megjegyzései</value>\n  </data>\n  <data name=\"LvNextProfile\" xml:space=\"preserve\">\n    <value>Következő proxy konfiguráció megjegyzései</value>\n  </data>\n  <data name=\"LvPrevProfileTip\" xml:space=\"preserve\">\n    <value>Kérjük, győződjön meg arról, hogy a konfigurációs megjegyzések léteznek és egyediek</value>\n  </data>\n  <data name=\"TbSettingsTunAutoRoute\" xml:space=\"preserve\">\n    <value>Automatikus útválasztás</value>\n  </data>\n  <data name=\"TbSettingsTunStrictRoute\" xml:space=\"preserve\">\n    <value>Szigorú útválasztás</value>\n  </data>\n  <data name=\"TbSettingsTunStack\" xml:space=\"preserve\">\n    <value>Hálózati verem</value>\n  </data>\n  <data name=\"TbSettingsTunMtu\" xml:space=\"preserve\">\n    <value>MTU</value>\n  </data>\n  <data name=\"TbSettingsEnableIPv6Address\" xml:space=\"preserve\">\n    <value>IPv6 cím engedélyezése</value>\n  </data>\n  <data name=\"menuAddWireguardServer\" xml:space=\"preserve\">\n    <value>WireGuard konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"TbPrivateKey\" xml:space=\"preserve\">\n    <value>Privát kulcs</value>\n  </data>\n  <data name=\"TbReserved\" xml:space=\"preserve\">\n    <value>Fenntartott (2,3,4)</value>\n  </data>\n  <data name=\"TbLocalAddress\" xml:space=\"preserve\">\n    <value>Cím (IPv4, IPv6)</value>\n  </data>\n  <data name=\"TbPath7\" xml:space=\"preserve\">\n    <value>obfs jelszó</value>\n  </data>\n  <data name=\"TbRuleMatchingTips\" xml:space=\"preserve\">\n    <value>(Tartomány vagy IP vagy folyamatnév) és port és protokoll és bejövő címke =&gt; kimenő címke</value>\n  </data>\n  <data name=\"TbAutoScrollToEnd\" xml:space=\"preserve\">\n    <value>Automatikus görgetés a végére</value>\n  </data>\n  <data name=\"TbSettingsSpeedPingTestUrl\" xml:space=\"preserve\">\n    <value>Sebesség Ping Teszt URL</value>\n  </data>\n  <data name=\"SpeedtestingStop\" xml:space=\"preserve\">\n    <value>Teszt megszakítása...</value>\n  </data>\n  <data name=\"TransportRequestHostTip5\" xml:space=\"preserve\">\n    <value>*grpc Authority</value>\n  </data>\n  <data name=\"menuAddHttpServer\" xml:space=\"preserve\">\n    <value>HTTP konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"TbSettingsEnableFragment\" xml:space=\"preserve\">\n    <value>Fragment engedélyezése</value>\n  </data>\n  <data name=\"TbSettingsEnableCacheFile4Sbox\" xml:space=\"preserve\">\n    <value>Gyorsítótár fájl engedélyezése sing-boxhoz (szabálykészlet fájlok)</value>\n  </data>\n  <data name=\"LvCustomRulesetPath4Singbox\" xml:space=\"preserve\">\n    <value>A sing-box szabálykészletének testreszabása</value>\n  </data>\n  <data name=\"NeedRebootTips\" xml:space=\"preserve\">\n    <value>Sikeres művelet. Kattintson a beállítások menüre az alkalmazás újraindításához.</value>\n  </data>\n  <data name=\"menuOpenTheFileLocation\" xml:space=\"preserve\">\n    <value>Fájl helyének megnyitása</value>\n  </data>\n  <data name=\"TbSorting\" xml:space=\"preserve\">\n    <value>Rendezés</value>\n  </data>\n  <data name=\"TbSortingChain\" xml:space=\"preserve\">\n    <value>Lánc</value>\n  </data>\n  <data name=\"TbSortingDefault\" xml:space=\"preserve\">\n    <value>Alapértelmezett</value>\n  </data>\n  <data name=\"TbSortingDelay\" xml:space=\"preserve\">\n    <value>Késleltetés</value>\n  </data>\n  <data name=\"TbSortingDownSpeed\" xml:space=\"preserve\">\n    <value>Letöltési sebesség</value>\n  </data>\n  <data name=\"TbSortingDownTraffic\" xml:space=\"preserve\">\n    <value>Letöltési forgalom</value>\n  </data>\n  <data name=\"TbSortingHost\" xml:space=\"preserve\">\n    <value>Host</value>\n  </data>\n  <data name=\"TbSortingName\" xml:space=\"preserve\">\n    <value>Név</value>\n  </data>\n  <data name=\"TbSortingNetwork\" xml:space=\"preserve\">\n    <value>Hálózat</value>\n  </data>\n  <data name=\"TbSortingTime\" xml:space=\"preserve\">\n    <value>Idő</value>\n  </data>\n  <data name=\"TbSortingType\" xml:space=\"preserve\">\n    <value>Típus</value>\n  </data>\n  <data name=\"TbSortingUpSpeed\" xml:space=\"preserve\">\n    <value>Feltöltési sebesség</value>\n  </data>\n  <data name=\"TbSortingUpTraffic\" xml:space=\"preserve\">\n    <value>Feltöltési forgalom</value>\n  </data>\n  <data name=\"TbConnections\" xml:space=\"preserve\">\n    <value>Kapcsolatok</value>\n  </data>\n  <data name=\"menuConnectionClose\" xml:space=\"preserve\">\n    <value>Kapcsolat bezárása</value>\n  </data>\n  <data name=\"menuConnectionCloseAll\" xml:space=\"preserve\">\n    <value>Összes kapcsolat bezárása</value>\n  </data>\n  <data name=\"TbProxies\" xml:space=\"preserve\">\n    <value>Proxyk</value>\n  </data>\n  <data name=\"menuRulemode\" xml:space=\"preserve\">\n    <value>Szabály mód</value>\n  </data>\n  <data name=\"menuModeDirect\" xml:space=\"preserve\">\n    <value>Közvetlen</value>\n  </data>\n  <data name=\"menuModeGlobal\" xml:space=\"preserve\">\n    <value>Globális</value>\n  </data>\n  <data name=\"menuModeNothing\" xml:space=\"preserve\">\n    <value>Ne változtassa meg</value>\n  </data>\n  <data name=\"menuModeRule\" xml:space=\"preserve\">\n    <value>Szabály</value>\n  </data>\n  <data name=\"menuProxiesDelaytest\" xml:space=\"preserve\">\n    <value>Késleltetés teszt</value>\n  </data>\n  <data name=\"menuProxiesDelaytestPart\" xml:space=\"preserve\">\n    <value>Részleges csomópont késleltetés teszt</value>\n  </data>\n  <data name=\"menuProxiesReload\" xml:space=\"preserve\">\n    <value>Proxyk frissítése</value>\n  </data>\n  <data name=\"menuProxiesSelectActivity\" xml:space=\"preserve\">\n    <value>Aktív csomópont kiválasztása</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Out\" xml:space=\"preserve\">\n    <value>Alapértelmezett tartomány stratégia kimenő forgalomhoz</value>\n  </data>\n  <data name=\"TbSettingsMainGirdOrientation\" xml:space=\"preserve\">\n    <value>Fő elrendezés iránya (újraindítást igényel)</value>\n  </data>\n  <data name=\"TbSettingsDomainDNSAddress\" xml:space=\"preserve\">\n    <value>Kimenő DNS cím</value>\n  </data>\n  <data name=\"menuProfileAutofitColumnWidth\" xml:space=\"preserve\">\n    <value>Oszlopszélesség automatikus beállítása</value>\n  </data>\n  <data name=\"menuExport2ShareUrlBase64\" xml:space=\"preserve\">\n    <value>Base64-kódolt megosztási linkek exportálása vágólapra</value>\n  </data>\n  <data name=\"menuExport2ClientConfigClipboard\" xml:space=\"preserve\">\n    <value>Kijelölt konfiguráció exportálása teljes konfigurációként a vágólapra</value>\n  </data>\n  <data name=\"menuShowOrHideMainWindow\" xml:space=\"preserve\">\n    <value>Főablak megjelenítése vagy elrejtése</value>\n  </data>\n  <data name=\"TbPreSocksPort4Sub\" xml:space=\"preserve\">\n    <value>Egyéni konfiguráció socks portja</value>\n  </data>\n  <data name=\"menuBackupAndRestore\" xml:space=\"preserve\">\n    <value>Biztonsági mentés és visszaállítás</value>\n  </data>\n  <data name=\"menuLocalBackup\" xml:space=\"preserve\">\n    <value>Biztonsági mentés helyi tárolóba</value>\n  </data>\n  <data name=\"menuLocalRestore\" xml:space=\"preserve\">\n    <value>Visszaállítás helyi tárolóból</value>\n  </data>\n  <data name=\"menuRemoteBackup\" xml:space=\"preserve\">\n    <value>Biztonsági mentés távoli helyre (WebDAV)</value>\n  </data>\n  <data name=\"menuRemoteRestore\" xml:space=\"preserve\">\n    <value>Visszaállítás távoli helyről (WebDAV)</value>\n  </data>\n  <data name=\"menuLocalBackupAndRestore\" xml:space=\"preserve\">\n    <value>Helyi</value>\n  </data>\n  <data name=\"menuRemoteBackupAndRestore\" xml:space=\"preserve\">\n    <value>Távoli (WebDAV)</value>\n  </data>\n  <data name=\"LvWebDavUrl\" xml:space=\"preserve\">\n    <value>WebDAV URL</value>\n  </data>\n  <data name=\"LvWebDavUserName\" xml:space=\"preserve\">\n    <value>WebDAV felhasználónév</value>\n  </data>\n  <data name=\"LvWebDavPassword\" xml:space=\"preserve\">\n    <value>WebDAV jelszó</value>\n  </data>\n  <data name=\"LvWebDavCheck\" xml:space=\"preserve\">\n    <value>WebDAV ellenőrzés</value>\n  </data>\n  <data name=\"LvWebDavDirName\" xml:space=\"preserve\">\n    <value>Távoli mappa neve (opcionális)</value>\n  </data>\n  <data name=\"LocalRestoreInvalidZipTips\" xml:space=\"preserve\">\n    <value>Érvénytelen biztonsági mentés fájl</value>\n  </data>\n  <data name=\"ConnectionsHostFilterTitle\" xml:space=\"preserve\">\n    <value>Host szűrő</value>\n  </data>\n  <data name=\"TipActiveServer\" xml:space=\"preserve\">\n    <value>Aktív</value>\n  </data>\n  <data name=\"TbSettingsGeoFilesSource\" xml:space=\"preserve\">\n    <value>Geo fájlok forrása (opcionális)</value>\n  </data>\n  <data name=\"TbSettingsSrsFilesSource\" xml:space=\"preserve\">\n    <value>sing-box szabálykészlet fájlok forrása (opcionális)</value>\n  </data>\n  <data name=\"UpgradeAppNotExistTip\" xml:space=\"preserve\">\n    <value>Frissítő alkalmazás nem létezik</value>\n  </data>\n  <data name=\"TbSettingsRoutingRulesSource\" xml:space=\"preserve\">\n    <value>Útválasztási szabályok forrása (opcionális)</value>\n  </data>\n  <data name=\"menuRegionalPresets\" xml:space=\"preserve\">\n    <value>Regionális előbeállítások</value>\n  </data>\n  <data name=\"menuRegionalPresetsDefault\" xml:space=\"preserve\">\n    <value>Alapértelmezett</value>\n  </data>\n  <data name=\"menuRegionalPresetsRussia\" xml:space=\"preserve\">\n    <value>Oroszország</value>\n  </data>\n  <data name=\"menuRegionalPresetsIran\" xml:space=\"preserve\">\n    <value>Irán</value>\n  </data>\n  <data name=\"TbSettingsChinaUserTip\" xml:space=\"preserve\">\n    <value>Kínai régióban lévő felhasználók figyelmen kívül hagyhatják ezt az elemet</value>\n  </data>\n  <data name=\"menuAddServerViaImage\" xml:space=\"preserve\">\n    <value>QR kód beolvasása a képből</value>\n  </data>\n  <data name=\"InvalidUrlTip\" xml:space=\"preserve\">\n    <value>Érvénytelen cím (URL)</value>\n  </data>\n  <data name=\"InsecureUrlProtocol\" xml:space=\"preserve\">\n    <value>Kérjük, ne használjon nem biztonságos HTTP protokoll előfizetési címet</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyLinuxTip\" xml:space=\"preserve\">\n    <value>Telepítse a betűtípust a rendszerbe, válassza ki vagy töltse ki a betűtípus nevét, indítsa újra a beállításokat</value>\n  </data>\n  <data name=\"menuExitTips\" xml:space=\"preserve\">\n    <value>Biztosan ki akar lépni?</value>\n  </data>\n  <data name=\"LvMemo\" xml:space=\"preserve\">\n    <value>Megjegyzések</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPassword\" xml:space=\"preserve\">\n    <value>Rendszer sudo jelszó</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPasswordTip\" xml:space=\"preserve\">\n    <value>A jelszót a parancssoron keresztül ellenőrizzük. Ha egy érvényesítési hiba miatt az alkalmazás hibásan működik, indítsa újra az alkalmazást. A jelszó nem kerül tárolásra, és minden újraindítás után újra meg kell adni.</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip5\" xml:space=\"preserve\">\n    <value>*xhttp mód</value>\n  </data>\n  <data name=\"TransportExtraTip\" xml:space=\"preserve\">\n    <value>XHTTP Extra nyers JSON, formátum: { XHTTP Objektum }</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenClose\" xml:space=\"preserve\">\n    <value>Ablak bezárásakor a tálcára rejtés</value>\n  </data>\n  <data name=\"TbSettingsMixedConcurrencyCount\" xml:space=\"preserve\">\n    <value>A párhuzamos tesztek száma több teszt során</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip2\" xml:space=\"preserve\">\n    <value>Kivételek: Ne használjon proxy szervert a következő címekhez. Vesszővel (,) válassza el a bejegyzéseket.</value>\n  </data>\n  <data name=\"TbSettingsDestOverride\" xml:space=\"preserve\">\n    <value>Sniffing típus</value>\n  </data>\n  <data name=\"TbSettingsSecondLocalPortEnabled\" xml:space=\"preserve\">\n    <value>Második vegyes port engedélyezése</value>\n  </data>\n  <data name=\"TbRoutingInboundTagTips\" xml:space=\"preserve\">\n    <value>socks: helyi port, socks2: második helyi port, socks3: LAN port</value>\n  </data>\n  <data name=\"TbSettingsTheme\" xml:space=\"preserve\">\n    <value>Téma</value>\n  </data>\n  <data name=\"menuCopyProxyCmdToClipboard\" xml:space=\"preserve\">\n    <value>Proxy parancs másolása vágólapra</value>\n  </data>\n  <data name=\"SpeedtestingTestFailedPart\" xml:space=\"preserve\">\n    <value>Sikertelen részek újratesztelése elindult, {0} maradt. ESC megnyomásával megszakítható...</value>\n  </data>\n  <data name=\"menuTestServerResult\" xml:space=\"preserve\">\n    <value>Teszt eredmény szerint</value>\n  </data>\n  <data name=\"menuRemoveInvalidServerResult\" xml:space=\"preserve\">\n    <value>Érvénytelenek eltávolítása teszteredmények alapján</value>\n  </data>\n  <data name=\"RemoveInvalidServerResultTip\" xml:space=\"preserve\">\n    <value>Eltávolítva {0} érvénytelen teszteredmény.</value>\n  </data>\n  <data name=\"TbPorts7\" xml:space=\"preserve\">\n    <value>Konfigurációs port tartomány</value>\n  </data>\n  <data name=\"TbPorts7Tips\" xml:space=\"preserve\">\n    <value>A portot lefedi, vesszővel (,) elválasztva</value>\n  </data>\n  <data name=\"menuExportConfig\" xml:space=\"preserve\">\n    <value>Konfiguráció exportálása</value>\n  </data>\n  <data name=\"TbSettingsIPAPIUrl\" xml:space=\"preserve\">\n    <value>Aktuális kapcsolat info teszt URL</value>\n  </data>\n  <data name=\"TbRuleOutboundTagTip\" xml:space=\"preserve\">\n    <value>Kitöltheti a konfigurációs megjegyzéseket, kérjük, győződjön meg róla, hogy létezik és egyedi</value>\n  </data>\n  <data name=\"SudoIncorrectPasswordTip\" xml:space=\"preserve\">\n    <value>Helytelen jelszó, próbálja újra.</value>\n  </data>\n  <data name=\"TbMldsa65Verify\" xml:space=\"preserve\">\n    <value>Mldsa65Verify</value>\n  </data>\n  <data name=\"menuAddAnytlsServer\" xml:space=\"preserve\">\n    <value>[Anytls] konfiguráció hozzáadása</value>\n  </data>\n  <data name=\"TbRemoteDNS\" xml:space=\"preserve\">\n    <value>Remote DNS</value>\n  </data>\n  <data name=\"TbDomesticDNS\" xml:space=\"preserve\">\n    <value>Domestic DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategy\" xml:space=\"preserve\">\n    <value>Direct Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategy\" xml:space=\"preserve\">\n    <value>Proxy Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbAddCommonDNSHosts\" xml:space=\"preserve\">\n    <value>Add Common DNS Hosts</value>\n  </data>\n  <data name=\"TbFakeIP\" xml:space=\"preserve\">\n    <value>FakeIP</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueries\" xml:space=\"preserve\">\n    <value>Block SVCB and HTTPS Queries</value>\n  </data>\n  <data name=\"TbDNSHostsConfig\" xml:space=\"preserve\">\n    <value>DNS Hosts: (\"domain1 ip1 ip2\" per line)</value>\n  </data>\n  <data name=\"ThBasicDNSSettings\" xml:space=\"preserve\">\n    <value>Basic DNS Settings</value>\n  </data>\n  <data name=\"ThAdvancedDNSSettings\" xml:space=\"preserve\">\n    <value>Advanced DNS Settings</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPs\" xml:space=\"preserve\">\n    <value>Validate Regional Domain IPs</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPsDesc\" xml:space=\"preserve\">\n    <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs</value>\n  </data>\n  <data name=\"TbCustomDNSEnable\" xml:space=\"preserve\">\n    <value>Enable Custom DNS</value>\n  </data>\n  <data name=\"TbCustomDNSEnabledPageInvalid\" xml:space=\"preserve\">\n    <value>Custom DNS Enabled, This Page's Settings Invalid</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueriesTips\" xml:space=\"preserve\">\n    <value>Block ECH and HTTP/3 availability checks when enabled</value>\n  </data>\n  <data name=\"FillCorrectConfigTemplateText\" xml:space=\"preserve\">\n    <value>Please fill in the correct config template</value>\n  </data>\n  <data name=\"menuFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Full Config Template Setting</value>\n  </data>\n  <data name=\"TbFullConfigTemplateEnable\" xml:space=\"preserve\">\n    <value>Enable Full Config Template</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplate\" xml:space=\"preserve\">\n    <value>v2ray Full Config Template</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>\n  </data>\n  <data name=\"TbAddProxyProtocolOutboundOnly\" xml:space=\"preserve\">\n    <value>Do Not Add Non-Proxy Protocol Outbound</value>\n  </data>\n  <data name=\"TbSetUpstreamProxyDetour\" xml:space=\"preserve\">\n    <value>Set Upstream Proxy Tag</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplate\" xml:space=\"preserve\">\n    <value>sing-box Full Config Template</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Add Outbound and Endpoint Config Only, Click to view the document</value>\n  </data>\n  <data name=\"TbFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>\n  </data>\n  <data name=\"MsgStartParsingSubscription\" xml:space=\"preserve\">\n    <value>Start parsing and processing subscription content</value>\n  </data>\n  <data name=\"TbSelectProfile\" xml:space=\"preserve\">\n    <value>Select Profile</value>\n  </data>\n  <data name=\"TbFakeIPTips\" xml:space=\"preserve\">\n    <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value>\n  </data>\n  <data name=\"PleaseAddAtLeastOneServer\" xml:space=\"preserve\">\n    <value>Please Add At Least One Configuration</value>\n  </data>\n  <data name=\"TbConfigTypePolicyGroup\" xml:space=\"preserve\">\n    <value>Policy Group</value>\n  </data>\n  <data name=\"TbConfigTypeProxyChain\" xml:space=\"preserve\">\n    <value>Proxy Chain</value>\n  </data>\n  <data name=\"TbLeastPing\" xml:space=\"preserve\">\n    <value>Lowest Latency</value>\n  </data>\n  <data name=\"TbRandom\" xml:space=\"preserve\">\n    <value>Random</value>\n  </data>\n  <data name=\"TbRoundRobin\" xml:space=\"preserve\">\n    <value>Round Robin</value>\n  </data>\n  <data name=\"TbLeastLoad\" xml:space=\"preserve\">\n    <value>Most Stable</value>\n  </data>\n  <data name=\"TbPolicyGroupType\" xml:space=\"preserve\">\n    <value>Policy Group Type</value>\n  </data>\n  <data name=\"menuAddPolicyGroupServer\" xml:space=\"preserve\">\n    <value>Add Policy Group Configuration</value>\n  </data>\n  <data name=\"menuAddProxyChainServer\" xml:space=\"preserve\">\n    <value>Add Proxy Chain Configuration</value>\n  </data>\n  <data name=\"menuAddChildServer\" xml:space=\"preserve\">\n    <value>Add Child Configuration</value>\n  </data>\n  <data name=\"menuRemoveChildServer\" xml:space=\"preserve\">\n    <value>Remove Child Configuration</value>\n  </data>\n  <data name=\"menuServerList\" xml:space=\"preserve\">\n    <value>Configuration item 1, Auto add from subscription group</value>\n  </data>\n  <data name=\"TbFallback\" xml:space=\"preserve\">\n    <value>Fallback</value>\n  </data>\n  <data name=\"MsgCoreNotSupportNetwork\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support network type '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocolTransport\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}' when using transport '{2}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}'</value>\n  </data>\n  <data name=\"MsgInvalidProperty\" xml:space=\"preserve\">\n    <value>The {0} property is invalid, please check</value>\n  </data>\n  <data name=\"MsgNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Not support protocol '{0}'</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenCloseTip\" xml:space=\"preserve\">\n    <value>If the system does not have a tray function, please do not enable it</value>\n  </data>\n  <data name=\"TbRuleTypeTips\" xml:space=\"preserve\">\n    <value>You can set separate rules for Routing and DNS, or select \"ALL\" to apply to both</value>\n  </data>\n  <data name=\"TbRuleType\" xml:space=\"preserve\">\n    <value>Rule Type</value>\n  </data>\n  <data name=\"TbBootstrapDNS\" xml:space=\"preserve\">\n    <value>Bootstrap DNS</value>\n  </data>\n  <data name=\"TbBootstrapDNSTips\" xml:space=\"preserve\">\n    <value>Resolve DNS server domains, requires IP</value>\n  </data>\n  <data name=\"menuFastRealPing\" xml:space=\"preserve\">\n    <value>Test real delay</value>\n  </data>\n  <data name=\"TbPolicyGroupSubChildTip\" xml:space=\"preserve\">\n    <value>Auto add filtered configuration from subscription groups</value>\n  </data>\n  <data name=\"TbCertPinning\" xml:space=\"preserve\">\n    <value>Certificate Pinning</value>\n  </data>\n  <data name=\"TbCertPinningTips\" xml:space=\"preserve\">\n    <value>Pinned certificate (fill in either one)\nWhen specified, the certificate will be pinned, and \"Allow Insecure\" will be disabled.\n\nThe \"Get Certificate\" action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA.</value>\n  </data>\n  <data name=\"TbFetchCert\" xml:space=\"preserve\">\n    <value>Fetch Certificate</value>\n  </data>\n  <data name=\"TbFetchCertChain\" xml:space=\"preserve\">\n    <value>Fetch Certificate Chain</value>\n  </data>\n  <data name=\"ServerNameMustBeValidDomain\" xml:space=\"preserve\">\n    <value>Please set a valid domain</value>\n  </data>\n  <data name=\"CertNotSet\" xml:space=\"preserve\">\n    <value>Certificate not set</value>\n  </data>\n  <data name=\"CertSet\" xml:space=\"preserve\">\n    <value>Certificate set</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyPacPath\" xml:space=\"preserve\">\n    <value>Custom PAC file path</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyScriptPath\" xml:space=\"preserve\">\n    <value>Custom system proxy script file path</value>\n  </data>\n  <data name=\"TbSettingsMacOSShowInDock\" xml:space=\"preserve\">\n    <value>macOS displays this in the Dock (requires restart)</value>\n  </data>\n  <data name=\"menuServerList2\" xml:space=\"preserve\">\n    <value>Configuration Item 2, Select and add from self-built</value>\n  </data>\n  <data name=\"TbEchConfigList\" xml:space=\"preserve\">\n    <value>EchConfigList</value>\n  </data>\n  <data name=\"TbEchForceQuery\" xml:space=\"preserve\">\n    <value>EchForceQuery</value>\n  </data>\n  <data name=\"TbFullCertTips\" xml:space=\"preserve\">\n    <value>Full certificate (chain), PEM format</value>\n  </data>\n  <data name=\"TbCertSha256Tips\" xml:space=\"preserve\">\n    <value>Certificate fingerprint (SHA-256)</value>\n  </data>\n  <data name=\"TbServeStale\" xml:space=\"preserve\">\n    <value>Serve Stale</value>\n  </data>\n  <data name=\"TbParallelQuery\" xml:space=\"preserve\">\n    <value>Parallel Query</value>\n  </data>\n  <data name=\"TbDomesticDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution</value>\n  </data>\n  <data name=\"TbRemoteDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution; ensure the remote server can reach this DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution uses the system DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbHopInt7\" xml:space=\"preserve\">\n    <value>Port hopping interval</value>\n  </data>\n  <data name=\"menuServerListPreview\" xml:space=\"preserve\">\n    <value>Configuration item preview</value>\n  </data>\n  <data name=\"TbFinalmask\" xml:space=\"preserve\">\n    <value>Finalmask</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeWarning\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeError\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} error: {2}. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgGroupCycleDependency\" xml:space=\"preserve\">\n    <value>Group {0} has a cycle dependency on child node {1}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupNoValidChildNode\" xml:space=\"preserve\">\n    <value>Group {0} has no valid child node.</value>\n  </data>\n  <data name=\"MsgRoutingRuleEmptyOutboundTag\" xml:space=\"preserve\">\n    <value>Routing rule {0} has an empty outbound tag. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeNotFound\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} not found. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgSubscriptionPrevProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription previous proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"MsgSubscriptionNextProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription next proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"menuGenGroupServer\" xml:space=\"preserve\">\n    <value>Generate Policy Group</value>\n  </data>\n  <data name=\"menuAllServers\" xml:space=\"preserve\">\n    <value>All configurations</value>\n  </data>\n  <data name=\"menuGenRegionGroup\" xml:space=\"preserve\">\n    <value>Group by Region</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BatchExportURLSuccessfully\" xml:space=\"preserve\">\n    <value>Export share link to clipboard successfully</value>\n  </data>\n  <data name=\"CheckServerSettings\" xml:space=\"preserve\">\n    <value>Please check the Configuration settings first.</value>\n  </data>\n  <data name=\"ConfigurationFormatIncorrect\" xml:space=\"preserve\">\n    <value>Invalid configuration format.</value>\n  </data>\n  <data name=\"CustomServerTips\" xml:space=\"preserve\">\n    <value>Note that custom configuration relies entirely on your own configuration and does not work with all settings. If you want to use the system proxy, please modify the listening port manually.</value>\n  </data>\n  <data name=\"Downloading\" xml:space=\"preserve\">\n    <value>Downloading...</value>\n  </data>\n  <data name=\"FailedConversionConfiguration\" xml:space=\"preserve\">\n    <value>Failed to convert configuration file</value>\n  </data>\n  <data name=\"FailedGenDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Failed to generate default configuration file</value>\n  </data>\n  <data name=\"FailedGetDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Failed to get the default configuration</value>\n  </data>\n  <data name=\"FailedImportedCustomServer\" xml:space=\"preserve\">\n    <value>Failed to import custom configuration Configuration</value>\n  </data>\n  <data name=\"FailedReadConfiguration\" xml:space=\"preserve\">\n    <value>Failed to read configuration file</value>\n  </data>\n  <data name=\"FillCorrectServerPort\" xml:space=\"preserve\">\n    <value>Please enter the correct port format.</value>\n  </data>\n  <data name=\"FillLocalListeningPort\" xml:space=\"preserve\">\n    <value>Please enter the local listening port.</value>\n  </data>\n  <data name=\"FillPassword\" xml:space=\"preserve\">\n    <value>Please enter the password.</value>\n  </data>\n  <data name=\"FillServerAddress\" xml:space=\"preserve\">\n    <value>Please enter the address.</value>\n  </data>\n  <data name=\"FillUUID\" xml:space=\"preserve\">\n    <value>Please enter the user ID.</value>\n  </data>\n  <data name=\"Incorrectconfiguration\" xml:space=\"preserve\">\n    <value>This is not the correct configuration, please check</value>\n  </data>\n  <data name=\"InitialConfiguration\" xml:space=\"preserve\">\n    <value>Initial Configuration</value>\n  </data>\n  <data name=\"IsLatestCore\" xml:space=\"preserve\">\n    <value>{0} {1} already up to date.</value>\n  </data>\n  <data name=\"IsLatestN\" xml:space=\"preserve\">\n    <value>{0} {1} already up to date.</value>\n  </data>\n  <data name=\"LvAddress\" xml:space=\"preserve\">\n    <value>Address</value>\n  </data>\n  <data name=\"LvEncryptionMethod\" xml:space=\"preserve\">\n    <value>Security</value>\n  </data>\n  <data name=\"LvPort\" xml:space=\"preserve\">\n    <value>Port</value>\n  </data>\n  <data name=\"LvServiceType\" xml:space=\"preserve\">\n    <value>Type</value>\n  </data>\n  <data name=\"LvSubscription\" xml:space=\"preserve\">\n    <value>Subs group</value>\n  </data>\n  <data name=\"LvTodayDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Download traffic today</value>\n  </data>\n  <data name=\"LvTodayUploadDataAmount\" xml:space=\"preserve\">\n    <value>Upload traffic today</value>\n  </data>\n  <data name=\"LvTotalDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Total download traffic</value>\n  </data>\n  <data name=\"LvTotalUploadDataAmount\" xml:space=\"preserve\">\n    <value>Total upload traffic</value>\n  </data>\n  <data name=\"LvTransportProtocol\" xml:space=\"preserve\">\n    <value>Transport</value>\n  </data>\n  <data name=\"MsgDownloadV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>Downloaded Core successfully</value>\n  </data>\n  <data name=\"MsgFailedImportSubscription\" xml:space=\"preserve\">\n    <value>Failed to import subscription content</value>\n  </data>\n  <data name=\"MsgGetSubscriptionSuccessfully\" xml:space=\"preserve\">\n    <value>Got subscription content successfully</value>\n  </data>\n  <data name=\"MsgNoValidSubscription\" xml:space=\"preserve\">\n    <value>No valid subscriptions set</value>\n  </data>\n  <data name=\"MsgParsingSuccessfully\" xml:space=\"preserve\">\n    <value>Resolved {0} successfully</value>\n  </data>\n  <data name=\"MsgStartGettingSubscriptions\" xml:space=\"preserve\">\n    <value>Started getting subscriptions</value>\n  </data>\n  <data name=\"MsgStartUpdating\" xml:space=\"preserve\">\n    <value>Started updating {0}...</value>\n  </data>\n  <data name=\"MsgSubscriptionDecodingFailed\" xml:space=\"preserve\">\n    <value>Invalid subscription content</value>\n  </data>\n  <data name=\"MsgUnpacking\" xml:space=\"preserve\">\n    <value>Unpacking...</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionEnd\" xml:space=\"preserve\">\n    <value>Subscription update ended</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionStart\" xml:space=\"preserve\">\n    <value>Subscription update started</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>Updated Core successfully</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfullyMore\" xml:space=\"preserve\">\n    <value>Updated Core successfully! Restarting service...</value>\n  </data>\n  <data name=\"NonvmessOrssProtocol\" xml:space=\"preserve\">\n    <value>Non-VMess or SS protocol</value>\n  </data>\n  <data name=\"NotFoundCore\" xml:space=\"preserve\">\n    <value>The Core file (file name: {1}) was not found under the folder ({0}), please download and put it in the folder, download address: {2}</value>\n  </data>\n  <data name=\"NoValidQRcodeFound\" xml:space=\"preserve\">\n    <value>Scan completed, no valid QR code found</value>\n  </data>\n  <data name=\"OperationFailed\" xml:space=\"preserve\">\n    <value>Operation failed, please check and retry</value>\n  </data>\n  <data name=\"PleaseFillRemarks\" xml:space=\"preserve\">\n    <value>Please fill Remarks</value>\n  </data>\n  <data name=\"PleaseSelectEncryption\" xml:space=\"preserve\">\n    <value>Please select the encryption method</value>\n  </data>\n  <data name=\"PleaseSelectProtocol\" xml:space=\"preserve\">\n    <value>Please select a protocol</value>\n  </data>\n  <data name=\"PleaseSelectServer\" xml:space=\"preserve\">\n    <value>Please select the Configuration first</value>\n  </data>\n  <data name=\"RemoveDuplicateServerResult\" xml:space=\"preserve\">\n    <value>Configurations deduplication completed. Old: {0}, New: {1}.</value>\n  </data>\n  <data name=\"RemoveServer\" xml:space=\"preserve\">\n    <value>Are you sure you want to remove?</value>\n  </data>\n  <data name=\"SaveClientConfigurationIn\" xml:space=\"preserve\">\n    <value>The client configuration file is saved at: {0}</value>\n  </data>\n  <data name=\"StartService\" xml:space=\"preserve\">\n    <value>Starting service ({0})...</value>\n  </data>\n  <data name=\"SuccessfulConfiguration\" xml:space=\"preserve\">\n    <value>Configuration successful. {0}</value>\n  </data>\n  <data name=\"SuccessfullyImportedCustomServer\" xml:space=\"preserve\">\n    <value>Custom configuration Configuration imported successfully</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaClipboard\" xml:space=\"preserve\">\n    <value>{0} Configurations have been imported from clipboard</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaScan\" xml:space=\"preserve\">\n    <value>Successfully scanned and imported the shared link</value>\n  </data>\n  <data name=\"TestMeOutput\" xml:space=\"preserve\">\n    <value>The delay: {0} ms, {1}</value>\n  </data>\n  <data name=\"OperationSuccess\" xml:space=\"preserve\">\n    <value>Operation successful</value>\n  </data>\n  <data name=\"PleaseSelectRules\" xml:space=\"preserve\">\n    <value>Please select rules</value>\n  </data>\n  <data name=\"RemoveRules\" xml:space=\"preserve\">\n    <value>Are you sure you want to remove the rules?</value>\n  </data>\n  <data name=\"RoutingRuleDetailRequiredTips\" xml:space=\"preserve\">\n    <value>{0}, one of the required fields.</value>\n  </data>\n  <data name=\"LvRemarks\" xml:space=\"preserve\">\n    <value>Remarks</value>\n  </data>\n  <data name=\"LvUrl\" xml:space=\"preserve\">\n    <value>URL (optional)</value>\n  </data>\n  <data name=\"LvCount\" xml:space=\"preserve\">\n    <value>Count</value>\n  </data>\n  <data name=\"MsgNeedUrl\" xml:space=\"preserve\">\n    <value>Please enter the URL</value>\n  </data>\n  <data name=\"AddBatchRoutingRulesYesNo\" xml:space=\"preserve\">\n    <value>Do you want to append rules? Choose yes to append, no to replace.</value>\n  </data>\n  <data name=\"MsgDownloadGeoFileSuccessfully\" xml:space=\"preserve\">\n    <value>Downloaded GeoFile: {0} successfully</value>\n  </data>\n  <data name=\"MsgInformationTitle\" xml:space=\"preserve\">\n    <value>Information</value>\n  </data>\n  <data name=\"LvCustomIcon\" xml:space=\"preserve\">\n    <value>Custom icon</value>\n  </data>\n  <data name=\"FillCorrectDNSText\" xml:space=\"preserve\">\n    <value>Please fill in the correct custom DNS</value>\n  </data>\n  <data name=\"TransportPathTip1\" xml:space=\"preserve\">\n    <value>*ws/http upgrade/xhttp path</value>\n  </data>\n  <data name=\"TransportPathTip2\" xml:space=\"preserve\">\n    <value>*h2 path</value>\n  </data>\n  <data name=\"TransportPathTip3\" xml:space=\"preserve\">\n    <value>*QUIC key/KCP seed</value>\n  </data>\n  <data name=\"TransportPathTip4\" xml:space=\"preserve\">\n    <value>*grpc service name</value>\n  </data>\n  <data name=\"TransportRequestHostTip1\" xml:space=\"preserve\">\n    <value>*http host separated by commas (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip2\" xml:space=\"preserve\">\n    <value>*ws/http upgrade/xhttp host</value>\n  </data>\n  <data name=\"TransportRequestHostTip3\" xml:space=\"preserve\">\n    <value>*h2 host separated by commas (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip4\" xml:space=\"preserve\">\n    <value>*QUIC security</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip1\" xml:space=\"preserve\">\n    <value>*tcp camouflage type</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip2\" xml:space=\"preserve\">\n    <value>*kcp camouflage type</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip3\" xml:space=\"preserve\">\n    <value>*QUIC camouflage type</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip4\" xml:space=\"preserve\">\n    <value>*grpc mode</value>\n  </data>\n  <data name=\"LvTLS\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TransportPathTip5\" xml:space=\"preserve\">\n    <value>*kcp seed</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeyFailed\" xml:space=\"preserve\">\n    <value>Global hotkey {0} registration failed, reason: {1}</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeySuccessfully\" xml:space=\"preserve\">\n    <value>Global hotkey {0} registered successfully</value>\n  </data>\n  <data name=\"AllGroupServers\" xml:space=\"preserve\">\n    <value>All</value>\n  </data>\n  <data name=\"FillServerAddressCustom\" xml:space=\"preserve\">\n    <value>Please browse to import Configuration configuration</value>\n  </data>\n  <data name=\"Speedtesting\" xml:space=\"preserve\">\n    <value>Testing...</value>\n  </data>\n  <data name=\"LabLAN\" xml:space=\"preserve\">\n    <value>LAN</value>\n  </data>\n  <data name=\"LabLocal\" xml:space=\"preserve\">\n    <value>Local</value>\n  </data>\n  <data name=\"MsgServerTitle\" xml:space=\"preserve\">\n    <value>Filter, press Enter to execute</value>\n  </data>\n  <data name=\"menuCheckUpdate\" xml:space=\"preserve\">\n    <value>Check Update</value>\n  </data>\n  <data name=\"menuClose\" xml:space=\"preserve\">\n    <value>Close</value>\n  </data>\n  <data name=\"menuExit\" xml:space=\"preserve\">\n    <value>Exit</value>\n  </data>\n  <data name=\"menuGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Global Hotkey Setting</value>\n  </data>\n  <data name=\"menuHelp\" xml:space=\"preserve\">\n    <value>Help</value>\n  </data>\n  <data name=\"menuOptionSetting\" xml:space=\"preserve\">\n    <value>Option Setting</value>\n  </data>\n  <data name=\"menuPromotion\" xml:space=\"preserve\">\n    <value>Promotion</value>\n  </data>\n  <data name=\"menuReload\" xml:space=\"preserve\">\n    <value>Reload</value>\n  </data>\n  <data name=\"menuRoutingSetting\" xml:space=\"preserve\">\n    <value>Routing Setting</value>\n  </data>\n  <data name=\"menuServers\" xml:space=\"preserve\">\n    <value>Configuration</value>\n  </data>\n  <data name=\"menuSetting\" xml:space=\"preserve\">\n    <value>Settings</value>\n  </data>\n  <data name=\"menuSubGroupUpdate\" xml:space=\"preserve\">\n    <value>Update current subscription without proxy</value>\n  </data>\n  <data name=\"menuSubGroupUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Update current subscription with proxy</value>\n  </data>\n  <data name=\"menuSubscription\" xml:space=\"preserve\">\n    <value>Subscription Group</value>\n  </data>\n  <data name=\"menuSubSetting\" xml:space=\"preserve\">\n    <value>Subscription group settings</value>\n  </data>\n  <data name=\"menuSubUpdate\" xml:space=\"preserve\">\n    <value>Update subscriptions without proxy</value>\n  </data>\n  <data name=\"menuSubUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Update subscriptions with proxy</value>\n  </data>\n  <data name=\"menuSystemproxy\" xml:space=\"preserve\">\n    <value>System proxy</value>\n  </data>\n  <data name=\"menuSystemProxyClear\" xml:space=\"preserve\">\n    <value>Clear system proxy</value>\n  </data>\n  <data name=\"menuSystemProxyNothing\" xml:space=\"preserve\">\n    <value>Do not change system proxy</value>\n  </data>\n  <data name=\"menuSystemProxyPac\" xml:space=\"preserve\">\n    <value>PAC mode</value>\n  </data>\n  <data name=\"menuSystemProxySet\" xml:space=\"preserve\">\n    <value>Set system proxy</value>\n  </data>\n  <data name=\"TbSettingsColor\" xml:space=\"preserve\">\n    <value>Color</value>\n  </data>\n  <data name=\"TbSettingsLanguage\" xml:space=\"preserve\">\n    <value>Language (Restart)</value>\n  </data>\n  <data name=\"menuAddServerViaClipboard\" xml:space=\"preserve\">\n    <value>Import Share Links from clipboard</value>\n  </data>\n  <data name=\"menuAddServerViaScan\" xml:space=\"preserve\">\n    <value>Scan QR code on the screen</value>\n  </data>\n  <data name=\"menuCopyServer\" xml:space=\"preserve\">\n    <value>Clone selected</value>\n  </data>\n  <data name=\"menuRemoveDuplicateServer\" xml:space=\"preserve\">\n    <value>Remove duplicate</value>\n  </data>\n  <data name=\"menuRemoveServer\" xml:space=\"preserve\">\n    <value>Remove selected</value>\n  </data>\n  <data name=\"menuSetDefaultServer\" xml:space=\"preserve\">\n    <value>Set as active</value>\n  </data>\n  <data name=\"menuClearServerStatistics\" xml:space=\"preserve\">\n    <value>Clear all service statistics</value>\n  </data>\n  <data name=\"menuRealPingServer\" xml:space=\"preserve\">\n    <value>Test real delay</value>\n  </data>\n  <data name=\"menuSortServerResult\" xml:space=\"preserve\">\n    <value>Sort by test result</value>\n  </data>\n  <data name=\"menuSpeedServer\" xml:space=\"preserve\">\n    <value>Test download speed</value>\n  </data>\n  <data name=\"menuTcpingServer\" xml:space=\"preserve\">\n    <value>Test tcping</value>\n  </data>\n  <data name=\"menuExport2ClientConfig\" xml:space=\"preserve\">\n    <value>Export selected for complete configuration</value>\n  </data>\n  <data name=\"menuExport2ShareUrl\" xml:space=\"preserve\">\n    <value>Export Share Link to Clipboard</value>\n  </data>\n  <data name=\"menuAddCustomServer\" xml:space=\"preserve\">\n    <value>Add a custom configuration</value>\n  </data>\n  <data name=\"menuAddShadowsocksServer\" xml:space=\"preserve\">\n    <value>Add [Shadowsocks] </value>\n  </data>\n  <data name=\"menuAddSocksServer\" xml:space=\"preserve\">\n    <value>Add [SOCKS] </value>\n  </data>\n  <data name=\"menuAddTrojanServer\" xml:space=\"preserve\">\n    <value>Add [Trojan] </value>\n  </data>\n  <data name=\"menuAddVlessServer\" xml:space=\"preserve\">\n    <value>Add [VLESS] </value>\n  </data>\n  <data name=\"menuAddVmessServer\" xml:space=\"preserve\">\n    <value>Add [VMess] </value>\n  </data>\n  <data name=\"menuSelectAll\" xml:space=\"preserve\">\n    <value>Select all</value>\n  </data>\n  <data name=\"menuMsgViewClear\" xml:space=\"preserve\">\n    <value>Clear all</value>\n  </data>\n  <data name=\"menuMsgViewCopy\" xml:space=\"preserve\">\n    <value>Copy</value>\n  </data>\n  <data name=\"menuMsgViewCopyAll\" xml:space=\"preserve\">\n    <value>Copy all</value>\n  </data>\n  <data name=\"menuMsgViewSelectAll\" xml:space=\"preserve\">\n    <value>Select all</value>\n  </data>\n  <data name=\"menuSubAdd\" xml:space=\"preserve\">\n    <value>Add</value>\n  </data>\n  <data name=\"menuSubDelete\" xml:space=\"preserve\">\n    <value>Delete</value>\n  </data>\n  <data name=\"menuSubEdit\" xml:space=\"preserve\">\n    <value>Edit</value>\n  </data>\n  <data name=\"menuSubShare\" xml:space=\"preserve\">\n    <value>Share</value>\n  </data>\n  <data name=\"LvEnabled\" xml:space=\"preserve\">\n    <value>Enable update</value>\n  </data>\n  <data name=\"LvSort\" xml:space=\"preserve\">\n    <value>Sort</value>\n  </data>\n  <data name=\"LvUserAgent\" xml:space=\"preserve\">\n    <value>User Agent</value>\n  </data>\n  <data name=\"TbCancel\" xml:space=\"preserve\">\n    <value>Cancel</value>\n  </data>\n  <data name=\"TbConfirm\" xml:space=\"preserve\">\n    <value>Confirm</value>\n  </data>\n  <data name=\"GbTransport\" xml:space=\"preserve\">\n    <value>Transport</value>\n  </data>\n  <data name=\"TbAddress\" xml:space=\"preserve\">\n    <value>Address</value>\n  </data>\n  <data name=\"TbAllowInsecure\" xml:space=\"preserve\">\n    <value>Allow Insecure</value>\n  </data>\n  <data name=\"TbAlpn\" xml:space=\"preserve\">\n    <value>ALPN</value>\n  </data>\n  <data name=\"TbAlterId\" xml:space=\"preserve\">\n    <value>Alter ID</value>\n  </data>\n  <data name=\"TbFingerprint\" xml:space=\"preserve\">\n    <value>Fingerprint</value>\n  </data>\n  <data name=\"TbHeaderType\" xml:space=\"preserve\">\n    <value>Camouflage type</value>\n  </data>\n  <data name=\"TbId\" xml:space=\"preserve\">\n    <value>UUID(id)</value>\n  </data>\n  <data name=\"TbNetwork\" xml:space=\"preserve\">\n    <value>Transport protocol(network)</value>\n  </data>\n  <data name=\"TbPath\" xml:space=\"preserve\">\n    <value>Path</value>\n  </data>\n  <data name=\"TbPort\" xml:space=\"preserve\">\n    <value>Port</value>\n  </data>\n  <data name=\"TbRemarks\" xml:space=\"preserve\">\n    <value>Alias (remarks)</value>\n  </data>\n  <data name=\"TbRequestHost\" xml:space=\"preserve\">\n    <value>Camouflage domain(host)</value>\n  </data>\n  <data name=\"TbSecurity\" xml:space=\"preserve\">\n    <value>Encryption method (security)</value>\n  </data>\n  <data name=\"TbSNI\" xml:space=\"preserve\">\n    <value>SNI</value>\n  </data>\n  <data name=\"TbStreamSecurity\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TipNetwork\" xml:space=\"preserve\">\n    <value>*Default value tcp</value>\n  </data>\n  <data name=\"TbCoreType\" xml:space=\"preserve\">\n    <value>Core Type</value>\n  </data>\n  <data name=\"TbFlow5\" xml:space=\"preserve\">\n    <value>Flow</value>\n  </data>\n  <data name=\"TbGUID\" xml:space=\"preserve\">\n    <value>Generate</value>\n  </data>\n  <data name=\"TbId3\" xml:space=\"preserve\">\n    <value>Password</value>\n  </data>\n  <data name=\"TbId4\" xml:space=\"preserve\">\n    <value>Password(Optional)</value>\n  </data>\n  <data name=\"TbId5\" xml:space=\"preserve\">\n    <value>UUID(id)</value>\n  </data>\n  <data name=\"TbSecurity3\" xml:space=\"preserve\">\n    <value>Encryption</value>\n  </data>\n  <data name=\"TbSecurity4\" xml:space=\"preserve\">\n    <value>User(Optional)</value>\n  </data>\n  <data name=\"TbSecurity5\" xml:space=\"preserve\">\n    <value>Encryption</value>\n  </data>\n  <data name=\"TbPreSocksPort\" xml:space=\"preserve\">\n    <value>Socks port</value>\n  </data>\n  <data name=\"TipPreSocksPort\" xml:space=\"preserve\">\n    <value>* After setting this value, a socks service will be started using Xray/sing-box(Tun) to provide functions such as speed display</value>\n  </data>\n  <data name=\"TbBrowse\" xml:space=\"preserve\">\n    <value>Browse</value>\n  </data>\n  <data name=\"TbEdit\" xml:space=\"preserve\">\n    <value>Edit</value>\n  </data>\n  <data name=\"TbSettingsAdvancedProtocol\" xml:space=\"preserve\">\n    <value>Advanced proxy settings, protocol selection (optional)</value>\n  </data>\n  <data name=\"TbSettingsAllowLAN\" xml:space=\"preserve\">\n    <value>Allow connections from the LAN</value>\n  </data>\n  <data name=\"TbSettingsAutoHideStartup\" xml:space=\"preserve\">\n    <value>Auto hide on startup</value>\n  </data>\n  <data name=\"TbSettingsAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Automatic update interval for Geo files (hours)</value>\n  </data>\n  <data name=\"TbSettingsCore\" xml:space=\"preserve\">\n    <value>Core: basic settings</value>\n  </data>\n  <data name=\"TbCustomDnsRay\" xml:space=\"preserve\">\n    <value>V2ray Custom DNS</value>\n  </data>\n  <data name=\"TbSettingsCoreKcp\" xml:space=\"preserve\">\n    <value>Core: KCP settings</value>\n  </data>\n  <data name=\"TbSettingsCoreType\" xml:space=\"preserve\">\n    <value>Core Type settings</value>\n  </data>\n  <data name=\"TbSettingsDefAllowInsecure\" xml:space=\"preserve\">\n    <value>Allow Insecure</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Freedom\" xml:space=\"preserve\">\n    <value>Outbound Freedom domain Strategy</value>\n  </data>\n  <data name=\"TbSettingsEnableAutoAdjustMainLvColWidth\" xml:space=\"preserve\">\n    <value>Automatically adjust column width after subscription update</value>\n  </data>\n  <data name=\"TbSettingsEnableCheckPreReleaseUpdate\" xml:space=\"preserve\">\n    <value>Check for pre-release updates</value>\n  </data>\n  <data name=\"TbSettingsException\" xml:space=\"preserve\">\n    <value>Exception</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip\" xml:space=\"preserve\">\n    <value>Exclusions: Do not use proxy server for addresses beginning with the following. Use semicolon (;) to separate entries.</value>\n  </data>\n  <data name=\"TbSettingsDisplayRealTimeSpeed\" xml:space=\"preserve\">\n    <value>Display real-time speed (requires restart)</value>\n  </data>\n  <data name=\"TbSettingsKeepOlderDedupl\" xml:space=\"preserve\">\n    <value>Keep older entries when de-duplicating</value>\n  </data>\n  <data name=\"TbSettingsLogEnabled\" xml:space=\"preserve\">\n    <value>Enable Log</value>\n  </data>\n  <data name=\"TbSettingsLogLevel\" xml:space=\"preserve\">\n    <value>Log Level</value>\n  </data>\n  <data name=\"TbSettingsMuxEnabled\" xml:space=\"preserve\">\n    <value>Turn on Mux Multiplexing</value>\n  </data>\n  <data name=\"TbSettingsN\" xml:space=\"preserve\">\n    <value>v2rayN settings</value>\n  </data>\n  <data name=\"TbSettingsPass\" xml:space=\"preserve\">\n    <value>Auth pass</value>\n  </data>\n  <data name=\"TbSettingsRemoteDNS\" xml:space=\"preserve\">\n    <value>Custom DNS (multiple, separated by commas (,))</value>\n  </data>\n  <data name=\"TbSettingsSetUWP\" xml:space=\"preserve\">\n    <value>Set Win10 UWP Loopback</value>\n  </data>\n  <data name=\"TbSettingsSniffingEnabled\" xml:space=\"preserve\">\n    <value>Turn on Sniffing</value>\n  </data>\n  <data name=\"TbSettingsSocksPort\" xml:space=\"preserve\">\n    <value>Mixed Port</value>\n  </data>\n  <data name=\"TbSettingsStartBoot\" xml:space=\"preserve\">\n    <value>Start on boot</value>\n  </data>\n  <data name=\"TbSettingsStatistics\" xml:space=\"preserve\">\n    <value>Enable traffic statistics (requires restart)</value>\n  </data>\n  <data name=\"TbSettingsSubConvert\" xml:space=\"preserve\">\n    <value>Subscription conversion URL</value>\n  </data>\n  <data name=\"TbSettingsSystemproxy\" xml:space=\"preserve\">\n    <value>System proxy settings</value>\n  </data>\n  <data name=\"TbSettingsTrayMenuServersLimit\" xml:space=\"preserve\">\n    <value>Tray right-click menu display limit</value>\n  </data>\n  <data name=\"TbSettingsUdpEnabled\" xml:space=\"preserve\">\n    <value>Enable UDP</value>\n  </data>\n  <data name=\"TbSettingsUser\" xml:space=\"preserve\">\n    <value>Auth user</value>\n  </data>\n  <data name=\"TbClearSystemProxy\" xml:space=\"preserve\">\n    <value>Clear system proxy</value>\n  </data>\n  <data name=\"TbDisplayGUI\" xml:space=\"preserve\">\n    <value>Display GUI</value>\n  </data>\n  <data name=\"TbGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Global Hotkey Settings</value>\n  </data>\n  <data name=\"TbGlobalHotkeySettingTip\" xml:space=\"preserve\">\n    <value>Set directly by pressing the keyboard; takes effect after restart</value>\n  </data>\n  <data name=\"TbNotChangeSystemProxy\" xml:space=\"preserve\">\n    <value>Do not change system proxy</value>\n  </data>\n  <data name=\"TbReset\" xml:space=\"preserve\">\n    <value>Reset</value>\n  </data>\n  <data name=\"TbSetSystemProxy\" xml:space=\"preserve\">\n    <value>Set system proxy</value>\n  </data>\n  <data name=\"TbSystemProxyPac\" xml:space=\"preserve\">\n    <value>PAC mode</value>\n  </data>\n  <data name=\"menuShareServer\" xml:space=\"preserve\">\n    <value>Share</value>\n  </data>\n  <data name=\"menuRouting\" xml:space=\"preserve\">\n    <value>Routing</value>\n  </data>\n  <data name=\"NotRunAsAdmin\" xml:space=\"preserve\">\n    <value>Not run as Admin</value>\n  </data>\n  <data name=\"RunAsAdmin\" xml:space=\"preserve\">\n    <value>Run as Admin</value>\n  </data>\n  <data name=\"menuMoveBottom\" xml:space=\"preserve\">\n    <value>Move to bottom</value>\n  </data>\n  <data name=\"menuMoveDown\" xml:space=\"preserve\">\n    <value>Down</value>\n  </data>\n  <data name=\"menuMoveTop\" xml:space=\"preserve\">\n    <value>Move to top</value>\n  </data>\n  <data name=\"menuMoveUp\" xml:space=\"preserve\">\n    <value>Up</value>\n  </data>\n  <data name=\"MsgFilterTitle\" xml:space=\"preserve\">\n    <value>Filter, supports regular expressions</value>\n  </data>\n  <data name=\"menuWebsiteItem\" xml:space=\"preserve\">\n    <value>{0} Website</value>\n  </data>\n  <data name=\"menuRoutingAdvancedAdd\" xml:space=\"preserve\">\n    <value>Add</value>\n  </data>\n  <data name=\"menuRoutingAdvancedImportRules\" xml:space=\"preserve\">\n    <value>Import Rules</value>\n  </data>\n  <data name=\"menuRoutingAdvancedRemove\" xml:space=\"preserve\">\n    <value>Remove selected</value>\n  </data>\n  <data name=\"menuRoutingAdvancedSetDefault\" xml:space=\"preserve\">\n    <value>Set as active rule</value>\n  </data>\n  <data name=\"TbdomainStrategy\" xml:space=\"preserve\">\n    <value>Domain strategy</value>\n  </data>\n  <data name=\"TbRoutingTabRuleList\" xml:space=\"preserve\">\n    <value>Pre-defined Rule Set List</value>\n  </data>\n  <data name=\"TbRoutingTips\" xml:space=\"preserve\">\n    <value>*Separate rules by commas (,); For a literal comma use &lt;COMMA&gt;; Prefix # to ignore a rule</value>\n  </data>\n  <data name=\"menuImportRulesFromClipboard\" xml:space=\"preserve\">\n    <value>Import Rules From Clipboard</value>\n  </data>\n  <data name=\"menuImportRulesFromFile\" xml:space=\"preserve\">\n    <value>Import Rules From File</value>\n  </data>\n  <data name=\"menuImportRulesFromUrl\" xml:space=\"preserve\">\n    <value>Import Rules From Subscription URL</value>\n  </data>\n  <data name=\"menuRoutingRuleSetting\" xml:space=\"preserve\">\n    <value>Rule Settings</value>\n  </data>\n  <data name=\"menuRuleAdd\" xml:space=\"preserve\">\n    <value>Add Rule</value>\n  </data>\n  <data name=\"menuRuleExportSelected\" xml:space=\"preserve\">\n    <value>Export Selected Rules</value>\n  </data>\n  <data name=\"menuRuleList\" xml:space=\"preserve\">\n    <value>Rule List</value>\n  </data>\n  <data name=\"menuRuleRemove\" xml:space=\"preserve\">\n    <value>Remove Rule</value>\n  </data>\n  <data name=\"menuRoutingRuleDetailsSetting\" xml:space=\"preserve\">\n    <value>Routing Rule Details Setting</value>\n  </data>\n  <data name=\"TbAutoSort\" xml:space=\"preserve\">\n    <value>Domain, IP, process are auto-sorted when saving</value>\n  </data>\n  <data name=\"TbRuleobjectDoc\" xml:space=\"preserve\">\n    <value>Rule object Doc</value>\n  </data>\n  <data name=\"TbDnsObjectDoc\" xml:space=\"preserve\">\n    <value>Supports DNS Object; Click to view documentation</value>\n  </data>\n  <data name=\"SubUrlTips\" xml:space=\"preserve\">\n    <value>For group please leave blank here</value>\n  </data>\n  <data name=\"TipChangeRouting\" xml:space=\"preserve\">\n    <value>Routing setting has changed</value>\n  </data>\n  <data name=\"TipChangeSystemProxy\" xml:space=\"preserve\">\n    <value>System proxy setting has changed</value>\n  </data>\n  <data name=\"TbSettingsRouteOnly\" xml:space=\"preserve\">\n    <value>Route Only</value>\n  </data>\n  <data name=\"TbSettingsNotProxyLocalAddress\" xml:space=\"preserve\">\n    <value>Do not use proxy servers for local (intranet) addresses</value>\n  </data>\n  <data name=\"menuMixedTestServer\" xml:space=\"preserve\">\n    <value>One-click multi-test latency and speed (Ctrl+E)</value>\n  </data>\n  <data name=\"LvTestDelay\" xml:space=\"preserve\">\n    <value>Delay (ms)</value>\n  </data>\n  <data name=\"LvTestSpeed\" xml:space=\"preserve\">\n    <value>Speed (MB/s)</value>\n  </data>\n  <data name=\"FailedToRunCore\" xml:space=\"preserve\">\n    <value>Failed to run Core, please check the prompt information</value>\n  </data>\n  <data name=\"LvFilter\" xml:space=\"preserve\">\n    <value>Remarks regular filter</value>\n  </data>\n  <data name=\"TbDisplayLog\" xml:space=\"preserve\">\n    <value>Display Log</value>\n  </data>\n  <data name=\"TbEnableTunAs\" xml:space=\"preserve\">\n    <value>Enable Tun</value>\n  </data>\n  <data name=\"TbSettingsNewPort4LAN\" xml:space=\"preserve\">\n    <value>New Port for LAN</value>\n  </data>\n  <data name=\"TbSettingsTunMode\" xml:space=\"preserve\">\n    <value>Tun Mode settings</value>\n  </data>\n  <data name=\"menuMoveToGroup\" xml:space=\"preserve\">\n    <value>Move to group</value>\n  </data>\n  <data name=\"TbSettingsEnableDragDropSort\" xml:space=\"preserve\">\n    <value>Enable sorting Configurations by drag-n-drop (requires restart)</value>\n  </data>\n  <data name=\"TbAutoRefresh\" xml:space=\"preserve\">\n    <value>Auto refresh</value>\n  </data>\n  <data name=\"SpeedtestingSkip\" xml:space=\"preserve\">\n    <value>Skip test</value>\n  </data>\n  <data name=\"menuEditServer\" xml:space=\"preserve\">\n    <value>Edit </value>\n  </data>\n  <data name=\"TbSettingsDoubleClick2Activate\" xml:space=\"preserve\">\n    <value>Double-clicking Configuration makes it active</value>\n  </data>\n  <data name=\"SpeedtestingCompleted\" xml:space=\"preserve\">\n    <value>Test completed</value>\n  </data>\n  <data name=\"TbSettingsDefFingerprint\" xml:space=\"preserve\">\n    <value>Default TLS fingerprint</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgent\" xml:space=\"preserve\">\n    <value>User-Agent</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgentTips\" xml:space=\"preserve\">\n    <value>This parameter is valid only for tcp/http and ws</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamily\" xml:space=\"preserve\">\n    <value>Font family (requires restart)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyTip\" xml:space=\"preserve\">\n    <value>Copy the font TTF/TTC file to the directory gui Fonts; Reopen the settings window</value>\n  </data>\n  <data name=\"TbSettingsSocksPortTip\" xml:space=\"preserve\">\n    <value>Pac port = +3; Xray API port = +4; mihomo API port = +5;</value>\n  </data>\n  <data name=\"TbSettingsStartBootTip\" xml:space=\"preserve\">\n    <value>Set this with admin privileges, get admin privileges after startup</value>\n  </data>\n  <data name=\"TbSettingsFontSize\" xml:space=\"preserve\">\n    <value>Font Size</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestTimeout\" xml:space=\"preserve\">\n    <value>Speed Test Single Timeout Value</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestUrl\" xml:space=\"preserve\">\n    <value>Speed Test URL</value>\n  </data>\n  <data name=\"menuMoveTo\" xml:space=\"preserve\">\n    <value>Move up and down</value>\n  </data>\n  <data name=\"TbPublicKey\" xml:space=\"preserve\">\n    <value>Public Key</value>\n  </data>\n  <data name=\"TbShortId\" xml:space=\"preserve\">\n    <value>Short Id</value>\n  </data>\n  <data name=\"TbSpiderX\" xml:space=\"preserve\">\n    <value>Spider X</value>\n  </data>\n  <data name=\"TbSettingsEnableHWA\" xml:space=\"preserve\">\n    <value>Enable hardware acceleration (requires restart)</value>\n  </data>\n  <data name=\"SpeedtestingWait\" xml:space=\"preserve\">\n    <value>Waiting...</value>\n  </data>\n  <data name=\"SpeedtestingPressEscToExit\" xml:space=\"preserve\">\n    <value>Press ESC to terminate the test</value>\n  </data>\n  <data name=\"TipDisplayLog\" xml:space=\"preserve\">\n    <value>Please turn off when there is an abnormal disconnection</value>\n  </data>\n  <data name=\"MsgSkipSubscriptionUpdate\" xml:space=\"preserve\">\n    <value>Updates are not enabled, skip this subscription</value>\n  </data>\n  <data name=\"menuRebootAsAdmin\" xml:space=\"preserve\">\n    <value>Restart as Administrator</value>\n  </data>\n  <data name=\"LvMoreUrl\" xml:space=\"preserve\">\n    <value>More URLs, separated by commas; Subscription conversion will be invalid</value>\n  </data>\n  <data name=\"SpeedDisplayText\" xml:space=\"preserve\">\n    <value>{0} : {1}/s↑ | {2}/s↓</value>\n  </data>\n  <data name=\"LvAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Automatic update interval (minutes)</value>\n  </data>\n  <data name=\"TbSettingsLogEnabledToFile\" xml:space=\"preserve\">\n    <value>Enable logging to file</value>\n  </data>\n  <data name=\"LvConvertTarget\" xml:space=\"preserve\">\n    <value>Convert target type</value>\n  </data>\n  <data name=\"LvConvertTargetTip\" xml:space=\"preserve\">\n    <value>Please leave blank if no conversion is required</value>\n  </data>\n  <data name=\"menuDNSSetting\" xml:space=\"preserve\">\n    <value>DNS Settings</value>\n  </data>\n  <data name=\"TbCustomDnsSingbox\" xml:space=\"preserve\">\n    <value>sing-box Custom DNS</value>\n  </data>\n  <data name=\"TbDnsSingboxObjectDoc\" xml:space=\"preserve\">\n    <value>Please fill in DNS Structure, Click to view the document</value>\n  </data>\n  <data name=\"TbSettingDnsImportDefConfig\" xml:space=\"preserve\">\n    <value>Click to import default DNS config</value>\n  </data>\n  <data name=\"TbdomainStrategy4Singbox\" xml:space=\"preserve\">\n    <value>sing-box domain strategy</value>\n  </data>\n  <data name=\"TbSettingsMux4SboxProtocol\" xml:space=\"preserve\">\n    <value>sing-box Mux Protocol</value>\n  </data>\n  <data name=\"TbRoutingRuleProcess\" xml:space=\"preserve\">\n    <value>Process (Linux/Windows)</value>\n  </data>\n  <data name=\"TbRoutingRuleIP\" xml:space=\"preserve\">\n    <value>IP or IP CIDR</value>\n  </data>\n  <data name=\"TbRoutingRuleDomain\" xml:space=\"preserve\">\n    <value>Domain</value>\n  </data>\n  <data name=\"menuAddHysteria2Server\" xml:space=\"preserve\">\n    <value>Add [Hysteria2] </value>\n  </data>\n  <data name=\"TbSettingsHysteriaBandwidth\" xml:space=\"preserve\">\n    <value>Hysteria Max bandwidth (Up/Down)</value>\n  </data>\n  <data name=\"TbSettingsUseSystemHosts\" xml:space=\"preserve\">\n    <value>Use System Hosts</value>\n  </data>\n  <data name=\"menuAddTuicServer\" xml:space=\"preserve\">\n    <value>Add [TUIC] </value>\n  </data>\n  <data name=\"TbHeaderType8\" xml:space=\"preserve\">\n    <value>Congestion control</value>\n  </data>\n  <data name=\"LvPrevProfile\" xml:space=\"preserve\">\n    <value>Previous proxy remarks</value>\n  </data>\n  <data name=\"LvNextProfile\" xml:space=\"preserve\">\n    <value>Next proxy remarks</value>\n  </data>\n  <data name=\"LvPrevProfileTip\" xml:space=\"preserve\">\n    <value>Please make sure the Configuration remarks exist and are unique</value>\n  </data>\n  <data name=\"TbSettingsTunAutoRoute\" xml:space=\"preserve\">\n    <value>Auto Route</value>\n  </data>\n  <data name=\"TbSettingsTunStrictRoute\" xml:space=\"preserve\">\n    <value>Strict Route</value>\n  </data>\n  <data name=\"TbSettingsTunStack\" xml:space=\"preserve\">\n    <value>Stack</value>\n  </data>\n  <data name=\"TbSettingsTunMtu\" xml:space=\"preserve\">\n    <value>MTU</value>\n  </data>\n  <data name=\"TbSettingsEnableIPv6Address\" xml:space=\"preserve\">\n    <value>Enable IPv6 Address</value>\n  </data>\n  <data name=\"menuAddWireguardServer\" xml:space=\"preserve\">\n    <value>Add [WireGuard] </value>\n  </data>\n  <data name=\"TbPrivateKey\" xml:space=\"preserve\">\n    <value>Private Key</value>\n  </data>\n  <data name=\"TbReserved\" xml:space=\"preserve\">\n    <value>Reserved (2,3,4)</value>\n  </data>\n  <data name=\"TbLocalAddress\" xml:space=\"preserve\">\n    <value>Address (IPv4, IPv6)</value>\n  </data>\n  <data name=\"TbPath7\" xml:space=\"preserve\">\n    <value>obfs password</value>\n  </data>\n  <data name=\"TbRuleMatchingTips\" xml:space=\"preserve\">\n    <value>(Domain or IP or Proc Name) and Port and Protocol and Inbound Tag =&gt; Outbound Tag</value>\n  </data>\n  <data name=\"TbAutoScrollToEnd\" xml:space=\"preserve\">\n    <value>Auto scroll to end</value>\n  </data>\n  <data name=\"TbSettingsSpeedPingTestUrl\" xml:space=\"preserve\">\n    <value>Speed Ping Test URL</value>\n  </data>\n  <data name=\"SpeedtestingStop\" xml:space=\"preserve\">\n    <value>Test terminating...</value>\n  </data>\n  <data name=\"TransportRequestHostTip5\" xml:space=\"preserve\">\n    <value>*grpc Authority</value>\n  </data>\n  <data name=\"menuAddHttpServer\" xml:space=\"preserve\">\n    <value>Add [HTTP]</value>\n  </data>\n  <data name=\"TbSettingsEnableFragment\" xml:space=\"preserve\">\n    <value>Enable fragment</value>\n  </data>\n  <data name=\"TbSettingsEnableCacheFile4Sbox\" xml:space=\"preserve\">\n    <value>Enable cache file for sing-box (ruleset files)</value>\n  </data>\n  <data name=\"LvCustomRulesetPath4Singbox\" xml:space=\"preserve\">\n    <value>Customize the rule-set of sing-box</value>\n  </data>\n  <data name=\"NeedRebootTips\" xml:space=\"preserve\">\n    <value>Successful operation. Click the settings menu to reboot the app.</value>\n  </data>\n  <data name=\"menuOpenTheFileLocation\" xml:space=\"preserve\">\n    <value>Open the storage location</value>\n  </data>\n  <data name=\"TbSorting\" xml:space=\"preserve\">\n    <value>Sorting</value>\n  </data>\n  <data name=\"TbSortingChain\" xml:space=\"preserve\">\n    <value>Chain</value>\n  </data>\n  <data name=\"TbSortingDefault\" xml:space=\"preserve\">\n    <value>Default</value>\n  </data>\n  <data name=\"TbSortingDelay\" xml:space=\"preserve\">\n    <value>Delay</value>\n  </data>\n  <data name=\"TbSortingDownSpeed\" xml:space=\"preserve\">\n    <value>Download Speed</value>\n  </data>\n  <data name=\"TbSortingDownTraffic\" xml:space=\"preserve\">\n    <value>Download Traffic</value>\n  </data>\n  <data name=\"TbSortingHost\" xml:space=\"preserve\">\n    <value>Host</value>\n  </data>\n  <data name=\"TbSortingName\" xml:space=\"preserve\">\n    <value>Name</value>\n  </data>\n  <data name=\"TbSortingNetwork\" xml:space=\"preserve\">\n    <value>Network</value>\n  </data>\n  <data name=\"TbSortingTime\" xml:space=\"preserve\">\n    <value>Time</value>\n  </data>\n  <data name=\"TbSortingType\" xml:space=\"preserve\">\n    <value>Type</value>\n  </data>\n  <data name=\"TbSortingUpSpeed\" xml:space=\"preserve\">\n    <value>Upload Speed</value>\n  </data>\n  <data name=\"TbSortingUpTraffic\" xml:space=\"preserve\">\n    <value>Upload Traffic</value>\n  </data>\n  <data name=\"TbConnections\" xml:space=\"preserve\">\n    <value>Connections</value>\n  </data>\n  <data name=\"menuConnectionClose\" xml:space=\"preserve\">\n    <value>Close Connection</value>\n  </data>\n  <data name=\"menuConnectionCloseAll\" xml:space=\"preserve\">\n    <value>Close All Connections</value>\n  </data>\n  <data name=\"TbProxies\" xml:space=\"preserve\">\n    <value>Proxies</value>\n  </data>\n  <data name=\"menuRulemode\" xml:space=\"preserve\">\n    <value>Rule mode</value>\n  </data>\n  <data name=\"menuModeDirect\" xml:space=\"preserve\">\n    <value>Direct</value>\n  </data>\n  <data name=\"menuModeGlobal\" xml:space=\"preserve\">\n    <value>Global</value>\n  </data>\n  <data name=\"menuModeNothing\" xml:space=\"preserve\">\n    <value>Do not change</value>\n  </data>\n  <data name=\"menuModeRule\" xml:space=\"preserve\">\n    <value>Rule</value>\n  </data>\n  <data name=\"menuProxiesDelaytest\" xml:space=\"preserve\">\n    <value>Latency Test</value>\n  </data>\n  <data name=\"menuProxiesDelaytestPart\" xml:space=\"preserve\">\n    <value>Part Node Latency Test</value>\n  </data>\n  <data name=\"menuProxiesReload\" xml:space=\"preserve\">\n    <value>Refresh Proxies</value>\n  </data>\n  <data name=\"menuProxiesSelectActivity\" xml:space=\"preserve\">\n    <value>Select active node</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Out\" xml:space=\"preserve\">\n    <value>Default domain strategy for outbound</value>\n  </data>\n  <data name=\"TbSettingsMainGirdOrientation\" xml:space=\"preserve\">\n    <value>Main layout orientation (requires restart)</value>\n  </data>\n  <data name=\"TbSettingsDomainDNSAddress\" xml:space=\"preserve\">\n    <value>Outbound DNS address</value>\n  </data>\n  <data name=\"menuProfileAutofitColumnWidth\" xml:space=\"preserve\">\n    <value>Auto column width adjustment</value>\n  </data>\n  <data name=\"menuExport2ShareUrlBase64\" xml:space=\"preserve\">\n    <value>Export Base64-encoded Share Links to Clipboard</value>\n  </data>\n  <data name=\"menuExport2ClientConfigClipboard\" xml:space=\"preserve\">\n    <value>Export selected for complete configuration to clipboard</value>\n  </data>\n  <data name=\"menuShowOrHideMainWindow\" xml:space=\"preserve\">\n    <value>Show or hide the main window</value>\n  </data>\n  <data name=\"TbPreSocksPort4Sub\" xml:space=\"preserve\">\n    <value>Custom config socks port</value>\n  </data>\n  <data name=\"menuBackupAndRestore\" xml:space=\"preserve\">\n    <value>Backup and Restore</value>\n  </data>\n  <data name=\"menuLocalBackup\" xml:space=\"preserve\">\n    <value>Backup to local</value>\n  </data>\n  <data name=\"menuLocalRestore\" xml:space=\"preserve\">\n    <value>Restore from local</value>\n  </data>\n  <data name=\"menuRemoteBackup\" xml:space=\"preserve\">\n    <value>Backup to remote (WebDAV)</value>\n  </data>\n  <data name=\"menuRemoteRestore\" xml:space=\"preserve\">\n    <value>Restore from remote (WebDAV)</value>\n  </data>\n  <data name=\"menuLocalBackupAndRestore\" xml:space=\"preserve\">\n    <value>Local</value>\n  </data>\n  <data name=\"menuRemoteBackupAndRestore\" xml:space=\"preserve\">\n    <value>Remote (WebDAV)</value>\n  </data>\n  <data name=\"LvWebDavUrl\" xml:space=\"preserve\">\n    <value>WebDAV URL</value>\n  </data>\n  <data name=\"LvWebDavUserName\" xml:space=\"preserve\">\n    <value>WebDAV User Name</value>\n  </data>\n  <data name=\"LvWebDavPassword\" xml:space=\"preserve\">\n    <value>WebDAV Password</value>\n  </data>\n  <data name=\"LvWebDavCheck\" xml:space=\"preserve\">\n    <value>WebDAV Check</value>\n  </data>\n  <data name=\"LvWebDavDirName\" xml:space=\"preserve\">\n    <value>Remote folder name (optional)</value>\n  </data>\n  <data name=\"LocalRestoreInvalidZipTips\" xml:space=\"preserve\">\n    <value>Invalid backup file</value>\n  </data>\n  <data name=\"ConnectionsHostFilterTitle\" xml:space=\"preserve\">\n    <value>Host filter</value>\n  </data>\n  <data name=\"TipActiveServer\" xml:space=\"preserve\">\n    <value>Active</value>\n  </data>\n  <data name=\"TbSettingsGeoFilesSource\" xml:space=\"preserve\">\n    <value>Geo files source (optional)</value>\n  </data>\n  <data name=\"TbSettingsSrsFilesSource\" xml:space=\"preserve\">\n    <value>sing-box ruleset files source (optional)</value>\n  </data>\n  <data name=\"UpgradeAppNotExistTip\" xml:space=\"preserve\">\n    <value>Upgrade App does not exist</value>\n  </data>\n  <data name=\"TbSettingsRoutingRulesSource\" xml:space=\"preserve\">\n    <value>Routing rules source (optional)</value>\n  </data>\n  <data name=\"menuRegionalPresets\" xml:space=\"preserve\">\n    <value>Regional presets setting</value>\n  </data>\n  <data name=\"menuRegionalPresetsDefault\" xml:space=\"preserve\">\n    <value>Default</value>\n  </data>\n  <data name=\"menuRegionalPresetsRussia\" xml:space=\"preserve\">\n    <value>Russia</value>\n  </data>\n  <data name=\"menuRegionalPresetsIran\" xml:space=\"preserve\">\n    <value>Iran</value>\n  </data>\n  <data name=\"TbSettingsChinaUserTip\" xml:space=\"preserve\">\n    <value>Users in China region can ignore this item</value>\n  </data>\n  <data name=\"menuAddServerViaImage\" xml:space=\"preserve\">\n    <value>Scan QR code in the image</value>\n  </data>\n  <data name=\"InvalidUrlTip\" xml:space=\"preserve\">\n    <value>Invalid address (URL)</value>\n  </data>\n  <data name=\"InsecureUrlProtocol\" xml:space=\"preserve\">\n    <value>Please do not use the insecure HTTP protocol subscription address</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyLinuxTip\" xml:space=\"preserve\">\n    <value>Install the font to the system, select or fill in the font name, restart the settings</value>\n  </data>\n  <data name=\"menuExitTips\" xml:space=\"preserve\">\n    <value>Are you sure you want to exit?</value>\n  </data>\n  <data name=\"LvMemo\" xml:space=\"preserve\">\n    <value>Remarks Memo</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPassword\" xml:space=\"preserve\">\n    <value>System sudo password</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPasswordTip\" xml:space=\"preserve\">\n    <value>The password will be validated via the command line. If a validation error causes the application to malfunction, please restart the application. The password will not be stored and must be entered again after each restart.</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip5\" xml:space=\"preserve\">\n    <value>*xhttp mode</value>\n  </data>\n  <data name=\"TransportExtraTip\" xml:space=\"preserve\">\n    <value>XHTTP Extra raw JSON, format: { XHTTP Object }</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenClose\" xml:space=\"preserve\">\n    <value>Hide to tray when closing the window</value>\n  </data>\n  <data name=\"TbSettingsMixedConcurrencyCount\" xml:space=\"preserve\">\n    <value>The number of concurrent tests during multi-test</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip2\" xml:space=\"preserve\">\n    <value>Exclusions: Do not use proxy server for the following addresses. Use comma (,) to separate entries.</value>\n  </data>\n  <data name=\"TbSettingsDestOverride\" xml:space=\"preserve\">\n    <value>Sniffing type</value>\n  </data>\n  <data name=\"TbSettingsSecondLocalPortEnabled\" xml:space=\"preserve\">\n    <value>Enable second mixed port</value>\n  </data>\n  <data name=\"TbRoutingInboundTagTips\" xml:space=\"preserve\">\n    <value>socks: local port, socks2: second local port, socks3: LAN port</value>\n  </data>\n  <data name=\"TbSettingsTheme\" xml:space=\"preserve\">\n    <value>Theme</value>\n  </data>\n  <data name=\"menuCopyProxyCmdToClipboard\" xml:space=\"preserve\">\n    <value>Copy proxy command to clipboard</value>\n  </data>\n  <data name=\"SpeedtestingTestFailedPart\" xml:space=\"preserve\">\n    <value>Starting retesting failed parts, {0} remaining. Press ESC to terminate...</value>\n  </data>\n  <data name=\"menuTestServerResult\" xml:space=\"preserve\">\n    <value>By test result</value>\n  </data>\n  <data name=\"menuRemoveInvalidServerResult\" xml:space=\"preserve\">\n    <value>Remove invalid by test results</value>\n  </data>\n  <data name=\"RemoveInvalidServerResultTip\" xml:space=\"preserve\">\n    <value>Removed {0} invalid test results.</value>\n  </data>\n  <data name=\"TbPorts7\" xml:space=\"preserve\">\n    <value>Configuration port range</value>\n  </data>\n  <data name=\"TbPorts7Tips\" xml:space=\"preserve\">\n    <value>Will cover the port, separate with commas (,)</value>\n  </data>\n  <data name=\"menuExportConfig\" xml:space=\"preserve\">\n    <value>Export</value>\n  </data>\n  <data name=\"TbSettingsIPAPIUrl\" xml:space=\"preserve\">\n    <value>Current connection info test URL</value>\n  </data>\n  <data name=\"TbRuleOutboundTagTip\" xml:space=\"preserve\">\n    <value>Can fill in the configuration remarks, please make sure it exist and are unique</value>\n  </data>\n  <data name=\"SudoIncorrectPasswordTip\" xml:space=\"preserve\">\n    <value>Incorrect password, please try again.</value>\n  </data>\n  <data name=\"TbMldsa65Verify\" xml:space=\"preserve\">\n    <value>Mldsa65Verify</value>\n  </data>\n  <data name=\"menuAddAnytlsServer\" xml:space=\"preserve\">\n    <value>Add [Anytls]</value>\n  </data>\n  <data name=\"TbRemoteDNS\" xml:space=\"preserve\">\n    <value>Remote DNS</value>\n  </data>\n  <data name=\"TbDomesticDNS\" xml:space=\"preserve\">\n    <value>Domestic DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategy\" xml:space=\"preserve\">\n    <value>Direct Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategy\" xml:space=\"preserve\">\n    <value>Proxy Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbAddCommonDNSHosts\" xml:space=\"preserve\">\n    <value>Add Common DNS Hosts</value>\n  </data>\n  <data name=\"TbFakeIP\" xml:space=\"preserve\">\n    <value>FakeIP</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueries\" xml:space=\"preserve\">\n    <value>Block SVCB and HTTPS Queries</value>\n  </data>\n  <data name=\"TbDNSHostsConfig\" xml:space=\"preserve\">\n    <value>DNS Hosts: (\"domain1 ip1 ip2\" per line)</value>\n  </data>\n  <data name=\"ThBasicDNSSettings\" xml:space=\"preserve\">\n    <value>Basic DNS Settings</value>\n  </data>\n  <data name=\"ThAdvancedDNSSettings\" xml:space=\"preserve\">\n    <value>Advanced DNS Settings</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPs\" xml:space=\"preserve\">\n    <value>Validate Regional Domain IPs</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPsDesc\" xml:space=\"preserve\">\n    <value>When configured, validates IPs returned for regional domains (e.g., geosite:cn - geoip:cn), returning only expected IPs</value>\n  </data>\n  <data name=\"TbCustomDNSEnable\" xml:space=\"preserve\">\n    <value>Enable Custom DNS</value>\n  </data>\n  <data name=\"TbCustomDNSEnabledPageInvalid\" xml:space=\"preserve\">\n    <value>Custom DNS Enabled, This Page's Settings Invalid</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueriesTips\" xml:space=\"preserve\">\n    <value>Block ECH and HTTP/3 availability checks when enabled</value>\n  </data>\n  <data name=\"FillCorrectConfigTemplateText\" xml:space=\"preserve\">\n    <value>Please fill in the correct config template</value>\n  </data>\n  <data name=\"menuFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Full Config Template Setting</value>\n  </data>\n  <data name=\"TbFullConfigTemplateEnable\" xml:space=\"preserve\">\n    <value>Enable Full Config Template</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplate\" xml:space=\"preserve\">\n    <value>v2ray Full Config Template</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Add Outbound Config Only, routing.balancers and routing.rules.outboundTag, Click to view the document</value>\n  </data>\n  <data name=\"TbAddProxyProtocolOutboundOnly\" xml:space=\"preserve\">\n    <value>Do Not Add Non-Proxy Protocol Outbound</value>\n  </data>\n  <data name=\"TbSetUpstreamProxyDetour\" xml:space=\"preserve\">\n    <value>Set Upstream Proxy Tag</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplate\" xml:space=\"preserve\">\n    <value>sing-box Full Config Template</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Add Outbound and Endpoint Config Only, Click to view the document</value>\n  </data>\n  <data name=\"TbFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>This feature is intended for advanced users and those with special requirements. Once enabled, it will ignore the Core's basic settings, DNS settings, and routing settings. You must ensure that the system proxy port, traffic statistics, and other related configurations are set correctly — everything will be configured by you.</value>\n  </data>\n  <data name=\"MsgStartParsingSubscription\" xml:space=\"preserve\">\n    <value>Start parsing and processing subscription content</value>\n  </data>\n  <data name=\"TbSelectProfile\" xml:space=\"preserve\">\n    <value>Select Profile</value>\n  </data>\n  <data name=\"TbFakeIPTips\" xml:space=\"preserve\">\n    <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value>\n  </data>\n  <data name=\"PleaseAddAtLeastOneServer\" xml:space=\"preserve\">\n    <value>Please Add At Least One Configuration</value>\n  </data>\n  <data name=\"TbConfigTypePolicyGroup\" xml:space=\"preserve\">\n    <value>Policy Group</value>\n  </data>\n  <data name=\"TbConfigTypeProxyChain\" xml:space=\"preserve\">\n    <value>Proxy Chain</value>\n  </data>\n  <data name=\"TbLeastPing\" xml:space=\"preserve\">\n    <value>Lowest Latency</value>\n  </data>\n  <data name=\"TbRandom\" xml:space=\"preserve\">\n    <value>Random</value>\n  </data>\n  <data name=\"TbRoundRobin\" xml:space=\"preserve\">\n    <value>Round Robin</value>\n  </data>\n  <data name=\"TbLeastLoad\" xml:space=\"preserve\">\n    <value>Most Stable</value>\n  </data>\n  <data name=\"TbPolicyGroupType\" xml:space=\"preserve\">\n    <value>Policy Group Type</value>\n  </data>\n  <data name=\"menuAddPolicyGroupServer\" xml:space=\"preserve\">\n    <value>Add Policy Group </value>\n  </data>\n  <data name=\"menuAddProxyChainServer\" xml:space=\"preserve\">\n    <value>Add Proxy Chain</value>\n  </data>\n  <data name=\"menuAddChildServer\" xml:space=\"preserve\">\n    <value>Add Child </value>\n  </data>\n  <data name=\"menuRemoveChildServer\" xml:space=\"preserve\">\n    <value>Remove Child </value>\n  </data>\n  <data name=\"menuServerList\" xml:space=\"preserve\">\n    <value>Configuration item 1, Auto add from subscription group</value>\n  </data>\n  <data name=\"TbFallback\" xml:space=\"preserve\">\n    <value>Fallback</value>\n  </data>\n  <data name=\"MsgCoreNotSupportNetwork\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support network type '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocolTransport\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}' when using transport '{2}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}'</value>\n  </data>\n  <data name=\"MsgInvalidProperty\" xml:space=\"preserve\">\n    <value>The {0} property is invalid, please check</value>\n  </data>\n  <data name=\"MsgNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Not support protocol '{0}'</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenCloseTip\" xml:space=\"preserve\">\n    <value>If the system does not have a tray function, please do not enable it</value>\n  </data>\n  <data name=\"TbRuleTypeTips\" xml:space=\"preserve\">\n    <value>You can set separate rules for Routing and DNS, or select \"ALL\" to apply to both</value>\n  </data>\n  <data name=\"TbRuleType\" xml:space=\"preserve\">\n    <value>Rule Type</value>\n  </data>\n  <data name=\"TbBootstrapDNS\" xml:space=\"preserve\">\n    <value>Bootstrap DNS</value>\n  </data>\n  <data name=\"TbBootstrapDNSTips\" xml:space=\"preserve\">\n    <value>Resolve DNS server domains, requires IP</value>\n  </data>\n  <data name=\"menuFastRealPing\" xml:space=\"preserve\">\n    <value>Test real delay</value>\n  </data>\n  <data name=\"TbPolicyGroupSubChildTip\" xml:space=\"preserve\">\n    <value>Auto add filtered configuration from subscription groups</value>\n  </data>\n  <data name=\"TbCertPinning\" xml:space=\"preserve\">\n    <value>Certificate Pinning</value>\n  </data>\n  <data name=\"TbCertPinningTips\" xml:space=\"preserve\">\n    <value>Pinned certificate (fill in either one)\nWhen specified, the certificate will be pinned, and \"Allow Insecure\" will be disabled.\n\nThe \"Get Certificate\" action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA.</value>\n  </data>\n  <data name=\"TbFetchCert\" xml:space=\"preserve\">\n    <value>Fetch Certificate</value>\n  </data>\n  <data name=\"TbFetchCertChain\" xml:space=\"preserve\">\n    <value>Fetch Certificate Chain</value>\n  </data>\n  <data name=\"ServerNameMustBeValidDomain\" xml:space=\"preserve\">\n    <value>Please set a valid domain</value>\n  </data>\n  <data name=\"CertNotSet\" xml:space=\"preserve\">\n    <value>Certificate not set</value>\n  </data>\n  <data name=\"CertSet\" xml:space=\"preserve\">\n    <value>Certificate set</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyPacPath\" xml:space=\"preserve\">\n    <value>Custom PAC file path</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyScriptPath\" xml:space=\"preserve\">\n    <value>Custom system proxy script file path</value>\n  </data>\n  <data name=\"TbSettingsMacOSShowInDock\" xml:space=\"preserve\">\n    <value>macOS displays this in the Dock (requires restart)</value>\n  </data>\n  <data name=\"menuServerList2\" xml:space=\"preserve\">\n    <value>Configuration Item 2, Select and add from self-built</value>\n  </data>\n  <data name=\"TbEchConfigList\" xml:space=\"preserve\">\n    <value>EchConfigList</value>\n  </data>\n  <data name=\"TbEchForceQuery\" xml:space=\"preserve\">\n    <value>EchForceQuery</value>\n  </data>\n  <data name=\"TbFullCertTips\" xml:space=\"preserve\">\n    <value>Full certificate (chain), PEM format</value>\n  </data>\n  <data name=\"TbCertSha256Tips\" xml:space=\"preserve\">\n    <value>Certificate fingerprint (SHA-256)</value>\n  </data>\n  <data name=\"TbServeStale\" xml:space=\"preserve\">\n    <value>Serve Stale</value>\n  </data>\n  <data name=\"TbParallelQuery\" xml:space=\"preserve\">\n    <value>Parallel Query</value>\n  </data>\n  <data name=\"TbDomesticDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution</value>\n  </data>\n  <data name=\"TbRemoteDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution; ensure the remote server can reach this DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution uses the system DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbHopInt7\" xml:space=\"preserve\">\n    <value>Port hopping interval</value>\n  </data>\n  <data name=\"menuServerListPreview\" xml:space=\"preserve\">\n    <value>Configuration item preview</value>\n  </data>\n  <data name=\"TbFinalmask\" xml:space=\"preserve\">\n    <value>Finalmask</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeWarning\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeError\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} error: {2}. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgGroupCycleDependency\" xml:space=\"preserve\">\n    <value>Group {0} has a cycle dependency on child node {1}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupNoValidChildNode\" xml:space=\"preserve\">\n    <value>Group {0} has no valid child node.</value>\n  </data>\n  <data name=\"MsgRoutingRuleEmptyOutboundTag\" xml:space=\"preserve\">\n    <value>Routing rule {0} has an empty outbound tag. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeNotFound\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} not found. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgSubscriptionPrevProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription previous proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"MsgSubscriptionNextProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription next proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"menuGenGroupServer\" xml:space=\"preserve\">\n    <value>Generate Policy Group</value>\n  </data>\n  <data name=\"menuAllServers\" xml:space=\"preserve\">\n    <value>All configurations</value>\n  </data>\n  <data name=\"menuGenRegionGroup\" xml:space=\"preserve\">\n    <value>Group by Region</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.ru.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BatchExportURLSuccessfully\" xml:space=\"preserve\">\n    <value>Ссылка успешно скопирована в буфер обмена</value>\n  </data>\n  <data name=\"CheckServerSettings\" xml:space=\"preserve\">\n    <value>Сначала проверьте настройки сервера</value>\n  </data>\n  <data name=\"ConfigurationFormatIncorrect\" xml:space=\"preserve\">\n    <value>Недопустимый формат конфигурации</value>\n  </data>\n  <data name=\"CustomServerTips\" xml:space=\"preserve\">\n    <value>Обратите внимание, что пользовательская конфигурация полностью зависит от вашей собственной конфигурации и работает не со всеми настройками. Если вы хотите использовать системный прокси, то измените порт прослушивания вручную</value>\n  </data>\n  <data name=\"Downloading\" xml:space=\"preserve\">\n    <value>Загрузка...</value>\n  </data>\n  <data name=\"FailedConversionConfiguration\" xml:space=\"preserve\">\n    <value>Не удалось преобразовать файл конфигурации</value>\n  </data>\n  <data name=\"FailedGenDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Не удалось создать файл конфигурации по умолчанию</value>\n  </data>\n  <data name=\"FailedGetDefaultConfiguration\" xml:space=\"preserve\">\n    <value>Не удалось получить конфигурацию по умолчанию</value>\n  </data>\n  <data name=\"FailedImportedCustomServer\" xml:space=\"preserve\">\n    <value>Не удалось импортировать сервер пользовательской конфигурации</value>\n  </data>\n  <data name=\"FailedReadConfiguration\" xml:space=\"preserve\">\n    <value>Не удалось прочитать файл конфигурации</value>\n  </data>\n  <data name=\"FillCorrectServerPort\" xml:space=\"preserve\">\n    <value>Укажите порт сервера в правильном формате</value>\n  </data>\n  <data name=\"FillLocalListeningPort\" xml:space=\"preserve\">\n    <value>Введите локальный порт для прослушивания</value>\n  </data>\n  <data name=\"FillPassword\" xml:space=\"preserve\">\n    <value>Введите пароль</value>\n  </data>\n  <data name=\"FillServerAddress\" xml:space=\"preserve\">\n    <value>Введите адрес сервера</value>\n  </data>\n  <data name=\"FillUUID\" xml:space=\"preserve\">\n    <value>Введите идентификатор пользователя</value>\n  </data>\n  <data name=\"Incorrectconfiguration\" xml:space=\"preserve\">\n    <value>Некорректная конфигурация. Проверьте</value>\n  </data>\n  <data name=\"InitialConfiguration\" xml:space=\"preserve\">\n    <value>Исходная конфигурация</value>\n  </data>\n  <data name=\"IsLatestCore\" xml:space=\"preserve\">\n    <value>{0} {1} является последней версией</value>\n  </data>\n  <data name=\"IsLatestN\" xml:space=\"preserve\">\n    <value>{0} {1} является последней версией</value>\n  </data>\n  <data name=\"LvAddress\" xml:space=\"preserve\">\n    <value>Адрес</value>\n  </data>\n  <data name=\"LvEncryptionMethod\" xml:space=\"preserve\">\n    <value>Метод шифрования</value>\n  </data>\n  <data name=\"LvPort\" xml:space=\"preserve\">\n    <value>Порт</value>\n  </data>\n  <data name=\"LvServiceType\" xml:space=\"preserve\">\n    <value>Тип</value>\n  </data>\n  <data name=\"LvSubscription\" xml:space=\"preserve\">\n    <value>Группа подписки</value>\n  </data>\n  <data name=\"LvTodayDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Загружено трафика сегодня</value>\n  </data>\n  <data name=\"LvTodayUploadDataAmount\" xml:space=\"preserve\">\n    <value>Отправлено сегодня</value>\n  </data>\n  <data name=\"LvTotalDownloadDataAmount\" xml:space=\"preserve\">\n    <value>Всего загружено</value>\n  </data>\n  <data name=\"LvTotalUploadDataAmount\" xml:space=\"preserve\">\n    <value>Всего отдано</value>\n  </data>\n  <data name=\"LvTransportProtocol\" xml:space=\"preserve\">\n    <value>Протокол</value>\n  </data>\n  <data name=\"MsgDownloadV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>Ядро успешно загружено</value>\n  </data>\n  <data name=\"MsgFailedImportSubscription\" xml:space=\"preserve\">\n    <value>Не удалось импортировать подписку</value>\n  </data>\n  <data name=\"MsgGetSubscriptionSuccessfully\" xml:space=\"preserve\">\n    <value>Содержимое подписки успешно импортировано</value>\n  </data>\n  <data name=\"MsgNoValidSubscription\" xml:space=\"preserve\">\n    <value>Нет установленных подписок</value>\n  </data>\n  <data name=\"MsgParsingSuccessfully\" xml:space=\"preserve\">\n    <value>Парсинг {0} прошел успешно</value>\n  </data>\n  <data name=\"MsgStartGettingSubscriptions\" xml:space=\"preserve\">\n    <value>Начинаю получать подписки</value>\n  </data>\n  <data name=\"MsgStartUpdating\" xml:space=\"preserve\">\n    <value>Начинаю обновление {0}...</value>\n  </data>\n  <data name=\"MsgSubscriptionDecodingFailed\" xml:space=\"preserve\">\n    <value>Некорректное содержимое подписки</value>\n  </data>\n  <data name=\"MsgUnpacking\" xml:space=\"preserve\">\n    <value>Распаковка…</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionEnd\" xml:space=\"preserve\">\n    <value>Обновление подписки закончено</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionStart\" xml:space=\"preserve\">\n    <value>Обновление подписки начинается</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>Ядро успешно обновлено</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfullyMore\" xml:space=\"preserve\">\n    <value>Успешное обновление ядра! Перезапуск службы...</value>\n  </data>\n  <data name=\"NonvmessOrssProtocol\" xml:space=\"preserve\">\n    <value>Не является протоколом VMess или Shadowsocks</value>\n  </data>\n  <data name=\"NotFoundCore\" xml:space=\"preserve\">\n    <value>Файл ядра ({1}) не найден в папке {0}. Скачайте по адресу {2} и поместите его туда</value>\n  </data>\n  <data name=\"NoValidQRcodeFound\" xml:space=\"preserve\">\n    <value>Сканирование завершено, не найден корректный QR код</value>\n  </data>\n  <data name=\"OperationFailed\" xml:space=\"preserve\">\n    <value>Операция безуспешна, проверьте и попробуйте ещё раз</value>\n  </data>\n  <data name=\"PleaseFillRemarks\" xml:space=\"preserve\">\n    <value>Введите примечания</value>\n  </data>\n  <data name=\"PleaseSelectEncryption\" xml:space=\"preserve\">\n    <value>Выберите метод шифрования</value>\n  </data>\n  <data name=\"PleaseSelectProtocol\" xml:space=\"preserve\">\n    <value>Выберите протокол</value>\n  </data>\n  <data name=\"PleaseSelectServer\" xml:space=\"preserve\">\n    <value>Сначала выберите сервер</value>\n  </data>\n  <data name=\"RemoveDuplicateServerResult\" xml:space=\"preserve\">\n    <value>Удаление дублей завершено. Старая: {0}, Новая: {1}</value>\n  </data>\n  <data name=\"RemoveServer\" xml:space=\"preserve\">\n    <value>Вы уверены, что хотите удалить сервер?</value>\n  </data>\n  <data name=\"SaveClientConfigurationIn\" xml:space=\"preserve\">\n    <value>Файл конфигурации клиента сохранен по адресу: {0}</value>\n  </data>\n  <data name=\"StartService\" xml:space=\"preserve\">\n    <value>Запуск сервиса ({0})...</value>\n  </data>\n  <data name=\"SuccessfulConfiguration\" xml:space=\"preserve\">\n    <value>Конфигурация выполнена успешно {0}</value>\n  </data>\n  <data name=\"SuccessfullyImportedCustomServer\" xml:space=\"preserve\">\n    <value>Пользовательская конфигурация сервера успешно импортирована</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaClipboard\" xml:space=\"preserve\">\n    <value>{0} серверов импортировано из буфера обмена</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaScan\" xml:space=\"preserve\">\n    <value>Сканирование URL-адреса импорта прошло успешно</value>\n  </data>\n  <data name=\"TestMeOutput\" xml:space=\"preserve\">\n    <value>Задержка текущего сервера: {0} мс, {1}</value>\n  </data>\n  <data name=\"OperationSuccess\" xml:space=\"preserve\">\n    <value>Операция успешна</value>\n  </data>\n  <data name=\"PleaseSelectRules\" xml:space=\"preserve\">\n    <value>Выберите правила</value>\n  </data>\n  <data name=\"RemoveRules\" xml:space=\"preserve\">\n    <value>Вы уверены, что хотите удалить правила?</value>\n  </data>\n  <data name=\"RoutingRuleDetailRequiredTips\" xml:space=\"preserve\">\n    <value>{0}: одно из обязательных полей</value>\n  </data>\n  <data name=\"LvRemarks\" xml:space=\"preserve\">\n    <value>Примечания</value>\n  </data>\n  <data name=\"LvUrl\" xml:space=\"preserve\">\n    <value>URL (необязательно)</value>\n  </data>\n  <data name=\"LvCount\" xml:space=\"preserve\">\n    <value>Количество</value>\n  </data>\n  <data name=\"MsgNeedUrl\" xml:space=\"preserve\">\n    <value>Введите URL-адрес</value>\n  </data>\n  <data name=\"AddBatchRoutingRulesYesNo\" xml:space=\"preserve\">\n    <value>Хотите добавить правила? Выберите «Да» для добавления или «Нет» для замены</value>\n  </data>\n  <data name=\"MsgDownloadGeoFileSuccessfully\" xml:space=\"preserve\">\n    <value>Загрузка GeoFile {0} прошла успешно</value>\n  </data>\n  <data name=\"MsgInformationTitle\" xml:space=\"preserve\">\n    <value>Информация</value>\n  </data>\n  <data name=\"LvCustomIcon\" xml:space=\"preserve\">\n    <value>Пользовательская иконка</value>\n  </data>\n  <data name=\"FillCorrectDNSText\" xml:space=\"preserve\">\n    <value>Введите корректный пользовательский DNS</value>\n  </data>\n  <data name=\"TransportPathTip1\" xml:space=\"preserve\">\n    <value>*WebSocket-путь</value>\n  </data>\n  <data name=\"TransportPathTip2\" xml:space=\"preserve\">\n    <value>*HTTP2-путь</value>\n  </data>\n  <data name=\"TransportPathTip3\" xml:space=\"preserve\">\n    <value>*QUIC-ключ / KCP-seed</value>\n  </data>\n  <data name=\"TransportPathTip4\" xml:space=\"preserve\">\n    <value>Имя сервиса *gRPC</value>\n  </data>\n  <data name=\"TransportRequestHostTip1\" xml:space=\"preserve\">\n    <value>*http-хосты, разделённые запятыми (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip2\" xml:space=\"preserve\">\n    <value>*WebSocket-хост</value>\n  </data>\n  <data name=\"TransportRequestHostTip3\" xml:space=\"preserve\">\n    <value>*HTTP2-хосты, разделённые запятыми (,)</value>\n  </data>\n  <data name=\"TransportRequestHostTip4\" xml:space=\"preserve\">\n    <value>Безопасность *QUIC</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip1\" xml:space=\"preserve\">\n    <value>Тип *TCP-камуфляжа</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip2\" xml:space=\"preserve\">\n    <value>Тип *KCP-камуфляжа</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip3\" xml:space=\"preserve\">\n    <value>Тип *QUIC-камуфляжа</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip4\" xml:space=\"preserve\">\n    <value>Режим *gRPC</value>\n  </data>\n  <data name=\"LvTLS\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TransportPathTip5\" xml:space=\"preserve\">\n    <value>*KCP-seed</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeyFailed\" xml:space=\"preserve\">\n    <value>Не удалось зарегистрировать глобальную горячую клавишу {0}, причина: {1}</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeySuccessfully\" xml:space=\"preserve\">\n    <value>Глобальная горячая клавиша {0} зарегистрирована успешно</value>\n  </data>\n  <data name=\"AllGroupServers\" xml:space=\"preserve\">\n    <value>Все серверы</value>\n  </data>\n  <data name=\"FillServerAddressCustom\" xml:space=\"preserve\">\n    <value>Выберите файл конфигурации сервера для импорта</value>\n  </data>\n  <data name=\"Speedtesting\" xml:space=\"preserve\">\n    <value>Тестирование...</value>\n  </data>\n  <data name=\"LabLAN\" xml:space=\"preserve\">\n    <value>LAN</value>\n  </data>\n  <data name=\"LabLocal\" xml:space=\"preserve\">\n    <value>Локальный</value>\n  </data>\n  <data name=\"MsgServerTitle\" xml:space=\"preserve\">\n    <value>Фильтр серверов</value>\n  </data>\n  <data name=\"menuCheckUpdate\" xml:space=\"preserve\">\n    <value>Проверить обновления</value>\n  </data>\n  <data name=\"menuClose\" xml:space=\"preserve\">\n    <value>Закрыть</value>\n  </data>\n  <data name=\"menuExit\" xml:space=\"preserve\">\n    <value>Выход</value>\n  </data>\n  <data name=\"menuGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Глобальная настройка горячих клавиш</value>\n  </data>\n  <data name=\"menuHelp\" xml:space=\"preserve\">\n    <value>Помощь</value>\n  </data>\n  <data name=\"menuOptionSetting\" xml:space=\"preserve\">\n    <value>Настройка параметров</value>\n  </data>\n  <data name=\"menuPromotion\" xml:space=\"preserve\">\n    <value>Содействие</value>\n  </data>\n  <data name=\"menuReload\" xml:space=\"preserve\">\n    <value>Перезагрузка</value>\n  </data>\n  <data name=\"menuRoutingSetting\" xml:space=\"preserve\">\n    <value>Настройки маршрутизации</value>\n  </data>\n  <data name=\"menuServers\" xml:space=\"preserve\">\n    <value>Серверы</value>\n  </data>\n  <data name=\"menuSetting\" xml:space=\"preserve\">\n    <value>Настройки</value>\n  </data>\n  <data name=\"menuSubGroupUpdate\" xml:space=\"preserve\">\n    <value>Обновить текущую подписку без прокси</value>\n  </data>\n  <data name=\"menuSubGroupUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Обновить подписку через прокси</value>\n  </data>\n  <data name=\"menuSubscription\" xml:space=\"preserve\">\n    <value>Группа подписки</value>\n  </data>\n  <data name=\"menuSubSetting\" xml:space=\"preserve\">\n    <value>Настройки группы подписки</value>\n  </data>\n  <data name=\"menuSubUpdate\" xml:space=\"preserve\">\n    <value>Обновить подписку без прокси</value>\n  </data>\n  <data name=\"menuSubUpdateViaProxy\" xml:space=\"preserve\">\n    <value>Обновить подписку с прокси</value>\n  </data>\n  <data name=\"menuSystemproxy\" xml:space=\"preserve\">\n    <value>Системный прокси</value>\n  </data>\n  <data name=\"menuSystemProxyClear\" xml:space=\"preserve\">\n    <value>Очистить системный прокси</value>\n  </data>\n  <data name=\"menuSystemProxyNothing\" xml:space=\"preserve\">\n    <value>Не менять системный прокси</value>\n  </data>\n  <data name=\"menuSystemProxyPac\" xml:space=\"preserve\">\n    <value>Режим PAC</value>\n  </data>\n  <data name=\"menuSystemProxySet\" xml:space=\"preserve\">\n    <value>Установить системный прокси</value>\n  </data>\n  <data name=\"TbSettingsColor\" xml:space=\"preserve\">\n    <value>Цвет</value>\n  </data>\n  <data name=\"TbSettingsLanguage\" xml:space=\"preserve\">\n    <value>Язык (требуется перезапуск)</value>\n  </data>\n  <data name=\"menuAddServerViaClipboard\" xml:space=\"preserve\">\n    <value>Импорт массива URL из буфера обмена</value>\n  </data>\n  <data name=\"menuAddServerViaScan\" xml:space=\"preserve\">\n    <value>Сканировать QR-код с экрана</value>\n  </data>\n  <data name=\"menuCopyServer\" xml:space=\"preserve\">\n    <value>Клонировать выбранный сервер</value>\n  </data>\n  <data name=\"menuRemoveDuplicateServer\" xml:space=\"preserve\">\n    <value>Удалить дубликаты серверов</value>\n  </data>\n  <data name=\"menuRemoveServer\" xml:space=\"preserve\">\n    <value>Удалить выбранные серверы</value>\n  </data>\n  <data name=\"menuSetDefaultServer\" xml:space=\"preserve\">\n    <value>Установить как активный сервер</value>\n  </data>\n  <data name=\"menuClearServerStatistics\" xml:space=\"preserve\">\n    <value>Очистить всю статистику</value>\n  </data>\n  <data name=\"menuRealPingServer\" xml:space=\"preserve\">\n    <value>Тест на реальную задержку сервера</value>\n  </data>\n  <data name=\"menuSortServerResult\" xml:space=\"preserve\">\n    <value>Сортировать по результату теста</value>\n  </data>\n  <data name=\"menuSpeedServer\" xml:space=\"preserve\">\n    <value>Тест на скорость загрузки сервера</value>\n  </data>\n  <data name=\"menuTcpingServer\" xml:space=\"preserve\">\n    <value>Тест задержки с tcping</value>\n  </data>\n  <data name=\"menuExport2ClientConfig\" xml:space=\"preserve\">\n    <value>Экспортировать выбранный сервер для клиента</value>\n  </data>\n  <data name=\"menuExport2ShareUrl\" xml:space=\"preserve\">\n    <value>Экспорт URL-адресов общего доступа в буфер обмена</value>\n  </data>\n  <data name=\"menuAddCustomServer\" xml:space=\"preserve\">\n    <value>Добавить сервер пользовательской конфигурации</value>\n  </data>\n  <data name=\"menuAddShadowsocksServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [Shadowsocks]</value>\n  </data>\n  <data name=\"menuAddSocksServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [SOCKS]</value>\n  </data>\n  <data name=\"menuAddTrojanServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [Trojan]</value>\n  </data>\n  <data name=\"menuAddVlessServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [VLESS]</value>\n  </data>\n  <data name=\"menuAddVmessServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [VMess]</value>\n  </data>\n  <data name=\"menuSelectAll\" xml:space=\"preserve\">\n    <value>Выбрать все</value>\n  </data>\n  <data name=\"menuMsgViewClear\" xml:space=\"preserve\">\n    <value>Очистить все</value>\n  </data>\n  <data name=\"menuMsgViewCopy\" xml:space=\"preserve\">\n    <value>Скопировать</value>\n  </data>\n  <data name=\"menuMsgViewCopyAll\" xml:space=\"preserve\">\n    <value>Скопировать все</value>\n  </data>\n  <data name=\"menuMsgViewSelectAll\" xml:space=\"preserve\">\n    <value>Выбрать все</value>\n  </data>\n  <data name=\"menuSubAdd\" xml:space=\"preserve\">\n    <value>Добавить</value>\n  </data>\n  <data name=\"menuSubDelete\" xml:space=\"preserve\">\n    <value>Удалить</value>\n  </data>\n  <data name=\"menuSubEdit\" xml:space=\"preserve\">\n    <value>Редактировать</value>\n  </data>\n  <data name=\"menuSubShare\" xml:space=\"preserve\">\n    <value>Поделиться</value>\n  </data>\n  <data name=\"LvEnabled\" xml:space=\"preserve\">\n    <value>Включены обновления</value>\n  </data>\n  <data name=\"LvSort\" xml:space=\"preserve\">\n    <value>Сортировка</value>\n  </data>\n  <data name=\"LvUserAgent\" xml:space=\"preserve\">\n    <value>Заголовок User-Agent</value>\n  </data>\n  <data name=\"TbCancel\" xml:space=\"preserve\">\n    <value>Отмена</value>\n  </data>\n  <data name=\"TbConfirm\" xml:space=\"preserve\">\n    <value>Подтвердить</value>\n  </data>\n  <data name=\"GbTransport\" xml:space=\"preserve\">\n    <value>Транспорт</value>\n  </data>\n  <data name=\"TbAddress\" xml:space=\"preserve\">\n    <value>Адрес</value>\n  </data>\n  <data name=\"TbAllowInsecure\" xml:space=\"preserve\">\n    <value>Разрешить небезопасные</value>\n  </data>\n  <data name=\"TbAlpn\" xml:space=\"preserve\">\n    <value>ALPN</value>\n  </data>\n  <data name=\"TbAlterId\" xml:space=\"preserve\">\n    <value>AlterId</value>\n  </data>\n  <data name=\"TbFingerprint\" xml:space=\"preserve\">\n    <value>Отпечаток</value>\n  </data>\n  <data name=\"TbHeaderType\" xml:space=\"preserve\">\n    <value>Тип камуфляжа</value>\n  </data>\n  <data name=\"TbId\" xml:space=\"preserve\">\n    <value>UUID (id)</value>\n  </data>\n  <data name=\"TbNetwork\" xml:space=\"preserve\">\n    <value>Транспортный протокол сети</value>\n  </data>\n  <data name=\"TbPath\" xml:space=\"preserve\">\n    <value>Путь</value>\n  </data>\n  <data name=\"TbPort\" xml:space=\"preserve\">\n    <value>Порт</value>\n  </data>\n  <data name=\"TbRemarks\" xml:space=\"preserve\">\n    <value>Примечание</value>\n  </data>\n  <data name=\"TbRequestHost\" xml:space=\"preserve\">\n    <value>Маскирующий домен (хост)</value>\n  </data>\n  <data name=\"TbSecurity\" xml:space=\"preserve\">\n    <value>Метод шифрования</value>\n  </data>\n  <data name=\"TbSNI\" xml:space=\"preserve\">\n    <value>SNI</value>\n  </data>\n  <data name=\"TbStreamSecurity\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TipNetwork\" xml:space=\"preserve\">\n    <value>*По-умолчанию TCP</value>\n  </data>\n  <data name=\"TbCoreType\" xml:space=\"preserve\">\n    <value>Ядро</value>\n  </data>\n  <data name=\"TbFlow5\" xml:space=\"preserve\">\n    <value>Поток</value>\n  </data>\n  <data name=\"TbGUID\" xml:space=\"preserve\">\n    <value>Генерировать</value>\n  </data>\n  <data name=\"TbId3\" xml:space=\"preserve\">\n    <value>Пароль</value>\n  </data>\n  <data name=\"TbId4\" xml:space=\"preserve\">\n    <value>Пароль(Необязательно)</value>\n  </data>\n  <data name=\"TbId5\" xml:space=\"preserve\">\n    <value>UUID(id)</value>\n  </data>\n  <data name=\"TbSecurity3\" xml:space=\"preserve\">\n    <value>Шифрование</value>\n  </data>\n  <data name=\"TbSecurity4\" xml:space=\"preserve\">\n    <value>Пользователь(Необязательно)</value>\n  </data>\n  <data name=\"TbSecurity5\" xml:space=\"preserve\">\n    <value>Шифрования</value>\n  </data>\n  <data name=\"TbPreSocksPort\" xml:space=\"preserve\">\n    <value>Порт SOCKS</value>\n  </data>\n  <data name=\"TipPreSocksPort\" xml:space=\"preserve\">\n    <value>* После установки этого значения служба SOCKS будет запущена с использованием Xray/sing-box(TUN) для обеспечения таких функций, как отображение скорости</value>\n  </data>\n  <data name=\"TbBrowse\" xml:space=\"preserve\">\n    <value>Просмотр</value>\n  </data>\n  <data name=\"TbEdit\" xml:space=\"preserve\">\n    <value>Редактировать</value>\n  </data>\n  <data name=\"TbSettingsAdvancedProtocol\" xml:space=\"preserve\">\n    <value>Расширенные настройки прокси, выбор протокола (необязательно)</value>\n  </data>\n  <data name=\"TbSettingsAllowLAN\" xml:space=\"preserve\">\n    <value>Разрешить подключения из локальной сети</value>\n  </data>\n  <data name=\"TbSettingsAutoHideStartup\" xml:space=\"preserve\">\n    <value>Автоскрытие при автозапуске</value>\n  </data>\n  <data name=\"TbSettingsAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Интервал автоматического обновления Geo в часах</value>\n  </data>\n  <data name=\"TbSettingsCore\" xml:space=\"preserve\">\n    <value>Ядро: базовые настройки</value>\n  </data>\n  <data name=\"TbCustomDnsRay\" xml:space=\"preserve\">\n    <value>V2ray Custom DNS</value>\n  </data>\n  <data name=\"TbSettingsCoreKcp\" xml:space=\"preserve\">\n    <value>Ядро: настройки KCP</value>\n  </data>\n  <data name=\"TbSettingsCoreType\" xml:space=\"preserve\">\n    <value>Настройки типа ядра</value>\n  </data>\n  <data name=\"TbSettingsDefAllowInsecure\" xml:space=\"preserve\">\n    <value>Разрешить небезопасные</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Freedom\" xml:space=\"preserve\">\n    <value>«Freedom»: стратегия обработки доменов исходящего трафика</value>\n  </data>\n  <data name=\"TbSettingsEnableAutoAdjustMainLvColWidth\" xml:space=\"preserve\">\n    <value>Автоматически регулировать ширину столбца после обновления подписки</value>\n  </data>\n  <data name=\"TbSettingsEnableCheckPreReleaseUpdate\" xml:space=\"preserve\">\n    <value>Проверить наличие предварительных обновлений</value>\n  </data>\n  <data name=\"TbSettingsException\" xml:space=\"preserve\">\n    <value>Исключение</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip\" xml:space=\"preserve\">\n    <value>Исключение. Не используйте прокси-сервер для адресов, начинающихся с (,), используйте точку с запятой (;)</value>\n  </data>\n  <data name=\"TbSettingsDisplayRealTimeSpeed\" xml:space=\"preserve\">\n    <value>Показывать скорость в реальном времени</value>\n  </data>\n  <data name=\"TbSettingsKeepOlderDedupl\" xml:space=\"preserve\">\n    <value>Сохранить старые при удалении дублей</value>\n  </data>\n  <data name=\"TbSettingsLogEnabled\" xml:space=\"preserve\">\n    <value>Записывать логи</value>\n  </data>\n  <data name=\"TbSettingsLogLevel\" xml:space=\"preserve\">\n    <value>Уровень записи логов</value>\n  </data>\n  <data name=\"TbSettingsMuxEnabled\" xml:space=\"preserve\">\n    <value>Включить мультиплексирование Mux</value>\n  </data>\n  <data name=\"TbSettingsN\" xml:space=\"preserve\">\n    <value>Настройки v2rayN</value>\n  </data>\n  <data name=\"TbSettingsPass\" xml:space=\"preserve\">\n    <value>Пароль аутентификации</value>\n  </data>\n  <data name=\"TbSettingsRemoteDNS\" xml:space=\"preserve\">\n    <value>Пользовательский DNS (если несколько, то делите запятыми (,))</value>\n  </data>\n  <data name=\"TbSettingsSetUWP\" xml:space=\"preserve\">\n    <value>Разрешить loopback для приложений UWP (Win10)</value>\n  </data>\n  <data name=\"TbSettingsSniffingEnabled\" xml:space=\"preserve\">\n    <value>Включить сниффинг</value>\n  </data>\n  <data name=\"TbSettingsSocksPort\" xml:space=\"preserve\">\n    <value>Смешанный порт</value>\n  </data>\n  <data name=\"TbSettingsStartBoot\" xml:space=\"preserve\">\n    <value>Автозапуск</value>\n  </data>\n  <data name=\"TbSettingsStatistics\" xml:space=\"preserve\">\n    <value>Включить статистику (требуется перезагрузка)</value>\n  </data>\n  <data name=\"TbSettingsSubConvert\" xml:space=\"preserve\">\n    <value>URL конвертации подписок</value>\n  </data>\n  <data name=\"TbSettingsSystemproxy\" xml:space=\"preserve\">\n    <value>Настройки системного прокси</value>\n  </data>\n  <data name=\"TbSettingsTrayMenuServersLimit\" xml:space=\"preserve\">\n    <value>Лимит серверов в меню трея</value>\n  </data>\n  <data name=\"TbSettingsUdpEnabled\" xml:space=\"preserve\">\n    <value>Включить UDP</value>\n  </data>\n  <data name=\"TbSettingsUser\" xml:space=\"preserve\">\n    <value>Имя пользователя (логин)</value>\n  </data>\n  <data name=\"TbClearSystemProxy\" xml:space=\"preserve\">\n    <value>Очистить системный прокси</value>\n  </data>\n  <data name=\"TbDisplayGUI\" xml:space=\"preserve\">\n    <value>Показать GUI</value>\n  </data>\n  <data name=\"TbGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>Настройка горячих клавиш</value>\n  </data>\n  <data name=\"TbGlobalHotkeySettingTip\" xml:space=\"preserve\">\n    <value>Установите непосредственно, нажав на клавиатуру, вступит в силу после перезапуска</value>\n  </data>\n  <data name=\"TbNotChangeSystemProxy\" xml:space=\"preserve\">\n    <value>Не изменять системный прокси</value>\n  </data>\n  <data name=\"TbReset\" xml:space=\"preserve\">\n    <value>Обнулить</value>\n  </data>\n  <data name=\"TbSetSystemProxy\" xml:space=\"preserve\">\n    <value>Установить системный прокси</value>\n  </data>\n  <data name=\"TbSystemProxyPac\" xml:space=\"preserve\">\n    <value>Режим PAC</value>\n  </data>\n  <data name=\"menuShareServer\" xml:space=\"preserve\">\n    <value>Поделиться сервером</value>\n  </data>\n  <data name=\"menuRouting\" xml:space=\"preserve\">\n    <value>Маршрутизация</value>\n  </data>\n  <data name=\"NotRunAsAdmin\" xml:space=\"preserve\">\n    <value>Пользователь</value>\n  </data>\n  <data name=\"RunAsAdmin\" xml:space=\"preserve\">\n    <value>Администратор</value>\n  </data>\n  <data name=\"menuMoveBottom\" xml:space=\"preserve\">\n    <value>Спуститься вниз</value>\n  </data>\n  <data name=\"menuMoveDown\" xml:space=\"preserve\">\n    <value>Вниз</value>\n  </data>\n  <data name=\"menuMoveTop\" xml:space=\"preserve\">\n    <value>Подняться наверх</value>\n  </data>\n  <data name=\"menuMoveUp\" xml:space=\"preserve\">\n    <value>Вверх</value>\n  </data>\n  <data name=\"MsgFilterTitle\" xml:space=\"preserve\">\n    <value>Фильтр, поддерживает regex</value>\n  </data>\n  <data name=\"menuWebsiteItem\" xml:space=\"preserve\">\n    <value>{0} веб-сайт</value>\n  </data>\n  <data name=\"menuRoutingAdvancedAdd\" xml:space=\"preserve\">\n    <value>Добавить</value>\n  </data>\n  <data name=\"menuRoutingAdvancedImportRules\" xml:space=\"preserve\">\n    <value>Добавить расширенные правила</value>\n  </data>\n  <data name=\"menuRoutingAdvancedRemove\" xml:space=\"preserve\">\n    <value>Удалить выбранные</value>\n  </data>\n  <data name=\"menuRoutingAdvancedSetDefault\" xml:space=\"preserve\">\n    <value>Установить как активное правило</value>\n  </data>\n  <data name=\"TbdomainStrategy\" xml:space=\"preserve\">\n    <value>Доменная стратегия</value>\n  </data>\n  <data name=\"TbRoutingTabRuleList\" xml:space=\"preserve\">\n    <value>Предустановленный список наборов правил</value>\n  </data>\n  <data name=\"TbRoutingTips\" xml:space=\"preserve\">\n    <value>*Разделяйте правила запятыми (,). Литерал «,» — &lt;COMMA&gt;. Префикс # — отключить правило</value>\n  </data>\n  <data name=\"menuImportRulesFromClipboard\" xml:space=\"preserve\">\n    <value>Импорт правил из буфера обмена</value>\n  </data>\n  <data name=\"menuImportRulesFromFile\" xml:space=\"preserve\">\n    <value>Импорт правил из файла</value>\n  </data>\n  <data name=\"menuImportRulesFromUrl\" xml:space=\"preserve\">\n    <value>Импорт правил из URL</value>\n  </data>\n  <data name=\"menuRoutingRuleSetting\" xml:space=\"preserve\">\n    <value>Настройка правил</value>\n  </data>\n  <data name=\"menuRuleAdd\" xml:space=\"preserve\">\n    <value>Добавить правило</value>\n  </data>\n  <data name=\"menuRuleExportSelected\" xml:space=\"preserve\">\n    <value>Экспорт выделенных правил</value>\n  </data>\n  <data name=\"menuRuleList\" xml:space=\"preserve\">\n    <value>Список правил</value>\n  </data>\n  <data name=\"menuRuleRemove\" xml:space=\"preserve\">\n    <value>Удалить правила</value>\n  </data>\n  <data name=\"menuRoutingRuleDetailsSetting\" xml:space=\"preserve\">\n    <value>Детальные настройки правил маршрутизации</value>\n  </data>\n  <data name=\"TbAutoSort\" xml:space=\"preserve\">\n    <value>Домен и IP автоматически сортируются при сохранении</value>\n  </data>\n  <data name=\"TbRuleobjectDoc\" xml:space=\"preserve\">\n    <value>Документация RuleObject</value>\n  </data>\n  <data name=\"TbDnsObjectDoc\" xml:space=\"preserve\">\n    <value>Поддерживаются DNS-объекты, нажмите для просмотра документации</value>\n  </data>\n  <data name=\"SubUrlTips\" xml:space=\"preserve\">\n    <value>Необязательное поле</value>\n  </data>\n  <data name=\"TipChangeRouting\" xml:space=\"preserve\">\n    <value>Настройки маршрутизации изменены</value>\n  </data>\n  <data name=\"TipChangeSystemProxy\" xml:space=\"preserve\">\n    <value>Системные прокси изменены</value>\n  </data>\n  <data name=\"TbSettingsRouteOnly\" xml:space=\"preserve\">\n    <value>Только маршрут</value>\n  </data>\n  <data name=\"TbSettingsNotProxyLocalAddress\" xml:space=\"preserve\">\n    <value>Не используйте прокси-серверы для локальных (интранет) адресов</value>\n  </data>\n  <data name=\"menuMixedTestServer\" xml:space=\"preserve\">\n    <value>Тест задержки и скорости всех серверов (Ctrl+E)</value>\n  </data>\n  <data name=\"LvTestDelay\" xml:space=\"preserve\">\n    <value>Задержка (мс)</value>\n  </data>\n  <data name=\"LvTestSpeed\" xml:space=\"preserve\">\n    <value>Скорость (МБ/с)</value>\n  </data>\n  <data name=\"FailedToRunCore\" xml:space=\"preserve\">\n    <value>Не удалось запустить ядро, посмотрите логи</value>\n  </data>\n  <data name=\"LvFilter\" xml:space=\"preserve\">\n    <value>Фильтр примечаний (Regex)</value>\n  </data>\n  <data name=\"TbDisplayLog\" xml:space=\"preserve\">\n    <value>Показать логи</value>\n  </data>\n  <data name=\"TbEnableTunAs\" xml:space=\"preserve\">\n    <value>Режим VPN</value>\n  </data>\n  <data name=\"TbSettingsNewPort4LAN\" xml:space=\"preserve\">\n    <value>Новый порт для локальной сети</value>\n  </data>\n  <data name=\"TbSettingsTunMode\" xml:space=\"preserve\">\n    <value>Настройки режима TUN</value>\n  </data>\n  <data name=\"menuMoveToGroup\" xml:space=\"preserve\">\n    <value>Перейти в группу</value>\n  </data>\n  <data name=\"TbSettingsEnableDragDropSort\" xml:space=\"preserve\">\n    <value>Включить сортировку перетаскиванием сервера (требуется перезагрузка)</value>\n  </data>\n  <data name=\"TbAutoRefresh\" xml:space=\"preserve\">\n    <value>Автообновление</value>\n  </data>\n  <data name=\"SpeedtestingSkip\" xml:space=\"preserve\">\n    <value>Пропустить тест</value>\n  </data>\n  <data name=\"menuEditServer\" xml:space=\"preserve\">\n    <value>Редактировать сервер</value>\n  </data>\n  <data name=\"TbSettingsDoubleClick2Activate\" xml:space=\"preserve\">\n    <value>Двойной клик чтобы сделать сервер активным</value>\n  </data>\n  <data name=\"SpeedtestingCompleted\" xml:space=\"preserve\">\n    <value>Тест завершен</value>\n  </data>\n  <data name=\"TbSettingsDefFingerprint\" xml:space=\"preserve\">\n    <value>TLS отпечаток по умолчанию</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgent\" xml:space=\"preserve\">\n    <value>User-Agent</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgentTips\" xml:space=\"preserve\">\n    <value>Параметр действует только для TCP/HTTP и WebSocket (WS)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamily\" xml:space=\"preserve\">\n    <value>Шрифт (требуется перезагрузка)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyTip\" xml:space=\"preserve\">\n    <value>Скопируйте файл шрифта TTF/TTC в каталог guiFonts и заново откройте окно настроек</value>\n  </data>\n  <data name=\"TbSettingsSocksPortTip\" xml:space=\"preserve\">\n    <value>Pac порт = +3,Xray API порт = +4, mihomo API порт = +5</value>\n  </data>\n  <data name=\"TbSettingsStartBootTip\" xml:space=\"preserve\">\n    <value>Установите это с правами администратора</value>\n  </data>\n  <data name=\"TbSettingsFontSize\" xml:space=\"preserve\">\n    <value>Размер шрифта</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestTimeout\" xml:space=\"preserve\">\n    <value>Тайм-аут одиночного тестирования скорости</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestUrl\" xml:space=\"preserve\">\n    <value>URL для тестирования скорости</value>\n  </data>\n  <data name=\"menuMoveTo\" xml:space=\"preserve\">\n    <value>Переместить вверх/вниз</value>\n  </data>\n  <data name=\"TbPublicKey\" xml:space=\"preserve\">\n    <value>PublicKey</value>\n  </data>\n  <data name=\"TbShortId\" xml:space=\"preserve\">\n    <value>ShortId</value>\n  </data>\n  <data name=\"TbSpiderX\" xml:space=\"preserve\">\n    <value>SpiderX</value>\n  </data>\n  <data name=\"TbSettingsEnableHWA\" xml:space=\"preserve\">\n    <value>Включить аппаратное ускорение (требуется перезагрузка)</value>\n  </data>\n  <data name=\"SpeedtestingWait\" xml:space=\"preserve\">\n    <value>Ожидание тестирования…</value>\n  </data>\n  <data name=\"SpeedtestingPressEscToExit\" xml:space=\"preserve\">\n    <value>нажмите ESC для отмены</value>\n  </data>\n  <data name=\"TipDisplayLog\" xml:space=\"preserve\">\n    <value>Отключите при аномальном разрыве соединения</value>\n  </data>\n  <data name=\"MsgSkipSubscriptionUpdate\" xml:space=\"preserve\">\n    <value>Обновления не включены — подписка пропущена</value>\n  </data>\n  <data name=\"menuRebootAsAdmin\" xml:space=\"preserve\">\n    <value>Перезагрузить как администратор</value>\n  </data>\n  <data name=\"LvMoreUrl\" xml:space=\"preserve\">\n    <value>Дополнительные URL через запятую, конвертация подписки недоступна</value>\n  </data>\n  <data name=\"SpeedDisplayText\" xml:space=\"preserve\">\n    <value>{0} : {1}/s↑ | {2}/s↓</value>\n  </data>\n  <data name=\"LvAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>Интервал автоматического обновления в минутах</value>\n  </data>\n  <data name=\"TbSettingsLogEnabledToFile\" xml:space=\"preserve\">\n    <value>Включить запись логов в файл</value>\n  </data>\n  <data name=\"LvConvertTarget\" xml:space=\"preserve\">\n    <value>Преобразовать тип цели</value>\n  </data>\n  <data name=\"LvConvertTargetTip\" xml:space=\"preserve\">\n    <value>Если преобразование не требуется, оставьте поле пустым</value>\n  </data>\n  <data name=\"menuDNSSetting\" xml:space=\"preserve\">\n    <value>Настройки DNS</value>\n  </data>\n  <data name=\"TbCustomDnsSingbox\" xml:space=\"preserve\">\n    <value>sing-box Custom DNS</value>\n  </data>\n  <data name=\"TbDnsSingboxObjectDoc\" xml:space=\"preserve\">\n    <value>Заполните структуру DNS, нажмите, чтобы открыть документ</value>\n  </data>\n  <data name=\"TbSettingDnsImportDefConfig\" xml:space=\"preserve\">\n    <value>Нажмите, чтобы импортировать конфигурацию DNS по умолчанию</value>\n  </data>\n  <data name=\"TbdomainStrategy4Singbox\" xml:space=\"preserve\">\n    <value>Стратегия домена для sing-box</value>\n  </data>\n  <data name=\"TbSettingsMux4SboxProtocol\" xml:space=\"preserve\">\n    <value>Протокол Mux для sing-box</value>\n  </data>\n  <data name=\"TbRoutingRuleProcess\" xml:space=\"preserve\">\n    <value>Process (Linux/Windows)</value>\n  </data>\n  <data name=\"TbRoutingRuleIP\" xml:space=\"preserve\">\n    <value>IP-адрес или сеть CIDR</value>\n  </data>\n  <data name=\"TbRoutingRuleDomain\" xml:space=\"preserve\">\n    <value>Домен</value>\n  </data>\n  <data name=\"menuAddHysteria2Server\" xml:space=\"preserve\">\n    <value>Добавить сервер [Hysteria2]</value>\n  </data>\n  <data name=\"TbSettingsHysteriaBandwidth\" xml:space=\"preserve\">\n    <value>Максимальная пропускная способность Hysteria (загрузка/отдача)</value>\n  </data>\n  <data name=\"TbSettingsUseSystemHosts\" xml:space=\"preserve\">\n    <value>Использовать системные узлы</value>\n  </data>\n  <data name=\"menuAddTuicServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [TUIC]</value>\n  </data>\n  <data name=\"TbHeaderType8\" xml:space=\"preserve\">\n    <value>Контроль перегрузок</value>\n  </data>\n  <data name=\"LvPrevProfile\" xml:space=\"preserve\">\n    <value>Примечания к предыдущему прокси</value>\n  </data>\n  <data name=\"LvNextProfile\" xml:space=\"preserve\">\n    <value>Примечания к следующему прокси</value>\n  </data>\n  <data name=\"LvPrevProfileTip\" xml:space=\"preserve\">\n    <value>Убедитесь, что примечание существует и является уникальным</value>\n  </data>\n  <data name=\"TbSettingsTunAutoRoute\" xml:space=\"preserve\">\n    <value>Автоматическая маршрутизация</value>\n  </data>\n  <data name=\"TbSettingsTunStrictRoute\" xml:space=\"preserve\">\n    <value>Строгая маршрутизация</value>\n  </data>\n  <data name=\"TbSettingsTunStack\" xml:space=\"preserve\">\n    <value>Сетевой стек</value>\n  </data>\n  <data name=\"TbSettingsTunMtu\" xml:space=\"preserve\">\n    <value>MTU</value>\n  </data>\n  <data name=\"TbSettingsEnableIPv6Address\" xml:space=\"preserve\">\n    <value>Включить IPv6 адреса</value>\n  </data>\n  <data name=\"menuAddWireguardServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [WireGuard]</value>\n  </data>\n  <data name=\"TbPrivateKey\" xml:space=\"preserve\">\n    <value>Приватный ключ</value>\n  </data>\n  <data name=\"TbReserved\" xml:space=\"preserve\">\n    <value>Зарезервировано (2, 3, 4)</value>\n  </data>\n  <data name=\"TbLocalAddress\" xml:space=\"preserve\">\n    <value>Адрес (Ipv4,Ipv6)</value>\n  </data>\n  <data name=\"TbPath7\" xml:space=\"preserve\">\n    <value>Пароль obfs</value>\n  </data>\n  <data name=\"TbRuleMatchingTips\" xml:space=\"preserve\">\n    <value>(Домен или IP или имя процесса) и порт, и протокол, и InboundTag =&gt; OutboundTag</value>\n  </data>\n  <data name=\"TbAutoScrollToEnd\" xml:space=\"preserve\">\n    <value>Автоматическая прокрутка в конец</value>\n  </data>\n  <data name=\"TbSettingsSpeedPingTestUrl\" xml:space=\"preserve\">\n    <value>URL для быстрой проверки реальной задержки</value>\n  </data>\n  <data name=\"SpeedtestingStop\" xml:space=\"preserve\">\n    <value>Отмена тестирования...</value>\n  </data>\n  <data name=\"TransportRequestHostTip5\" xml:space=\"preserve\">\n    <value>* gRPC Authority (HTTP/2 псевдозаголовок :authority)</value>\n  </data>\n  <data name=\"menuAddHttpServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [HTTP]</value>\n  </data>\n  <data name=\"TbSettingsEnableFragment\" xml:space=\"preserve\">\n    <value>Включить фрагментацию (Fragment)</value>\n  </data>\n  <data name=\"TbSettingsEnableCacheFile4Sbox\" xml:space=\"preserve\">\n    <value>Включить файл кэша для sing-box (файлы наборов правил)</value>\n  </data>\n  <data name=\"LvCustomRulesetPath4Singbox\" xml:space=\"preserve\">\n    <value>Пользовательский набор правил для sing-box</value>\n  </data>\n  <data name=\"NeedRebootTips\" xml:space=\"preserve\">\n    <value>Операция успешна. Перезапустите приложение</value>\n  </data>\n  <data name=\"menuOpenTheFileLocation\" xml:space=\"preserve\">\n    <value>Открыть место хранения</value>\n  </data>\n  <data name=\"TbSorting\" xml:space=\"preserve\">\n    <value>Сортировка</value>\n  </data>\n  <data name=\"TbSortingChain\" xml:space=\"preserve\">\n    <value>Цепочка</value>\n  </data>\n  <data name=\"TbSortingDefault\" xml:space=\"preserve\">\n    <value>По умолчанию</value>\n  </data>\n  <data name=\"TbSortingDelay\" xml:space=\"preserve\">\n    <value>Задержка</value>\n  </data>\n  <data name=\"TbSortingDownSpeed\" xml:space=\"preserve\">\n    <value>Скорость загрузки</value>\n  </data>\n  <data name=\"TbSortingDownTraffic\" xml:space=\"preserve\">\n    <value>Скачанный трафик</value>\n  </data>\n  <data name=\"TbSortingHost\" xml:space=\"preserve\">\n    <value>Узел</value>\n  </data>\n  <data name=\"TbSortingName\" xml:space=\"preserve\">\n    <value>Имя</value>\n  </data>\n  <data name=\"TbSortingNetwork\" xml:space=\"preserve\">\n    <value>Сеть</value>\n  </data>\n  <data name=\"TbSortingTime\" xml:space=\"preserve\">\n    <value>Время</value>\n  </data>\n  <data name=\"TbSortingType\" xml:space=\"preserve\">\n    <value>Тип</value>\n  </data>\n  <data name=\"TbSortingUpSpeed\" xml:space=\"preserve\">\n    <value>Скорость отдачи</value>\n  </data>\n  <data name=\"TbSortingUpTraffic\" xml:space=\"preserve\">\n    <value>Отправленный трафик</value>\n  </data>\n  <data name=\"TbConnections\" xml:space=\"preserve\">\n    <value>Соединения</value>\n  </data>\n  <data name=\"menuConnectionClose\" xml:space=\"preserve\">\n    <value>Закрыть соединение</value>\n  </data>\n  <data name=\"menuConnectionCloseAll\" xml:space=\"preserve\">\n    <value>Закрыть все соединения</value>\n  </data>\n  <data name=\"TbProxies\" xml:space=\"preserve\">\n    <value>Прокси</value>\n  </data>\n  <data name=\"menuRulemode\" xml:space=\"preserve\">\n    <value>Режим правила</value>\n  </data>\n  <data name=\"menuModeDirect\" xml:space=\"preserve\">\n    <value>Прямое соединение</value>\n  </data>\n  <data name=\"menuModeGlobal\" xml:space=\"preserve\">\n    <value>Глобальный режим</value>\n  </data>\n  <data name=\"menuModeNothing\" xml:space=\"preserve\">\n    <value>Не менять</value>\n  </data>\n  <data name=\"menuModeRule\" xml:space=\"preserve\">\n    <value>Правила</value>\n  </data>\n  <data name=\"menuProxiesDelaytest\" xml:space=\"preserve\">\n    <value>Тест задержки</value>\n  </data>\n  <data name=\"menuProxiesDelaytestPart\" xml:space=\"preserve\">\n    <value>Тест задержки выбранных узлов</value>\n  </data>\n  <data name=\"menuProxiesReload\" xml:space=\"preserve\">\n    <value>Обновить прокси</value>\n  </data>\n  <data name=\"menuProxiesSelectActivity\" xml:space=\"preserve\">\n    <value>Сделать узел активным</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Out\" xml:space=\"preserve\">\n    <value>Стратегия домена по умолчанию для исходящих</value>\n  </data>\n  <data name=\"TbSettingsMainGirdOrientation\" xml:space=\"preserve\">\n    <value>Основная ориентация макета (требуется перезагрузка)</value>\n  </data>\n  <data name=\"TbSettingsDomainDNSAddress\" xml:space=\"preserve\">\n    <value>Исходящий DNS адрес</value>\n  </data>\n  <data name=\"menuProfileAutofitColumnWidth\" xml:space=\"preserve\">\n    <value>Автоматическая регулировка ширины столбца</value>\n  </data>\n  <data name=\"menuExport2ShareUrlBase64\" xml:space=\"preserve\">\n    <value>Экспорт ссылок в формате Base64 в буфер обмена</value>\n  </data>\n  <data name=\"menuExport2ClientConfigClipboard\" xml:space=\"preserve\">\n    <value>Экспортировать выбранный сервер для полной конфигурации в буфер обмена</value>\n  </data>\n  <data name=\"menuShowOrHideMainWindow\" xml:space=\"preserve\">\n    <value>Показать или скрыть главное окно</value>\n  </data>\n  <data name=\"TbPreSocksPort4Sub\" xml:space=\"preserve\">\n    <value>Пользовательская конфигурация порта SOCKS</value>\n  </data>\n  <data name=\"menuBackupAndRestore\" xml:space=\"preserve\">\n    <value>Резервное копирование и восстановление</value>\n  </data>\n  <data name=\"menuLocalBackup\" xml:space=\"preserve\">\n    <value>Сохранить в файл</value>\n  </data>\n  <data name=\"menuLocalRestore\" xml:space=\"preserve\">\n    <value>Восстановить из файла</value>\n  </data>\n  <data name=\"menuRemoteBackup\" xml:space=\"preserve\">\n    <value>Резервное копирование на удалённый сервер (WebDAV)</value>\n  </data>\n  <data name=\"menuRemoteRestore\" xml:space=\"preserve\">\n    <value>Восстановить с удалённого сервера (WebDAV)</value>\n  </data>\n  <data name=\"menuLocalBackupAndRestore\" xml:space=\"preserve\">\n    <value>Локально</value>\n  </data>\n  <data name=\"menuRemoteBackupAndRestore\" xml:space=\"preserve\">\n    <value>Удалённо (WebDAV)</value>\n  </data>\n  <data name=\"LvWebDavUrl\" xml:space=\"preserve\">\n    <value>URL WebDAV</value>\n  </data>\n  <data name=\"LvWebDavUserName\" xml:space=\"preserve\">\n    <value>Имя пользователя WebDAV</value>\n  </data>\n  <data name=\"LvWebDavPassword\" xml:space=\"preserve\">\n    <value>Пароль WebDAV</value>\n  </data>\n  <data name=\"LvWebDavCheck\" xml:space=\"preserve\">\n    <value>Проверить WebDAV</value>\n  </data>\n  <data name=\"LvWebDavDirName\" xml:space=\"preserve\">\n    <value>Имя удаленной папки (необязательно)</value>\n  </data>\n  <data name=\"LocalRestoreInvalidZipTips\" xml:space=\"preserve\">\n    <value>Неверный файл резервной копии</value>\n  </data>\n  <data name=\"ConnectionsHostFilterTitle\" xml:space=\"preserve\">\n    <value>Фильтр хостов</value>\n  </data>\n  <data name=\"TipActiveServer\" xml:space=\"preserve\">\n    <value>Активный</value>\n  </data>\n  <data name=\"TbSettingsGeoFilesSource\" xml:space=\"preserve\">\n    <value>Источник файлов Geo (необязательно)</value>\n  </data>\n  <data name=\"TbSettingsSrsFilesSource\" xml:space=\"preserve\">\n    <value>Источник файлов наборов правил sing-box (необязательно)</value>\n  </data>\n  <data name=\"UpgradeAppNotExistTip\" xml:space=\"preserve\">\n    <value>Программы для обновления не существует</value>\n  </data>\n  <data name=\"TbSettingsRoutingRulesSource\" xml:space=\"preserve\">\n    <value>Источник правил маршрутизации</value>\n  </data>\n  <data name=\"menuRegionalPresets\" xml:space=\"preserve\">\n    <value>Региональные пресеты</value>\n  </data>\n  <data name=\"menuRegionalPresetsDefault\" xml:space=\"preserve\">\n    <value>По умолчанию (Китай)</value>\n  </data>\n  <data name=\"menuRegionalPresetsRussia\" xml:space=\"preserve\">\n    <value>Россия</value>\n  </data>\n  <data name=\"menuRegionalPresetsIran\" xml:space=\"preserve\">\n    <value>Иран</value>\n  </data>\n  <data name=\"TbSettingsChinaUserTip\" xml:space=\"preserve\">\n    <value>Пользователи из Китая могут пропустить этот пункт</value>\n  </data>\n  <data name=\"menuAddServerViaImage\" xml:space=\"preserve\">\n    <value>Сканировать QR-код с изображения</value>\n  </data>\n  <data name=\"InvalidUrlTip\" xml:space=\"preserve\">\n    <value>Неверный адрес (Url)</value>\n  </data>\n  <data name=\"InsecureUrlProtocol\" xml:space=\"preserve\">\n    <value>Не используйте небезопасный адрес подписки по протоколу HTTP</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyLinuxTip\" xml:space=\"preserve\">\n    <value>Установите шрифт в систему и перезапустите настройки</value>\n  </data>\n  <data name=\"menuExitTips\" xml:space=\"preserve\">\n    <value>Вы уверены, что хотите выйти?</value>\n  </data>\n  <data name=\"LvMemo\" xml:space=\"preserve\">\n    <value>Заметка (Memo)</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPassword\" xml:space=\"preserve\">\n    <value>Пароль sudo системы</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPasswordTip\" xml:space=\"preserve\">\n    <value>Пароль sudo будет проверен в терминале. Если из-за ошибки проверки приложение начнёт работать некорректно, перезапустите его. Пароль не сохраняется — его нужно вводить после каждого перезапуска.</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip5\" xml:space=\"preserve\">\n    <value>*XHTTP-режим</value>\n  </data>\n  <data name=\"TransportExtraTip\" xml:space=\"preserve\">\n    <value>Дополнительный „сырой“ JSON для XHTTP, формат: { XHTTP Object }</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenClose\" xml:space=\"preserve\">\n    <value>Скрыть в трее при закрытии окна</value>\n  </data>\n  <data name=\"TbSettingsMixedConcurrencyCount\" xml:space=\"preserve\">\n    <value>Количество одновременно выполняемых тестов при многоэтапном тестировании</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip2\" xml:space=\"preserve\">\n    <value>Исключение. Не используйте прокси-сервер для адресов с запятой (,)</value>\n  </data>\n  <data name=\"TbSettingsDestOverride\" xml:space=\"preserve\">\n    <value>Тип сниффинга</value>\n  </data>\n  <data name=\"TbSettingsSecondLocalPortEnabled\" xml:space=\"preserve\">\n    <value>Включить второй смешанный порт</value>\n  </data>\n  <data name=\"TbRoutingInboundTagTips\" xml:space=\"preserve\">\n    <value>socks: локальный порт, socks2: второй локальный порт, socks3: LAN порт</value>\n  </data>\n  <data name=\"TbSettingsTheme\" xml:space=\"preserve\">\n    <value>Темы</value>\n  </data>\n  <data name=\"menuCopyProxyCmdToClipboard\" xml:space=\"preserve\">\n    <value>Копировать команду прокси в буфер обмена</value>\n  </data>\n  <data name=\"SpeedtestingTestFailedPart\" xml:space=\"preserve\">\n    <value>Повторное тестирование неудачных элементов, осталось {0}. Нажмите ESC для остановки…</value>\n  </data>\n  <data name=\"menuTestServerResult\" xml:space=\"preserve\">\n    <value>По результату теста</value>\n  </data>\n  <data name=\"menuRemoveInvalidServerResult\" xml:space=\"preserve\">\n    <value>Удалить недействительные по результатам теста</value>\n  </data>\n  <data name=\"RemoveInvalidServerResultTip\" xml:space=\"preserve\">\n    <value>Удалено {0} недействительных</value>\n  </data>\n  <data name=\"TbPorts7\" xml:space=\"preserve\">\n    <value>Диапазон портов сервера</value>\n  </data>\n  <data name=\"TbPorts7Tips\" xml:space=\"preserve\">\n    <value>Заменит указанный порт, перечисляйте через запятую (,)</value>\n  </data>\n  <data name=\"menuExportConfig\" xml:space=\"preserve\">\n    <value>Экспортировать конфигурацию</value>\n  </data>\n  <data name=\"TbSettingsIPAPIUrl\" xml:space=\"preserve\">\n    <value>URL для тестирования текущего соединения</value>\n  </data>\n  <data name=\"TbRuleOutboundTagTip\" xml:space=\"preserve\">\n    <value>Можно указать название (Remarks) из конфигурации, убедитесь, что оно существует и уникально</value>\n  </data>\n  <data name=\"SudoIncorrectPasswordTip\" xml:space=\"preserve\">\n    <value>Неверный пароль, попробуйте ещё раз.</value>\n  </data>\n  <data name=\"TbMldsa65Verify\" xml:space=\"preserve\">\n    <value>Mldsa65Verify</value>\n  </data>\n  <data name=\"menuAddAnytlsServer\" xml:space=\"preserve\">\n    <value>Добавить сервер [Anytls]</value>\n  </data>\n  <data name=\"TbRemoteDNS\" xml:space=\"preserve\">\n    <value>Удалённый DNS</value>\n  </data>\n  <data name=\"TbDomesticDNS\" xml:space=\"preserve\">\n    <value>Внутренний DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategy\" xml:space=\"preserve\">\n    <value>Direct Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategy\" xml:space=\"preserve\">\n    <value>Proxy Target Resolution Strategy</value>\n  </data>\n  <data name=\"TbAddCommonDNSHosts\" xml:space=\"preserve\">\n    <value>Добавить стандартные записи hosts (DNS)</value>\n  </data>\n  <data name=\"TbFakeIP\" xml:space=\"preserve\">\n    <value>FakeIP</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueries\" xml:space=\"preserve\">\n    <value>Блокировать DNS-запросы SVCB и HTTPS</value>\n  </data>\n  <data name=\"TbDNSHostsConfig\" xml:space=\"preserve\">\n    <value>DNS hosts: (каждая строка в формате \"domain1 ip1 ip2\")</value>\n  </data>\n  <data name=\"ThBasicDNSSettings\" xml:space=\"preserve\">\n    <value>Базовые настройки DNS</value>\n  </data>\n  <data name=\"ThAdvancedDNSSettings\" xml:space=\"preserve\">\n    <value>Расширенные настройки DNS</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPs\" xml:space=\"preserve\">\n    <value>Проверять IP-адреса региональных доменов</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPsDesc\" xml:space=\"preserve\">\n    <value>При включении проверяет IP-адреса, возвращаемые для региональных доменов (например, geosite:cn - geoip:cn), и оставляет только ожидаемые IP-адреса</value>\n  </data>\n  <data name=\"TbCustomDNSEnable\" xml:space=\"preserve\">\n    <value>Включить пользовательский DNS</value>\n  </data>\n  <data name=\"TbCustomDNSEnabledPageInvalid\" xml:space=\"preserve\">\n    <value>Включён пользовательский DNS — настройки на этой странице не применяются</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueriesTips\" xml:space=\"preserve\">\n    <value>Block ECH and HTTP/3 availability checks when enabled</value>\n  </data>\n  <data name=\"FillCorrectConfigTemplateText\" xml:space=\"preserve\">\n    <value>Пожалуйста, заполните корректный шаблон конфигурации</value>\n  </data>\n  <data name=\"menuFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Настройка полного шаблона конфигурации</value>\n  </data>\n  <data name=\"TbFullConfigTemplateEnable\" xml:space=\"preserve\">\n    <value>Включить полный шаблон конфигурации</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Полный шаблон конфигурации v2ray</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Добавляет только конфигурацию исходящих (outbound), а также routing.balancers и routing.rules.outboundTag. Нажмите, чтобы открыть документ</value>\n  </data>\n  <data name=\"TbAddProxyProtocolOutboundOnly\" xml:space=\"preserve\">\n    <value>Не добавлять исходящие для непрокси-протоколов</value>\n  </data>\n  <data name=\"TbSetUpstreamProxyDetour\" xml:space=\"preserve\">\n    <value>Задать тег верхнего прокси (upstream)</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplate\" xml:space=\"preserve\">\n    <value>Полный шаблон конфигурации sing-box</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Добавляет только конфигурацию Outbound и Endpoint. Нажмите, чтобы открыть документ</value>\n  </data>\n  <data name=\"TbFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>Эта функция предназначена для продвинутых пользователей и особых случаев. После включения игнорируются базовые настройки ядра, DNS и маршрутизации. Вы должны самостоятельно корректно задать порт системного прокси, учёт трафика и другие связанные параметры — всё настраивается вручную.</value>\n  </data>\n  <data name=\"MsgStartParsingSubscription\" xml:space=\"preserve\">\n    <value>Start parsing and processing subscription content</value>\n  </data>\n  <data name=\"TbSelectProfile\" xml:space=\"preserve\">\n    <value>Select Profile</value>\n  </data>\n  <data name=\"TbFakeIPTips\" xml:space=\"preserve\">\n    <value>Applies globally by default, with built-in FakeIP filtering (sing-box only).</value>\n  </data>\n  <data name=\"PleaseAddAtLeastOneServer\" xml:space=\"preserve\">\n    <value>Please Add At Least One Configuration</value>\n  </data>\n  <data name=\"TbConfigTypePolicyGroup\" xml:space=\"preserve\">\n    <value>Policy Group</value>\n  </data>\n  <data name=\"TbConfigTypeProxyChain\" xml:space=\"preserve\">\n    <value>Proxy Chain</value>\n  </data>\n  <data name=\"TbLeastPing\" xml:space=\"preserve\">\n    <value>Lowest Latency</value>\n  </data>\n  <data name=\"TbRandom\" xml:space=\"preserve\">\n    <value>Random</value>\n  </data>\n  <data name=\"TbRoundRobin\" xml:space=\"preserve\">\n    <value>Round Robin</value>\n  </data>\n  <data name=\"TbLeastLoad\" xml:space=\"preserve\">\n    <value>Most Stable</value>\n  </data>\n  <data name=\"TbPolicyGroupType\" xml:space=\"preserve\">\n    <value>Policy Group Type</value>\n  </data>\n  <data name=\"menuAddPolicyGroupServer\" xml:space=\"preserve\">\n    <value>Add Policy Group Configuration</value>\n  </data>\n  <data name=\"menuAddProxyChainServer\" xml:space=\"preserve\">\n    <value>Add Proxy Chain Configuration</value>\n  </data>\n  <data name=\"menuAddChildServer\" xml:space=\"preserve\">\n    <value>Add Child Configuration</value>\n  </data>\n  <data name=\"menuRemoveChildServer\" xml:space=\"preserve\">\n    <value>Remove Child Configuration</value>\n  </data>\n  <data name=\"menuServerList\" xml:space=\"preserve\">\n    <value>Configuration item 1, Auto add from subscription group</value>\n  </data>\n  <data name=\"TbFallback\" xml:space=\"preserve\">\n    <value>Fallback</value>\n  </data>\n  <data name=\"MsgCoreNotSupportNetwork\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support network type '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocolTransport\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}' when using transport '{2}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Core '{0}' does not support protocol '{1}'</value>\n  </data>\n  <data name=\"MsgInvalidProperty\" xml:space=\"preserve\">\n    <value>The {0} property is invalid, please check</value>\n  </data>\n  <data name=\"MsgNotSupportProtocol\" xml:space=\"preserve\">\n    <value>Not support protocol '{0}'</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenCloseTip\" xml:space=\"preserve\">\n    <value>If the system does not have a tray function, please do not enable it</value>\n  </data>\n  <data name=\"TbRuleTypeTips\" xml:space=\"preserve\">\n    <value>You can set separate rules for Routing and DNS, or select \"ALL\" to apply to both</value>\n  </data>\n  <data name=\"TbRuleType\" xml:space=\"preserve\">\n    <value>Rule Type</value>\n  </data>\n  <data name=\"TbBootstrapDNS\" xml:space=\"preserve\">\n    <value>Bootstrap DNS</value>\n  </data>\n  <data name=\"TbBootstrapDNSTips\" xml:space=\"preserve\">\n    <value>Resolve DNS server domains, requires IP</value>\n  </data>\n  <data name=\"menuFastRealPing\" xml:space=\"preserve\">\n    <value>Test real delay</value>\n  </data>\n  <data name=\"TbPolicyGroupSubChildTip\" xml:space=\"preserve\">\n    <value>Auto add filtered configuration from subscription groups</value>\n  </data>\n  <data name=\"TbCertPinning\" xml:space=\"preserve\">\n    <value>Certificate Pinning</value>\n  </data>\n  <data name=\"TbCertPinningTips\" xml:space=\"preserve\">\n    <value>Pinned certificate (fill in either one)\nWhen specified, the certificate will be pinned, and \"Allow Insecure\" will be disabled.\n\nThe \"Get Certificate\" action may fail if a self-signed certificate is used or if the system contains an untrusted or malicious CA.</value>\n  </data>\n  <data name=\"TbFetchCert\" xml:space=\"preserve\">\n    <value>Fetch Certificate</value>\n  </data>\n  <data name=\"TbFetchCertChain\" xml:space=\"preserve\">\n    <value>Fetch Certificate Chain</value>\n  </data>\n  <data name=\"ServerNameMustBeValidDomain\" xml:space=\"preserve\">\n    <value>Please set a valid domain</value>\n  </data>\n  <data name=\"CertNotSet\" xml:space=\"preserve\">\n    <value>Certificate not set</value>\n  </data>\n  <data name=\"CertSet\" xml:space=\"preserve\">\n    <value>Certificate set</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyPacPath\" xml:space=\"preserve\">\n    <value>Custom PAC file path</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyScriptPath\" xml:space=\"preserve\">\n    <value>Custom system proxy script file path</value>\n  </data>\n  <data name=\"TbSettingsMacOSShowInDock\" xml:space=\"preserve\">\n    <value>macOS displays this in the Dock (requires restart)</value>\n  </data>\n  <data name=\"menuServerList2\" xml:space=\"preserve\">\n    <value>Configuration Item 2, Select and add from self-built</value>\n  </data>\n  <data name=\"TbEchConfigList\" xml:space=\"preserve\">\n    <value>EchConfigList</value>\n  </data>\n  <data name=\"TbEchForceQuery\" xml:space=\"preserve\">\n    <value>EchForceQuery</value>\n  </data>\n  <data name=\"TbFullCertTips\" xml:space=\"preserve\">\n    <value>Full certificate (chain), PEM format</value>\n  </data>\n  <data name=\"TbCertSha256Tips\" xml:space=\"preserve\">\n    <value>Certificate fingerprint (SHA-256)</value>\n  </data>\n  <data name=\"TbServeStale\" xml:space=\"preserve\">\n    <value>Serve Stale</value>\n  </data>\n  <data name=\"TbParallelQuery\" xml:space=\"preserve\">\n    <value>Parallel Query</value>\n  </data>\n  <data name=\"TbDomesticDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution</value>\n  </data>\n  <data name=\"TbRemoteDNSTips\" xml:space=\"preserve\">\n    <value>By default, invoked only during routing for resolution; ensure the remote server can reach this DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution uses the system DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategyTips\" xml:space=\"preserve\">\n    <value>If unset or \"AsIs\", DNS resolution is performed by the remote server's DNS; otherwise, the internal DNS module is used.</value>\n  </data>\n  <data name=\"TbHopInt7\" xml:space=\"preserve\">\n    <value>Port hopping interval</value>\n  </data>\n  <data name=\"menuServerListPreview\" xml:space=\"preserve\">\n    <value>Configuration item preview</value>\n  </data>\n  <data name=\"TbFinalmask\" xml:space=\"preserve\">\n    <value>Finalmask</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeWarning\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeError\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} error: {2}. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgGroupCycleDependency\" xml:space=\"preserve\">\n    <value>Group {0} has a cycle dependency on child node {1}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeWarning\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} warning: {2}</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeError\" xml:space=\"preserve\">\n    <value>Group {0} child group node {1} error: {2}. Skipping this node.</value>\n  </data>\n  <data name=\"MsgGroupNoValidChildNode\" xml:space=\"preserve\">\n    <value>Group {0} has no valid child node.</value>\n  </data>\n  <data name=\"MsgRoutingRuleEmptyOutboundTag\" xml:space=\"preserve\">\n    <value>Routing rule {0} has an empty outbound tag. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeNotFound\" xml:space=\"preserve\">\n    <value>Routing rule {0} outbound node {1} not found. Fallback to proxy node only.</value>\n  </data>\n  <data name=\"MsgSubscriptionPrevProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription previous proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"MsgSubscriptionNextProfileNotFound\" xml:space=\"preserve\">\n    <value>Subscription next proxy {0} not found. Skipping.</value>\n  </data>\n  <data name=\"menuGenGroupServer\" xml:space=\"preserve\">\n    <value>Generate Policy Group</value>\n  </data>\n  <data name=\"menuAllServers\" xml:space=\"preserve\">\n    <value>All configurations</value>\n  </data>\n  <data name=\"menuGenRegionGroup\" xml:space=\"preserve\">\n    <value>Group by Region</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BatchExportURLSuccessfully\" xml:space=\"preserve\">\n    <value>导出分享链接至剪贴板成功</value>\n  </data>\n  <data name=\"CheckServerSettings\" xml:space=\"preserve\">\n    <value>请先检查设置</value>\n  </data>\n  <data name=\"ConfigurationFormatIncorrect\" xml:space=\"preserve\">\n    <value>配置格式不正确</value>\n  </data>\n  <data name=\"CustomServerTips\" xml:space=\"preserve\">\n    <value>注意，自定义配置完全依赖您自己的配置，不能使用所有设置功能。如需使用系统代理请手动修改监听端口。</value>\n  </data>\n  <data name=\"Downloading\" xml:space=\"preserve\">\n    <value>下载开始...</value>\n  </data>\n  <data name=\"FailedConversionConfiguration\" xml:space=\"preserve\">\n    <value>转换配置失败</value>\n  </data>\n  <data name=\"FailedGenDefaultConfiguration\" xml:space=\"preserve\">\n    <value>生成默认配置文件失败</value>\n  </data>\n  <data name=\"FailedGetDefaultConfiguration\" xml:space=\"preserve\">\n    <value>获取默认配置失败</value>\n  </data>\n  <data name=\"FailedImportedCustomServer\" xml:space=\"preserve\">\n    <value>导入自定义配置失败</value>\n  </data>\n  <data name=\"FailedReadConfiguration\" xml:space=\"preserve\">\n    <value>读取配置失败</value>\n  </data>\n  <data name=\"FillCorrectServerPort\" xml:space=\"preserve\">\n    <value>请填写正确格式的端口</value>\n  </data>\n  <data name=\"FillLocalListeningPort\" xml:space=\"preserve\">\n    <value>请填写本地监听端口</value>\n  </data>\n  <data name=\"FillPassword\" xml:space=\"preserve\">\n    <value>请填写密码</value>\n  </data>\n  <data name=\"FillServerAddress\" xml:space=\"preserve\">\n    <value>请填写地址</value>\n  </data>\n  <data name=\"FillUUID\" xml:space=\"preserve\">\n    <value>请填写用户 ID</value>\n  </data>\n  <data name=\"Incorrectconfiguration\" xml:space=\"preserve\">\n    <value>配置不正确，请检查</value>\n  </data>\n  <data name=\"InitialConfiguration\" xml:space=\"preserve\">\n    <value>初始化配置</value>\n  </data>\n  <data name=\"IsLatestCore\" xml:space=\"preserve\">\n    <value>{0} {1} 已是最新版本。</value>\n  </data>\n  <data name=\"IsLatestN\" xml:space=\"preserve\">\n    <value>{0} {1} 已是最新版本。</value>\n  </data>\n  <data name=\"LvAddress\" xml:space=\"preserve\">\n    <value>地址</value>\n  </data>\n  <data name=\"LvEncryptionMethod\" xml:space=\"preserve\">\n    <value>加密方式</value>\n  </data>\n  <data name=\"LvPort\" xml:space=\"preserve\">\n    <value>端口</value>\n  </data>\n  <data name=\"LvServiceType\" xml:space=\"preserve\">\n    <value>类型</value>\n  </data>\n  <data name=\"LvSubscription\" xml:space=\"preserve\">\n    <value>订阅分组</value>\n  </data>\n  <data name=\"LvTodayDownloadDataAmount\" xml:space=\"preserve\">\n    <value>今日下载</value>\n  </data>\n  <data name=\"LvTodayUploadDataAmount\" xml:space=\"preserve\">\n    <value>今日上传</value>\n  </data>\n  <data name=\"LvTotalDownloadDataAmount\" xml:space=\"preserve\">\n    <value>总下载</value>\n  </data>\n  <data name=\"LvTotalUploadDataAmount\" xml:space=\"preserve\">\n    <value>总上传</value>\n  </data>\n  <data name=\"LvTransportProtocol\" xml:space=\"preserve\">\n    <value>传输协议</value>\n  </data>\n  <data name=\"MsgDownloadV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>下载 Core 成功</value>\n  </data>\n  <data name=\"MsgFailedImportSubscription\" xml:space=\"preserve\">\n    <value>导入订阅内容失败</value>\n  </data>\n  <data name=\"MsgGetSubscriptionSuccessfully\" xml:space=\"preserve\">\n    <value>获取订阅内容成功</value>\n  </data>\n  <data name=\"MsgNoValidSubscription\" xml:space=\"preserve\">\n    <value>未设置有效的订阅</value>\n  </data>\n  <data name=\"MsgParsingSuccessfully\" xml:space=\"preserve\">\n    <value>解析 {0} 成功</value>\n  </data>\n  <data name=\"MsgStartGettingSubscriptions\" xml:space=\"preserve\">\n    <value>开始获取订阅内容</value>\n  </data>\n  <data name=\"MsgStartUpdating\" xml:space=\"preserve\">\n    <value>开始更新 {0}...</value>\n  </data>\n  <data name=\"MsgSubscriptionDecodingFailed\" xml:space=\"preserve\">\n    <value>无效的订阅内容</value>\n  </data>\n  <data name=\"MsgUnpacking\" xml:space=\"preserve\">\n    <value>正在解压......</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionEnd\" xml:space=\"preserve\">\n    <value>更新订阅结束</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionStart\" xml:space=\"preserve\">\n    <value>更新订阅开始</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>更新 Core 成功</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfullyMore\" xml:space=\"preserve\">\n    <value>更新 Core 成功！正在重启服务...</value>\n  </data>\n  <data name=\"NonvmessOrssProtocol\" xml:space=\"preserve\">\n    <value>非 VMess 或 ss 协议</value>\n  </data>\n  <data name=\"NotFoundCore\" xml:space=\"preserve\">\n    <value>在文件夹 ({0}) 下未找到 Core 文件 (文件名: {1})，请下载后放入文件夹，下载地址: {2}</value>\n  </data>\n  <data name=\"NoValidQRcodeFound\" xml:space=\"preserve\">\n    <value>扫描完成，未发现有效二维码</value>\n  </data>\n  <data name=\"OperationFailed\" xml:space=\"preserve\">\n    <value>操作失败，请检查并重试</value>\n  </data>\n  <data name=\"PleaseFillRemarks\" xml:space=\"preserve\">\n    <value>请填写别名</value>\n  </data>\n  <data name=\"PleaseSelectEncryption\" xml:space=\"preserve\">\n    <value>请选择加密方式</value>\n  </data>\n  <data name=\"PleaseSelectProtocol\" xml:space=\"preserve\">\n    <value>请选择协议</value>\n  </data>\n  <data name=\"PleaseSelectServer\" xml:space=\"preserve\">\n    <value>请先选择配置</value>\n  </data>\n  <data name=\"RemoveDuplicateServerResult\" xml:space=\"preserve\">\n    <value>配置去重完成。原数量: {0}，现数量: {1}。</value>\n  </data>\n  <data name=\"RemoveServer\" xml:space=\"preserve\">\n    <value>是否确定移除？</value>\n  </data>\n  <data name=\"SaveClientConfigurationIn\" xml:space=\"preserve\">\n    <value>客户端配置文件保存在：{0}</value>\n  </data>\n  <data name=\"StartService\" xml:space=\"preserve\">\n    <value>启动服务 ({0})...</value>\n  </data>\n  <data name=\"SuccessfulConfiguration\" xml:space=\"preserve\">\n    <value>配置成功。 {0}</value>\n  </data>\n  <data name=\"SuccessfullyImportedCustomServer\" xml:space=\"preserve\">\n    <value>成功导入自定义配置</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaClipboard\" xml:space=\"preserve\">\n    <value>成功从剪贴板导入 {0} 个配置</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaScan\" xml:space=\"preserve\">\n    <value>扫描导入分享链接成功</value>\n  </data>\n  <data name=\"TestMeOutput\" xml:space=\"preserve\">\n    <value>当前延迟: {0} ms，{1}</value>\n  </data>\n  <data name=\"OperationSuccess\" xml:space=\"preserve\">\n    <value>操作成功</value>\n  </data>\n  <data name=\"PleaseSelectRules\" xml:space=\"preserve\">\n    <value>请先选择规则</value>\n  </data>\n  <data name=\"RemoveRules\" xml:space=\"preserve\">\n    <value>是否确定移除规则？</value>\n  </data>\n  <data name=\"RoutingRuleDetailRequiredTips\" xml:space=\"preserve\">\n    <value>{0}，必填其中一项.</value>\n  </data>\n  <data name=\"LvRemarks\" xml:space=\"preserve\">\n    <value>别名</value>\n  </data>\n  <data name=\"LvUrl\" xml:space=\"preserve\">\n    <value>可选地址 (Url)</value>\n  </data>\n  <data name=\"LvCount\" xml:space=\"preserve\">\n    <value>数量</value>\n  </data>\n  <data name=\"MsgNeedUrl\" xml:space=\"preserve\">\n    <value>请填写 Url</value>\n  </data>\n  <data name=\"AddBatchRoutingRulesYesNo\" xml:space=\"preserve\">\n    <value>是否追加规则？选择\"是\"则追加，选择\"否\"则全部替换。</value>\n  </data>\n  <data name=\"MsgDownloadGeoFileSuccessfully\" xml:space=\"preserve\">\n    <value>下载 GeoFile：{0} 成功</value>\n  </data>\n  <data name=\"MsgInformationTitle\" xml:space=\"preserve\">\n    <value>信息</value>\n  </data>\n  <data name=\"LvCustomIcon\" xml:space=\"preserve\">\n    <value>自定义图标</value>\n  </data>\n  <data name=\"FillCorrectDNSText\" xml:space=\"preserve\">\n    <value>请填写正确的自定义 DNS</value>\n  </data>\n  <data name=\"TransportPathTip1\" xml:space=\"preserve\">\n    <value>*ws/httpupgrade/xhttp path</value>\n  </data>\n  <data name=\"TransportPathTip2\" xml:space=\"preserve\">\n    <value>*h2 path</value>\n  </data>\n  <data name=\"TransportPathTip3\" xml:space=\"preserve\">\n    <value>*QUIC 加密密钥</value>\n  </data>\n  <data name=\"TransportPathTip4\" xml:space=\"preserve\">\n    <value>*grpc serviceName</value>\n  </data>\n  <data name=\"TransportRequestHostTip1\" xml:space=\"preserve\">\n    <value>*http host 中间逗号 (,) 分隔</value>\n  </data>\n  <data name=\"TransportRequestHostTip2\" xml:space=\"preserve\">\n    <value>*ws/httpupgrade/xhttp host</value>\n  </data>\n  <data name=\"TransportRequestHostTip3\" xml:space=\"preserve\">\n    <value>*h2 host 中间逗号 (,) 分隔</value>\n  </data>\n  <data name=\"TransportRequestHostTip4\" xml:space=\"preserve\">\n    <value>*QUIC 加密方式</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip1\" xml:space=\"preserve\">\n    <value>*tcp 伪装类型</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip2\" xml:space=\"preserve\">\n    <value>*kcp 伪装类型</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip3\" xml:space=\"preserve\">\n    <value>*QUIC 伪装类型</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip4\" xml:space=\"preserve\">\n    <value>*grpc 模式</value>\n  </data>\n  <data name=\"LvTLS\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TransportPathTip5\" xml:space=\"preserve\">\n    <value>*Kcp seed</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeyFailed\" xml:space=\"preserve\">\n    <value>注册全局热键 {0} 失败，原因：{1}</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeySuccessfully\" xml:space=\"preserve\">\n    <value>注册全局热键 {0} 成功</value>\n  </data>\n  <data name=\"AllGroupServers\" xml:space=\"preserve\">\n    <value>所有</value>\n  </data>\n  <data name=\"FillServerAddressCustom\" xml:space=\"preserve\">\n    <value>请浏览导入配置</value>\n  </data>\n  <data name=\"Speedtesting\" xml:space=\"preserve\">\n    <value>测试中...</value>\n  </data>\n  <data name=\"LabLAN\" xml:space=\"preserve\">\n    <value>局域网</value>\n  </data>\n  <data name=\"LabLocal\" xml:space=\"preserve\">\n    <value>本地</value>\n  </data>\n  <data name=\"MsgServerTitle\" xml:space=\"preserve\">\n    <value>过滤器，按回车执行</value>\n  </data>\n  <data name=\"menuCheckUpdate\" xml:space=\"preserve\">\n    <value>检查更新</value>\n  </data>\n  <data name=\"menuClose\" xml:space=\"preserve\">\n    <value>关闭</value>\n  </data>\n  <data name=\"menuExit\" xml:space=\"preserve\">\n    <value>退出</value>\n  </data>\n  <data name=\"menuGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>全局热键设置</value>\n  </data>\n  <data name=\"menuHelp\" xml:space=\"preserve\">\n    <value>帮助</value>\n  </data>\n  <data name=\"menuOptionSetting\" xml:space=\"preserve\">\n    <value>参数设置</value>\n  </data>\n  <data name=\"menuPromotion\" xml:space=\"preserve\">\n    <value>推广</value>\n  </data>\n  <data name=\"menuReload\" xml:space=\"preserve\">\n    <value>重启服务</value>\n  </data>\n  <data name=\"menuRoutingSetting\" xml:space=\"preserve\">\n    <value>路由设置</value>\n  </data>\n  <data name=\"menuServers\" xml:space=\"preserve\">\n    <value>配置项</value>\n  </data>\n  <data name=\"menuSetting\" xml:space=\"preserve\">\n    <value>设置</value>\n  </data>\n  <data name=\"menuSubGroupUpdate\" xml:space=\"preserve\">\n    <value>更新当前订阅 (不通过代理)</value>\n  </data>\n  <data name=\"menuSubGroupUpdateViaProxy\" xml:space=\"preserve\">\n    <value>更新当前订阅 (通过代理)</value>\n  </data>\n  <data name=\"menuSubscription\" xml:space=\"preserve\">\n    <value>订阅分组</value>\n  </data>\n  <data name=\"menuSubSetting\" xml:space=\"preserve\">\n    <value>订阅分组设置</value>\n  </data>\n  <data name=\"menuSubUpdate\" xml:space=\"preserve\">\n    <value>更新全部订阅 (不通过代理)</value>\n  </data>\n  <data name=\"menuSubUpdateViaProxy\" xml:space=\"preserve\">\n    <value>更新全部订阅 (通过代理)</value>\n  </data>\n  <data name=\"menuSystemproxy\" xml:space=\"preserve\">\n    <value>系统代理</value>\n  </data>\n  <data name=\"menuSystemProxyClear\" xml:space=\"preserve\">\n    <value>清除系统代理</value>\n  </data>\n  <data name=\"menuSystemProxyNothing\" xml:space=\"preserve\">\n    <value>不改变系统代理</value>\n  </data>\n  <data name=\"menuSystemProxyPac\" xml:space=\"preserve\">\n    <value>Pac 模式</value>\n  </data>\n  <data name=\"menuSystemProxySet\" xml:space=\"preserve\">\n    <value>自动配置系统代理</value>\n  </data>\n  <data name=\"TbSettingsColor\" xml:space=\"preserve\">\n    <value>颜色</value>\n  </data>\n  <data name=\"TbSettingsLanguage\" xml:space=\"preserve\">\n    <value>语言 (需重启)</value>\n  </data>\n  <data name=\"menuAddServerViaClipboard\" xml:space=\"preserve\">\n    <value>从剪贴板导入分享链接</value>\n  </data>\n  <data name=\"menuAddServerViaScan\" xml:space=\"preserve\">\n    <value>扫描屏幕上的二维码</value>\n  </data>\n  <data name=\"menuCopyServer\" xml:space=\"preserve\">\n    <value>克隆所选</value>\n  </data>\n  <data name=\"menuRemoveDuplicateServer\" xml:space=\"preserve\">\n    <value>移除重复</value>\n  </data>\n  <data name=\"menuRemoveServer\" xml:space=\"preserve\">\n    <value>移除所选 (多选)</value>\n  </data>\n  <data name=\"menuSetDefaultServer\" xml:space=\"preserve\">\n    <value>设为活动</value>\n  </data>\n  <data name=\"menuClearServerStatistics\" xml:space=\"preserve\">\n    <value>清除所有服务统计数据</value>\n  </data>\n  <data name=\"menuRealPingServer\" xml:space=\"preserve\">\n    <value>测试真连接延迟 (多选)</value>\n  </data>\n  <data name=\"menuSortServerResult\" xml:space=\"preserve\">\n    <value>按测试结果排序</value>\n  </data>\n  <data name=\"menuSpeedServer\" xml:space=\"preserve\">\n    <value>测试速度 (多选)</value>\n  </data>\n  <data name=\"menuTcpingServer\" xml:space=\"preserve\">\n    <value>测试延迟 Tcping (多选)</value>\n  </data>\n  <data name=\"menuExport2ClientConfig\" xml:space=\"preserve\">\n    <value>导出所选完整配置</value>\n  </data>\n  <data name=\"menuExport2ShareUrl\" xml:space=\"preserve\">\n    <value>导出分享链接至剪贴板 (多选)</value>\n  </data>\n  <data name=\"menuAddCustomServer\" xml:space=\"preserve\">\n    <value>添加自定义配置</value>\n  </data>\n  <data name=\"menuAddShadowsocksServer\" xml:space=\"preserve\">\n    <value>添加 [Shadowsocks]</value>\n  </data>\n  <data name=\"menuAddSocksServer\" xml:space=\"preserve\">\n    <value>添加 [SOCKS] </value>\n  </data>\n  <data name=\"menuAddTrojanServer\" xml:space=\"preserve\">\n    <value>添加 [Trojan] </value>\n  </data>\n  <data name=\"menuAddVlessServer\" xml:space=\"preserve\">\n    <value>添加 [VLESS] </value>\n  </data>\n  <data name=\"menuAddVmessServer\" xml:space=\"preserve\">\n    <value>添加 [VMess] </value>\n  </data>\n  <data name=\"menuSelectAll\" xml:space=\"preserve\">\n    <value>全选</value>\n  </data>\n  <data name=\"menuMsgViewClear\" xml:space=\"preserve\">\n    <value>清除所有</value>\n  </data>\n  <data name=\"menuMsgViewCopy\" xml:space=\"preserve\">\n    <value>复制</value>\n  </data>\n  <data name=\"menuMsgViewCopyAll\" xml:space=\"preserve\">\n    <value>复制所有</value>\n  </data>\n  <data name=\"menuMsgViewSelectAll\" xml:space=\"preserve\">\n    <value>全选</value>\n  </data>\n  <data name=\"menuSubAdd\" xml:space=\"preserve\">\n    <value>添加</value>\n  </data>\n  <data name=\"menuSubDelete\" xml:space=\"preserve\">\n    <value>删除</value>\n  </data>\n  <data name=\"menuSubEdit\" xml:space=\"preserve\">\n    <value>编辑</value>\n  </data>\n  <data name=\"menuSubShare\" xml:space=\"preserve\">\n    <value>分享</value>\n  </data>\n  <data name=\"LvEnabled\" xml:space=\"preserve\">\n    <value>启用更新</value>\n  </data>\n  <data name=\"LvSort\" xml:space=\"preserve\">\n    <value>排序</value>\n  </data>\n  <data name=\"LvUserAgent\" xml:space=\"preserve\">\n    <value>User Agent (可选)</value>\n  </data>\n  <data name=\"TbCancel\" xml:space=\"preserve\">\n    <value>取消</value>\n  </data>\n  <data name=\"TbConfirm\" xml:space=\"preserve\">\n    <value>确定</value>\n  </data>\n  <data name=\"GbTransport\" xml:space=\"preserve\">\n    <value>底层传输方式 (transport)</value>\n  </data>\n  <data name=\"TbAddress\" xml:space=\"preserve\">\n    <value>地址 (address)</value>\n  </data>\n  <data name=\"TbAllowInsecure\" xml:space=\"preserve\">\n    <value>跳过证书验证 (allowInsecure)</value>\n  </data>\n  <data name=\"TbAlpn\" xml:space=\"preserve\">\n    <value>Alpn</value>\n  </data>\n  <data name=\"TbAlterId\" xml:space=\"preserve\">\n    <value>额外 ID (alterId)</value>\n  </data>\n  <data name=\"TbFingerprint\" xml:space=\"preserve\">\n    <value>Fingerprint</value>\n  </data>\n  <data name=\"TbHeaderType\" xml:space=\"preserve\">\n    <value>伪装类型 (type)</value>\n  </data>\n  <data name=\"TbId\" xml:space=\"preserve\">\n    <value>用户 ID (id)</value>\n  </data>\n  <data name=\"TbNetwork\" xml:space=\"preserve\">\n    <value>传输协议 (network)</value>\n  </data>\n  <data name=\"TbPath\" xml:space=\"preserve\">\n    <value>路径 (path)</value>\n  </data>\n  <data name=\"TbPort\" xml:space=\"preserve\">\n    <value>端口 (port)</value>\n  </data>\n  <data name=\"TbRemarks\" xml:space=\"preserve\">\n    <value>别名 (remarks)</value>\n  </data>\n  <data name=\"TbRequestHost\" xml:space=\"preserve\">\n    <value>伪装域名 (host)</value>\n  </data>\n  <data name=\"TbSecurity\" xml:space=\"preserve\">\n    <value>加密方式 (security)</value>\n  </data>\n  <data name=\"TbSNI\" xml:space=\"preserve\">\n    <value>SNI</value>\n  </data>\n  <data name=\"TbStreamSecurity\" xml:space=\"preserve\">\n    <value>传输层安全 (TLS)</value>\n  </data>\n  <data name=\"TipNetwork\" xml:space=\"preserve\">\n    <value>*默认 tcp，选错会无法连接</value>\n  </data>\n  <data name=\"TbCoreType\" xml:space=\"preserve\">\n    <value>Core 类型</value>\n  </data>\n  <data name=\"TbFlow5\" xml:space=\"preserve\">\n    <value>流控 (flow)</value>\n  </data>\n  <data name=\"TbGUID\" xml:space=\"preserve\">\n    <value>生成</value>\n  </data>\n  <data name=\"TbId3\" xml:space=\"preserve\">\n    <value>密码 (password)</value>\n  </data>\n  <data name=\"TbId4\" xml:space=\"preserve\">\n    <value>密码 (可选)</value>\n  </data>\n  <data name=\"TbId5\" xml:space=\"preserve\">\n    <value>用户 ID (id)</value>\n  </data>\n  <data name=\"TbSecurity3\" xml:space=\"preserve\">\n    <value>加密方式 (encryption)</value>\n  </data>\n  <data name=\"TbSecurity4\" xml:space=\"preserve\">\n    <value>用户名 (可选)</value>\n  </data>\n  <data name=\"TbSecurity5\" xml:space=\"preserve\">\n    <value>加密方式 (encryption)</value>\n  </data>\n  <data name=\"TbPreSocksPort\" xml:space=\"preserve\">\n    <value>Socks 端口</value>\n  </data>\n  <data name=\"TipPreSocksPort\" xml:space=\"preserve\">\n    <value>*自定义配置的 Socks 端口值，可不设置；当设置此值后，将使用 Xray/sing-box (Tun) 额外启动一个前置 Socks 服务，提供分流和速度显示等功能</value>\n  </data>\n  <data name=\"TbBrowse\" xml:space=\"preserve\">\n    <value>浏览</value>\n  </data>\n  <data name=\"TbEdit\" xml:space=\"preserve\">\n    <value>编辑</value>\n  </data>\n  <data name=\"TbSettingsAdvancedProtocol\" xml:space=\"preserve\">\n    <value>高级代理设置，协议选择 (可选)</value>\n  </data>\n  <data name=\"TbSettingsAllowLAN\" xml:space=\"preserve\">\n    <value>允许来自局域网的连接</value>\n  </data>\n  <data name=\"TbSettingsAutoHideStartup\" xml:space=\"preserve\">\n    <value>启动后隐藏窗口</value>\n  </data>\n  <data name=\"TbSettingsAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>自动更新 Geo 文件的间隔 (小时)</value>\n  </data>\n  <data name=\"TbSettingsCore\" xml:space=\"preserve\">\n    <value>Core: 基础设置</value>\n  </data>\n  <data name=\"TbCustomDnsRay\" xml:space=\"preserve\">\n    <value>v2ray 自定义 DNS</value>\n  </data>\n  <data name=\"TbSettingsCoreKcp\" xml:space=\"preserve\">\n    <value>Core: KCP 设置</value>\n  </data>\n  <data name=\"TbSettingsCoreType\" xml:space=\"preserve\">\n    <value>Core 类型设置</value>\n  </data>\n  <data name=\"TbSettingsDefAllowInsecure\" xml:space=\"preserve\">\n    <value>默认跳过证书验证 (allowInsecure)</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Freedom\" xml:space=\"preserve\">\n    <value>Outbound Freedom domainStrategy</value>\n  </data>\n  <data name=\"TbSettingsEnableAutoAdjustMainLvColWidth\" xml:space=\"preserve\">\n    <value>自动调整配置列宽在更新订阅后</value>\n  </data>\n  <data name=\"TbSettingsEnableCheckPreReleaseUpdate\" xml:space=\"preserve\">\n    <value>检查 Pre-Release 更新 (请谨慎启用)</value>\n  </data>\n  <data name=\"TbSettingsException\" xml:space=\"preserve\">\n    <value>例外</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip\" xml:space=\"preserve\">\n    <value>例外：对于下列字符开头的地址，不使用代理配置。使用分号 (;) 分隔。</value>\n  </data>\n  <data name=\"TbSettingsDisplayRealTimeSpeed\" xml:space=\"preserve\">\n    <value>显示实时速度 (需重启)</value>\n  </data>\n  <data name=\"TbSettingsKeepOlderDedupl\" xml:space=\"preserve\">\n    <value>去重时保留序号较小的项</value>\n  </data>\n  <data name=\"TbSettingsLogEnabled\" xml:space=\"preserve\">\n    <value>启用日志</value>\n  </data>\n  <data name=\"TbSettingsLogLevel\" xml:space=\"preserve\">\n    <value>日志等级</value>\n  </data>\n  <data name=\"TbSettingsMuxEnabled\" xml:space=\"preserve\">\n    <value>开启 Mux 多路复用</value>\n  </data>\n  <data name=\"TbSettingsN\" xml:space=\"preserve\">\n    <value>v2rayN 设置</value>\n  </data>\n  <data name=\"TbSettingsPass\" xml:space=\"preserve\">\n    <value>认证密码</value>\n  </data>\n  <data name=\"TbSettingsRemoteDNS\" xml:space=\"preserve\">\n    <value>自定义 DNS (可多个，用逗号 (,) 分隔)</value>\n  </data>\n  <data name=\"TbSettingsSetUWP\" xml:space=\"preserve\">\n    <value>解除 Win10 UWP 应用回环代理限制</value>\n  </data>\n  <data name=\"TbSettingsSniffingEnabled\" xml:space=\"preserve\">\n    <value>开启流量探测</value>\n  </data>\n  <data name=\"TbSettingsSocksPort\" xml:space=\"preserve\">\n    <value>本地混合监听端口</value>\n  </data>\n  <data name=\"TbSettingsStartBoot\" xml:space=\"preserve\">\n    <value>开机启动 (可能会不成功)</value>\n  </data>\n  <data name=\"TbSettingsStatistics\" xml:space=\"preserve\">\n    <value>启用流量统计 (需重启)</value>\n  </data>\n  <data name=\"TbSettingsSubConvert\" xml:space=\"preserve\">\n    <value>订阅转换网址 (可选)</value>\n  </data>\n  <data name=\"TbSettingsSystemproxy\" xml:space=\"preserve\">\n    <value>系统代理设置</value>\n  </data>\n  <data name=\"TbSettingsTrayMenuServersLimit\" xml:space=\"preserve\">\n    <value>托盘右键菜单配置展示数量限制</value>\n  </data>\n  <data name=\"TbSettingsUdpEnabled\" xml:space=\"preserve\">\n    <value>开启 UDP</value>\n  </data>\n  <data name=\"TbSettingsUser\" xml:space=\"preserve\">\n    <value>认证用户名</value>\n  </data>\n  <data name=\"TbClearSystemProxy\" xml:space=\"preserve\">\n    <value>清除系统代理</value>\n  </data>\n  <data name=\"TbDisplayGUI\" xml:space=\"preserve\">\n    <value>显示主界面</value>\n  </data>\n  <data name=\"TbGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>全局热键设置</value>\n  </data>\n  <data name=\"TbGlobalHotkeySettingTip\" xml:space=\"preserve\">\n    <value>直接按键盘进行设置，重启后生效</value>\n  </data>\n  <data name=\"TbNotChangeSystemProxy\" xml:space=\"preserve\">\n    <value>不改变系统代理</value>\n  </data>\n  <data name=\"TbReset\" xml:space=\"preserve\">\n    <value>重置</value>\n  </data>\n  <data name=\"TbSetSystemProxy\" xml:space=\"preserve\">\n    <value>自动配置系统代理</value>\n  </data>\n  <data name=\"TbSystemProxyPac\" xml:space=\"preserve\">\n    <value>Pac 模式</value>\n  </data>\n  <data name=\"menuShareServer\" xml:space=\"preserve\">\n    <value>分享</value>\n  </data>\n  <data name=\"menuRouting\" xml:space=\"preserve\">\n    <value>路由</value>\n  </data>\n  <data name=\"NotRunAsAdmin\" xml:space=\"preserve\">\n    <value>以非管理员身份运行</value>\n  </data>\n  <data name=\"RunAsAdmin\" xml:space=\"preserve\">\n    <value>以管理员身份运行</value>\n  </data>\n  <data name=\"menuMoveBottom\" xml:space=\"preserve\">\n    <value>下移至底</value>\n  </data>\n  <data name=\"menuMoveDown\" xml:space=\"preserve\">\n    <value>下移</value>\n  </data>\n  <data name=\"menuMoveTop\" xml:space=\"preserve\">\n    <value>上移至顶</value>\n  </data>\n  <data name=\"menuMoveUp\" xml:space=\"preserve\">\n    <value>上移</value>\n  </data>\n  <data name=\"MsgFilterTitle\" xml:space=\"preserve\">\n    <value>过滤器 (支持正则)</value>\n  </data>\n  <data name=\"menuWebsiteItem\" xml:space=\"preserve\">\n    <value>{0} 官网</value>\n  </data>\n  <data name=\"menuRoutingAdvancedAdd\" xml:space=\"preserve\">\n    <value>添加规则集</value>\n  </data>\n  <data name=\"menuRoutingAdvancedImportRules\" xml:space=\"preserve\">\n    <value>一键导入规则集</value>\n  </data>\n  <data name=\"menuRoutingAdvancedRemove\" xml:space=\"preserve\">\n    <value>移除所选规则</value>\n  </data>\n  <data name=\"menuRoutingAdvancedSetDefault\" xml:space=\"preserve\">\n    <value>设为活动规则</value>\n  </data>\n  <data name=\"TbdomainStrategy\" xml:space=\"preserve\">\n    <value>域名解析策略</value>\n  </data>\n  <data name=\"TbRoutingTabRuleList\" xml:space=\"preserve\">\n    <value>预定义规则集列表</value>\n  </data>\n  <data name=\"TbRoutingTips\" xml:space=\"preserve\">\n    <value>*设置的路由规则，用逗号 (,) 分隔；正则中的逗号用 &lt;COMMA&gt; 替代</value>\n  </data>\n  <data name=\"menuImportRulesFromClipboard\" xml:space=\"preserve\">\n    <value>从剪贴板中导入规则</value>\n  </data>\n  <data name=\"menuImportRulesFromFile\" xml:space=\"preserve\">\n    <value>从文件中导入规则</value>\n  </data>\n  <data name=\"menuImportRulesFromUrl\" xml:space=\"preserve\">\n    <value>从订阅 Url 中导入规则</value>\n  </data>\n  <data name=\"menuRoutingRuleSetting\" xml:space=\"preserve\">\n    <value>规则集设置</value>\n  </data>\n  <data name=\"menuRuleAdd\" xml:space=\"preserve\">\n    <value>添加规则</value>\n  </data>\n  <data name=\"menuRuleExportSelected\" xml:space=\"preserve\">\n    <value>导出所选规则至剪贴板</value>\n  </data>\n  <data name=\"menuRuleList\" xml:space=\"preserve\">\n    <value>规则列表</value>\n  </data>\n  <data name=\"menuRuleRemove\" xml:space=\"preserve\">\n    <value>移除所选规则</value>\n  </data>\n  <data name=\"menuRoutingRuleDetailsSetting\" xml:space=\"preserve\">\n    <value>路由规则详情设置</value>\n  </data>\n  <data name=\"TbAutoSort\" xml:space=\"preserve\">\n    <value>保存时 Domain, IP, 进程名 自动排序</value>\n  </data>\n  <data name=\"TbRuleobjectDoc\" xml:space=\"preserve\">\n    <value>规则详细说明文档</value>\n  </data>\n  <data name=\"TbDnsObjectDoc\" xml:space=\"preserve\">\n    <value>支持填写 DnsObject，JSON 格式，点击查看文档</value>\n  </data>\n  <data name=\"SubUrlTips\" xml:space=\"preserve\">\n    <value>普通分组此处请留空</value>\n  </data>\n  <data name=\"TipChangeRouting\" xml:space=\"preserve\">\n    <value>路由设置改变</value>\n  </data>\n  <data name=\"TipChangeSystemProxy\" xml:space=\"preserve\">\n    <value>系统代理设置改变</value>\n  </data>\n  <data name=\"TbSettingsRouteOnly\" xml:space=\"preserve\">\n    <value>仅限路由 (routeOnly)</value>\n  </data>\n  <data name=\"TbSettingsNotProxyLocalAddress\" xml:space=\"preserve\">\n    <value>请勿将代理服务器用于本地 (Intranet) 地址</value>\n  </data>\n  <data name=\"menuMixedTestServer\" xml:space=\"preserve\">\n    <value>一键多线程测试延迟和速度 (Ctrl+E)</value>\n  </data>\n  <data name=\"LvTestDelay\" xml:space=\"preserve\">\n    <value>延迟 (ms)</value>\n  </data>\n  <data name=\"LvTestSpeed\" xml:space=\"preserve\">\n    <value>速度 (MB/s)</value>\n  </data>\n  <data name=\"FailedToRunCore\" xml:space=\"preserve\">\n    <value>运行 Core 失败，请查看提示信息</value>\n  </data>\n  <data name=\"LvFilter\" xml:space=\"preserve\">\n    <value>别名正则过滤</value>\n  </data>\n  <data name=\"TbDisplayLog\" xml:space=\"preserve\">\n    <value>显示日志</value>\n  </data>\n  <data name=\"TbEnableTunAs\" xml:space=\"preserve\">\n    <value>启用 Tun</value>\n  </data>\n  <data name=\"TbSettingsNewPort4LAN\" xml:space=\"preserve\">\n    <value>为局域网开启新的端口</value>\n  </data>\n  <data name=\"TbSettingsTunMode\" xml:space=\"preserve\">\n    <value>Tun 模式设置</value>\n  </data>\n  <data name=\"menuMoveToGroup\" xml:space=\"preserve\">\n    <value>移至订阅分组</value>\n  </data>\n  <data name=\"TbSettingsEnableDragDropSort\" xml:space=\"preserve\">\n    <value>启用配置拖放排序 (需重启)</value>\n  </data>\n  <data name=\"TbAutoRefresh\" xml:space=\"preserve\">\n    <value>自动刷新</value>\n  </data>\n  <data name=\"SpeedtestingSkip\" xml:space=\"preserve\">\n    <value>跳过测试</value>\n  </data>\n  <data name=\"menuEditServer\" xml:space=\"preserve\">\n    <value>编辑</value>\n  </data>\n  <data name=\"TbSettingsDoubleClick2Activate\" xml:space=\"preserve\">\n    <value>主界面双击设为活动</value>\n  </data>\n  <data name=\"SpeedtestingCompleted\" xml:space=\"preserve\">\n    <value>测试完成</value>\n  </data>\n  <data name=\"TbSettingsDefFingerprint\" xml:space=\"preserve\">\n    <value>默认 TLS 指纹 (fingerprint)</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgent\" xml:space=\"preserve\">\n    <value>用户代理 (User-Agent)</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgentTips\" xml:space=\"preserve\">\n    <value>仅对 tcp/http、ws 协议生效</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamily\" xml:space=\"preserve\">\n    <value>当前字体 (需重启)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyTip\" xml:space=\"preserve\">\n    <value>拷贝字体 TTF/TTC 文件到目录 guiFonts，重启生效</value>\n  </data>\n  <data name=\"TbSettingsSocksPortTip\" xml:space=\"preserve\">\n    <value>Pac 端口 = +3；Xray API 端口 = +4；mihomo API 端口 = +5；</value>\n  </data>\n  <data name=\"TbSettingsStartBootTip\" xml:space=\"preserve\">\n    <value>以管理员权限设置此项，在启动后获得管理员权限</value>\n  </data>\n  <data name=\"TbSettingsFontSize\" xml:space=\"preserve\">\n    <value>字体大小</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestTimeout\" xml:space=\"preserve\">\n    <value>测速单个超时值</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestUrl\" xml:space=\"preserve\">\n    <value>测速文件地址</value>\n  </data>\n  <data name=\"menuMoveTo\" xml:space=\"preserve\">\n    <value>移至上下</value>\n  </data>\n  <data name=\"TbPublicKey\" xml:space=\"preserve\">\n    <value>PublicKey</value>\n  </data>\n  <data name=\"TbShortId\" xml:space=\"preserve\">\n    <value>ShortId</value>\n  </data>\n  <data name=\"TbSpiderX\" xml:space=\"preserve\">\n    <value>SpiderX</value>\n  </data>\n  <data name=\"TbSettingsEnableHWA\" xml:space=\"preserve\">\n    <value>启用硬件加速 (需重启)</value>\n  </data>\n  <data name=\"SpeedtestingWait\" xml:space=\"preserve\">\n    <value>等待测试...</value>\n  </data>\n  <data name=\"SpeedtestingPressEscToExit\" xml:space=\"preserve\">\n    <value>按 ESC 可终止测试</value>\n  </data>\n  <data name=\"TipDisplayLog\" xml:space=\"preserve\">\n    <value>当有异常断流时请关闭</value>\n  </data>\n  <data name=\"MsgSkipSubscriptionUpdate\" xml:space=\"preserve\">\n    <value>未启用更新，跳过此订阅</value>\n  </data>\n  <data name=\"menuRebootAsAdmin\" xml:space=\"preserve\">\n    <value>以管理员身份重启</value>\n  </data>\n  <data name=\"LvMoreUrl\" xml:space=\"preserve\">\n    <value>更多地址 (url)，用逗号 (,) 分隔；订阅转换将失效</value>\n  </data>\n  <data name=\"LvAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>自动更新间隔 (分钟)</value>\n  </data>\n  <data name=\"TbSettingsLogEnabledToFile\" xml:space=\"preserve\">\n    <value>启用日志存到文件</value>\n  </data>\n  <data name=\"LvConvertTarget\" xml:space=\"preserve\">\n    <value>订阅转换目标类型</value>\n  </data>\n  <data name=\"LvConvertTargetTip\" xml:space=\"preserve\">\n    <value>不需要转换时请留空</value>\n  </data>\n  <data name=\"menuDNSSetting\" xml:space=\"preserve\">\n    <value>DNS 设置</value>\n  </data>\n  <data name=\"TbCustomDnsSingbox\" xml:space=\"preserve\">\n    <value>sing-box 自定义 DNS</value>\n  </data>\n  <data name=\"TbDnsSingboxObjectDoc\" xml:space=\"preserve\">\n    <value>请填写 DNS JSON 结构，点击查看文档</value>\n  </data>\n  <data name=\"TbSettingDnsImportDefConfig\" xml:space=\"preserve\">\n    <value>点击导入默认 DNS 配置</value>\n  </data>\n  <data name=\"TbdomainStrategy4Singbox\" xml:space=\"preserve\">\n    <value>sing-box 域名解析策略</value>\n  </data>\n  <data name=\"TbSettingsMux4SboxProtocol\" xml:space=\"preserve\">\n    <value>sing-box Mux 多路复用协议</value>\n  </data>\n  <data name=\"TbRoutingRuleProcess\" xml:space=\"preserve\">\n    <value>进程 (Linux/Windows)</value>\n  </data>\n  <data name=\"TbRoutingRuleIP\" xml:space=\"preserve\">\n    <value>IP 或 IP CIDR</value>\n  </data>\n  <data name=\"TbRoutingRuleDomain\" xml:space=\"preserve\">\n    <value>Domain</value>\n  </data>\n  <data name=\"menuAddHysteria2Server\" xml:space=\"preserve\">\n    <value>添加 [Hysteria2] </value>\n  </data>\n  <data name=\"TbSettingsHysteriaBandwidth\" xml:space=\"preserve\">\n    <value>Hysteria 最大带宽 (Up/Dw)</value>\n  </data>\n  <data name=\"TbSettingsUseSystemHosts\" xml:space=\"preserve\">\n    <value>使用系统 hosts</value>\n  </data>\n  <data name=\"menuAddTuicServer\" xml:space=\"preserve\">\n    <value>添加 [TUIC] </value>\n  </data>\n  <data name=\"TbHeaderType8\" xml:space=\"preserve\">\n    <value>拥塞控制算法</value>\n  </data>\n  <data name=\"LvPrevProfile\" xml:space=\"preserve\">\n    <value>前置代理配置别名</value>\n  </data>\n  <data name=\"LvNextProfile\" xml:space=\"preserve\">\n    <value>落地代理配置別名</value>\n  </data>\n  <data name=\"LvPrevProfileTip\" xml:space=\"preserve\">\n    <value>请确保配置别名存在并唯一</value>\n  </data>\n  <data name=\"TbSettingsTunAutoRoute\" xml:space=\"preserve\">\n    <value>自动路由</value>\n  </data>\n  <data name=\"TbSettingsTunStrictRoute\" xml:space=\"preserve\">\n    <value>严格路由</value>\n  </data>\n  <data name=\"TbSettingsTunStack\" xml:space=\"preserve\">\n    <value>协议栈</value>\n  </data>\n  <data name=\"TbSettingsTunMtu\" xml:space=\"preserve\">\n    <value>MTU</value>\n  </data>\n  <data name=\"TbSettingsEnableIPv6Address\" xml:space=\"preserve\">\n    <value>启用 IPv6</value>\n  </data>\n  <data name=\"menuAddWireguardServer\" xml:space=\"preserve\">\n    <value>添加 [WireGuard] </value>\n  </data>\n  <data name=\"TbPrivateKey\" xml:space=\"preserve\">\n    <value>PrivateKey</value>\n  </data>\n  <data name=\"TbReserved\" xml:space=\"preserve\">\n    <value>Reserved (2,3,4)</value>\n  </data>\n  <data name=\"TbLocalAddress\" xml:space=\"preserve\">\n    <value>Address (IPv4,IPv6)</value>\n  </data>\n  <data name=\"TbPath7\" xml:space=\"preserve\">\n    <value>混淆密码 (obfs password)</value>\n  </data>\n  <data name=\"TbRuleMatchingTips\" xml:space=\"preserve\">\n    <value>(Domain 或 IP 或 进程名) 与 Port 与 Protocol 与 InboundTag =&gt; OutboundTag</value>\n  </data>\n  <data name=\"TbAutoScrollToEnd\" xml:space=\"preserve\">\n    <value>自动滚动到末尾</value>\n  </data>\n  <data name=\"TbSettingsSpeedPingTestUrl\" xml:space=\"preserve\">\n    <value>真连接测试地址</value>\n  </data>\n  <data name=\"SpeedtestingStop\" xml:space=\"preserve\">\n    <value>测试终止中...</value>\n  </data>\n  <data name=\"TransportRequestHostTip5\" xml:space=\"preserve\">\n    <value>*grpc Authority</value>\n  </data>\n  <data name=\"menuAddHttpServer\" xml:space=\"preserve\">\n    <value>添加 [HTTP] </value>\n  </data>\n  <data name=\"TbSettingsEnableFragment\" xml:space=\"preserve\">\n    <value>启用分片 (Fragment)</value>\n  </data>\n  <data name=\"TbSettingsEnableCacheFile4Sbox\" xml:space=\"preserve\">\n    <value>启用 sing-box (规则集文件) 的缓存文件</value>\n  </data>\n  <data name=\"LvCustomRulesetPath4Singbox\" xml:space=\"preserve\">\n    <value>自定义 sing-box rule-set</value>\n  </data>\n  <data name=\"NeedRebootTips\" xml:space=\"preserve\">\n    <value>操作成功。请点击设置菜单重启应用。</value>\n  </data>\n  <data name=\"menuOpenTheFileLocation\" xml:space=\"preserve\">\n    <value>打开存储所在的位置</value>\n  </data>\n  <data name=\"TbSorting\" xml:space=\"preserve\">\n    <value>排序</value>\n  </data>\n  <data name=\"TbSortingChain\" xml:space=\"preserve\">\n    <value>路由链</value>\n  </data>\n  <data name=\"TbSortingDefault\" xml:space=\"preserve\">\n    <value>默认</value>\n  </data>\n  <data name=\"TbSortingDelay\" xml:space=\"preserve\">\n    <value>延迟</value>\n  </data>\n  <data name=\"TbSortingDownSpeed\" xml:space=\"preserve\">\n    <value>下载速度</value>\n  </data>\n  <data name=\"TbSortingDownTraffic\" xml:space=\"preserve\">\n    <value>下载流量</value>\n  </data>\n  <data name=\"TbSortingHost\" xml:space=\"preserve\">\n    <value>主机</value>\n  </data>\n  <data name=\"TbSortingName\" xml:space=\"preserve\">\n    <value>名称</value>\n  </data>\n  <data name=\"TbSortingNetwork\" xml:space=\"preserve\">\n    <value>网络</value>\n  </data>\n  <data name=\"TbSortingTime\" xml:space=\"preserve\">\n    <value>时间</value>\n  </data>\n  <data name=\"TbSortingType\" xml:space=\"preserve\">\n    <value>类型</value>\n  </data>\n  <data name=\"TbSortingUpSpeed\" xml:space=\"preserve\">\n    <value>上传速度</value>\n  </data>\n  <data name=\"TbSortingUpTraffic\" xml:space=\"preserve\">\n    <value>上传流量</value>\n  </data>\n  <data name=\"TbConnections\" xml:space=\"preserve\">\n    <value>当前连接</value>\n  </data>\n  <data name=\"menuConnectionClose\" xml:space=\"preserve\">\n    <value>关闭连接</value>\n  </data>\n  <data name=\"menuConnectionCloseAll\" xml:space=\"preserve\">\n    <value>关闭所有连接</value>\n  </data>\n  <data name=\"TbProxies\" xml:space=\"preserve\">\n    <value>当前代理</value>\n  </data>\n  <data name=\"menuRulemode\" xml:space=\"preserve\">\n    <value>规则模式</value>\n  </data>\n  <data name=\"menuModeDirect\" xml:space=\"preserve\">\n    <value>直连</value>\n  </data>\n  <data name=\"menuModeGlobal\" xml:space=\"preserve\">\n    <value>全局</value>\n  </data>\n  <data name=\"menuModeNothing\" xml:space=\"preserve\">\n    <value>随原配置</value>\n  </data>\n  <data name=\"menuModeRule\" xml:space=\"preserve\">\n    <value>规则</value>\n  </data>\n  <data name=\"menuProxiesDelaytest\" xml:space=\"preserve\">\n    <value>延迟测试</value>\n  </data>\n  <data name=\"menuProxiesDelaytestPart\" xml:space=\"preserve\">\n    <value>当前部分延迟测试</value>\n  </data>\n  <data name=\"menuProxiesReload\" xml:space=\"preserve\">\n    <value>刷新</value>\n  </data>\n  <data name=\"menuProxiesSelectActivity\" xml:space=\"preserve\">\n    <value>设为活动</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Out\" xml:space=\"preserve\">\n    <value>Outbound 默认解析策略</value>\n  </data>\n  <data name=\"TbSettingsMainGirdOrientation\" xml:space=\"preserve\">\n    <value>主界面布局方向 (需重启)</value>\n  </data>\n  <data name=\"TbSettingsDomainDNSAddress\" xml:space=\"preserve\">\n    <value>Outbound 域名解析地址</value>\n  </data>\n  <data name=\"menuProfileAutofitColumnWidth\" xml:space=\"preserve\">\n    <value>自动调整列宽</value>\n  </data>\n  <data name=\"menuExport2ShareUrlBase64\" xml:space=\"preserve\">\n    <value>导出分享链接至剪贴板 (多选) Base64 编码</value>\n  </data>\n  <data name=\"menuExport2ClientConfigClipboard\" xml:space=\"preserve\">\n    <value>导出所选完整配置至剪贴板</value>\n  </data>\n  <data name=\"menuShowOrHideMainWindow\" xml:space=\"preserve\">\n    <value>显示或隐藏主界面</value>\n  </data>\n  <data name=\"TbPreSocksPort4Sub\" xml:space=\"preserve\">\n    <value>自定义配置的 Socks 端口</value>\n  </data>\n  <data name=\"menuBackupAndRestore\" xml:space=\"preserve\">\n    <value>备份和还原</value>\n  </data>\n  <data name=\"menuLocalBackup\" xml:space=\"preserve\">\n    <value>备份到本地</value>\n  </data>\n  <data name=\"menuLocalRestore\" xml:space=\"preserve\">\n    <value>从本地恢复</value>\n  </data>\n  <data name=\"menuRemoteBackup\" xml:space=\"preserve\">\n    <value>备份到远程 (WebDAV)</value>\n  </data>\n  <data name=\"menuRemoteRestore\" xml:space=\"preserve\">\n    <value>从远程恢复 (WebDAV)</value>\n  </data>\n  <data name=\"menuLocalBackupAndRestore\" xml:space=\"preserve\">\n    <value>本地</value>\n  </data>\n  <data name=\"menuRemoteBackupAndRestore\" xml:space=\"preserve\">\n    <value>远程 (WebDAV)</value>\n  </data>\n  <data name=\"LvWebDavUrl\" xml:space=\"preserve\">\n    <value>WebDav 服务器地址</value>\n  </data>\n  <data name=\"LvWebDavUserName\" xml:space=\"preserve\">\n    <value>WebDav 账户</value>\n  </data>\n  <data name=\"LvWebDavPassword\" xml:space=\"preserve\">\n    <value>WebDav 密码</value>\n  </data>\n  <data name=\"LvWebDavCheck\" xml:space=\"preserve\">\n    <value>WebDav 可用检查</value>\n  </data>\n  <data name=\"LvWebDavDirName\" xml:space=\"preserve\">\n    <value>远程文件夹名称 (可选)</value>\n  </data>\n  <data name=\"LocalRestoreInvalidZipTips\" xml:space=\"preserve\">\n    <value>无效备份文件</value>\n  </data>\n  <data name=\"ConnectionsHostFilterTitle\" xml:space=\"preserve\">\n    <value>主机过滤器</value>\n  </data>\n  <data name=\"TipActiveServer\" xml:space=\"preserve\">\n    <value>活动</value>\n  </data>\n  <data name=\"TbSettingsGeoFilesSource\" xml:space=\"preserve\">\n    <value>Geo 文件来源 (可选)</value>\n  </data>\n  <data name=\"TbSettingsSrsFilesSource\" xml:space=\"preserve\">\n    <value>sing-box ruleset 文件来源 (可选)</value>\n  </data>\n  <data name=\"UpgradeAppNotExistTip\" xml:space=\"preserve\">\n    <value>升级工具 App 不存在</value>\n  </data>\n  <data name=\"TbSettingsRoutingRulesSource\" xml:space=\"preserve\">\n    <value>路由规则集来源 (可选)</value>\n  </data>\n  <data name=\"menuRegionalPresets\" xml:space=\"preserve\">\n    <value>区域预置设置</value>\n  </data>\n  <data name=\"menuRegionalPresetsDefault\" xml:space=\"preserve\">\n    <value>默认区域</value>\n  </data>\n  <data name=\"menuRegionalPresetsRussia\" xml:space=\"preserve\">\n    <value>俄罗斯</value>\n  </data>\n  <data name=\"menuRegionalPresetsIran\" xml:space=\"preserve\">\n    <value>伊朗</value>\n  </data>\n  <data name=\"TbSettingsChinaUserTip\" xml:space=\"preserve\">\n    <value>中国区域用户可忽略此项</value>\n  </data>\n  <data name=\"menuAddServerViaImage\" xml:space=\"preserve\">\n    <value>扫描图片中的二维码</value>\n  </data>\n  <data name=\"InvalidUrlTip\" xml:space=\"preserve\">\n    <value>地址 (Url) 无效</value>\n  </data>\n  <data name=\"InsecureUrlProtocol\" xml:space=\"preserve\">\n    <value>请不要使用不安全的 HTTP 协议订阅地址</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyLinuxTip\" xml:space=\"preserve\">\n    <value>安装字体到系统中，选择或填入字体名称，重启生效</value>\n  </data>\n  <data name=\"menuExitTips\" xml:space=\"preserve\">\n    <value>是否确定退出？</value>\n  </data>\n  <data name=\"LvMemo\" xml:space=\"preserve\">\n    <value>备注备忘</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPassword\" xml:space=\"preserve\">\n    <value>系统的 sudo 密码</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPasswordTip\" xml:space=\"preserve\">\n    <value>密码将调用命令行校验，如果因为校验错误导致无法正常运行时，请重启本应用。 密码不会存储，每次重启后都需要再次输入。</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip5\" xml:space=\"preserve\">\n    <value>*XHTTP 模式</value>\n  </data>\n  <data name=\"TransportExtraTip\" xml:space=\"preserve\">\n    <value>XHTTP Extra 原始 JSON，格式： { XHTTPObject }</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenClose\" xml:space=\"preserve\">\n    <value>关闭窗口时隐藏至托盘</value>\n  </data>\n  <data name=\"TbSettingsMixedConcurrencyCount\" xml:space=\"preserve\">\n    <value>多线程测试时的并发数量</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip2\" xml:space=\"preserve\">\n    <value>例外：对于下列地址不使用代理配置。使用逗号 (,) 分隔。</value>\n  </data>\n  <data name=\"TbSettingsDestOverride\" xml:space=\"preserve\">\n    <value>流量探测类型</value>\n  </data>\n  <data name=\"TbSettingsSecondLocalPortEnabled\" xml:space=\"preserve\">\n    <value>开启第二个本地监听端口</value>\n  </data>\n  <data name=\"TbRoutingInboundTagTips\" xml:space=\"preserve\">\n    <value>Socks：本地端口，Socks2：第二个本地端口，Socks3：局域网端口</value>\n  </data>\n  <data name=\"TbSettingsTheme\" xml:space=\"preserve\">\n    <value>主题</value>\n  </data>\n  <data name=\"menuCopyProxyCmdToClipboard\" xml:space=\"preserve\">\n    <value>复制终端代理命令至剪贴板</value>\n  </data>\n  <data name=\"SpeedtestingTestFailedPart\" xml:space=\"preserve\">\n    <value>开始对失败部分进行重新测试，剩余 {0} 个。可按 ESC 终止...</value>\n  </data>\n  <data name=\"menuTestServerResult\" xml:space=\"preserve\">\n    <value>按测试结果</value>\n  </data>\n  <data name=\"menuRemoveInvalidServerResult\" xml:space=\"preserve\">\n    <value>按测试结果移除无效</value>\n  </data>\n  <data name=\"RemoveInvalidServerResultTip\" xml:space=\"preserve\">\n    <value>移除无效测试结果 {0} 个。</value>\n  </data>\n  <data name=\"TbPorts7\" xml:space=\"preserve\">\n    <value>跳跃端口范围</value>\n  </data>\n  <data name=\"TbPorts7Tips\" xml:space=\"preserve\">\n    <value>会覆盖端口，多组时用逗号 (,) 隔开</value>\n  </data>\n  <data name=\"menuExportConfig\" xml:space=\"preserve\">\n    <value>导出</value>\n  </data>\n  <data name=\"TbSettingsIPAPIUrl\" xml:space=\"preserve\">\n    <value>当前连接信息测试地址</value>\n  </data>\n  <data name=\"TbRuleOutboundTagTip\" xml:space=\"preserve\">\n    <value>可以填写配置别名，请确保存在并唯一</value>\n  </data>\n  <data name=\"SudoIncorrectPasswordTip\" xml:space=\"preserve\">\n    <value>密码错误，请重试。</value>\n  </data>\n  <data name=\"TbMldsa65Verify\" xml:space=\"preserve\">\n    <value>Mldsa65Verify</value>\n  </data>\n  <data name=\"menuAddAnytlsServer\" xml:space=\"preserve\">\n    <value>添加 [Anytls] </value>\n  </data>\n  <data name=\"TbRemoteDNS\" xml:space=\"preserve\">\n    <value>远程 DNS</value>\n  </data>\n  <data name=\"TbDomesticDNS\" xml:space=\"preserve\">\n    <value>直连 DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategy\" xml:space=\"preserve\">\n    <value>直连目标解析策略</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategy\" xml:space=\"preserve\">\n    <value>代理目标解析策略</value>\n  </data>\n  <data name=\"TbAddCommonDNSHosts\" xml:space=\"preserve\">\n    <value>添加常用 DNS Hosts</value>\n  </data>\n  <data name=\"TbFakeIP\" xml:space=\"preserve\">\n    <value>FakeIP</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueries\" xml:space=\"preserve\">\n    <value>阻止 SVCB 和 HTTPS 查询</value>\n  </data>\n  <data name=\"TbDNSHostsConfig\" xml:space=\"preserve\">\n    <value>DNS Hosts：（“域名1 ip1 ip2” 一行一个）</value>\n  </data>\n  <data name=\"ThBasicDNSSettings\" xml:space=\"preserve\">\n    <value>DNS 基础设置</value>\n  </data>\n  <data name=\"ThAdvancedDNSSettings\" xml:space=\"preserve\">\n    <value>DNS 进阶设置</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPs\" xml:space=\"preserve\">\n    <value>校验相应地区域名 IP</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPsDesc\" xml:space=\"preserve\">\n    <value>配置后，会对相应地区域名（如 geosite:cn - geoip:cn）的返回 IP 进行校验，仅返回期望 IP</value>\n  </data>\n  <data name=\"TbCustomDNSEnable\" xml:space=\"preserve\">\n    <value>启用自定义 DNS</value>\n  </data>\n  <data name=\"TbCustomDNSEnabledPageInvalid\" xml:space=\"preserve\">\n    <value>自定义 DNS 已启用，此页面配置将无效</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueriesTips\" xml:space=\"preserve\">\n    <value>开启后将阻止 ECH 和 HTTP/3 可用性查询</value>\n  </data>\n  <data name=\"FillCorrectConfigTemplateText\" xml:space=\"preserve\">\n    <value>请填写正确的配置模板</value>\n  </data>\n  <data name=\"menuFullConfigTemplate\" xml:space=\"preserve\">\n    <value>完整配置模板设置</value>\n  </data>\n  <data name=\"TbFullConfigTemplateEnable\" xml:space=\"preserve\">\n    <value>启用完整配置模板</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplate\" xml:space=\"preserve\">\n    <value>v2ray 完整配置模板</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>仅添加出站配置，routing.balancers 和 routing.rules.outboundTag，点击查看文档</value>\n  </data>\n  <data name=\"TbAddProxyProtocolOutboundOnly\" xml:space=\"preserve\">\n    <value>不添加非代理协议出站</value>\n  </data>\n  <data name=\"TbSetUpstreamProxyDetour\" xml:space=\"preserve\">\n    <value>设置上游代理 tag</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplate\" xml:space=\"preserve\">\n    <value>sing-box 完整配置模板</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>仅添加出站和端点配置，点击查看文档</value>\n  </data>\n  <data name=\"TbFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>此功能供高级用户和有特殊需求的用户使用。 启用此功能后，将忽略 Core 的基础设置，DNS 设置 ，路由设置。你需要保证系统代理的端口和流量统计等功能的配置正确，一切都由你来设置。</value>\n  </data>\n  <data name=\"MsgStartParsingSubscription\" xml:space=\"preserve\">\n    <value>开始解析和处理订阅内容</value>\n  </data>\n  <data name=\"TbSelectProfile\" xml:space=\"preserve\">\n    <value>选择配置</value>\n  </data>\n  <data name=\"TbFakeIPTips\" xml:space=\"preserve\">\n    <value>默认全局生效，内置 FakeIP 过滤，仅在 sing-box 中生效</value>\n  </data>\n  <data name=\"PleaseAddAtLeastOneServer\" xml:space=\"preserve\">\n    <value>请至少添加一个配置</value>\n  </data>\n  <data name=\"TbConfigTypePolicyGroup\" xml:space=\"preserve\">\n    <value>策略组</value>\n  </data>\n  <data name=\"TbConfigTypeProxyChain\" xml:space=\"preserve\">\n    <value>链式代理</value>\n  </data>\n  <data name=\"TbLeastPing\" xml:space=\"preserve\">\n    <value>最低延迟</value>\n  </data>\n  <data name=\"TbRandom\" xml:space=\"preserve\">\n    <value>随机</value>\n  </data>\n  <data name=\"TbRoundRobin\" xml:space=\"preserve\">\n    <value>负载均衡</value>\n  </data>\n  <data name=\"TbLeastLoad\" xml:space=\"preserve\">\n    <value>最稳定</value>\n  </data>\n  <data name=\"TbPolicyGroupType\" xml:space=\"preserve\">\n    <value>策略组类型</value>\n  </data>\n  <data name=\"menuAddPolicyGroupServer\" xml:space=\"preserve\">\n    <value>添加策略组</value>\n  </data>\n  <data name=\"menuAddProxyChainServer\" xml:space=\"preserve\">\n    <value>添加链式代理</value>\n  </data>\n  <data name=\"menuAddChildServer\" xml:space=\"preserve\">\n    <value>添加子配置</value>\n  </data>\n  <data name=\"menuRemoveChildServer\" xml:space=\"preserve\">\n    <value>删除子配置</value>\n  </data>\n  <data name=\"menuServerList\" xml:space=\"preserve\">\n    <value>子配置项一，从订阅分组中自动添加</value>\n  </data>\n  <data name=\"TbFallback\" xml:space=\"preserve\">\n    <value>故障转移</value>\n  </data>\n  <data name=\"MsgCoreNotSupportNetwork\" xml:space=\"preserve\">\n    <value>核心 '{0}' 不支持网络类型 '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocolTransport\" xml:space=\"preserve\">\n    <value>核心 '{0}' 在使用传输方式 '{2}' 时不支持协议 '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocol\" xml:space=\"preserve\">\n    <value>核心 '{0}' 不支持协议 '{1}'</value>\n  </data>\n  <data name=\"MsgInvalidProperty\" xml:space=\"preserve\">\n    <value>{0} 属性无效，请检查</value>\n  </data>\n  <data name=\"MsgNotSupportProtocol\" xml:space=\"preserve\">\n    <value>不支持协议 '{0}'</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenCloseTip\" xml:space=\"preserve\">\n    <value>如果系统没有托盘功能，请不要开启</value>\n  </data>\n  <data name=\"TbRuleType\" xml:space=\"preserve\">\n    <value>规则类型</value>\n  </data>\n  <data name=\"TbRuleTypeTips\" xml:space=\"preserve\">\n    <value>可对 Routing 和 DNS 单独设定规则，ALL 则都生效</value>\n  </data>\n  <data name=\"TbBootstrapDNS\" xml:space=\"preserve\">\n    <value>Bootstrap DNS</value>\n  </data>\n  <data name=\"TbBootstrapDNSTips\" xml:space=\"preserve\">\n    <value>解析 DNS 服务器域名，需指定为 IP</value>\n  </data>\n  <data name=\"menuFastRealPing\" xml:space=\"preserve\">\n    <value>一键测试真连接延迟</value>\n  </data>\n  <data name=\"TbPolicyGroupSubChildTip\" xml:space=\"preserve\">\n    <value>自动从订阅分组添加过滤后的配置</value>\n  </data>\n  <data name=\"TbCertPinning\" xml:space=\"preserve\">\n    <value>固定证书</value>\n  </data>\n  <data name=\"TbCertPinningTips\" xml:space=\"preserve\">\n    <value>固定证书（二选一填写即可）\n当指定此证书后，将固定该证书，并禁用“跳过证书验证”选项。\n\n“获取证书”操作可能失败，原因包括使用了自签名证书，或系统中存在不受信任甚至恶意的 CA。</value>\n  </data>\n  <data name=\"TbFetchCert\" xml:space=\"preserve\">\n    <value>获取证书</value>\n  </data>\n  <data name=\"TbFetchCertChain\" xml:space=\"preserve\">\n    <value>获取证书链</value>\n  </data>\n  <data name=\"ServerNameMustBeValidDomain\" xml:space=\"preserve\">\n    <value>请设置有效的域名</value>\n  </data>\n  <data name=\"CertNotSet\" xml:space=\"preserve\">\n    <value>证书未设置</value>\n  </data>\n  <data name=\"CertSet\" xml:space=\"preserve\">\n    <value>证书已设置</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyPacPath\" xml:space=\"preserve\">\n    <value>自定义 PAC 文件路径</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyScriptPath\" xml:space=\"preserve\">\n    <value>自定义系统代理脚本文件路径</value>\n  </data>\n  <data name=\"TbSettingsMacOSShowInDock\" xml:space=\"preserve\">\n    <value>macOS 在 Dock 栏中显示 (需重启)</value>\n  </data>\n  <data name=\"menuServerList2\" xml:space=\"preserve\">\n    <value>子配置项二，从自建中选择添加</value>\n  </data>\n  <data name=\"TbEchConfigList\" xml:space=\"preserve\">\n    <value>EchConfigList</value>\n  </data>\n  <data name=\"TbEchForceQuery\" xml:space=\"preserve\">\n    <value>EchForceQuery</value>\n  </data>\n  <data name=\"TbFullCertTips\" xml:space=\"preserve\">\n    <value>完整证书（链），PEM 格式</value>\n  </data>\n  <data name=\"TbCertSha256Tips\" xml:space=\"preserve\">\n    <value>证书指纹（SHA-256）</value>\n  </data>\n  <data name=\"TbServeStale\" xml:space=\"preserve\">\n    <value>乐观缓存</value>\n  </data>\n  <data name=\"TbParallelQuery\" xml:space=\"preserve\">\n    <value>并行查询</value>\n  </data>\n  <data name=\"TbDomesticDNSTips\" xml:space=\"preserve\">\n    <value>默认仅在路由阶段被调用解析</value>\n  </data>\n  <data name=\"TbRemoteDNSTips\" xml:space=\"preserve\">\n    <value>默认仅在路由阶段被调用解析；请确保远程服务器可访问该 DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategyTips\" xml:space=\"preserve\">\n    <value>当未选择或 \"AsIs\" 时，使用系统 DNS 进行解析；否则，使用内部 DNS 模块解析。</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategyTips\" xml:space=\"preserve\">\n    <value>当未选择或 \"AsIs\" 时，由远程服务器端 DNS 解析；否则，使用内部 DNS 模块解析。</value>\n  </data>\n  <data name=\"TbHopInt7\" xml:space=\"preserve\">\n    <value>端口跳跃间隔</value>\n  </data>\n  <data name=\"menuServerListPreview\" xml:space=\"preserve\">\n    <value>子配置项预览</value>\n  </data>\n  <data name=\"TbFinalmask\" xml:space=\"preserve\">\n    <value>Finalmask</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeWarning\" xml:space=\"preserve\">\n    <value>路由规则 {0} 出站节点 {1} 警告：{2}</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeError\" xml:space=\"preserve\">\n    <value>路由规则 {0} 出站节点 {1} 错误：{2}。已回退为仅使用代理节点。</value>\n  </data>\n  <data name=\"MsgGroupCycleDependency\" xml:space=\"preserve\">\n    <value>节点组 {0} 与子节点 {1} 存在循环依赖，已跳过该节点。</value>\n  </data>\n  <data name=\"MsgGroupChildNodeWarning\" xml:space=\"preserve\">\n    <value>节点组 {0} 子节点 {1} 警告：{2}</value>\n  </data>\n  <data name=\"MsgGroupChildNodeError\" xml:space=\"preserve\">\n    <value>节点组 {0} 子节点 {1} 错误：{2}。已跳过该节点。</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeWarning\" xml:space=\"preserve\">\n    <value>节点组 {0} 子节点组 {1} 警告：{2}</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeError\" xml:space=\"preserve\">\n    <value>节点组 {0} 子节点组 {1} 错误：{2}。已跳过该节点。</value>\n  </data>\n  <data name=\"MsgGroupNoValidChildNode\" xml:space=\"preserve\">\n    <value>节点组 {0} 下没有有效的子节点。</value>\n  </data>\n  <data name=\"MsgRoutingRuleEmptyOutboundTag\" xml:space=\"preserve\">\n    <value>路由规则 {0} 的出站标签为空，已回退为仅使用代理节点。</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeNotFound\" xml:space=\"preserve\">\n    <value>路由规则 {0} 的出站节点 {1} 未找到，已回退为仅使用代理节点。</value>\n  </data>\n  <data name=\"MsgSubscriptionPrevProfileNotFound\" xml:space=\"preserve\">\n    <value>订阅前置节点 {0} 未找到，已跳过。</value>\n  </data>\n  <data name=\"MsgSubscriptionNextProfileNotFound\" xml:space=\"preserve\">\n    <value>订阅后置节点 {0} 未找到，已跳过。</value>\n  </data>\n  <data name=\"menuGenGroupServer\" xml:space=\"preserve\">\n    <value>一键生成策略组</value>\n  </data>\n  <data name=\"menuAllServers\" xml:space=\"preserve\">\n    <value>全部配置项</value>\n  </data>\n  <data name=\"menuGenRegionGroup\" xml:space=\"preserve\">\n    <value>按地区分组</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!--\n    Microsoft ResX Schema\n\n    Version 2.0\n\n    The primary goals of this format is to allow a simple XML format\n    that is mostly human readable. The generation and parsing of the\n    various data types are done through the TypeConverter classes\n    associated with the data types.\n\n    Example:\n\n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n\n    There are any number of \"resheader\" rows that contain simple\n    name/value pairs.\n\n    Each data row contains a name, and value. The row also contains a\n    type or mimetype. Type corresponds to a .NET class that support\n    text/value conversion through the TypeConverter architecture.\n    Classes that don't support this are serialized and stored with the\n    mimetype set.\n\n    The mimetype is used for serialized objects, and tells the\n    ResXResourceReader how to depersist the object. This is currently not\n    extensible. For a given mimetype the value must be set accordingly:\n\n    Note - application/x-microsoft.net.object.binary.base64 is the format\n    that the ResXResourceWriter will generate, however the reader can\n    read any of the formats listed below.\n\n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with\n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array\n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <data name=\"BatchExportURLSuccessfully\" xml:space=\"preserve\">\n    <value>匯出分享連結至剪貼簿成功</value>\n  </data>\n  <data name=\"CheckServerSettings\" xml:space=\"preserve\">\n    <value>請先檢查設定</value>\n  </data>\n  <data name=\"ConfigurationFormatIncorrect\" xml:space=\"preserve\">\n    <value>設定格式不正確</value>\n  </data>\n  <data name=\"CustomServerTips\" xml:space=\"preserve\">\n    <value>注意，自訂設定完全依賴您自行輸入的內容，部分功能可能無法使用。如需啟用系統代理，請手動調整監聽埠。</value>\n  </data>\n  <data name=\"Downloading\" xml:space=\"preserve\">\n    <value>下載開始...</value>\n  </data>\n  <data name=\"FailedConversionConfiguration\" xml:space=\"preserve\">\n    <value>轉換設定失敗</value>\n  </data>\n  <data name=\"FailedGenDefaultConfiguration\" xml:space=\"preserve\">\n    <value>生成預設設定檔失敗</value>\n  </data>\n  <data name=\"FailedGetDefaultConfiguration\" xml:space=\"preserve\">\n    <value>取得預設設定失敗</value>\n  </data>\n  <data name=\"FailedImportedCustomServer\" xml:space=\"preserve\">\n    <value>匯入自訂設定失敗</value>\n  </data>\n  <data name=\"FailedReadConfiguration\" xml:space=\"preserve\">\n    <value>讀取設定失敗</value>\n  </data>\n  <data name=\"FillCorrectServerPort\" xml:space=\"preserve\">\n    <value>請填寫有效的埠號</value>\n  </data>\n  <data name=\"FillLocalListeningPort\" xml:space=\"preserve\">\n    <value>請填寫本機偵聽埠</value>\n  </data>\n  <data name=\"FillPassword\" xml:space=\"preserve\">\n    <value>請填寫密碼</value>\n  </data>\n  <data name=\"FillServerAddress\" xml:space=\"preserve\">\n    <value>請填寫位址</value>\n  </data>\n  <data name=\"FillUUID\" xml:space=\"preserve\">\n    <value>請填寫使用者 ID</value>\n  </data>\n  <data name=\"Incorrectconfiguration\" xml:space=\"preserve\">\n    <value>設定不正確，請檢查</value>\n  </data>\n  <data name=\"InitialConfiguration\" xml:space=\"preserve\">\n    <value>初始化設定</value>\n  </data>\n  <data name=\"IsLatestCore\" xml:space=\"preserve\">\n    <value>{0} {1} 已是最新版本。</value>\n  </data>\n  <data name=\"IsLatestN\" xml:space=\"preserve\">\n    <value>{0} {1} 已是最新版本。</value>\n  </data>\n  <data name=\"LvAddress\" xml:space=\"preserve\">\n    <value>位址</value>\n  </data>\n  <data name=\"LvEncryptionMethod\" xml:space=\"preserve\">\n    <value>加密方式</value>\n  </data>\n  <data name=\"LvPort\" xml:space=\"preserve\">\n    <value>埠</value>\n  </data>\n  <data name=\"LvServiceType\" xml:space=\"preserve\">\n    <value>類型</value>\n  </data>\n  <data name=\"LvSubscription\" xml:space=\"preserve\">\n    <value>訂閱分組</value>\n  </data>\n  <data name=\"LvTodayDownloadDataAmount\" xml:space=\"preserve\">\n    <value>今日下載</value>\n  </data>\n  <data name=\"LvTodayUploadDataAmount\" xml:space=\"preserve\">\n    <value>今日上傳</value>\n  </data>\n  <data name=\"LvTotalDownloadDataAmount\" xml:space=\"preserve\">\n    <value>總下載</value>\n  </data>\n  <data name=\"LvTotalUploadDataAmount\" xml:space=\"preserve\">\n    <value>總上傳</value>\n  </data>\n  <data name=\"LvTransportProtocol\" xml:space=\"preserve\">\n    <value>傳輸協定</value>\n  </data>\n  <data name=\"MsgDownloadV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>下載 Core 成功</value>\n  </data>\n  <data name=\"MsgFailedImportSubscription\" xml:space=\"preserve\">\n    <value>匯入訂閱內容失敗</value>\n  </data>\n  <data name=\"MsgGetSubscriptionSuccessfully\" xml:space=\"preserve\">\n    <value>獲取訂閱內容成功</value>\n  </data>\n  <data name=\"MsgNoValidSubscription\" xml:space=\"preserve\">\n    <value>未設定有效的訂閱</value>\n  </data>\n  <data name=\"MsgParsingSuccessfully\" xml:space=\"preserve\">\n    <value>解析 {0} 成功</value>\n  </data>\n  <data name=\"MsgStartGettingSubscriptions\" xml:space=\"preserve\">\n    <value>開始獲取訂閱內容</value>\n  </data>\n  <data name=\"MsgStartUpdating\" xml:space=\"preserve\">\n    <value>開始更新 {0}...</value>\n  </data>\n  <data name=\"MsgSubscriptionDecodingFailed\" xml:space=\"preserve\">\n    <value>無效的訂閱內容</value>\n  </data>\n  <data name=\"MsgUnpacking\" xml:space=\"preserve\">\n    <value>正在解壓......</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionEnd\" xml:space=\"preserve\">\n    <value>更新訂閱結束</value>\n  </data>\n  <data name=\"MsgUpdateSubscriptionStart\" xml:space=\"preserve\">\n    <value>更新訂閱開始</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfully\" xml:space=\"preserve\">\n    <value>更新 Core 成功</value>\n  </data>\n  <data name=\"MsgUpdateV2rayCoreSuccessfullyMore\" xml:space=\"preserve\">\n    <value>更新 Core 成功！正在重啟服務...</value>\n  </data>\n  <data name=\"NonvmessOrssProtocol\" xml:space=\"preserve\">\n    <value>非 VMess 或 SS 協定</value>\n  </data>\n  <data name=\"NotFoundCore\" xml:space=\"preserve\">\n    <value>在資料夾 ({0}) 中找不到 Core 檔案（檔名：{1}）。請下載後放入該資料夾。下載網址：{2}</value>\n  </data>\n  <data name=\"NoValidQRcodeFound\" xml:space=\"preserve\">\n    <value>掃描完成，未發現有效二維碼</value>\n  </data>\n  <data name=\"OperationFailed\" xml:space=\"preserve\">\n    <value>操作失敗，請檢查後重試</value>\n  </data>\n  <data name=\"PleaseFillRemarks\" xml:space=\"preserve\">\n    <value>請填寫別名</value>\n  </data>\n  <data name=\"PleaseSelectEncryption\" xml:space=\"preserve\">\n    <value>請選擇加密方式</value>\n  </data>\n  <data name=\"PleaseSelectProtocol\" xml:space=\"preserve\">\n    <value>請選擇協定</value>\n  </data>\n  <data name=\"PleaseSelectServer\" xml:space=\"preserve\">\n    <value>請先選擇設定</value>\n  </data>\n  <data name=\"RemoveDuplicateServerResult\" xml:space=\"preserve\">\n    <value>去重完成。原數量: {0}，現數量: {1}。</value>\n  </data>\n  <data name=\"RemoveServer\" xml:space=\"preserve\">\n    <value>是否確定移除？</value>\n  </data>\n  <data name=\"SaveClientConfigurationIn\" xml:space=\"preserve\">\n    <value>用戶端設定檔儲存在：{0}</value>\n  </data>\n  <data name=\"StartService\" xml:space=\"preserve\">\n    <value>啟動服務 ({0})...</value>\n  </data>\n  <data name=\"SuccessfulConfiguration\" xml:space=\"preserve\">\n    <value>設定成功。{0}</value>\n  </data>\n  <data name=\"SuccessfullyImportedCustomServer\" xml:space=\"preserve\">\n    <value>成功匯入自訂節點</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaClipboard\" xml:space=\"preserve\">\n    <value>成功從剪貼簿匯入 {0} 個節點</value>\n  </data>\n  <data name=\"SuccessfullyImportedServerViaScan\" xml:space=\"preserve\">\n    <value>掃描匯入分享連結成功</value>\n  </data>\n  <data name=\"TestMeOutput\" xml:space=\"preserve\">\n    <value>目前延遲: {0} ms，{1}</value>\n  </data>\n  <data name=\"OperationSuccess\" xml:space=\"preserve\">\n    <value>操作成功</value>\n  </data>\n  <data name=\"PleaseSelectRules\" xml:space=\"preserve\">\n    <value>請先選擇規則</value>\n  </data>\n  <data name=\"RemoveRules\" xml:space=\"preserve\">\n    <value>是否確定移除規則？</value>\n  </data>\n  <data name=\"RoutingRuleDetailRequiredTips\" xml:space=\"preserve\">\n    <value>{0}，至少需填寫其中一項。</value>\n  </data>\n  <data name=\"LvRemarks\" xml:space=\"preserve\">\n    <value>別名</value>\n  </data>\n  <data name=\"LvUrl\" xml:space=\"preserve\">\n    <value>可選位址 (URL)</value>\n  </data>\n  <data name=\"LvCount\" xml:space=\"preserve\">\n    <value>數量</value>\n  </data>\n  <data name=\"MsgNeedUrl\" xml:space=\"preserve\">\n    <value>請填寫 URL</value>\n  </data>\n  <data name=\"AddBatchRoutingRulesYesNo\" xml:space=\"preserve\">\n    <value>是否追加規則？選擇\"是\"則追加，選擇\"否\"則完全取代。</value>\n  </data>\n  <data name=\"MsgDownloadGeoFileSuccessfully\" xml:space=\"preserve\">\n    <value>下載 GeoFile：{0} 成功</value>\n  </data>\n  <data name=\"MsgInformationTitle\" xml:space=\"preserve\">\n    <value>資訊</value>\n  </data>\n  <data name=\"LvCustomIcon\" xml:space=\"preserve\">\n    <value>自訂圖示</value>\n  </data>\n  <data name=\"FillCorrectDNSText\" xml:space=\"preserve\">\n    <value>請填寫正確的自訂 DNS</value>\n  </data>\n  <data name=\"TransportPathTip1\" xml:space=\"preserve\">\n    <value>*ws/httpupgrade/xhttp path</value>\n  </data>\n  <data name=\"TransportPathTip2\" xml:space=\"preserve\">\n    <value>*h2 path</value>\n  </data>\n  <data name=\"TransportPathTip3\" xml:space=\"preserve\">\n    <value>*QUIC 加密金鑰</value>\n  </data>\n  <data name=\"TransportPathTip4\" xml:space=\"preserve\">\n    <value>*grpc serviceName</value>\n  </data>\n  <data name=\"TransportRequestHostTip1\" xml:space=\"preserve\">\n    <value>*http host 中間逗號 (,) 分隔</value>\n  </data>\n  <data name=\"TransportRequestHostTip2\" xml:space=\"preserve\">\n    <value>*ws/httpupgrade/xhttp host</value>\n  </data>\n  <data name=\"TransportRequestHostTip3\" xml:space=\"preserve\">\n    <value>*h2 host 中間逗號 (,) 分隔</value>\n  </data>\n  <data name=\"TransportRequestHostTip4\" xml:space=\"preserve\">\n    <value>*QUIC 加密方式</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip1\" xml:space=\"preserve\">\n    <value>*TCP 偽裝類型</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip2\" xml:space=\"preserve\">\n    <value>*KCP 偽裝類型</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip3\" xml:space=\"preserve\">\n    <value>*QUIC 偽裝類型</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip4\" xml:space=\"preserve\">\n    <value>*GRPC 模式</value>\n  </data>\n  <data name=\"LvTLS\" xml:space=\"preserve\">\n    <value>TLS</value>\n  </data>\n  <data name=\"TransportPathTip5\" xml:space=\"preserve\">\n    <value>*KCP seed</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeyFailed\" xml:space=\"preserve\">\n    <value>註冊全域快速鍵 {0} 失敗，原因：{1}</value>\n  </data>\n  <data name=\"RegisterGlobalHotkeySuccessfully\" xml:space=\"preserve\">\n    <value>註冊全域快速鍵 {0} 成功</value>\n  </data>\n  <data name=\"AllGroupServers\" xml:space=\"preserve\">\n    <value>所有</value>\n  </data>\n  <data name=\"FillServerAddressCustom\" xml:space=\"preserve\">\n    <value>請選擇要匯入的設定檔</value>\n  </data>\n  <data name=\"Speedtesting\" xml:space=\"preserve\">\n    <value>測試中...</value>\n  </data>\n  <data name=\"LabLAN\" xml:space=\"preserve\">\n    <value>區域網路</value>\n  </data>\n  <data name=\"LabLocal\" xml:space=\"preserve\">\n    <value>本機</value>\n  </data>\n  <data name=\"MsgServerTitle\" xml:space=\"preserve\">\n    <value>過濾器，按 Enter 執行</value>\n  </data>\n  <data name=\"menuCheckUpdate\" xml:space=\"preserve\">\n    <value>檢查更新</value>\n  </data>\n  <data name=\"menuClose\" xml:space=\"preserve\">\n    <value>關閉</value>\n  </data>\n  <data name=\"menuExit\" xml:space=\"preserve\">\n    <value>退出</value>\n  </data>\n  <data name=\"menuGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>全域快速鍵設定</value>\n  </data>\n  <data name=\"menuHelp\" xml:space=\"preserve\">\n    <value>說明</value>\n  </data>\n  <data name=\"menuOptionSetting\" xml:space=\"preserve\">\n    <value>參數設定</value>\n  </data>\n  <data name=\"menuPromotion\" xml:space=\"preserve\">\n    <value>推廣</value>\n  </data>\n  <data name=\"menuReload\" xml:space=\"preserve\">\n    <value>重啟服務</value>\n  </data>\n  <data name=\"menuRoutingSetting\" xml:space=\"preserve\">\n    <value>路由設定</value>\n  </data>\n  <data name=\"menuServers\" xml:space=\"preserve\">\n    <value>設定檔</value>\n  </data>\n  <data name=\"menuSetting\" xml:space=\"preserve\">\n    <value>設定</value>\n  </data>\n  <data name=\"menuSubGroupUpdate\" xml:space=\"preserve\">\n    <value>更新目前訂閱 (不透過代理)</value>\n  </data>\n  <data name=\"menuSubGroupUpdateViaProxy\" xml:space=\"preserve\">\n    <value>更新目前訂閱 (透過代理)</value>\n  </data>\n  <data name=\"menuSubscription\" xml:space=\"preserve\">\n    <value>訂閱分組</value>\n  </data>\n  <data name=\"menuSubSetting\" xml:space=\"preserve\">\n    <value>訂閱分組設定</value>\n  </data>\n  <data name=\"menuSubUpdate\" xml:space=\"preserve\">\n    <value>更新全部訂閱 (不透過代理)</value>\n  </data>\n  <data name=\"menuSubUpdateViaProxy\" xml:space=\"preserve\">\n    <value>更新全部訂閱 (透過代理)</value>\n  </data>\n  <data name=\"menuSystemproxy\" xml:space=\"preserve\">\n    <value>系統代理</value>\n  </data>\n  <data name=\"menuSystemProxyClear\" xml:space=\"preserve\">\n    <value>清除系統代理</value>\n  </data>\n  <data name=\"menuSystemProxyNothing\" xml:space=\"preserve\">\n    <value>不改變系統代理</value>\n  </data>\n  <data name=\"menuSystemProxyPac\" xml:space=\"preserve\">\n    <value>PAC 模式</value>\n  </data>\n  <data name=\"menuSystemProxySet\" xml:space=\"preserve\">\n    <value>自動設定系統代理</value>\n  </data>\n  <data name=\"TbSettingsColor\" xml:space=\"preserve\">\n    <value>顏色</value>\n  </data>\n  <data name=\"TbSettingsLanguage\" xml:space=\"preserve\">\n    <value>語言 (需重啟)</value>\n  </data>\n  <data name=\"menuAddServerViaClipboard\" xml:space=\"preserve\">\n    <value>從剪貼簿匯入分享連結</value>\n  </data>\n  <data name=\"menuAddServerViaScan\" xml:space=\"preserve\">\n    <value>掃描螢幕上的二維碼</value>\n  </data>\n  <data name=\"menuCopyServer\" xml:space=\"preserve\">\n    <value>複製所選</value>\n  </data>\n  <data name=\"menuRemoveDuplicateServer\" xml:space=\"preserve\">\n    <value>移除重複</value>\n  </data>\n  <data name=\"menuRemoveServer\" xml:space=\"preserve\">\n    <value>移除所選 (多選)</value>\n  </data>\n  <data name=\"menuSetDefaultServer\" xml:space=\"preserve\">\n    <value>設為活動</value>\n  </data>\n  <data name=\"menuClearServerStatistics\" xml:space=\"preserve\">\n    <value>清除所有服務統計資料</value>\n  </data>\n  <data name=\"menuRealPingServer\" xml:space=\"preserve\">\n    <value>測試真連線延遲 (多選)</value>\n  </data>\n  <data name=\"menuSortServerResult\" xml:space=\"preserve\">\n    <value>按測試結果排序</value>\n  </data>\n  <data name=\"menuSpeedServer\" xml:space=\"preserve\">\n    <value>測試速度 (多選)</value>\n  </data>\n  <data name=\"menuTcpingServer\" xml:space=\"preserve\">\n    <value>測試延遲 Tcping (多選)</value>\n  </data>\n  <data name=\"menuExport2ClientConfig\" xml:space=\"preserve\">\n    <value>匯出所選完整設定</value>\n  </data>\n  <data name=\"menuExport2ShareUrl\" xml:space=\"preserve\">\n    <value>匯出分享連結至剪貼簿 (多選)</value>\n  </data>\n  <data name=\"menuAddCustomServer\" xml:space=\"preserve\">\n    <value>新增自訂節點</value>\n  </data>\n  <data name=\"menuAddShadowsocksServer\" xml:space=\"preserve\">\n    <value>新增 [Shadowsocks] 節點</value>\n  </data>\n  <data name=\"menuAddSocksServer\" xml:space=\"preserve\">\n    <value>新增 [SOCKS] 節點</value>\n  </data>\n  <data name=\"menuAddTrojanServer\" xml:space=\"preserve\">\n    <value>新增 [Trojan] 節點</value>\n  </data>\n  <data name=\"menuAddVlessServer\" xml:space=\"preserve\">\n    <value>新增 [VLESS] 節點</value>\n  </data>\n  <data name=\"menuAddVmessServer\" xml:space=\"preserve\">\n    <value>新增 [VMess] 節點</value>\n  </data>\n  <data name=\"menuSelectAll\" xml:space=\"preserve\">\n    <value>全選</value>\n  </data>\n  <data name=\"menuMsgViewClear\" xml:space=\"preserve\">\n    <value>清除所有</value>\n  </data>\n  <data name=\"menuMsgViewCopy\" xml:space=\"preserve\">\n    <value>複製</value>\n  </data>\n  <data name=\"menuMsgViewCopyAll\" xml:space=\"preserve\">\n    <value>複製所有</value>\n  </data>\n  <data name=\"menuMsgViewSelectAll\" xml:space=\"preserve\">\n    <value>全選</value>\n  </data>\n  <data name=\"menuSubAdd\" xml:space=\"preserve\">\n    <value>新增</value>\n  </data>\n  <data name=\"menuSubDelete\" xml:space=\"preserve\">\n    <value>刪除</value>\n  </data>\n  <data name=\"menuSubEdit\" xml:space=\"preserve\">\n    <value>編輯</value>\n  </data>\n  <data name=\"menuSubShare\" xml:space=\"preserve\">\n    <value>分享</value>\n  </data>\n  <data name=\"LvEnabled\" xml:space=\"preserve\">\n    <value>啟用更新</value>\n  </data>\n  <data name=\"LvSort\" xml:space=\"preserve\">\n    <value>排序</value>\n  </data>\n  <data name=\"LvUserAgent\" xml:space=\"preserve\">\n    <value>User Agent (可選)</value>\n  </data>\n  <data name=\"TbCancel\" xml:space=\"preserve\">\n    <value>取消</value>\n  </data>\n  <data name=\"TbConfirm\" xml:space=\"preserve\">\n    <value>確定</value>\n  </data>\n  <data name=\"GbTransport\" xml:space=\"preserve\">\n    <value>底層傳輸方式 (transport)</value>\n  </data>\n  <data name=\"TbAddress\" xml:space=\"preserve\">\n    <value>位址 (address)</value>\n  </data>\n  <data name=\"TbAllowInsecure\" xml:space=\"preserve\">\n    <value>跳過憑證驗證 (allowinsecure)</value>\n  </data>\n  <data name=\"TbAlpn\" xml:space=\"preserve\">\n    <value>ALPN</value>\n  </data>\n  <data name=\"TbAlterId\" xml:space=\"preserve\">\n    <value>額外 ID (alterid)</value>\n  </data>\n  <data name=\"TbFingerprint\" xml:space=\"preserve\">\n    <value>Fingerprint</value>\n  </data>\n  <data name=\"TbHeaderType\" xml:space=\"preserve\">\n    <value>偽裝類型 (type)</value>\n  </data>\n  <data name=\"TbId\" xml:space=\"preserve\">\n    <value>使用者 ID (id)</value>\n  </data>\n  <data name=\"TbNetwork\" xml:space=\"preserve\">\n    <value>傳輸協定 (network)</value>\n  </data>\n  <data name=\"TbPath\" xml:space=\"preserve\">\n    <value>路徑 (path)</value>\n  </data>\n  <data name=\"TbPort\" xml:space=\"preserve\">\n    <value>埠 (port)</value>\n  </data>\n  <data name=\"TbRemarks\" xml:space=\"preserve\">\n    <value>別名 (remarks)</value>\n  </data>\n  <data name=\"TbRequestHost\" xml:space=\"preserve\">\n    <value>偽裝域名 (host)</value>\n  </data>\n  <data name=\"TbSecurity\" xml:space=\"preserve\">\n    <value>加密方式 (security)</value>\n  </data>\n  <data name=\"TbSNI\" xml:space=\"preserve\">\n    <value>SNI</value>\n  </data>\n  <data name=\"TbStreamSecurity\" xml:space=\"preserve\">\n    <value>傳輸層安全性 (TLS)</value>\n  </data>\n  <data name=\"TipNetwork\" xml:space=\"preserve\">\n    <value>*預設 TCP，選錯會無法連線</value>\n  </data>\n  <data name=\"TbCoreType\" xml:space=\"preserve\">\n    <value>Core 類型</value>\n  </data>\n  <data name=\"TbFlow5\" xml:space=\"preserve\">\n    <value>流控 (flow)</value>\n  </data>\n  <data name=\"TbGUID\" xml:space=\"preserve\">\n    <value>生成</value>\n  </data>\n  <data name=\"TbId3\" xml:space=\"preserve\">\n    <value>密碼 (password)</value>\n  </data>\n  <data name=\"TbId4\" xml:space=\"preserve\">\n    <value>密碼 (可選)</value>\n  </data>\n  <data name=\"TbId5\" xml:space=\"preserve\">\n    <value>使用者 ID (id)</value>\n  </data>\n  <data name=\"TbSecurity3\" xml:space=\"preserve\">\n    <value>加密方式 (encryption)</value>\n  </data>\n  <data name=\"TbSecurity4\" xml:space=\"preserve\">\n    <value>使用者名稱 (可選)</value>\n  </data>\n  <data name=\"TbSecurity5\" xml:space=\"preserve\">\n    <value>加密方式 (encryption)</value>\n  </data>\n  <data name=\"TbPreSocksPort\" xml:space=\"preserve\">\n    <value>SOCKS 埠</value>\n  </data>\n  <data name=\"TipPreSocksPort\" xml:space=\"preserve\">\n    <value>*自訂設定的 Socks 埠值，可留空；當設定此值後，將使用 Xray/sing-box (Tun) 額外啟動一個前置 Socks 服務，提供分流和速度顯示等功能</value>\n  </data>\n  <data name=\"TbBrowse\" xml:space=\"preserve\">\n    <value>瀏覽</value>\n  </data>\n  <data name=\"TbEdit\" xml:space=\"preserve\">\n    <value>編輯</value>\n  </data>\n  <data name=\"TbSettingsAdvancedProtocol\" xml:space=\"preserve\">\n    <value>進階代理設定，協定選擇 (可選)</value>\n  </data>\n  <data name=\"TbSettingsAllowLAN\" xml:space=\"preserve\">\n    <value>允許來自區域網路的連線</value>\n  </data>\n  <data name=\"TbSettingsAutoHideStartup\" xml:space=\"preserve\">\n    <value>啟動後隱藏視窗</value>\n  </data>\n  <data name=\"TbSettingsAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>自動更新 Geo 檔案的間隔 (小時)</value>\n  </data>\n  <data name=\"TbSettingsCore\" xml:space=\"preserve\">\n    <value>Core: 基礎設定</value>\n  </data>\n  <data name=\"TbCustomDnsRay\" xml:space=\"preserve\">\n    <value>v2ray 自訂 DNS</value>\n  </data>\n  <data name=\"TbSettingsCoreKcp\" xml:space=\"preserve\">\n    <value>Core: KCP 設定</value>\n  </data>\n  <data name=\"TbSettingsCoreType\" xml:space=\"preserve\">\n    <value>Core 類型設定</value>\n  </data>\n  <data name=\"TbSettingsDefAllowInsecure\" xml:space=\"preserve\">\n    <value>預設跳過憑證驗證 (allowinsecure)</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Freedom\" xml:space=\"preserve\">\n    <value>Outbound Freedom domainStrategy</value>\n  </data>\n  <data name=\"TbSettingsEnableAutoAdjustMainLvColWidth\" xml:space=\"preserve\">\n    <value>在更新訂閱後自動調整列寬</value>\n  </data>\n  <data name=\"TbSettingsEnableCheckPreReleaseUpdate\" xml:space=\"preserve\">\n    <value>檢查 Pre-Release 更新 (請謹慎啟用)</value>\n  </data>\n  <data name=\"TbSettingsException\" xml:space=\"preserve\">\n    <value>例外</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip\" xml:space=\"preserve\">\n    <value>例外：對於下列字元開頭的位址，不使用代理。使用分號 (;) 分隔。</value>\n  </data>\n  <data name=\"TbSettingsDisplayRealTimeSpeed\" xml:space=\"preserve\">\n    <value>顯示即時速度（需重啟）</value>\n  </data>\n  <data name=\"TbSettingsKeepOlderDedupl\" xml:space=\"preserve\">\n    <value>去重時保留序號較小的項</value>\n  </data>\n  <data name=\"TbSettingsLogEnabled\" xml:space=\"preserve\">\n    <value>啟用日誌</value>\n  </data>\n  <data name=\"TbSettingsLogLevel\" xml:space=\"preserve\">\n    <value>日誌等級</value>\n  </data>\n  <data name=\"TbSettingsMuxEnabled\" xml:space=\"preserve\">\n    <value>開啟 Mux 多路復用</value>\n  </data>\n  <data name=\"TbSettingsN\" xml:space=\"preserve\">\n    <value>v2rayN 設定</value>\n  </data>\n  <data name=\"TbSettingsPass\" xml:space=\"preserve\">\n    <value>認證密碼</value>\n  </data>\n  <data name=\"TbSettingsRemoteDNS\" xml:space=\"preserve\">\n    <value>自訂 DNS (可多個，用逗號 (,) 分隔)</value>\n  </data>\n  <data name=\"TbSettingsSetUWP\" xml:space=\"preserve\">\n    <value>解除 Win10 UWP 應用回環代理限制</value>\n  </data>\n  <data name=\"TbSettingsSniffingEnabled\" xml:space=\"preserve\">\n    <value>開啟流量探測</value>\n  </data>\n  <data name=\"TbSettingsSocksPort\" xml:space=\"preserve\">\n    <value>本機混合偵聽埠</value>\n  </data>\n  <data name=\"TbSettingsStartBoot\" xml:space=\"preserve\">\n    <value>開機啟動 (可能會不成功)</value>\n  </data>\n  <data name=\"TbSettingsStatistics\" xml:space=\"preserve\">\n    <value>啟用流量統計（需重啟）</value>\n  </data>\n  <data name=\"TbSettingsSubConvert\" xml:space=\"preserve\">\n    <value>訂閱轉換網址 (可選)</value>\n  </data>\n  <data name=\"TbSettingsSystemproxy\" xml:space=\"preserve\">\n    <value>系統代理設定</value>\n  </data>\n  <data name=\"TbSettingsTrayMenuServersLimit\" xml:space=\"preserve\">\n    <value>工具列右鍵選單設定展示數量限制</value>\n  </data>\n  <data name=\"TbSettingsUdpEnabled\" xml:space=\"preserve\">\n    <value>開啟 UDP</value>\n  </data>\n  <data name=\"TbSettingsUser\" xml:space=\"preserve\">\n    <value>認證使用者名稱</value>\n  </data>\n  <data name=\"TbClearSystemProxy\" xml:space=\"preserve\">\n    <value>清除系統代理</value>\n  </data>\n  <data name=\"TbDisplayGUI\" xml:space=\"preserve\">\n    <value>顯示主介面</value>\n  </data>\n  <data name=\"TbGlobalHotkeySetting\" xml:space=\"preserve\">\n    <value>全域快速鍵設定</value>\n  </data>\n  <data name=\"TbGlobalHotkeySettingTip\" xml:space=\"preserve\">\n    <value>直接按鍵盤進行設定，重啟後生效</value>\n  </data>\n  <data name=\"TbNotChangeSystemProxy\" xml:space=\"preserve\">\n    <value>不改變系統代理</value>\n  </data>\n  <data name=\"TbReset\" xml:space=\"preserve\">\n    <value>重設</value>\n  </data>\n  <data name=\"TbSetSystemProxy\" xml:space=\"preserve\">\n    <value>自動設定系統代理</value>\n  </data>\n  <data name=\"TbSystemProxyPac\" xml:space=\"preserve\">\n    <value>PAC 模式</value>\n  </data>\n  <data name=\"menuShareServer\" xml:space=\"preserve\">\n    <value>分享</value>\n  </data>\n  <data name=\"menuRouting\" xml:space=\"preserve\">\n    <value>路由</value>\n  </data>\n  <data name=\"NotRunAsAdmin\" xml:space=\"preserve\">\n    <value>以非管理員身份執行</value>\n  </data>\n  <data name=\"RunAsAdmin\" xml:space=\"preserve\">\n    <value>以管理員身份執行</value>\n  </data>\n  <data name=\"menuMoveBottom\" xml:space=\"preserve\">\n    <value>下移至底部</value>\n  </data>\n  <data name=\"menuMoveDown\" xml:space=\"preserve\">\n    <value>下移</value>\n  </data>\n  <data name=\"menuMoveTop\" xml:space=\"preserve\">\n    <value>上移至頂部</value>\n  </data>\n  <data name=\"menuMoveUp\" xml:space=\"preserve\">\n    <value>上移</value>\n  </data>\n  <data name=\"MsgFilterTitle\" xml:space=\"preserve\">\n    <value>過濾 (允許正則)</value>\n  </data>\n  <data name=\"menuWebsiteItem\" xml:space=\"preserve\">\n    <value>{0} 官網</value>\n  </data>\n  <data name=\"menuRoutingAdvancedAdd\" xml:space=\"preserve\">\n    <value>新增規則集</value>\n  </data>\n  <data name=\"menuRoutingAdvancedImportRules\" xml:space=\"preserve\">\n    <value>一鍵匯入規則集</value>\n  </data>\n  <data name=\"menuRoutingAdvancedRemove\" xml:space=\"preserve\">\n    <value>移除所選規則</value>\n  </data>\n  <data name=\"menuRoutingAdvancedSetDefault\" xml:space=\"preserve\">\n    <value>設為活動規則</value>\n  </data>\n  <data name=\"TbdomainStrategy\" xml:space=\"preserve\">\n    <value>域名解析策略</value>\n  </data>\n  <data name=\"TbRoutingTabRuleList\" xml:space=\"preserve\">\n    <value>預定義規則集列表</value>\n  </data>\n  <data name=\"TbRoutingTips\" xml:space=\"preserve\">\n    <value>*設定的路由規則，用逗號 (,) 分隔；正則中的逗號用 &lt;COMMA&gt; 替代</value>\n  </data>\n  <data name=\"menuImportRulesFromClipboard\" xml:space=\"preserve\">\n    <value>從剪貼簿中匯入規則</value>\n  </data>\n  <data name=\"menuImportRulesFromFile\" xml:space=\"preserve\">\n    <value>從檔案中匯入規則</value>\n  </data>\n  <data name=\"menuImportRulesFromUrl\" xml:space=\"preserve\">\n    <value>從訂閱 URL 中匯入規則</value>\n  </data>\n  <data name=\"menuRoutingRuleSetting\" xml:space=\"preserve\">\n    <value>規則集設定</value>\n  </data>\n  <data name=\"menuRuleAdd\" xml:space=\"preserve\">\n    <value>新增規則</value>\n  </data>\n  <data name=\"menuRuleExportSelected\" xml:space=\"preserve\">\n    <value>匯出所選規則至剪貼簿</value>\n  </data>\n  <data name=\"menuRuleList\" xml:space=\"preserve\">\n    <value>規則列表</value>\n  </data>\n  <data name=\"menuRuleRemove\" xml:space=\"preserve\">\n    <value>移除所選規則</value>\n  </data>\n  <data name=\"menuRoutingRuleDetailsSetting\" xml:space=\"preserve\">\n    <value>路由規則詳情設定</value>\n  </data>\n  <data name=\"TbAutoSort\" xml:space=\"preserve\">\n    <value>儲存時 Domain, IP, 行程名 自動排序</value>\n  </data>\n  <data name=\"TbRuleobjectDoc\" xml:space=\"preserve\">\n    <value>規則詳細說明檔案</value>\n  </data>\n  <data name=\"TbDnsObjectDoc\" xml:space=\"preserve\">\n    <value>支援填寫 DnsObject，JSON 格式，點擊查看說明</value>\n  </data>\n  <data name=\"SubUrlTips\" xml:space=\"preserve\">\n    <value>普通分組此處請留空</value>\n  </data>\n  <data name=\"TipChangeRouting\" xml:space=\"preserve\">\n    <value>路由設定已改變</value>\n  </data>\n  <data name=\"TipChangeSystemProxy\" xml:space=\"preserve\">\n    <value>系統代理設定已改變</value>\n  </data>\n  <data name=\"TbSettingsRouteOnly\" xml:space=\"preserve\">\n    <value>僅限路由 (routeOnly)</value>\n  </data>\n  <data name=\"TbSettingsNotProxyLocalAddress\" xml:space=\"preserve\">\n    <value>請勿將代理伺服器用於本機（Intranet）位址</value>\n  </data>\n  <data name=\"menuMixedTestServer\" xml:space=\"preserve\">\n    <value>一鍵延遲與速度測試 (Ctrl+E)</value>\n  </data>\n  <data name=\"LvTestDelay\" xml:space=\"preserve\">\n    <value>延遲 (ms)</value>\n  </data>\n  <data name=\"LvTestSpeed\" xml:space=\"preserve\">\n    <value>速度 (MB/s)</value>\n  </data>\n  <data name=\"FailedToRunCore\" xml:space=\"preserve\">\n    <value>執行 Core 失敗，請查看提示訊息</value>\n  </data>\n  <data name=\"LvFilter\" xml:space=\"preserve\">\n    <value>別名正則過濾</value>\n  </data>\n  <data name=\"TbDisplayLog\" xml:space=\"preserve\">\n    <value>顯示日誌</value>\n  </data>\n  <data name=\"TbEnableTunAs\" xml:space=\"preserve\">\n    <value>啟用 Tun</value>\n  </data>\n  <data name=\"TbSettingsNewPort4LAN\" xml:space=\"preserve\">\n    <value>為區域網路開啟新的埠</value>\n  </data>\n  <data name=\"TbSettingsTunMode\" xml:space=\"preserve\">\n    <value>Tun 模式設定</value>\n  </data>\n  <data name=\"menuMoveToGroup\" xml:space=\"preserve\">\n    <value>移至訂閱分組</value>\n  </data>\n  <data name=\"TbSettingsEnableDragDropSort\" xml:space=\"preserve\">\n    <value>啟用拖放排序 (需重啟)</value>\n  </data>\n  <data name=\"TbAutoRefresh\" xml:space=\"preserve\">\n    <value>自動重新整理</value>\n  </data>\n  <data name=\"SpeedtestingSkip\" xml:space=\"preserve\">\n    <value>跳過測試</value>\n  </data>\n  <data name=\"menuEditServer\" xml:space=\"preserve\">\n    <value>編輯</value>\n  </data>\n  <data name=\"TbSettingsDoubleClick2Activate\" xml:space=\"preserve\">\n    <value>主介面輕按兩下設為活動</value>\n  </data>\n  <data name=\"SpeedtestingCompleted\" xml:space=\"preserve\">\n    <value>測試完成</value>\n  </data>\n  <data name=\"TbSettingsDefFingerprint\" xml:space=\"preserve\">\n    <value>預設 TLS 指紋 (fingerprint)</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgent\" xml:space=\"preserve\">\n    <value>使用者代理 (User-Agent)</value>\n  </data>\n  <data name=\"TbSettingsDefUserAgentTips\" xml:space=\"preserve\">\n    <value>僅對 TCP/HTTP、WS 協定生效</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamily\" xml:space=\"preserve\">\n    <value>目前字型 (需重啟)</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyTip\" xml:space=\"preserve\">\n    <value>複製字型 TTF/TTC 檔案到目錄 guiFonts，重新啟動後生效</value>\n  </data>\n  <data name=\"TbSettingsSocksPortTip\" xml:space=\"preserve\">\n    <value>Pac 連接埠 = +3；Xray API 連接埠 = +4；mihomo API 連接埠 = +5；</value>\n  </data>\n  <data name=\"TbSettingsStartBootTip\" xml:space=\"preserve\">\n    <value>以管理員權限設定此項，在啟動後獲得管理員權限</value>\n  </data>\n  <data name=\"TbSettingsFontSize\" xml:space=\"preserve\">\n    <value>字型大小</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestTimeout\" xml:space=\"preserve\">\n    <value>測速單個超時值</value>\n  </data>\n  <data name=\"TbSettingsSpeedTestUrl\" xml:space=\"preserve\">\n    <value>測速檔案位址</value>\n  </data>\n  <data name=\"menuMoveTo\" xml:space=\"preserve\">\n    <value>移至上下</value>\n  </data>\n  <data name=\"TbPublicKey\" xml:space=\"preserve\">\n    <value>PublicKey</value>\n  </data>\n  <data name=\"TbShortId\" xml:space=\"preserve\">\n    <value>ShortId</value>\n  </data>\n  <data name=\"TbSpiderX\" xml:space=\"preserve\">\n    <value>SpiderX</value>\n  </data>\n  <data name=\"TbSettingsEnableHWA\" xml:space=\"preserve\">\n    <value>啟用硬體加速 (需重啟)</value>\n  </data>\n  <data name=\"SpeedtestingWait\" xml:space=\"preserve\">\n    <value>等待測試中...</value>\n  </data>\n  <data name=\"SpeedtestingPressEscToExit\" xml:space=\"preserve\">\n    <value>按 ECS 以終止測試</value>\n  </data>\n  <data name=\"TipDisplayLog\" xml:space=\"preserve\">\n    <value>當有異常斷流時請關閉</value>\n  </data>\n  <data name=\"MsgSkipSubscriptionUpdate\" xml:space=\"preserve\">\n    <value>未啟動更新，跳過此訂閱</value>\n  </data>\n  <data name=\"menuRebootAsAdmin\" xml:space=\"preserve\">\n    <value>以管理員身份重啟</value>\n  </data>\n  <data name=\"LvMoreUrl\" xml:space=\"preserve\">\n    <value>更多位址 (url)，用逗號 (,) 分隔；訂閱轉換將失效</value>\n  </data>\n  <data name=\"LvAutoUpdateInterval\" xml:space=\"preserve\">\n    <value>自動更新間隔 (分鐘)</value>\n  </data>\n  <data name=\"TbSettingsLogEnabledToFile\" xml:space=\"preserve\">\n    <value>啟動日誌存到檔案</value>\n  </data>\n  <data name=\"LvConvertTarget\" xml:space=\"preserve\">\n    <value>訂閱轉換目標類型</value>\n  </data>\n  <data name=\"LvConvertTargetTip\" xml:space=\"preserve\">\n    <value>不需要轉換時請留空</value>\n  </data>\n  <data name=\"menuDNSSetting\" xml:space=\"preserve\">\n    <value>DNS設定</value>\n  </data>\n  <data name=\"TbCustomDnsSingbox\" xml:space=\"preserve\">\n    <value>sing-box 自訂 DNS</value>\n  </data>\n  <data name=\"TbDnsSingboxObjectDoc\" xml:space=\"preserve\">\n    <value>請填寫 DNS JSON 結構，點擊查看檔案</value>\n  </data>\n  <data name=\"TbSettingDnsImportDefConfig\" xml:space=\"preserve\">\n    <value>點擊匯入預設 DNS 設定</value>\n  </data>\n  <data name=\"TbdomainStrategy4Singbox\" xml:space=\"preserve\">\n    <value>sing-box 域名解析策略</value>\n  </data>\n  <data name=\"TbSettingsMux4SboxProtocol\" xml:space=\"preserve\">\n    <value>sing-box Mux 多路復用協定</value>\n  </data>\n  <data name=\"TbRoutingRuleProcess\" xml:space=\"preserve\">\n    <value>行程 (Linux/Windows)</value>\n  </data>\n  <data name=\"TbRoutingRuleIP\" xml:space=\"preserve\">\n    <value>IP 或 IP CIDR</value>\n  </data>\n  <data name=\"TbRoutingRuleDomain\" xml:space=\"preserve\">\n    <value>Domain</value>\n  </data>\n  <data name=\"menuAddHysteria2Server\" xml:space=\"preserve\">\n    <value>新增 [Hysteria2] 節點</value>\n  </data>\n  <data name=\"TbSettingsHysteriaBandwidth\" xml:space=\"preserve\">\n    <value>Hysteria 最大頻寬 (Up/Dw)</value>\n  </data>\n  <data name=\"TbSettingsUseSystemHosts\" xml:space=\"preserve\">\n    <value>使用系統 hosts</value>\n  </data>\n  <data name=\"menuAddTuicServer\" xml:space=\"preserve\">\n    <value>新增 [TUIC] 節點</value>\n  </data>\n  <data name=\"TbHeaderType8\" xml:space=\"preserve\">\n    <value>擁塞控制算法</value>\n  </data>\n  <data name=\"LvPrevProfile\" xml:space=\"preserve\">\n    <value>前置代理節點別名</value>\n  </data>\n  <data name=\"LvNextProfile\" xml:space=\"preserve\">\n    <value>落地代理節點別名</value>\n  </data>\n  <data name=\"LvPrevProfileTip\" xml:space=\"preserve\">\n    <value>請確保節點別名存在並且唯一</value>\n  </data>\n  <data name=\"TbSettingsTunAutoRoute\" xml:space=\"preserve\">\n    <value>自動路由</value>\n  </data>\n  <data name=\"TbSettingsTunStrictRoute\" xml:space=\"preserve\">\n    <value>嚴格路由</value>\n  </data>\n  <data name=\"TbSettingsTunStack\" xml:space=\"preserve\">\n    <value>協定堆疊</value>\n  </data>\n  <data name=\"TbSettingsTunMtu\" xml:space=\"preserve\">\n    <value>MTU</value>\n  </data>\n  <data name=\"TbSettingsEnableIPv6Address\" xml:space=\"preserve\">\n    <value>啟用 IPv6</value>\n  </data>\n  <data name=\"menuAddWireguardServer\" xml:space=\"preserve\">\n    <value>新增 [WireGuard] 節點</value>\n  </data>\n  <data name=\"TbPrivateKey\" xml:space=\"preserve\">\n    <value>PrivateKey</value>\n  </data>\n  <data name=\"TbReserved\" xml:space=\"preserve\">\n    <value>Reserved (2,3,4)</value>\n  </data>\n  <data name=\"TbLocalAddress\" xml:space=\"preserve\">\n    <value>Address (Ipv4,Ipv6)</value>\n  </data>\n  <data name=\"TbPath7\" xml:space=\"preserve\">\n    <value>混淆密碼 (obfs password)</value>\n  </data>\n  <data name=\"TbRuleMatchingTips\" xml:space=\"preserve\">\n    <value>(Domain 或 IP 或 行程名) 與 Port 與 Protocol 與 InboundTag =&gt; OutboundTag</value>\n  </data>\n  <data name=\"TbAutoScrollToEnd\" xml:space=\"preserve\">\n    <value>自動滾動到末尾</value>\n  </data>\n  <data name=\"TbSettingsSpeedPingTestUrl\" xml:space=\"preserve\">\n    <value>真連線測試位址</value>\n  </data>\n  <data name=\"SpeedtestingStop\" xml:space=\"preserve\">\n    <value>測試終止中...</value>\n  </data>\n  <data name=\"TransportRequestHostTip5\" xml:space=\"preserve\">\n    <value>*grpc Authority</value>\n  </data>\n  <data name=\"menuAddHttpServer\" xml:space=\"preserve\">\n    <value>新增 [HTTP] 節點</value>\n  </data>\n  <data name=\"TbSettingsEnableFragment\" xml:space=\"preserve\">\n    <value>啟用分片（Fragment）</value>\n  </data>\n  <data name=\"TbSettingsEnableCacheFile4Sbox\" xml:space=\"preserve\">\n    <value>啟用 sing-box（規則集檔案）的快取檔案</value>\n  </data>\n  <data name=\"LvCustomRulesetPath4Singbox\" xml:space=\"preserve\">\n    <value>自訂 sing-box rule-set</value>\n  </data>\n  <data name=\"NeedRebootTips\" xml:space=\"preserve\">\n    <value>操作成功。請點選設定選單重啟應用程式。</value>\n  </data>\n  <data name=\"menuOpenTheFileLocation\" xml:space=\"preserve\">\n    <value>打開儲存所在的位置</value>\n  </data>\n  <data name=\"TbSorting\" xml:space=\"preserve\">\n    <value>排序</value>\n  </data>\n  <data name=\"TbSortingChain\" xml:space=\"preserve\">\n    <value>路由鏈</value>\n  </data>\n  <data name=\"TbSortingDefault\" xml:space=\"preserve\">\n    <value>預設</value>\n  </data>\n  <data name=\"TbSortingDelay\" xml:space=\"preserve\">\n    <value>延遲</value>\n  </data>\n  <data name=\"TbSortingDownSpeed\" xml:space=\"preserve\">\n    <value>下載速度</value>\n  </data>\n  <data name=\"TbSortingDownTraffic\" xml:space=\"preserve\">\n    <value>下載流量</value>\n  </data>\n  <data name=\"TbSortingHost\" xml:space=\"preserve\">\n    <value>主機</value>\n  </data>\n  <data name=\"TbSortingName\" xml:space=\"preserve\">\n    <value>名稱</value>\n  </data>\n  <data name=\"TbSortingNetwork\" xml:space=\"preserve\">\n    <value>網路</value>\n  </data>\n  <data name=\"TbSortingTime\" xml:space=\"preserve\">\n    <value>時間</value>\n  </data>\n  <data name=\"TbSortingType\" xml:space=\"preserve\">\n    <value>類型</value>\n  </data>\n  <data name=\"TbSortingUpSpeed\" xml:space=\"preserve\">\n    <value>上傳速度</value>\n  </data>\n  <data name=\"TbSortingUpTraffic\" xml:space=\"preserve\">\n    <value>上傳流量</value>\n  </data>\n  <data name=\"TbConnections\" xml:space=\"preserve\">\n    <value>目前連線</value>\n  </data>\n  <data name=\"menuConnectionClose\" xml:space=\"preserve\">\n    <value>關閉連線</value>\n  </data>\n  <data name=\"menuConnectionCloseAll\" xml:space=\"preserve\">\n    <value>關閉所有連線</value>\n  </data>\n  <data name=\"TbProxies\" xml:space=\"preserve\">\n    <value>目前代理</value>\n  </data>\n  <data name=\"menuRulemode\" xml:space=\"preserve\">\n    <value>規則模式</value>\n  </data>\n  <data name=\"menuModeDirect\" xml:space=\"preserve\">\n    <value>直連</value>\n  </data>\n  <data name=\"menuModeGlobal\" xml:space=\"preserve\">\n    <value>全局</value>\n  </data>\n  <data name=\"menuModeNothing\" xml:space=\"preserve\">\n    <value>隨原配置</value>\n  </data>\n  <data name=\"menuModeRule\" xml:space=\"preserve\">\n    <value>規則</value>\n  </data>\n  <data name=\"menuProxiesDelaytest\" xml:space=\"preserve\">\n    <value>延遲測試</value>\n  </data>\n  <data name=\"menuProxiesDelaytestPart\" xml:space=\"preserve\">\n    <value>目前部分節點延遲測試</value>\n  </data>\n  <data name=\"menuProxiesReload\" xml:space=\"preserve\">\n    <value>重新整理</value>\n  </data>\n  <data name=\"menuProxiesSelectActivity\" xml:space=\"preserve\">\n    <value>設為活動節點</value>\n  </data>\n  <data name=\"TbSettingsDomainStrategy4Out\" xml:space=\"preserve\">\n    <value>Outbound 預設解析策略</value>\n  </data>\n  <data name=\"TbSettingsMainGirdOrientation\" xml:space=\"preserve\">\n    <value>主界面佈局方向 (需重啟)</value>\n  </data>\n  <data name=\"TbSettingsDomainDNSAddress\" xml:space=\"preserve\">\n    <value>Outbound 域名解析位址</value>\n  </data>\n  <data name=\"menuProfileAutofitColumnWidth\" xml:space=\"preserve\">\n    <value>自動調整列寬</value>\n  </data>\n  <data name=\"menuExport2ShareUrlBase64\" xml:space=\"preserve\">\n    <value>匯出分享連結至剪貼簿 (多選) Base64 編碼</value>\n  </data>\n  <data name=\"menuExport2ClientConfigClipboard\" xml:space=\"preserve\">\n    <value>匯出所選完整設定至剪貼簿</value>\n  </data>\n  <data name=\"menuShowOrHideMainWindow\" xml:space=\"preserve\">\n    <value>顯示或隱藏主介面</value>\n  </data>\n  <data name=\"TbPreSocksPort4Sub\" xml:space=\"preserve\">\n    <value>自訂 Socks 連接埠</value>\n  </data>\n  <data name=\"menuBackupAndRestore\" xml:space=\"preserve\">\n    <value>備份和還原</value>\n  </data>\n  <data name=\"menuLocalBackup\" xml:space=\"preserve\">\n    <value>備份到本地</value>\n  </data>\n  <data name=\"menuLocalRestore\" xml:space=\"preserve\">\n    <value>從本地恢復</value>\n  </data>\n  <data name=\"menuRemoteBackup\" xml:space=\"preserve\">\n    <value>備份到遠端 (WebDAV)</value>\n  </data>\n  <data name=\"menuRemoteRestore\" xml:space=\"preserve\">\n    <value>從遠端恢復 (WebDAV)</value>\n  </data>\n  <data name=\"menuLocalBackupAndRestore\" xml:space=\"preserve\">\n    <value>本地</value>\n  </data>\n  <data name=\"menuRemoteBackupAndRestore\" xml:space=\"preserve\">\n    <value>遠端 (WebDAV)</value>\n  </data>\n  <data name=\"LvWebDavUrl\" xml:space=\"preserve\">\n    <value>WebDav 伺服器位址</value>\n  </data>\n  <data name=\"LvWebDavUserName\" xml:space=\"preserve\">\n    <value>WebDav 帳戶</value>\n  </data>\n  <data name=\"LvWebDavPassword\" xml:space=\"preserve\">\n    <value>WebDav 密碼</value>\n  </data>\n  <data name=\"LvWebDavCheck\" xml:space=\"preserve\">\n    <value>WebDav 可用檢查</value>\n  </data>\n  <data name=\"LvWebDavDirName\" xml:space=\"preserve\">\n    <value>遠端資料夾名稱 (可選)</value>\n  </data>\n  <data name=\"LocalRestoreInvalidZipTips\" xml:space=\"preserve\">\n    <value>無效備份檔案</value>\n  </data>\n  <data name=\"ConnectionsHostFilterTitle\" xml:space=\"preserve\">\n    <value>主機過濾</value>\n  </data>\n  <data name=\"TipActiveServer\" xml:space=\"preserve\">\n    <value>活動</value>\n  </data>\n  <data name=\"TbSettingsGeoFilesSource\" xml:space=\"preserve\">\n    <value>Geo 檔案來源 (可選)</value>\n  </data>\n  <data name=\"TbSettingsSrsFilesSource\" xml:space=\"preserve\">\n    <value>sing-box ruleset 檔案來源 (可選)</value>\n  </data>\n  <data name=\"UpgradeAppNotExistTip\" xml:space=\"preserve\">\n    <value>升級工具 App 不存在</value>\n  </data>\n  <data name=\"TbSettingsRoutingRulesSource\" xml:space=\"preserve\">\n    <value>路由規則集來源 (可選)</value>\n  </data>\n  <data name=\"menuRegionalPresets\" xml:space=\"preserve\">\n    <value>區域預置設定</value>\n  </data>\n  <data name=\"menuRegionalPresetsDefault\" xml:space=\"preserve\">\n    <value>預設區域</value>\n  </data>\n  <data name=\"menuRegionalPresetsRussia\" xml:space=\"preserve\">\n    <value>俄羅斯</value>\n  </data>\n  <data name=\"menuRegionalPresetsIran\" xml:space=\"preserve\">\n    <value>伊朗</value>\n  </data>\n  <data name=\"TbSettingsChinaUserTip\" xml:space=\"preserve\">\n    <value>中國區域用戶可忽略此項</value>\n  </data>\n  <data name=\"menuAddServerViaImage\" xml:space=\"preserve\">\n    <value>掃描圖片中的二維碼</value>\n  </data>\n  <data name=\"InvalidUrlTip\" xml:space=\"preserve\">\n    <value>位址 (Url) 無效</value>\n  </data>\n  <data name=\"InsecureUrlProtocol\" xml:space=\"preserve\">\n    <value>請不要使用不安全的 HTTP 協定訂閱位址</value>\n  </data>\n  <data name=\"TbSettingsCurrentFontFamilyLinuxTip\" xml:space=\"preserve\">\n    <value>安裝字體到系統中，選擇或填入字體名稱，重新啟動後生效</value>\n  </data>\n  <data name=\"menuExitTips\" xml:space=\"preserve\">\n    <value>確定要退出嗎？</value>\n  </data>\n  <data name=\"LvMemo\" xml:space=\"preserve\">\n    <value>備註備忘</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPassword\" xml:space=\"preserve\">\n    <value>系統的 sudo 密碼</value>\n  </data>\n  <data name=\"TbSettingsLinuxSudoPasswordTip\" xml:space=\"preserve\">\n    <value>密碼將調用命令行校驗，如果因為校驗錯誤導致無法正常運行時，請重啟本應用。密碼不會存儲，每次重啟後都需要再次輸入。</value>\n  </data>\n  <data name=\"TransportHeaderTypeTip5\" xml:space=\"preserve\">\n    <value>*xhttp 模式</value>\n  </data>\n  <data name=\"TransportExtraTip\" xml:space=\"preserve\">\n    <value>XHTTP Extra 原始 JSON，格式： { XHTTPObject }</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenClose\" xml:space=\"preserve\">\n    <value>關閉視窗時隱藏至托盤</value>\n  </data>\n  <data name=\"TbSettingsMixedConcurrencyCount\" xml:space=\"preserve\">\n    <value>多執行緒測試時的並發數量</value>\n  </data>\n  <data name=\"TbSettingsExceptionTip2\" xml:space=\"preserve\">\n    <value>例外：對於下列位址不使用代理，使用逗號 (,) 分隔。</value>\n  </data>\n  <data name=\"TbSettingsDestOverride\" xml:space=\"preserve\">\n    <value>流量探測類型</value>\n  </data>\n  <data name=\"TbSettingsSecondLocalPortEnabled\" xml:space=\"preserve\">\n    <value>開啟第二個本機監聽埠</value>\n  </data>\n  <data name=\"TbRoutingInboundTagTips\" xml:space=\"preserve\">\n    <value>socks：本地埠，socks2：第二個本地埠，socks3：區域網路埠</value>\n  </data>\n  <data name=\"TbSettingsTheme\" xml:space=\"preserve\">\n    <value>主題</value>\n  </data>\n  <data name=\"menuCopyProxyCmdToClipboard\" xml:space=\"preserve\">\n    <value>複製終端代理指令至剪貼簿</value>\n  </data>\n  <data name=\"SpeedtestingTestFailedPart\" xml:space=\"preserve\">\n    <value>開始對失敗部分進行重新測試，剩餘 {0} 個。可按 ESC 終止...</value>\n  </data>\n  <data name=\"menuTestServerResult\" xml:space=\"preserve\">\n    <value>按測試結果</value>\n  </data>\n  <data name=\"menuRemoveInvalidServerResult\" xml:space=\"preserve\">\n    <value>按測試結果移除無效</value>\n  </data>\n  <data name=\"RemoveInvalidServerResultTip\" xml:space=\"preserve\">\n    <value>移除無效測試結果 {0} 個。</value>\n  </data>\n  <data name=\"TbPorts7\" xml:space=\"preserve\">\n    <value>跳躍埠範圍</value>\n  </data>\n  <data name=\"TbPorts7Tips\" xml:space=\"preserve\">\n    <value>會覆蓋埠，多組時用逗號 (,) 隔開</value>\n  </data>\n  <data name=\"menuExportConfig\" xml:space=\"preserve\">\n    <value>匯出</value>\n  </data>\n  <data name=\"TbSettingsIPAPIUrl\" xml:space=\"preserve\">\n    <value>目前連接資訊測試地址</value>\n  </data>\n  <data name=\"TbRuleOutboundTagTip\" xml:space=\"preserve\">\n    <value>可以填寫節點別名，請確保存在並唯一</value>\n  </data>\n  <data name=\"SudoIncorrectPasswordTip\" xml:space=\"preserve\">\n    <value>密碼錯誤，請重試。</value>\n  </data>\n  <data name=\"TbMldsa65Verify\" xml:space=\"preserve\">\n    <value>Mldsa65Verify</value>\n  </data>\n  <data name=\"menuAddAnytlsServer\" xml:space=\"preserve\">\n    <value>新增 [Anytls] 節點</value>\n  </data>\n  <data name=\"TbRemoteDNS\" xml:space=\"preserve\">\n    <value>遠程 DNS</value>\n  </data>\n  <data name=\"TbDomesticDNS\" xml:space=\"preserve\">\n    <value>直連 DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategy\" xml:space=\"preserve\">\n    <value>直連目標解析策略</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategy\" xml:space=\"preserve\">\n    <value>代理目標解析策略</value>\n  </data>\n  <data name=\"TbAddCommonDNSHosts\" xml:space=\"preserve\">\n    <value>新增常用 DNS Hosts</value>\n  </data>\n  <data name=\"TbFakeIP\" xml:space=\"preserve\">\n    <value>FakeIP</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueries\" xml:space=\"preserve\">\n    <value>阻止 SVCB 和 HTTPS 查詢</value>\n  </data>\n  <data name=\"TbDNSHostsConfig\" xml:space=\"preserve\">\n    <value>DNS Hosts：（“網域名稱1 ip1 ip2” 一行一個）</value>\n  </data>\n  <data name=\"ThBasicDNSSettings\" xml:space=\"preserve\">\n    <value>DNS 基礎設定</value>\n  </data>\n  <data name=\"ThAdvancedDNSSettings\" xml:space=\"preserve\">\n    <value>DNS 進階設定</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPs\" xml:space=\"preserve\">\n    <value>校驗相應地區域名 IP</value>\n  </data>\n  <data name=\"TbValidateDirectExpectedIPsDesc\" xml:space=\"preserve\">\n    <value>配置後，會對相應地區域名（如 geosite:cn - geoip:cn）的返回 IP 進行校驗，僅返回期望 IP</value>\n  </data>\n  <data name=\"TbCustomDNSEnable\" xml:space=\"preserve\">\n    <value>啟用自訂 DNS</value>\n  </data>\n  <data name=\"TbCustomDNSEnabledPageInvalid\" xml:space=\"preserve\">\n    <value>自訂 DNS 已啟用，此頁面配置將無效</value>\n  </data>\n  <data name=\"TbBlockSVCBHTTPSQueriesTips\" xml:space=\"preserve\">\n    <value>開啟後將阻止 ECH 和 HTTP/3 可用性查詢</value>\n  </data>\n  <data name=\"FillCorrectConfigTemplateText\" xml:space=\"preserve\">\n    <value>請填寫正確的配置範本</value>\n  </data>\n  <data name=\"menuFullConfigTemplate\" xml:space=\"preserve\">\n    <value>完整配置範本設定</value>\n  </data>\n  <data name=\"TbFullConfigTemplateEnable\" xml:space=\"preserve\">\n    <value>啟用完整配置範本</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplate\" xml:space=\"preserve\">\n    <value>v2ray 完整配置範本</value>\n  </data>\n  <data name=\"TbRayFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>僅添加出站配置，routing.balancers 和 routing.rules.outboundTag，點擊查看文檔</value>\n  </data>\n  <data name=\"TbAddProxyProtocolOutboundOnly\" xml:space=\"preserve\">\n    <value>不添加非代理協定出站</value>\n  </data>\n  <data name=\"TbSetUpstreamProxyDetour\" xml:space=\"preserve\">\n    <value>設定上游代理 tag</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplate\" xml:space=\"preserve\">\n    <value>sing-box 完整配置範本</value>\n  </data>\n  <data name=\"TbSBFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>僅添加出站和端點配置，點擊查看文檔</value>\n  </data>\n  <data name=\"TbFullConfigTemplateDesc\" xml:space=\"preserve\">\n    <value>此功能供高級用戶和有特殊需求的用戶使用。 啟用此功能後，將忽略 Core 的基礎設定，DNS 設定 ，路由設定。你需要保證系統代理的埠和流量統計等功能的配置正確，一切都由你來設定。</value>\n  </data>\n  <data name=\"MsgStartParsingSubscription\" xml:space=\"preserve\">\n    <value>開始解析和處理訂閱內容</value>\n  </data>\n  <data name=\"TbSelectProfile\" xml:space=\"preserve\">\n    <value>選擇節點</value>\n  </data>\n  <data name=\"TbFakeIPTips\" xml:space=\"preserve\">\n    <value>默認全域生效，內置 FakeIP 過濾，僅在 sing-box 中生效</value>\n  </data>\n  <data name=\"PleaseAddAtLeastOneServer\" xml:space=\"preserve\">\n    <value>請至少添加一個節點</value>\n  </data>\n  <data name=\"TbConfigTypePolicyGroup\" xml:space=\"preserve\">\n    <value>策略組</value>\n  </data>\n  <data name=\"TbConfigTypeProxyChain\" xml:space=\"preserve\">\n    <value>鏈式代理</value>\n  </data>\n  <data name=\"TbLeastPing\" xml:space=\"preserve\">\n    <value>最低延遲</value>\n  </data>\n  <data name=\"TbRandom\" xml:space=\"preserve\">\n    <value>隨機</value>\n  </data>\n  <data name=\"TbRoundRobin\" xml:space=\"preserve\">\n    <value>負載均衡</value>\n  </data>\n  <data name=\"TbLeastLoad\" xml:space=\"preserve\">\n    <value>最穩定</value>\n  </data>\n  <data name=\"TbPolicyGroupType\" xml:space=\"preserve\">\n    <value>策略組類型</value>\n  </data>\n  <data name=\"menuAddPolicyGroupServer\" xml:space=\"preserve\">\n    <value>新增策略組</value>\n  </data>\n  <data name=\"menuAddProxyChainServer\" xml:space=\"preserve\">\n    <value>新增鏈式代理</value>\n  </data>\n  <data name=\"menuAddChildServer\" xml:space=\"preserve\">\n    <value>新增子配置</value>\n  </data>\n  <data name=\"menuRemoveChildServer\" xml:space=\"preserve\">\n    <value>刪除子配置</value>\n  </data>\n  <data name=\"menuServerList\" xml:space=\"preserve\">\n    <value>子配置項目一，從訂閱分組中自動新增</value>\n  </data>\n  <data name=\"TbFallback\" xml:space=\"preserve\">\n    <value>容錯移轉</value>\n  </data>\n  <data name=\"MsgCoreNotSupportNetwork\" xml:space=\"preserve\">\n    <value>核心 '{0}' 不支援網路類型 '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocolTransport\" xml:space=\"preserve\">\n    <value>核心 '{0}' 在使用傳輸方式 '{2}' 時不支援協定 '{1}'</value>\n  </data>\n  <data name=\"MsgCoreNotSupportProtocol\" xml:space=\"preserve\">\n    <value>核心 '{0}' 不支援協定 '{1}'</value>\n  </data>\n  <data name=\"MsgInvalidProperty\" xml:space=\"preserve\">\n    <value>{0} 屬性無效，請檢查</value>\n  </data>\n  <data name=\"MsgNotSupportProtocol\" xml:space=\"preserve\">\n    <value>不支援協定 '{0}'</value>\n  </data>\n  <data name=\"TbSettingsHide2TrayWhenCloseTip\" xml:space=\"preserve\">\n    <value>如果系統沒有託盤功能，請不要開啟</value>\n  </data>\n  <data name=\"TbRuleType\" xml:space=\"preserve\">\n    <value>規則類型</value>\n  </data>\n  <data name=\"TbRuleTypeTips\" xml:space=\"preserve\">\n    <value>可對 Routing 和 DNS 單獨設定規則，ALL 則都生效</value>\n  </data>\n  <data name=\"TbBootstrapDNS\" xml:space=\"preserve\">\n    <value>Bootstrap DNS</value>\n  </data>\n  <data name=\"TbBootstrapDNSTips\" xml:space=\"preserve\">\n    <value>解析 DNS 伺服器網域名稱,需指定為 IP</value>\n  </data>\n  <data name=\"menuFastRealPing\" xml:space=\"preserve\">\n    <value>一鍵測試真連線延遲</value>\n  </data>\n  <data name=\"TbPolicyGroupSubChildTip\" xml:space=\"preserve\">\n    <value>自動從訂閱分組新增過濾後的配置</value>\n  </data>\n  <data name=\"TbCertPinning\" xml:space=\"preserve\">\n    <value>憑證綁定</value>\n  </data>\n  <data name=\"TbCertPinningTips\" xml:space=\"preserve\">\n    <value>固定憑證（二選一填寫即可）\n若已指定，憑證將會被綁定，並且「跳過憑證驗證」將被停用。\n\n若使用自簽憑證，或系統中存在不受信任或惡意的 CA，「取得憑證」動作可能會失敗。</value>\n  </data>\n  <data name=\"TbFetchCert\" xml:space=\"preserve\">\n    <value>獲取憑證</value>\n  </data>\n  <data name=\"TbFetchCertChain\" xml:space=\"preserve\">\n    <value>獲取憑證鏈</value>\n  </data>\n  <data name=\"ServerNameMustBeValidDomain\" xml:space=\"preserve\">\n    <value>請設定有效的網域名稱</value>\n  </data>\n  <data name=\"CertNotSet\" xml:space=\"preserve\">\n    <value>尚未設定憑證</value>\n  </data>\n  <data name=\"CertSet\" xml:space=\"preserve\">\n    <value>已設定憑證</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyPacPath\" xml:space=\"preserve\">\n    <value>自訂 PAC 檔案路徑</value>\n  </data>\n  <data name=\"TbSettingsCustomSystemProxyScriptPath\" xml:space=\"preserve\">\n    <value>自訂系統代理程式腳本檔案路徑</value>\n  </data>\n  <data name=\"TbSettingsMacOSShowInDock\" xml:space=\"preserve\">\n    <value>macOS 在 Dock 欄顯示 (需重啟)</value>\n  </data>\n  <data name=\"menuServerList2\" xml:space=\"preserve\">\n    <value>子配置項二，從自建中選擇新增</value>\n  </data>\n  <data name=\"TbEchConfigList\" xml:space=\"preserve\">\n    <value>EchConfigList</value>\n  </data>\n  <data name=\"TbEchForceQuery\" xml:space=\"preserve\">\n    <value>EchForceQuery</value>\n  </data>\n  <data name=\"TbFullCertTips\" xml:space=\"preserve\">\n    <value>完整憑證（鏈），PEM 格式</value>\n  </data>\n  <data name=\"TbCertSha256Tips\" xml:space=\"preserve\">\n    <value>憑證指紋（SHA-256）</value>\n  </data>\n  <data name=\"TbServeStale\" xml:space=\"preserve\">\n    <value>提供過期快取（Serve Stale）</value>\n  </data>\n  <data name=\"TbParallelQuery\" xml:space=\"preserve\">\n    <value>并行查詢</value>\n  </data>\n  <data name=\"TbDomesticDNSTips\" xml:space=\"preserve\">\n    <value>預設僅在路由期間進行解析時調用</value>\n  </data>\n  <data name=\"TbRemoteDNSTips\" xml:space=\"preserve\">\n    <value>預設僅在路由期間進行解析時調用；請確保遠端伺服器能連線至此 DNS</value>\n  </data>\n  <data name=\"TbDirectResolveStrategyTips\" xml:space=\"preserve\">\n    <value>若未設定或為 \"AsIs\"，使用系統 DNS 解析；否則將使用內建 DNS 模組。</value>\n  </data>\n  <data name=\"TbRemoteResolveStrategyTips\" xml:space=\"preserve\">\n    <value>若未設定或為 \"AsIs\"，由遠端伺服器的 DNS 解析；否則將使用內建 DNS 模組。</value>\n  </data>\n  <data name=\"TbHopInt7\" xml:space=\"preserve\">\n    <value>連接埠跳轉間隔</value>\n  </data>\n  <data name=\"menuServerListPreview\" xml:space=\"preserve\">\n    <value>子配置項預覽</value>\n  </data>\n  <data name=\"TbFinalmask\" xml:space=\"preserve\">\n    <value>Finalmask</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeWarning\" xml:space=\"preserve\">\n    <value>路由規則 {0} 的出站節點 {1} 發出警告：{2}</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeError\" xml:space=\"preserve\">\n    <value>路由規則 {0} 的出站節點 {1} 發生錯誤：{2}。已回退為僅使用代理節點。</value>\n  </data>\n  <data name=\"MsgGroupCycleDependency\" xml:space=\"preserve\">\n    <value>節點組 {0} 與子節點 {1} 存在循環依賴。已跳過此節點。</value>\n  </data>\n  <data name=\"MsgGroupChildNodeWarning\" xml:space=\"preserve\">\n    <value>節點組 {0} 的子節點 {1} 發出警告：{2}</value>\n  </data>\n  <data name=\"MsgGroupChildNodeError\" xml:space=\"preserve\">\n    <value>節點組 {0} 的子節點 {1} 發生錯誤：{2}。已跳過此節點。</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeWarning\" xml:space=\"preserve\">\n    <value>節點組 {0} 的子節點組 {1} 發出警告：{2}</value>\n  </data>\n  <data name=\"MsgGroupChildGroupNodeError\" xml:space=\"preserve\">\n    <value>節點組 {0} 的子節點組 {1} 發生錯誤：{2}。已跳過此節點。</value>\n  </data>\n  <data name=\"MsgGroupNoValidChildNode\" xml:space=\"preserve\">\n    <value>節點組 {0} 沒有可用的有效子節點。</value>\n  </data>\n  <data name=\"MsgRoutingRuleEmptyOutboundTag\" xml:space=\"preserve\">\n    <value>路由規則 {0} 的出站標籤為空。已回退為僅使用代理節點。</value>\n  </data>\n  <data name=\"MsgRoutingRuleOutboundNodeNotFound\" xml:space=\"preserve\">\n    <value>找不到路由規則 {0} 的出站節點 {1}。已回退為僅使用代理節點。</value>\n  </data>\n  <data name=\"MsgSubscriptionPrevProfileNotFound\" xml:space=\"preserve\">\n    <value>找不到訂閱的前一個代理 {0}。已跳過。</value>\n  </data>\n  <data name=\"MsgSubscriptionNextProfileNotFound\" xml:space=\"preserve\">\n    <value>找不到訂閱的下一個代理 {0}。已跳過。</value>\n  </data>\n  <data name=\"menuGenGroupServer\" xml:space=\"preserve\">\n    <value>生成策略組</value>\n  </data>\n  <data name=\"menuAllServers\" xml:space=\"preserve\">\n    <value>所有配置項</value>\n  </data>\n  <data name=\"menuGenRegionGroup\" xml:space=\"preserve\">\n    <value>按區域分組</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/SampleClientConfig",
    "content": "{\n\t\"log\": {\n\t\t\"access\": \"Vaccess.log\",\n\t\t\"error\": \"Verror.log\",\n\t\t\"loglevel\": \"warning\"\n\t},\n\t\"inbounds\": [],\n\t\"outbounds\": [\n\t\t{\n\t\t\t\"protocol\": \"freedom\",\n\t\t\t\"tag\": \"direct\"\n\t\t},\n\t\t{\n\t\t\t\"protocol\": \"blackhole\",\n\t\t\t\"tag\": \"block\"\n\t\t}\n\t],\n\t\"routing\": {\n\t\t\"domainStrategy\": \"IPIfNonMatch\",\n\t\t\"rules\": [\n\t\t\t{\n\t\t\t\t\"inboundTag\": [\n\t\t\t\t\t\"api\"\n\t\t\t\t],\n\t\t\t\t\"outboundTag\": \"api\",\n\t\t\t\t\"type\": \"field\"\n\t\t\t}\n\t\t]\n\t}\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/SampleHttpRequest",
    "content": "﻿{\"version\":\"1.1\",\"method\":\"GET\",\"path\":[$requestPath$],\"headers\":{\"Host\":[$requestHost$],\"User-Agent\":[$requestUserAgent$],\"Accept-Encoding\":[\"gzip, deflate\"],\"Connection\":[\"keep-alive\"],\"Pragma\":\"no-cache\"}}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/SampleHttpResponse",
    "content": "﻿{\"version\":\"1.1\",\"status\":\"200\",\"reason\":\"OK\",\"headers\":{\"Content-Type\":[\"application/octet-stream\",\"video/mpeg\"],\"Transfer-Encoding\":[\"chunked\"],\"Connection\":[\"keep-alive\"],\"Pragma\":\"no-cache\"}}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/SampleInbound",
    "content": "﻿{\n\t\"tag\": \"tag1\",\n\t\"port\": 10808,\n\t\"protocol\": \"socks\",\n\t\"listen\": \"127.0.0.1\",\n\t\"settings\": {\n\t\t\"auth\": \"noauth\",\n\t\t\"udp\": true,\n\t\t\"allowTransparent\": false\n\t},\n\t\"sniffing\": {\n\t\t\"enabled\": true,\n\t\t\"destOverride\": [\n\t\t\t\"http\",\n\t\t\t\"tls\"\n\t\t]\n\t}\n} "
  },
  {
    "path": "v2rayN/ServiceLib/Sample/SampleOutbound",
    "content": "﻿{\n\t\"tag\": \"proxy\",\n\t\"protocol\": \"vmess\",\n\t\"settings\": {\n\t\t\"vnext\": [\n\t\t\t{\n\t\t\t\t\"address\": \"v2ray.cool\",\n\t\t\t\t\"port\": 10086,\n\t\t\t\t\"users\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"id\": \"a3482e88-686a-4a58-8126-99c9df64b7bf\",\n\t\t\t\t\t\t\"security\": \"auto\"\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t],\n\t\t\"servers\": [\n\t\t\t{\n\t\t\t\t\"address\": \"v2ray.cool\",\n\t\t\t\t\"method\": \"chacha20\",\n\t\t\t\t\"ota\": false,\n\t\t\t\t\"password\": \"123456\",\n\t\t\t\t\"port\": 10086,\n\t\t\t\t\"level\": 1\n\t\t\t}\n\t\t]\n\t},\n\t\"streamSettings\": {\n\t\t\"network\": \"tcp\"\n\t},\n\t\"mux\": {\n\t\t\"enabled\": false\n\t}\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/SingboxSampleClientConfig",
    "content": "{\n\t\"log\": {\n\t\t\"level\": \"debug\",\n\t\t\"timestamp\": true\n\t},\n\t\"inbounds\": [],\n\t\"outbounds\": [\n\t\t{\n\t\t\t\"type\": \"direct\",\n\t\t\t\"tag\": \"direct\"\n\t\t}\n\t],\n\t\"route\": {\n\t\t\"rules\": []\n\t}\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/SingboxSampleOutbound",
    "content": "﻿{\n\t\"type\": \"vless\",\n\t\"tag\": \"proxy\",\n\t\"server\": \"\",\n\t\"server_port\": 443\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/clash_mixin_yaml",
    "content": "#\n# 配置文件内容不会被修改，混合行为只会发生在内存中\n#\n# 注意下面缩进，请用支持yaml显示的编辑器打开\n#\n# 使用clash配置文件关键字则覆盖原配置\n#\n# removed-rules    循环匹配rules数组每行,符合则移除当前行 (此规则请放最前面)\n#\n# append-rules    数组合并至原配置rules数组后\n# prepend-rules   数组合并至原配置rules数组前\n# append-proxies      数组合并至原配置proxies数组后\n# prepend-proxies     数组合并至原配置proxies数组前\n# append-proxy-groups     数组合并至原配置proxy-groups数组后\n# prepend-proxy-groups    数组合并至原配置proxy-groups数组前\n# append-rule-providers     数组合并至原配置rule-providers数组后\n# prepend-rule-providers    数组合并至原配置rule-providers数组前\n#\n\ndns:\n  enable: true\n  enhanced-mode: fake-ip\n  nameserver:\n    - 114.114.114.114\n    - 223.5.5.5\n    - 8.8.8.8\n  fallback: []\n  fake-ip-filter:\n    - +.stun.*.*\n    - +.stun.*.*.*\n    - +.stun.*.*.*.*\n    - +.stun.*.*.*.*.*\n    - \"*.n.n.srv.nintendo.net\"\n    - +.stun.playstation.net\n    - xbox.*.*.microsoft.com\n    - \"*.*.xboxlive.com\"\n    - \"*.msftncsi.com\"\n    - \"*.msftconnecttest.com\"\n    - WORKGROUP"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/clash_tun_yaml",
    "content": "tun:\n  enable: true\n  stack: gvisor\n  dns-hijack:\n  - 0.0.0.0:53\n  auto-route: true\n  auto-detect-interface: true\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/custom_routing_black",
    "content": "[\n  {\n    \"remarks\": \"绕过bittorrent\",\n    \"outboundTag\": \"direct\",\n    \"protocol\": [\n      \"bittorrent\"\n    ]\n  },\n  {\n    \"remarks\": \"api.ip.sb\",\n    \"outboundTag\": \"proxy\",\n    \"domain\": [\n      \"api.ip.sb\"\n    ]\n  },\n  {\n    \"remarks\": \"阻断udp443\",\n    \"outboundTag\": \"block\",\n    \"port\": \"443\",\n    \"network\": \"udp\"\n  },\n  {\n    \"remarks\": \"代理Google\",\n    \"outboundTag\": \"proxy\",\n    \"domain\": [\n      \"geosite:google\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过局域网IP\",\n    \"outboundTag\": \"direct\",\n    \"ip\": [\n      \"geoip:private\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过局域网域名\",\n    \"outboundTag\": \"direct\",\n    \"domain\": [\n      \"geosite:private\"\n    ]\n  },\n  {\n    \"remarks\": \"代理海外公共DNSIP\",\n    \"outboundTag\": \"proxy\",\n    \"ip\": [\n      \"1.1.1.1\",\n      \"1.0.0.1\",\n      \"2606:4700:4700::1111\",\n      \"2606:4700:4700::1001\",\n      \"1.1.1.2\",\n      \"1.0.0.2\",\n      \"2606:4700:4700::1112\",\n      \"2606:4700:4700::1002\",\n      \"1.1.1.3\",\n      \"1.0.0.3\",\n      \"2606:4700:4700::1113\",\n      \"2606:4700:4700::1003\",\n      \"8.8.8.8\",\n      \"8.8.4.4\",\n      \"2001:4860:4860::8888\",\n      \"2001:4860:4860::8844\",\n      \"94.140.14.14\",\n      \"94.140.15.15\",\n      \"2a10:50c0::ad1:ff\",\n      \"2a10:50c0::ad2:ff\",\n      \"94.140.14.15\",\n      \"94.140.15.16\",\n      \"2a10:50c0::bad1:ff\",\n      \"2a10:50c0::bad2:ff\",\n      \"94.140.14.140\",\n      \"94.140.14.141\",\n      \"2a10:50c0::1:ff\",\n      \"2a10:50c0::2:ff\",\n      \"208.67.222.222\",\n      \"208.67.220.220\",\n      \"2620:119:35::35\",\n      \"2620:119:53::53\",\n      \"208.67.222.123\",\n      \"208.67.220.123\",\n      \"2620:119:35::123\",\n      \"2620:119:53::123\",\n      \"9.9.9.9\",\n      \"149.112.112.112\",\n      \"2620:fe::9\",\n      \"2620:fe::fe\",\n      \"9.9.9.11\",\n      \"149.112.112.11\",\n      \"2620:fe::11\",\n      \"2620:fe::fe:11\",\n      \"9.9.9.10\",\n      \"149.112.112.10\",\n      \"2620:fe::10\",\n      \"2620:fe::fe:10\",\n      \"77.88.8.8\",\n      \"77.88.8.1\",\n      \"2a02:6b8::feed:0ff\",\n      \"2a02:6b8:0:1::feed:0ff\",\n      \"77.88.8.88\",\n      \"77.88.8.2\",\n      \"2a02:6b8::feed:bad\",\n      \"2a02:6b8:0:1::feed:bad\",\n      \"77.88.8.7\",\n      \"77.88.8.3\",\n      \"2a02:6b8::feed:a11\",\n      \"2a02:6b8:0:1::feed:a11\"\n    ]\n  },\n  {\n    \"remarks\": \"代理海外公共DNS域名\",\n    \"outboundTag\": \"proxy\",\n    \"domain\": [\n      \"domain:cloudflare-dns.com\",\n      \"domain:one.one.one.one\",\n      \"domain:dns.google\",\n      \"domain:adguard-dns.com\",\n      \"domain:opendns.com\",\n      \"domain:umbrella.com\",\n      \"domain:quad9.net\",\n      \"domain:yandex.net\"\n    ]\n  },\n  {\n    \"remarks\": \"代理IP\",\n    \"outboundTag\": \"proxy\",\n    \"ip\": [\n      \"geoip:facebook\",\n      \"geoip:fastly\",\n      \"geoip:google\",\n      \"geoip:netflix\",\n      \"geoip:telegram\",\n      \"geoip:twitter\"\n    ]\n  },\n  {\n    \"remarks\": \"代理GFW\",\n    \"outboundTag\": \"proxy\",\n    \"domain\": [\n      \"geosite:gfw\",\n      \"geosite:greatfire\"\n    ]\n  },\n  {\n    \"remarks\": \"最终直连\",\n    \"port\": \"0-65535\",\n    \"outboundTag\": \"direct\"\n  }\n]\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/custom_routing_global",
    "content": "[\n\t{\n\t\t\"remarks\": \"阻断udp443\",\n\t\t\"outboundTag\": \"block\",\n\t\t\"port\": \"443\",\n\t\t\"network\": \"udp\"\n\t},\n\t{\n\t\t\"remarks\": \"绕过局域网IP\",\n\t\t\"outboundTag\": \"direct\",\n\t\t\"ip\": [\n\t\t\t\"geoip:private\"\n\t\t]\n\t},\n\t{\n\t\t\"remarks\": \"绕过局域网域名\",\n\t\t\"outboundTag\": \"direct\",\n\t\t\"domain\": [\n\t\t\t\"geosite:private\"\n\t\t]\n\t},\n\t{\n\t\t\"remarks\": \"最终代理\",\n\t\t\"port\": \"0-65535\",\n\t\t\"outboundTag\": \"proxy\"\n\t}\n]\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/custom_routing_white",
    "content": "[\n  {\n    \"remarks\": \"阻断udp443\",\n    \"outboundTag\": \"block\",\n    \"port\": \"443\",\n    \"network\": \"udp\"\n  },\n  {\n    \"remarks\": \"代理Google\",\n    \"outboundTag\": \"proxy\",\n    \"domain\": [\n      \"geosite:google\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过局域网IP\",\n    \"outboundTag\": \"direct\",\n    \"ip\": [\n      \"geoip:private\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过局域网域名\",\n    \"outboundTag\": \"direct\",\n    \"domain\": [\n      \"geosite:private\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过中国公共DNSIP\",\n    \"outboundTag\": \"direct\",\n    \"ip\": [\n      \"223.5.5.5\",\n      \"223.6.6.6\",\n      \"2400:3200::1\",\n      \"2400:3200:baba::1\",\n      \"119.29.29.29\",\n      \"1.12.12.12\",\n      \"120.53.53.53\",\n      \"2402:4e00::\",\n      \"2402:4e00:1::\",\n      \"180.76.76.76\",\n      \"2400:da00::6666\",\n      \"114.114.114.114\",\n      \"114.114.115.115\",\n      \"114.114.114.119\",\n      \"114.114.115.119\",\n      \"114.114.114.110\",\n      \"114.114.115.110\",\n      \"180.184.1.1\",\n      \"180.184.2.2\",\n      \"101.226.4.6\",\n      \"218.30.118.6\",\n      \"123.125.81.6\",\n      \"140.207.198.6\",\n      \"1.2.4.8\",\n      \"210.2.4.8\",\n      \"52.80.66.66\",\n      \"117.50.22.22\",\n      \"2400:7fc0:849e:200::4\",\n      \"2404:c2c0:85d8:901::4\",\n      \"117.50.10.10\",\n      \"52.80.52.52\",\n      \"2400:7fc0:849e:200::8\",\n      \"2404:c2c0:85d8:901::8\",\n      \"117.50.60.30\",\n      \"52.80.60.30\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过中国公共DNS域名\",\n    \"outboundTag\": \"direct\",\n    \"domain\": [\n      \"domain:alidns.com\",\n      \"domain:doh.pub\",\n      \"domain:dot.pub\",\n      \"domain:360.cn\",\n      \"domain:onedns.net\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过中国IP\",\n    \"outboundTag\": \"direct\",\n    \"ip\": [\n      \"geoip:cn\"\n    ]\n  },\n  {\n    \"remarks\": \"绕过中国域名\",\n    \"outboundTag\": \"direct\",\n    \"domain\": [\n      \"geosite:cn\"\n    ]\n  }\n]\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/dns_singbox_normal",
    "content": "{\n  \"servers\": [\n    {\n      \"tag\": \"remote\",\n      \"type\": \"tcp\",\n      \"server\": \"8.8.8.8\",\n      \"detour\": \"proxy\"\n    },\n    {\n      \"tag\": \"local\",\n      \"type\": \"udp\",\n      \"server\": \"223.5.5.5\"\n    }\n  ],\n  \"rules\": [\n    {\n      \"rule_set\": [\n        \"geosite-google\"\n      ],\n      \"server\": \"remote\",\n      \"strategy\": \"prefer_ipv4\"\n    },\n    {\n      \"rule_set\": [\n        \"geosite-cn\"\n      ],\n      \"server\": \"local\",\n      \"strategy\": \"prefer_ipv4\"\n    }\n  ],\n  \"final\": \"remote\",\n  \"strategy\": \"prefer_ipv4\"\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/dns_v2ray_normal",
    "content": "{\n  \"hosts\": {\n    \"dns.google\": \"8.8.8.8\",\n    \"proxy.example.com\": \"127.0.0.1\"\n  },\n  \"servers\": [\n    {\n      \"address\": \"1.1.1.1\",\n      \"skipFallback\": true,\n      \"domains\": [\n        \"geosite:google\"\n      ]\n    },\n    {\n      \"address\": \"223.5.5.5\",\n      \"skipFallback\": true,\n      \"domains\": [\n        \"geosite:cn\"\n      ],\n      \"expectIPs\": [\n        \"geoip:cn\"\n      ]\n    },\n    \"1.1.1.1\",\n    \"8.8.8.8\",\n    \"https://dns.google/dns-query\"\n  ]\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/kill_as_sudo_linux_sh",
    "content": "#!/bin/bash\n#\n# Process Terminator Script for Linux\n# This script forcibly terminates a process and all its child processes\n#\n\n# Check if PID argument is provided\nif [ $# -ne 1 ]; then\n    echo \"Usage: $0 <PID>\"\n    exit 1\nfi\n\nPID=$1\n\n# Validate that input is a valid PID (numeric)\nif ! [[ \"$PID\" =~ ^[0-9]+$ ]]; then\n    echo \"Error: The PID must be a numeric value\"\n    exit 1\nfi\n\n# Check if the process exists\nif ! ps -p $PID > /dev/null; then\n    echo \"Warning: No process found with PID $PID\"\n    exit 0\nfi\n\n# Recursive function to find and kill all child processes\nkill_children() {\n    local parent=$1\n    local children=$(ps -o pid --no-headers --ppid \"$parent\")\n\n    # Output information about processes being terminated\n    echo \"Processing children of PID: $parent...\"\n\n    # Process each child\n    for child in $children; do\n        # Recursively find and kill child's children first\n        kill_children \"$child\"\n\n        # Force kill the child process\n        echo \"Terminating child process: $child\"\n        kill -9 \"$child\" 2>/dev/null || true\n    done\n}\n\necho \"============================================\"\necho \"Starting termination of process $PID and all its children\"\necho \"============================================\"\n\n# Try graceful termination first\necho \"Attempting graceful termination (SIGTERM) of PID: $PID\"\nkill -15 \"$PID\" 2>/dev/null || true\nsleep 1\n# If still running, fall back to kill_children\nif ps -p $PID > /dev/null; then\n    echo \"Process $PID did not exit after SIGTERM; proceeding with forced termination of its children and itself\"\nelse\n    echo \"Process $PID exited cleanly after SIGTERM\"\n    exit 0\nfi\n\n# Find and kill all child processes\nkill_children \"$PID\"\n\n# Finally kill the main process\necho \"Terminating main process: $PID\"\nkill -9 \"$PID\" 2>/dev/null || true\n\necho \"============================================\"\necho \"Process $PID and all its children have been terminated\"\necho \"============================================\"\n\nexit 0\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/kill_as_sudo_osx_sh",
    "content": "#!/bin/bash\n#\n# Process Terminator Script for macOS\n# This script forcibly terminates a process and all its descendant processes\n#\n\n# Check if PID argument is provided\nif [ $# -ne 1 ]; then\n    echo \"Usage: $0 <PID>\"\n    exit 1\nfi\n\nPID=$1\n\n# Validate that input is a valid PID (numeric)\nif ! [[ \"$PID\" =~ ^[0-9]+$ ]]; then\n    echo \"Error: The PID must be a numeric value\"\n    exit 1\nfi\n\n# Check if the process exists - using kill -0 which is more reliable on macOS\nif ! kill -0 $PID 2>/dev/null; then\n    echo \"Warning: No process found with PID $PID\"\n    exit 0\nfi\n\n# Recursive function to find and kill all descendant processes\nkill_descendants() {\n    local parent=$1\n    # Use ps -axo for macOS to ensure all processes are included\n    local children=$(ps -axo pid=,ppid= | awk -v ppid=$parent '$2==ppid {print $1}')\n\n    echo \"Processing children of PID: $parent...\"\n    for child in $children; do\n        kill_descendants \"$child\"\n        echo \"Terminating child process: $child\"\n        kill -9 \"$child\" 2>/dev/null || true\n    done\n}\n\necho \"============================================\"\necho \"Starting termination of process $PID and all its descendants\"\necho \"============================================\"\n\n# Try graceful termination first\necho \"Attempting graceful termination (SIGTERM) of PID: $PID\"\nkill -15 \"$PID\" 2>/dev/null || true\nsleep 1\n\n# If still running, fall back to kill_descendants\n# Use the macOS-native 'kill -0' check\nif kill -0 $PID 2>/dev/null; then\n    echo \"Process $PID did not exit after SIGTERM; proceeding with forced termination of its descendants and itself\"\nelse\n    echo \"Process $PID exited cleanly after SIGTERM\"\n    exit 0\nfi\n\n# Find and kill all descendant processes\nkill_descendants \"$PID\"\n\n# Finally kill the main process\necho \"Terminating main process: $PID\"\nkill -9 \"$PID\" 2>/dev/null || true\n\necho \"============================================\"\necho \"Process $PID and all its descendants have been terminated\"\necho \"============================================\"\n\nexit 0\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/linux_autostart_config",
    "content": "[Desktop Entry]\nType=Application\nExec=$ExecPath$\nHidden=false\nNoDisplay=false\nX-GNOME-Autostart-enabled=true\nName[en_US]=v2rayN\nName=v2rayN\nComment[en_US]=v2rayN\nComment=v2rayN\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/pac",
    "content": "var proxy = '__PROXY__';\nvar rules = [\n    [\n        [],\n        [\n            \"000webhost.com\",\n            \"030buy.com\",\n            \"0rz.tw\",\n            \"1-apple.com.tw\",\n            \"1000giri.net\",\n            \"100ke.org\",\n            \"10beasts.net\",\n            \"10conditionsoflove.com\",\n            \"10musume.com\",\n            \"111666.best\",\n            \"123rf.com\",\n            \"12bet.com\",\n            \"12vpn.com\",\n            \"12vpn.net\",\n            \"1337x.to\",\n            \"138.com\",\n            \"141-hk.com\",\n            \"141hongkong.com\",\n            \"141jj.com\",\n            \"141tube.com\",\n            \"1688.com.au\",\n            \"17.live\",\n            \"173ng.com\",\n            \"177pic.info\",\n            \"17t17p.com\",\n            \"18board.com\",\n            \"18comic.org\",\n            \"18comic.vip\",\n            \"18hmanga.click\",\n            \"18jav.tv\",\n            \"18onlygirls.com\",\n            \"18p2p.com\",\n            \"18virginsex.com\",\n            \"1949er.org\",\n            \"1984.city\",\n            \"1984bbs.com\",\n            \"1984bbs.org\",\n            \"1991way.com\",\n            \"1bao.org\",\n            \"1dumb.com\",\n            \"1e100.net\",\n            \"1eew.com\",\n            \"1lib.domains\",\n            \"1lib.sk\",\n            \"1mobile.com\",\n            \"1point3acres.com\",\n            \"1pondo.tv\",\n            \"2-hand.info\",\n            \"2000fun.com\",\n            \"2008xianzhang.info\",\n            \"2021hkcharter.com\",\n            \"2047.name\",\n            \"2047.one\",\n            \"2049bbs.xyz\",\n            \"21andy.com\",\n            \"21join.com\",\n            \"21pron.com\",\n            \"21sextury.com\",\n            \"228.net.tw\",\n            \"233abc.com\",\n            \"233v2.com\",\n            \"24hrs.ca\",\n            \"25u.com\",\n            \"2du5.com\",\n            \"2lipstube.com\",\n            \"2shared.com\",\n            \"2waky.com\",\n            \"3-a.net\",\n            \"30boxes.com\",\n            \"315lz.com\",\n            \"32red.com\",\n            \"36rain.com\",\n            \"3a5a.com\",\n            \"3arabtv.com\",\n            \"3boys2girls.com\",\n            \"3d-game.com\",\n            \"3proxy.ru\",\n            \"3ren.ca\",\n            \"3tui.net\",\n            \"404museum.com\",\n            \"466453.com\",\n            \"4bluestones.biz\",\n            \"4chan.com\",\n            \"4dq.com\",\n            \"4everland.io\",\n            \"4everproxy.com\",\n            \"4gtv.tv\",\n            \"4irc.com\",\n            \"4mydomain.com\",\n            \"4pu.com\",\n            \"4rbtv.com\",\n            \"4shared.com\",\n            \"4sqi.net\",\n            \"500px.com\",\n            \"500px.org\",\n            \"50webs.com\",\n            \"51.ca\",\n            \"51jav.org\",\n            \"51luoben.com\",\n            \"5278.cc\",\n            \"5299.tv\",\n            \"55comic.com\",\n            \"5657.com.tw\",\n            \"5i01.com\",\n            \"5isotoi5.org\",\n            \"5maodang.com\",\n            \"611.icu\",\n            \"611study.com\",\n            \"611study.icu\",\n            \"63i.com\",\n            \"64museum.org\",\n            \"64tianwang.com\",\n            \"64wiki.com\",\n            \"66.ca\",\n            \"666kb.com\",\n            \"666pool.cn\",\n            \"69shu.com\",\n            \"69shuba.com\",\n            \"69shuba.cx\",\n            \"6do.news\",\n            \"6do.world\",\n            \"6park.com\",\n            \"6parkbbs.com\",\n            \"6parker.com\",\n            \"6parknews.com\",\n            \"7capture.com\",\n            \"7cow.com\",\n            \"7mmtv.tv\",\n            \"8-d.com\",\n            \"85cc.net\",\n            \"85cc.us\",\n            \"85st.com\",\n            \"881903.com\",\n            \"888.com\",\n            \"888poker.com\",\n            \"89-64.org\",\n            \"8964museum.com\",\n            \"8news.com.tw\",\n            \"8world.com\",\n            \"8z1.net\",\n            \"91dasai.com\",\n            \"91jinman.com\",\n            \"91porn.com\",\n            \"91porny.com\",\n            \"91vps.club\",\n            \"92ccav.com\",\n            \"991.com\",\n            \"99btgc01.com\",\n            \"99cn.info\",\n            \"9bis.com\",\n            \"9bis.net\",\n            \"9cache.com\",\n            \"9gag.com\",\n            \"9news.com.au\",\n            \"a-normal-day.com\",\n            \"a5.com.ru\",\n            \"a5vpn.com\",\n            \"aamacau.com\",\n            \"abc.com\",\n            \"abc.net.au\",\n            \"abc.xyz\",\n            \"abchinese.com\",\n            \"abebooks.co.uk\",\n            \"abebooks.com\",\n            \"ablwang.com\",\n            \"aboluowang.com\",\n            \"about.me\",\n            \"abplive.com\",\n            \"abs.edu\",\n            \"acast.com\",\n            \"accim.org\",\n            \"accountkit.com\",\n            \"aceros-de-hispania.com\",\n            \"acevpn.com\",\n            \"acg.rip\",\n            \"acg18.me\",\n            \"acgbox.link\",\n            \"acgbox.org\",\n            \"acgkj.com\",\n            \"acgnx.se\",\n            \"acmedia365.com\",\n            \"acmetoy.com\",\n            \"acnw.com.au\",\n            \"actfortibet.org\",\n            \"actimes.com.au\",\n            \"activpn.com\",\n            \"aculo.us\",\n            \"adcex.com\",\n            \"addictedtocoffee.de\",\n            \"addyoutube.com\",\n            \"adelaidebbs.com\",\n            \"adguard-vpn.com\",\n            \"admob.com\",\n            \"adpl.org.hk\",\n            \"ads-twitter.com\",\n            \"adsense.com\",\n            \"adult-sex-games.com\",\n            \"adultfriendfinder.com\",\n            \"adultkeep.net\",\n            \"advanscene.com\",\n            \"advertfan.com\",\n            \"advertisercommunity.com\",\n            \"ae.org\",\n            \"aei.org\",\n            \"aenhancers.com\",\n            \"aex.com\",\n            \"af.mil\",\n            \"afantibbs.com\",\n            \"afr.com\",\n            \"afreecatv.com\",\n            \"agemys.net\",\n            \"agnesb.fr\",\n            \"agoogleaday.com\",\n            \"agro.hk\",\n            \"ai-kan.net\",\n            \"ai-wen.net\",\n            \"aiosearch.com\",\n            \"aiph.net\",\n            \"airasia.com\",\n            \"airconsole.com\",\n            \"aircrack-ng.org\",\n            \"airitilibrary.com\",\n            \"airvpn.org\",\n            \"aisex.com\",\n            \"ait.org.tw\",\n            \"aiv-cdn.net\",\n            \"aiv-delivery.net\",\n            \"aiweiwei.com\",\n            \"aiweiweiblog.com\",\n            \"ajsands.com\",\n            \"akademiye.org\",\n            \"akamai.net\",\n            \"akamaihd.net\",\n            \"akamaistream.net\",\n            \"akamaized.net\",\n            \"akiba-online.com\",\n            \"akiba-web.com\",\n            \"akinator.com\",\n            \"akow.org\",\n            \"al-islam.com\",\n            \"al-qimmah.net\",\n            \"alabout.com\",\n            \"alanhou.com\",\n            \"alarab.qa\",\n            \"alasbarricadas.org\",\n            \"alexlur.org\",\n            \"alforattv.net\",\n            \"alhayat.com\",\n            \"alicejapan.co.jp\",\n            \"aliengu.com\",\n            \"alive.bar\",\n            \"aljazeera.com\",\n            \"aljazeera.net\",\n            \"alkasir.com\",\n            \"all4mom.org\",\n            \"allcoin.com\",\n            \"allconnected.co\",\n            \"alldrawnsex.com\",\n            \"allervpn.com\",\n            \"allfinegirls.com\",\n            \"allgirlmassage.com\",\n            \"allgirlsallowed.org\",\n            \"allgravure.com\",\n            \"alliance.org.hk\",\n            \"allinfa.com\",\n            \"alljackpotscasino.com\",\n            \"allmovie.com\",\n            \"allowed.org\",\n            \"almasdarnews.com\",\n            \"almostmy.com\",\n            \"alphaporno.com\",\n            \"alternate-tools.com\",\n            \"alternativeto.net\",\n            \"altrec.com\",\n            \"alvinalexander.com\",\n            \"alwaysdata.com\",\n            \"alwaysdata.net\",\n            \"alwaysvpn.com\",\n            \"am730.com.hk\",\n            \"amazon.co.jp\",\n            \"amazon.com\",\n            \"amazonvideo.com\",\n            \"ameba.jp\",\n            \"ameblo.jp\",\n            \"america.gov\",\n            \"american.edu\",\n            \"americangreencard.com\",\n            \"americanunfinished.com\",\n            \"americorps.gov\",\n            \"amiblockedornot.com\",\n            \"amigobbs.net\",\n            \"amitabhafoundation.us\",\n            \"amnesty.org\",\n            \"amnesty.org.hk\",\n            \"amnesty.tw\",\n            \"amnestyusa.org\",\n            \"amnyemachen.org\",\n            \"ampproject.org\",\n            \"amtb-taipei.org\",\n            \"amuletmc.com\",\n            \"anchor.fm\",\n            \"anchorfree.com\",\n            \"ancsconf.org\",\n            \"andfaraway.net\",\n            \"android-x86.org\",\n            \"android.com\",\n            \"androidapksfree.com\",\n            \"androidcombo.com\",\n            \"androidify.com\",\n            \"androidplus.co\",\n            \"androidtv.com\",\n            \"andygod.com\",\n            \"angela-merkel.de\",\n            \"angelfire.com\",\n            \"angola.org\",\n            \"angularjs.org\",\n            \"animecrazy.net\",\n            \"animeshippuuden.com\",\n            \"animezilla.com\",\n            \"aniscartujo.com\",\n            \"annas-archive.org\",\n            \"annas-archive.se\",\n            \"annatam.com\",\n            \"anobii.com\",\n            \"anonfiles.com\",\n            \"anontext.com\",\n            \"anonymise.us\",\n            \"anonymitynetwork.com\",\n            \"anonymizer.com\",\n            \"anonymouse.org\",\n            \"anpopo.com\",\n            \"answering-islam.org\",\n            \"antd.org\",\n            \"anthonycalzadilla.com\",\n            \"anthropic.com\",\n            \"anti1984.com\",\n            \"antichristendom.com\",\n            \"antisocial.science\",\n            \"antiwave.net\",\n            \"antpool.com\",\n            \"anws.gov.tw\",\n            \"anyporn.com\",\n            \"anysex.com\",\n            \"ao3.org\",\n            \"aobo.com.au\",\n            \"aofriend.com\",\n            \"aofriend.com.au\",\n            \"aojiao.org\",\n            \"aol.ca\",\n            \"aol.co.uk\",\n            \"aol.com\",\n            \"aolnews.com\",\n            \"aomedia.org\",\n            \"aomiwang.com\",\n            \"apartmentratings.com\",\n            \"apartments.com\",\n            \"apat1989.org\",\n            \"apetube.com\",\n            \"api.ai\",\n            \"apiary.io\",\n            \"apigee.com\",\n            \"apk-dl.com\",\n            \"apk.support\",\n            \"apk.tw\",\n            \"apkcombo.com\",\n            \"apkmirror.com\",\n            \"apkmonk.com\",\n            \"apkplz.com\",\n            \"apkpure.com\",\n            \"apkpure.net\",\n            \"aplusvpn.com\",\n            \"appadvice.com\",\n            \"appbrain.com\",\n            \"appdefensealliance.dev\",\n            \"appdownloader.net\",\n            \"appledaily.com\",\n            \"appledaily.com.hk\",\n            \"appledaily.com.tw\",\n            \"appshopper.com\",\n            \"appsocks.net\",\n            \"appspot-preview.com\",\n            \"appspot.com\",\n            \"appsto.re\",\n            \"aptoide.com\",\n            \"archive.fo\",\n            \"archive.is\",\n            \"archive.li\",\n            \"archive.md\",\n            \"archive.org\",\n            \"archive.ph\",\n            \"archive.today\",\n            \"archive.vn\",\n            \"archiveofourown.com\",\n            \"archiveofourown.org\",\n            \"archives.gov\",\n            \"archives.gov.tw\",\n            \"arctosia.com\",\n            \"areca-backup.org\",\n            \"arena.taipei\",\n            \"arethusa.su\",\n            \"arlingtoncemetery.mil\",\n            \"army.mil\",\n            \"arstechnica.net\",\n            \"art4tibet1998.org\",\n            \"arte.tv\",\n            \"artofpeacefoundation.org\",\n            \"artstation.com\",\n            \"artsy.net\",\n            \"arunachalforests.gov.in\",\n            \"arvanstorage.ir\",\n            \"asacp.org\",\n            \"asdfg.jp\",\n            \"asg.to\",\n            \"asia-gaming.com\",\n            \"asiaharvest.org\",\n            \"asianage.com\",\n            \"asianews.it\",\n            \"asiansexdiary.com\",\n            \"asiaone.com\",\n            \"asiatgp.com\",\n            \"asiatimes.com\",\n            \"asiatoday.us\",\n            \"ask.com\",\n            \"askstudent.com\",\n            \"askynz.net\",\n            \"aspi.org.au\",\n            \"aspistrategist.org.au\",\n            \"asrockind.com\",\n            \"assembla.com\",\n            \"assimp.org\",\n            \"astrill.com\",\n            \"atc.org.au\",\n            \"atchinese.com\",\n            \"atgfw.org\",\n            \"athenaeizou.com\",\n            \"atlanta168.com\",\n            \"atnext.com\",\n            \"audacy.com\",\n            \"audionow.com\",\n            \"authorizeddns.net\",\n            \"authorizeddns.org\",\n            \"autodraw.com\",\n            \"av-e-body.com\",\n            \"av.com\",\n            \"av.movie\",\n            \"av01.tv\",\n            \"avaaz.org\",\n            \"avbody.tv\",\n            \"avcity.tv\",\n            \"avcool.com\",\n            \"avdb.in\",\n            \"avdb.tv\",\n            \"avfantasy.com\",\n            \"avg.com\",\n            \"avgle.com\",\n            \"avidemux.org\",\n            \"avmo.pw\",\n            \"avmoo.com\",\n            \"avmoo.net\",\n            \"avmoo.pw\",\n            \"avoision.com\",\n            \"avyahoo.com\",\n            \"axios.com\",\n            \"axureformac.com\",\n            \"azerbaycan.tv\",\n            \"azerimix.com\",\n            \"azirevpn.com\",\n            \"azurewebsites.net\",\n            \"b-cdn.net\",\n            \"b-ok.cc\",\n            \"b0ne.com\",\n            \"baby-kingdom.com\",\n            \"babylonbee.com\",\n            \"babynet.com.hk\",\n            \"backchina.com\",\n            \"backpackers.com.tw\",\n            \"backtotiananmen.com\",\n            \"bad.news\",\n            \"badiucao.com\",\n            \"badjojo.com\",\n            \"badoo.com\",\n            \"bahamut.com.tw\",\n            \"baidu.jp\",\n            \"baijie.org\",\n            \"bailandaily.com\",\n            \"baixing.me\",\n            \"baizhi.org\",\n            \"bakgeekhome.tk\",\n            \"bamgrid.com\",\n            \"banana-vpn.com\",\n            \"band.us\",\n            \"bandcamp.com\",\n            \"bandpage.com\",\n            \"bandwagonhost.com\",\n            \"bangbrosnetwork.com\",\n            \"bangchen.net\",\n            \"bangdream.space\",\n            \"bangkokpost.com\",\n            \"bangumi.moe\",\n            \"bangyoulater.com\",\n            \"bankmobilevibe.com\",\n            \"bannedbook.org\",\n            \"bannednews.org\",\n            \"banorte.com\",\n            \"baramangaonline.com\",\n            \"barenakedislam.com\",\n            \"barnabu.co.uk\",\n            \"barton.de\",\n            \"bartvpn.com\",\n            \"bastillepost.com\",\n            \"bayvoice.net\",\n            \"bb-chat.tv\",\n            \"bbc.co.uk\",\n            \"bbc.com\",\n            \"bbc.in\",\n            \"bbcchinese.com\",\n            \"bbchat.tv\",\n            \"bbci.co.uk\",\n            \"bbg.gov\",\n            \"bbkz.com\",\n            \"bbnradio.org\",\n            \"bbs-tw.com\",\n            \"bbsdigest.com\",\n            \"bbsfeed.com\",\n            \"bbsland.com\",\n            \"bbsmo.com\",\n            \"bbsone.com\",\n            \"bbtoystore.com\",\n            \"bcast.co.nz\",\n            \"bcc.com.tw\",\n            \"bcchinese.net\",\n            \"bcex.ca\",\n            \"bcmorning.com\",\n            \"bcrncdn.com\",\n            \"bdsmvideos.net\",\n            \"beaconevents.com\",\n            \"beanfun.com\",\n            \"bearteach.com\",\n            \"bebo.com\",\n            \"beeg.com\",\n            \"beepool.com\",\n            \"beepool.org\",\n            \"beevpn.com\",\n            \"behance.net\",\n            \"behindkink.com\",\n            \"beijing1989.com\",\n            \"beijing2022.art\",\n            \"beijingspring.com\",\n            \"beijingzx.org\",\n            \"belamionline.com\",\n            \"bell.wiki\",\n            \"bemywife.cc\",\n            \"beric.me\",\n            \"berlinerbericht.de\",\n            \"berlintwitterwall.com\",\n            \"berm.co.nz\",\n            \"bestforchina.org\",\n            \"bestgore.com\",\n            \"bestpornstardb.com\",\n            \"bestvpn.com\",\n            \"bestvpnanalysis.com\",\n            \"bestvpnforchina.net\",\n            \"bestvpnserver.com\",\n            \"bestvpnservice.com\",\n            \"bestvpnusa.com\",\n            \"bet365.com\",\n            \"betaclouds.net\",\n            \"betfair.com\",\n            \"betterhash.net\",\n            \"betternet.co\",\n            \"bettervpn.com\",\n            \"bettween.com\",\n            \"betvictor.com\",\n            \"bewww.net\",\n            \"beyondfirewall.com\",\n            \"bfnn.org\",\n            \"bfsh.hk\",\n            \"bgme.me\",\n            \"bgvpn.com\",\n            \"bianlei.com\",\n            \"biantailajiao.com\",\n            \"biantailajiao.in\",\n            \"biblesforamerica.org\",\n            \"bibliocommons.com\",\n            \"bibox.com\",\n            \"bic2011.org\",\n            \"bidswitch.net\",\n            \"biedian.me\",\n            \"big.one\",\n            \"bigfools.com\",\n            \"biggo.com.tw\",\n            \"bigjapanesesex.com\",\n            \"bigmoney.biz\",\n            \"bignews.org\",\n            \"bignewsnetwork.com\",\n            \"bigone.com\",\n            \"bigsound.org\",\n            \"bild.de\",\n            \"bilibili.tv\",\n            \"biliworld.com\",\n            \"billypan.com\",\n            \"binance.com\",\n            \"binance.org\",\n            \"binance.us\",\n            \"binancezh.cc\",\n            \"bing.com\",\n            \"binux.me\",\n            \"binwang.me\",\n            \"bipic.net\",\n            \"bird.so\",\n            \"bit-z.com\",\n            \"bit.do\",\n            \"bit.ly\",\n            \"bitbay.net\",\n            \"bitchute.com\",\n            \"bitcointalk.org\",\n            \"bitcoinworld.com\",\n            \"bitfinex.com\",\n            \"bitget.com\",\n            \"bithumb.com\",\n            \"bitmex.com\",\n            \"bitshare.com\",\n            \"bitsnoop.com\",\n            \"bitterwinter.org\",\n            \"bitvise.com\",\n            \"bitz.ai\",\n            \"bitz.com\",\n            \"bizhat.com\",\n            \"bjnewlife.org\",\n            \"bjs.org\",\n            \"bjzc.org\",\n            \"bl-doujinsouko.com\",\n            \"blacked.com\",\n            \"blacklogic.com\",\n            \"blackmagicdesign.com\",\n            \"blackvpn.com\",\n            \"blewpass.com\",\n            \"blingblingsquad.net\",\n            \"blinkx.com\",\n            \"blinw.com\",\n            \"blip.tv\",\n            \"blockcast.it\",\n            \"blockcn.com\",\n            \"blockedbyhk.com\",\n            \"blockless.com\",\n            \"blocktempo.com\",\n            \"blog.de\",\n            \"blog.jp\",\n            \"blogblog.com\",\n            \"blogcatalog.com\",\n            \"blogcity.me\",\n            \"blogdns.org\",\n            \"blogger.com\",\n            \"blogimg.jp\",\n            \"blogjav.net\",\n            \"bloglines.com\",\n            \"bloglovin.com\",\n            \"blogs.com\",\n            \"blogspot.ae\",\n            \"blogspot.al\",\n            \"blogspot.am\",\n            \"blogspot.ba\",\n            \"blogspot.be\",\n            \"blogspot.bg\",\n            \"blogspot.ca\",\n            \"blogspot.cat\",\n            \"blogspot.ch\",\n            \"blogspot.cl\",\n            \"blogspot.co.uk\",\n            \"blogspot.com\",\n            \"blogspot.com.ar\",\n            \"blogspot.com.au\",\n            \"blogspot.com.br\",\n            \"blogspot.com.by\",\n            \"blogspot.com.co\",\n            \"blogspot.com.cy\",\n            \"blogspot.com.ee\",\n            \"blogspot.com.eg\",\n            \"blogspot.com.es\",\n            \"blogspot.com.mt\",\n            \"blogspot.com.ng\",\n            \"blogspot.com.tr\",\n            \"blogspot.com.uy\",\n            \"blogspot.cz\",\n            \"blogspot.de\",\n            \"blogspot.dk\",\n            \"blogspot.fi\",\n            \"blogspot.fr\",\n            \"blogspot.gr\",\n            \"blogspot.hk\",\n            \"blogspot.hr\",\n            \"blogspot.hu\",\n            \"blogspot.ie\",\n            \"blogspot.in\",\n            \"blogspot.is\",\n            \"blogspot.it\",\n            \"blogspot.jp\",\n            \"blogspot.kr\",\n            \"blogspot.li\",\n            \"blogspot.lt\",\n            \"blogspot.lu\",\n            \"blogspot.md\",\n            \"blogspot.mk\",\n            \"blogspot.mx\",\n            \"blogspot.my\",\n            \"blogspot.nl\",\n            \"blogspot.no\",\n            \"blogspot.pe\",\n            \"blogspot.pt\",\n            \"blogspot.qa\",\n            \"blogspot.ro\",\n            \"blogspot.ru\",\n            \"blogspot.se\",\n            \"blogspot.sg\",\n            \"blogspot.si\",\n            \"blogspot.sk\",\n            \"blogspot.sn\",\n            \"blogspot.tw\",\n            \"blogspot.ug\",\n            \"blogtd.net\",\n            \"blogtd.org\",\n            \"bloodshed.net\",\n            \"bloomberg.cn\",\n            \"bloomberg.com\",\n            \"bloomberg.de\",\n            \"bloombergview.com\",\n            \"bloomfortune.com\",\n            \"blubrry.com\",\n            \"blueangellive.com\",\n            \"bmdru.com\",\n            \"bmfinn.com\",\n            \"bnbstatic.com\",\n            \"bnews.co\",\n            \"bnext.com.tw\",\n            \"bnn.co\",\n            \"bnrmetal.com\",\n            \"bntrace.com\",\n            \"boardreader.com\",\n            \"bod.asia\",\n            \"bodog88.com\",\n            \"bolehvpn.net\",\n            \"bonbonme.com\",\n            \"bonfoundation.org\",\n            \"bongacams.com\",\n            \"boobstagram.com\",\n            \"book.com.tw\",\n            \"bookdepository.com\",\n            \"bookepub.com\",\n            \"booklive.jp\",\n            \"bookmeter.com\",\n            \"books.com.tw\",\n            \"booktopia.com.au\",\n            \"bookwalker.com.tw\",\n            \"bookwalker.jp\",\n            \"bootstrapcdn.com\",\n            \"borgenmagazine.com\",\n            \"bot.nu\",\n            \"botanwang.com\",\n            \"bowenpress.com\",\n            \"box.com\",\n            \"box.net\",\n            \"boxpn.com\",\n            \"boxun.com\",\n            \"boxun.tv\",\n            \"boxunblog.com\",\n            \"boxunclub.com\",\n            \"boyangu.com\",\n            \"boyfriendtv.com\",\n            \"boysfood.com\",\n            \"boysmaster.com\",\n            \"br.st\",\n            \"brainyquote.com\",\n            \"brandonhutchinson.com\",\n            \"braumeister.org\",\n            \"brave.com\",\n            \"bravotube.net\",\n            \"brazzers.com\",\n            \"breached.to\",\n            \"break.com\",\n            \"breakgfw.com\",\n            \"breaking911.com\",\n            \"breakingtweets.com\",\n            \"breakwall.net\",\n            \"briian.com\",\n            \"brill.com\",\n            \"brizzly.com\",\n            \"broadbook.com\",\n            \"broadpressinc.com\",\n            \"brockbbs.com\",\n            \"brookings.edu\",\n            \"brucewang.net\",\n            \"brutaltgp.com\",\n            \"bsky.app\",\n            \"bsky.network\",\n            \"bsky.social\",\n            \"bt2mag.com\",\n            \"bt4g.org\",\n            \"bt4gprx.com\",\n            \"bt95.com\",\n            \"btaia.com\",\n            \"btbit.net\",\n            \"btbtav.com\",\n            \"btbtt.co\",\n            \"btbtt.me\",\n            \"btc.com\",\n            \"btc98.com\",\n            \"btcbank.bank\",\n            \"btctrade.im\",\n            \"btdig.com\",\n            \"btdigg.org\",\n            \"btguard.com\",\n            \"btku.me\",\n            \"btku.org\",\n            \"btloader.com\",\n            \"btspread.com\",\n            \"btsynckeys.com\",\n            \"budaedu.org\",\n            \"buddhanet.com.tw\",\n            \"buddhistchannel.tv\",\n            \"buffered.com\",\n            \"bullguard.com\",\n            \"bullog.org\",\n            \"bullogger.com\",\n            \"bumingbai.net\",\n            \"bunbunhk.com\",\n            \"busayari.com\",\n            \"business-humanrights.org\",\n            \"business.page\",\n            \"business.site\",\n            \"businessinsider.com\",\n            \"businessinsider.com.au\",\n            \"businesstoday.com.tw\",\n            \"businessweek.com\",\n            \"businessweekly.com.tw\",\n            \"busu.org\",\n            \"busytrade.com\",\n            \"buugaa.com\",\n            \"buzzhand.com\",\n            \"buzzhand.net\",\n            \"buzzorange.com\",\n            \"buzzsprout.com\",\n            \"bvpn.com\",\n            \"bwbx.io\",\n            \"bwgyhw.com\",\n            \"bwh1.net\",\n            \"bwsj.hk\",\n            \"bx.in.th\",\n            \"bx.tl\",\n            \"bybit.com\",\n            \"bynet.co.il\",\n            \"bypasscensorship.org\",\n            \"byrut.org\",\n            \"byteoversea.com\",\n            \"c-est-simple.com\",\n            \"c-span.org\",\n            \"c-spanvideo.org\",\n            \"c.gle\",\n            \"c100tibet.org\",\n            \"c2cx.com\",\n            \"c3pool.com\",\n            \"ca.gov\",\n            \"cableav.tv\",\n            \"cablegatesearch.net\",\n            \"cachefly.com\",\n            \"cachefly.net\",\n            \"cachinese.com\",\n            \"cacnw.com\",\n            \"cactusvpn.com\",\n            \"cafepress.com\",\n            \"cahr.org.tw\",\n            \"calameo.com\",\n            \"calebelston.com\",\n            \"calendarz.com\",\n            \"calgarychinese.ca\",\n            \"calgarychinese.com\",\n            \"calgarychinese.net\",\n            \"cam4.com\",\n            \"cam4.jp\",\n            \"cam4.sg\",\n            \"camfrog.com\",\n            \"campaign-archive.com\",\n            \"campaignforuyghurs.org\",\n            \"cams.com\",\n            \"cams.org.sg\",\n            \"canadameet.com\",\n            \"canalporno.com\",\n            \"cantonese.asia\",\n            \"canyu.org\",\n            \"cao.im\",\n            \"caobian.info\",\n            \"caochangqing.com\",\n            \"caoporn.us\",\n            \"cap.org.hk\",\n            \"captainfawcett.com\",\n            \"carabinasypistolas.com\",\n            \"cardinalkungfoundation.org\",\n            \"careerengine.us\",\n            \"carfax.com\",\n            \"cari.com.my\",\n            \"caribbeancom.com\",\n            \"carmotorshow.com\",\n            \"carousell.com.hk\",\n            \"carrd.co\",\n            \"carryzhou.com\",\n            \"cartoon18.com\",\n            \"cartoonmovement.com\",\n            \"casadeltibetbcn.org\",\n            \"casatibet.org.mx\",\n            \"casinobellini.com\",\n            \"casinoking.com\",\n            \"casinoriva.com\",\n            \"castbox.fm\",\n            \"catbox.moe\",\n            \"catch22.net\",\n            \"catchgod.com\",\n            \"catfightpayperview.xxx\",\n            \"catholic.org.hk\",\n            \"catholic.org.tw\",\n            \"cathvoice.org.tw\",\n            \"cato.org\",\n            \"cattt.com\",\n            \"caus.com\",\n            \"cbc.ca\",\n            \"cbsnews.com\",\n            \"cbtc.org.hk\",\n            \"cc.com\",\n            \"cccat.cc\",\n            \"cccat.co\",\n            \"ccdtr.org\",\n            \"ccfd.org.tw\",\n            \"cchere.com\",\n            \"ccim.org\",\n            \"cclife.ca\",\n            \"cclife.org\",\n            \"cclifefl.org\",\n            \"ccthere.com\",\n            \"ccthere.net\",\n            \"cctmweb.net\",\n            \"cctongbao.com\",\n            \"ccu.edu.tw\",\n            \"ccue.ca\",\n            \"ccue.com\",\n            \"ccvoice.ca\",\n            \"ccw.org.tw\",\n            \"cdbook.org\",\n            \"cdcparty.com\",\n            \"cdef.org\",\n            \"cdig.info\",\n            \"cdjp.org\",\n            \"cdn-apple.com\",\n            \"cdn-telegram.org\",\n            \"cdnews.com.tw\",\n            \"cdninstagram.com\",\n            \"cdp1989.org\",\n            \"cdp1998.org\",\n            \"cdp2006.org\",\n            \"cdpa.url.tw\",\n            \"cdpeu.org\",\n            \"cdpuk.co.uk\",\n            \"cdpusa.org\",\n            \"cdpweb.org\",\n            \"cdpwu.org\",\n            \"cdw.com\",\n            \"cecc.gov\",\n            \"celestiallight.org\",\n            \"cellulo.info\",\n            \"cenews.eu\",\n            \"centauro.com.br\",\n            \"centerforhumanreprod.com\",\n            \"centralnation.com\",\n            \"centurys.net\",\n            \"certificate-transparency.org\",\n            \"cex.io\",\n            \"cfhks.org.hk\",\n            \"cfos.de\",\n            \"cfr.org\",\n            \"cfsh99.com\",\n            \"cftfc.com\",\n            \"cgdepot.org\",\n            \"cgst.edu\",\n            \"change.org\",\n            \"changeip.name\",\n            \"changeip.net\",\n            \"changeip.org\",\n            \"changp.com\",\n            \"changsa.net\",\n            \"channel8news.sg\",\n            \"channelnewsasia.com\",\n            \"chanworld.org\",\n            \"chaoex.com\",\n            \"chaos.social\",\n            \"chapm25.com\",\n            \"character.ai\",\n            \"chatgpt.com\",\n            \"chatnook.com\",\n            \"chaturbate.com\",\n            \"checkgfw.com\",\n            \"chengmingmag.com\",\n            \"chenguangcheng.com\",\n            \"chenpokong.com\",\n            \"chenpokong.net\",\n            \"chenpokongvip.com\",\n            \"cherrysave.com\",\n            \"chhongbi.org\",\n            \"chicagoncmtv.com\",\n            \"china-mmm.jp.net\",\n            \"china-mmm.net\",\n            \"china-review.com.ua\",\n            \"china-week.com\",\n            \"china101.com\",\n            \"china18.org\",\n            \"china21.com\",\n            \"china21.org\",\n            \"china5000.us\",\n            \"chinaaffairs.org\",\n            \"chinaaid.me\",\n            \"chinaaid.net\",\n            \"chinaaid.org\",\n            \"chinaaid.us\",\n            \"chinachange.org\",\n            \"chinachannel.hk\",\n            \"chinacitynews.be\",\n            \"chinacomments.org\",\n            \"chinademocrats.org\",\n            \"chinadialogue.net\",\n            \"chinadigitaltimes.net\",\n            \"chinaelections.org\",\n            \"chinaeweekly.com\",\n            \"chinafile.com\",\n            \"chinafreepress.org\",\n            \"chinagate.com\",\n            \"chinageeks.org\",\n            \"chinagfw.org\",\n            \"chinagonet.com\",\n            \"chinagreenparty.org\",\n            \"chinahorizon.org\",\n            \"chinahrc.org\",\n            \"chinahush.com\",\n            \"chinainperspective.com\",\n            \"chinainterimgov.org\",\n            \"chinalaborwatch.org\",\n            \"chinalawandpolicy.com\",\n            \"chinalawtranslate.com\",\n            \"chinamule.com\",\n            \"chinamz.org\",\n            \"chinanewscenter.com\",\n            \"chinapost.com.tw\",\n            \"chinapress.com.my\",\n            \"chinarightsia.org\",\n            \"chinasmile.net\",\n            \"chinasocialdemocraticparty.com\",\n            \"chinasoul.org\",\n            \"chinasucks.net\",\n            \"chinatopsex.com\",\n            \"chinatown.com.au\",\n            \"chinatweeps.com\",\n            \"chinauncensored.tv\",\n            \"chinaway.org\",\n            \"chinaworker.info\",\n            \"chinaxchina.com\",\n            \"chinayouth.org.hk\",\n            \"chinayuanmin.org\",\n            \"chinese-hermit.net\",\n            \"chinese-leaders.org\",\n            \"chinese-memorial.org\",\n            \"chinesedaily.com\",\n            \"chinesedailynews.com\",\n            \"chinesedemocracy.com\",\n            \"chinesegay.org\",\n            \"chinesen.de\",\n            \"chinesenews.net.au\",\n            \"chinesepen.org\",\n            \"chineseradioseattle.com\",\n            \"chinesetalks.net\",\n            \"chineseupress.com\",\n            \"chingcheong.com\",\n            \"chinman.net\",\n            \"chithu.org\",\n            \"chobit.cc\",\n            \"chosun.com\",\n            \"chped.com\",\n            \"chrdnet.com\",\n            \"christianfreedom.org\",\n            \"christianstudy.com\",\n            \"christiantimes.org.hk\",\n            \"christusrex.org\",\n            \"chrlawyers.hk\",\n            \"chrome.com\",\n            \"chromecast.com\",\n            \"chromeexperiments.com\",\n            \"chromercise.com\",\n            \"chromestatus.com\",\n            \"chromium.org\",\n            \"cht.com.tw\",\n            \"chuang-yen.org\",\n            \"chubold.com\",\n            \"chubun.com\",\n            \"chuizi.net\",\n            \"churchinhongkong.org\",\n            \"chushigangdrug.ch\",\n            \"ci-en.jp\",\n            \"cia.gov\",\n            \"cici.com\",\n            \"ciciai.com\",\n            \"ciciaicdn.com\",\n            \"cienen.com\",\n            \"cineastentreff.de\",\n            \"cipfg.org\",\n            \"circlethebayfortibet.org\",\n            \"cirosantilli.com\",\n            \"citizencn.com\",\n            \"citizenlab.ca\",\n            \"citizenlab.org\",\n            \"citizenpowerforchina.org\",\n            \"citizenscommission.hk\",\n            \"citizensradio.org\",\n            \"city365.ca\",\n            \"city9x.com\",\n            \"citypopulation.de\",\n            \"citytalk.tw\",\n            \"civicparty.hk\",\n            \"civildisobediencemovement.org\",\n            \"civilhrfront.org\",\n            \"civiliangunner.com\",\n            \"civilmedia.tw\",\n            \"civitai.com\",\n            \"cixiaoya.club\",\n            \"cjb.net\",\n            \"ck101.com\",\n            \"clarionproject.org\",\n            \"classicalguitarblog.net\",\n            \"claude.ai\",\n            \"clb.org.hk\",\n            \"cleansite.biz\",\n            \"cleansite.info\",\n            \"cleansite.us\",\n            \"clearharmony.net\",\n            \"clearsurance.com\",\n            \"clearwisdom.net\",\n            \"clementine-player.org\",\n            \"clickme.net\",\n            \"clinica-tibet.ru\",\n            \"clipconverter.cc\",\n            \"clipfish.de\",\n            \"clips4sale.com\",\n            \"cloakpoint.com\",\n            \"cloudcone.com\",\n            \"cloudflare-dns.com\",\n            \"cloudflare-ipfs.com\",\n            \"cloudfunctions.net\",\n            \"cloudokyo.cloud\",\n            \"club1069.com\",\n            \"clubhouseapi.com\",\n            \"clyp.it\",\n            \"cmcn.org\",\n            \"cmegroup.com\",\n            \"cmi.org.tw\",\n            \"cmoinc.org\",\n            \"cms.gov\",\n            \"cmu.edu\",\n            \"cmule.com\",\n            \"cmule.org\",\n            \"cmx.im\",\n            \"cn-proxy.com\",\n            \"cn6.eu\",\n            \"cna.com.tw\",\n            \"cnabc.com\",\n            \"cnbeta.com.tw\",\n            \"cnd.org\",\n            \"cnet.com\",\n            \"cnex.org.cn\",\n            \"cnineu.com\",\n            \"cnitter.com\",\n            \"cnn.com\",\n            \"cnpolitics.org\",\n            \"cnproxy.com\",\n            \"cnyes.com\",\n            \"coat.co.jp\",\n            \"cobinhood.com\",\n            \"cochina.co\",\n            \"cochina.org\",\n            \"code1984.com\",\n            \"codeshare.io\",\n            \"codeskulptor.org\",\n            \"cofacts.tw\",\n            \"coffeemanga.to\",\n            \"coinbase.com\",\n            \"coinbene.com\",\n            \"coinegg.com\",\n            \"coinex.com\",\n            \"coingecko.com\",\n            \"coingi.com\",\n            \"coinmarketcap.com\",\n            \"coinrail.co.kr\",\n            \"cointiger.com\",\n            \"cointobe.com\",\n            \"coinut.com\",\n            \"colacloud.net\",\n            \"collateralmurder.com\",\n            \"collateralmurder.org\",\n            \"com.uk\",\n            \"comedycentral.com\",\n            \"comefromchina.com\",\n            \"comic-mega.me\",\n            \"commandarms.com\",\n            \"comments.app\",\n            \"commentshk.com\",\n            \"communistcrimes.org\",\n            \"communitychoicecu.com\",\n            \"comparitech.com\",\n            \"compileheart.com\",\n            \"compress.to\",\n            \"compython.net\",\n            \"congyu.moe\",\n            \"conoha.jp\",\n            \"constitutionalism.solutions\",\n            \"contactmagazine.net\",\n            \"convio.net\",\n            \"coobay.com\",\n            \"cool18.com\",\n            \"coolaler.com\",\n            \"coolder.com\",\n            \"coolloud.org.tw\",\n            \"coolncute.com\",\n            \"coolstuffinc.com\",\n            \"corumcollege.com\",\n            \"cos-moe.com\",\n            \"cosplayjav.pl\",\n            \"costco.com\",\n            \"cotweet.com\",\n            \"counter.social\",\n            \"coursehero.com\",\n            \"covenantswatch.org.tw\",\n            \"coze.com\",\n            \"cpj.org\",\n            \"cpu-monkey.com\",\n            \"cq99.us\",\n            \"crackle.com\",\n            \"crashlytics.com\",\n            \"crazypool.org\",\n            \"crazys.cc\",\n            \"crazyshit.com\",\n            \"crbug.com\",\n            \"crchina.org\",\n            \"crd-net.org\",\n            \"creaders.net\",\n            \"creadersnet.com\",\n            \"creativelab5.com\",\n            \"cristyli.com\",\n            \"crocotube.com\",\n            \"crossfire.co.kr\",\n            \"crossthewall.net\",\n            \"crossvpn.net\",\n            \"crosswall.org\",\n            \"croxyproxy.com\",\n            \"crrev.com\",\n            \"crucial.com\",\n            \"crunchyroll.com\",\n            \"cruxpool.com\",\n            \"crwdcntrl.net\",\n            \"crypto.com\",\n            \"cryptographyengineering.com\",\n            \"csdparty.com\",\n            \"csis.org\",\n            \"csmonitor.com\",\n            \"csuchen.de\",\n            \"csw.org.uk\",\n            \"ct.org.tw\",\n            \"ctao.org\",\n            \"ctfriend.net\",\n            \"ctinews.com\",\n            \"ctitv.com.tw\",\n            \"ctowc.org\",\n            \"cts.com.tw\",\n            \"ctwant.com\",\n            \"cuhk.edu.hk\",\n            \"cuhkacs.org\",\n            \"cuihua.org\",\n            \"cuiweiping.net\",\n            \"culture.tw\",\n            \"cumlouder.com\",\n            \"cuntcrack.com\",\n            \"curvefish.com\",\n            \"cusp.hk\",\n            \"cusu.hk\",\n            \"cutout.pro\",\n            \"cutscenes.net\",\n            \"cw.com.tw\",\n            \"cwb.gov.tw\",\n            \"cyberctm.com\",\n            \"cyberghostvpn.com\",\n            \"cynscribe.com\",\n            \"cytode.us\",\n            \"cz.cc\",\n            \"d-fukyu.com\",\n            \"d.cash\",\n            \"d100.net\",\n            \"d2bay.com\",\n            \"d2pass.com\",\n            \"dabr.co.uk\",\n            \"dabr.eu\",\n            \"dabr.me\",\n            \"dabr.mobi\",\n            \"dadazim.com\",\n            \"dadi360.com\",\n            \"dafabet.com\",\n            \"dafagood.com\",\n            \"dafahao.com\",\n            \"dafoh.org\",\n            \"daftporn.com\",\n            \"dagelijksestandaard.nl\",\n            \"daidostup.ru\",\n            \"dailidaili.com\",\n            \"dailymail.co.uk\",\n            \"dailymotion.com\",\n            \"dailysabah.com\",\n            \"dailyview.tw\",\n            \"daiphapinfo.net\",\n            \"dajiyuan.com\",\n            \"dajiyuan.de\",\n            \"dajiyuan.eu\",\n            \"dalailama-archives.org\",\n            \"dalailama.com\",\n            \"dalailama.mn\",\n            \"dalailama.ru\",\n            \"dalailama80.org\",\n            \"dalailamacenter.org\",\n            \"dalailamafellows.org\",\n            \"dalailamafilm.com\",\n            \"dalailamafoundation.org\",\n            \"dalailamahindi.com\",\n            \"dalailamainaustralia.org\",\n            \"dalailamajapanese.com\",\n            \"dalailamaprotesters.info\",\n            \"dalailamaquotes.org\",\n            \"dalailamatrust.org\",\n            \"dalailamavisit.org.nz\",\n            \"dalailamaworld.com\",\n            \"dalianmeng.org\",\n            \"daliulian.org\",\n            \"danke4china.net\",\n            \"danwei.org\",\n            \"daolan.net\",\n            \"daozhongxing.org\",\n            \"darktech.org\",\n            \"darktoy.net\",\n            \"darpa.mil\",\n            \"darrenliuwei.com\",\n            \"dashlane.com\",\n            \"dastrassi.org\",\n            \"data-vocabulary.org\",\n            \"data.gov.tw\",\n            \"datalabour.com\",\n            \"daum.net\",\n            \"david-kilgour.com\",\n            \"dawangidc.com\",\n            \"daxa.cn\",\n            \"daylife.com\",\n            \"db.tt\",\n            \"dbgjd.com\",\n            \"dcard.tw\",\n            \"dcmilitary.com\",\n            \"ddc.com.tw\",\n            \"ddex.io\",\n            \"ddhw.info\",\n            \"ddns.info\",\n            \"ddns.me.uk\",\n            \"ddns.mobi\",\n            \"ddns.ms\",\n            \"ddns.name\",\n            \"ddns.net\",\n            \"ddns.us\",\n            \"de-sci.org\",\n            \"deadhouse.org\",\n            \"deadline.com\",\n            \"deaftone.com\",\n            \"debug.com\",\n            \"deck.ly\",\n            \"deck.new\",\n            \"decodet.co\",\n            \"deepai.org\",\n            \"deepdiscount.com\",\n            \"deepmind.com\",\n            \"deezer.com\",\n            \"definebabe.com\",\n            \"deja.com\",\n            \"delcamp.net\",\n            \"delicious.com\",\n            \"democrats.org\",\n            \"demosisto.hk\",\n            \"deno.com\",\n            \"deno.dev\",\n            \"depositphotos.com\",\n            \"derekhsu.homeip.net\",\n            \"desc.se\",\n            \"desipro.de\",\n            \"dessci.com\",\n            \"destroy-china.jp\",\n            \"detroitnews.com\",\n            \"deutsche-welle.de\",\n            \"deviantart.com\",\n            \"deviantart.net\",\n            \"devio.us\",\n            \"devpn.com\",\n            \"devv.ai\",\n            \"dfas.mil\",\n            \"dfn.org\",\n            \"dharamsalanet.com\",\n            \"dharmakara.net\",\n            \"dhcp.biz\",\n            \"diaoyuislands.org\",\n            \"difangwenge.org\",\n            \"dify.ai\",\n            \"digg.com\",\n            \"digiland.tw\",\n            \"digisfera.com\",\n            \"digitalnomadsproject.org\",\n            \"diigo.com\",\n            \"dilber.se\",\n            \"dipity.com\",\n            \"directcreative.com\",\n            \"discoins.com\",\n            \"disconnect.me\",\n            \"discord.com\",\n            \"discord.gg\",\n            \"discord.media\",\n            \"discordapp.com\",\n            \"discordapp.net\",\n            \"discuss.com.hk\",\n            \"discuss4u.com\",\n            \"dish.com\",\n            \"disk.yandex\",\n            \"disney-plus.net\",\n            \"disneyplus.com\",\n            \"disp.cc\",\n            \"disqus.com\",\n            \"dit-inc.us\",\n            \"diyin.org\",\n            \"dizhidizhi.com\",\n            \"dizhuzhishang.com\",\n            \"djangosnippets.org\",\n            \"djorz.com\",\n            \"dl-laby.jp\",\n            \"dlive.tv\",\n            \"dlsite.com\",\n            \"dlsite.jp\",\n            \"dlyoutube.com\",\n            \"dm530.net\",\n            \"dma.mil\",\n            \"dmarcnetworks.com\",\n            \"dmc.nico\",\n            \"dmcdn.net\",\n            \"dmhy.org\",\n            \"dmm.co.jp\",\n            \"dmm.com\",\n            \"dns-dns.com\",\n            \"dns-stuff.com\",\n            \"dns04.com\",\n            \"dns05.com\",\n            \"dns1.us\",\n            \"dns2.us\",\n            \"dns2go.com\",\n            \"dnscrypt.org\",\n            \"dnset.com\",\n            \"dnsrd.com\",\n            \"dnssec.net\",\n            \"dnvod.tv\",\n            \"doc.new\",\n            \"docker.com\",\n            \"docker.io\",\n            \"docs.new\",\n            \"doctorvoice.org\",\n            \"documentingreality.com\",\n            \"dogfartnetwork.com\",\n            \"dojin.com\",\n            \"dok-forum.net\",\n            \"dolc.de\",\n            \"dolf.org.hk\",\n            \"domain.club.tw\",\n            \"domain.glass\",\n            \"domaintoday.com.au\",\n            \"donga.com\",\n            \"dongtaiwang.com\",\n            \"dongtaiwang.net\",\n            \"dongyangjing.com\",\n            \"donmai.us\",\n            \"dontfilter.us\",\n            \"dontmovetochina.com\",\n            \"doom9.org\",\n            \"doosho.com\",\n            \"doourbest.org\",\n            \"dorjeshugden.com\",\n            \"dotplane.com\",\n            \"dotsub.com\",\n            \"dotvpn.com\",\n            \"doub.io\",\n            \"doubibackup.com\",\n            \"doubiyunbackup.com\",\n            \"doublethinklab.org\",\n            \"douchi.space\",\n            \"dougscripts.com\",\n            \"doujincafe.com\",\n            \"dowei.org\",\n            \"dowjones.com\",\n            \"dphk.org\",\n            \"dpool.top\",\n            \"dpp.org.tw\",\n            \"dpr.info\",\n            \"dragonex.io\",\n            \"dragonsprings.org\",\n            \"dreamamateurs.com\",\n            \"drepung.org\",\n            \"drgan.net\",\n            \"drmingxia.org\",\n            \"dropbooks.tv\",\n            \"dropbox.com\",\n            \"dropboxapi.com\",\n            \"dropboxusercontent.com\",\n            \"drsunacademy.com\",\n            \"drtuber.com\",\n            \"dscn.info\",\n            \"dsmtp.com\",\n            \"dssott.com\",\n            \"dstk.dk\",\n            \"dtiblog.com\",\n            \"dtic.mil\",\n            \"dtwang.org\",\n            \"duanzhihu.com\",\n            \"dubox.com\",\n            \"duck.com\",\n            \"duckduckgo.com\",\n            \"duckload.com\",\n            \"duckmylife.com\",\n            \"duga.jp\",\n            \"duihua.org\",\n            \"duihuahrjournal.org\",\n            \"dumb1.com\",\n            \"dunyabulteni.net\",\n            \"duoweitimes.com\",\n            \"duping.net\",\n            \"duplicati.com\",\n            \"dupola.com\",\n            \"dupola.net\",\n            \"dushi.ca\",\n            \"duyaoss.com\",\n            \"dvdpac.com\",\n            \"dvorak.org\",\n            \"dw-world.com\",\n            \"dw-world.de\",\n            \"dw.com\",\n            \"dw.de\",\n            \"dweb.link\",\n            \"dwheeler.com\",\n            \"dwnews.com\",\n            \"dwnews.net\",\n            \"dxiong.com\",\n            \"dynamic-dns.net\",\n            \"dynamicdns.biz\",\n            \"dynamicdns.co.uk\",\n            \"dynamicdns.me.uk\",\n            \"dynamicdns.org.uk\",\n            \"dynawebinc.com\",\n            \"dyndns-ip.com\",\n            \"dyndns-pics.com\",\n            \"dyndns.org\",\n            \"dyndns.pro\",\n            \"dynssl.com\",\n            \"dynu.com\",\n            \"dynu.net\",\n            \"dysfz.cc\",\n            \"dzze.com\",\n            \"e-classical.com.tw\",\n            \"e-gold.com\",\n            \"e-hentai.org\",\n            \"e-hentaidb.com\",\n            \"e-info.org.tw\",\n            \"e-traderland.net\",\n            \"e-zone.com.hk\",\n            \"e123.hk\",\n            \"e621.net\",\n            \"earlytibet.com\",\n            \"earthcam.com\",\n            \"earthvpn.com\",\n            \"eastasiaforum.org\",\n            \"eastern-ark.com\",\n            \"easternlightning.org\",\n            \"eastturkestan.com\",\n            \"eastturkistan-gov.org\",\n            \"eastturkistan.net\",\n            \"eastturkistancc.org\",\n            \"eastturkistangovernmentinexile.us\",\n            \"easyca.ca\",\n            \"easypic.com\",\n            \"ebc.net.tw\",\n            \"ebony-beauty.com\",\n            \"ebookbrowse.com\",\n            \"ebookee.com\",\n            \"ebtcbank.com\",\n            \"ecfa.org.tw\",\n            \"echofon.com\",\n            \"ecimg.tw\",\n            \"eckosia.org\",\n            \"ecministry.net\",\n            \"economist.com\",\n            \"ecstart.com\",\n            \"edgecastcdn.net\",\n            \"edgesuite.net\",\n            \"edicypages.com\",\n            \"edmontonchina.cn\",\n            \"edmontonservice.com\",\n            \"edns.biz\",\n            \"edoors.com\",\n            \"edrdg.org\",\n            \"edubridge.com\",\n            \"edupro.org\",\n            \"edx-cdn.org\",\n            \"eesti.ee\",\n            \"eevpn.com\",\n            \"efcc.org.hk\",\n            \"effers.com\",\n            \"efksoft.com\",\n            \"efreenews.com\",\n            \"efukt.com\",\n            \"eic-av.com\",\n            \"eireinikotaerukai.com\",\n            \"eisbb.com\",\n            \"eksisozluk.com\",\n            \"elconfidencial.com\",\n            \"electionsmeter.com\",\n            \"elgoog.im\",\n            \"ellawine.org\",\n            \"elpais.com\",\n            \"eltondisney.com\",\n            \"emaga.com\",\n            \"emanna.com\",\n            \"embr.in\",\n            \"emilylau.org.hk\",\n            \"emory.edu\",\n            \"empfil.com\",\n            \"emule-ed2k.com\",\n            \"emulefans.com\",\n            \"emuparadise.me\",\n            \"enanyang.my\",\n            \"enca.com\",\n            \"encrypt.me\",\n            \"encyclopedia.com\",\n            \"enewstree.com\",\n            \"enfal.de\",\n            \"engadget.com\",\n            \"engagedaily.org\",\n            \"englishforeveryone.org\",\n            \"englishfromengland.co.uk\",\n            \"englishpen.org\",\n            \"enlighten.org.tw\",\n            \"entermap.com\",\n            \"entnt.com\",\n            \"epac.to\",\n            \"episcopalchurch.org\",\n            \"epochhk.com\",\n            \"epochtimes-bg.com\",\n            \"epochtimes-romania.com\",\n            \"epochtimes.co.il\",\n            \"epochtimes.co.kr\",\n            \"epochtimes.com\",\n            \"epochtimes.com.tw\",\n            \"epochtimes.cz\",\n            \"epochtimes.de\",\n            \"epochtimes.fr\",\n            \"epochtimes.ie\",\n            \"epochtimes.it\",\n            \"epochtimes.jp\",\n            \"epochtimes.ru\",\n            \"epochtimes.se\",\n            \"epochtimestr.com\",\n            \"epochweek.com\",\n            \"epochweekly.com\",\n            \"eporner.com\",\n            \"eprice.com.hk\",\n            \"equinenow.com\",\n            \"erabaru.net\",\n            \"eracom.com.tw\",\n            \"eraysoft.com.tr\",\n            \"erepublik.com\",\n            \"erights.net\",\n            \"eriversoft.com\",\n            \"erktv.com\",\n            \"ernestmandel.org\",\n            \"erodaizensyu.com\",\n            \"erodoujinlog.com\",\n            \"erodoujinworld.com\",\n            \"eromanga-kingdom.com\",\n            \"eromangadouzin.com\",\n            \"eromon.net\",\n            \"eroprofile.com\",\n            \"eroticsaloon.net\",\n            \"eslite.com\",\n            \"esmtp.biz\",\n            \"esu.im\",\n            \"esurance.com\",\n            \"etaa.org.au\",\n            \"etadult.com\",\n            \"etaiwannews.com\",\n            \"etherdelta.com\",\n            \"ethermine.org\",\n            \"etherscan.com\",\n            \"etherscan.io\",\n            \"etizer.org\",\n            \"etokki.com\",\n            \"etowns.net\",\n            \"etowns.org\",\n            \"etsy.com\",\n            \"ettoday.net\",\n            \"etvonline.hk\",\n            \"eu.org\",\n            \"eucasino.com\",\n            \"eulam.com\",\n            \"eurekavpt.com\",\n            \"eurodasp.com\",\n            \"euronews.com\",\n            \"europa.eu\",\n            \"everipedia.org\",\n            \"evozi.com\",\n            \"evschool.net\",\n            \"exam.gov.tw\",\n            \"exblog.jp\",\n            \"exchristian.hk\",\n            \"excite.co.jp\",\n            \"exhentai.org\",\n            \"exmo.com\",\n            \"exmormon.org\",\n            \"expatshield.com\",\n            \"expecthim.com\",\n            \"expekt.com\",\n            \"experts-univers.com\",\n            \"exploader.net\",\n            \"expofutures.com\",\n            \"expressvpn.com\",\n            \"exrates.me\",\n            \"extmatrix.com\",\n            \"extrabux.com\",\n            \"extremetube.com\",\n            \"ey.gov.tw\",\n            \"eyevio.jp\",\n            \"eyny.com\",\n            \"ezpc.tk\",\n            \"ezpeer.com\",\n            \"ezua.com\",\n            \"f-droid.org\",\n            \"f2pool.com\",\n            \"f8.com\",\n            \"fa.gov.tw\",\n            \"facebook.br\",\n            \"facebook.com\",\n            \"facebook.de\",\n            \"facebook.design\",\n            \"facebook.hu\",\n            \"facebook.in\",\n            \"facebook.net\",\n            \"facebook.nl\",\n            \"facebook.se\",\n            \"facebookmail.com\",\n            \"facebookquotes4u.com\",\n            \"faceless.me\",\n            \"facesofnyfw.com\",\n            \"facesoftibetanselfimmolators.info\",\n            \"factchecklab.org\",\n            \"factpedia.org\",\n            \"fail.hk\",\n            \"faith100.org\",\n            \"faithfuleye.com\",\n            \"faiththedog.info\",\n            \"fakku.net\",\n            \"fallenark.com\",\n            \"falsefire.com\",\n            \"falun-co.org\",\n            \"falun-ny.net\",\n            \"falunart.org\",\n            \"falunasia.info\",\n            \"falunau.org\",\n            \"falunaz.net\",\n            \"falundafa-dc.org\",\n            \"falundafa-florida.org\",\n            \"falundafa-nc.org\",\n            \"falundafa-pa.net\",\n            \"falundafa-sacramento.org\",\n            \"falundafa.org\",\n            \"falundafaindia.org\",\n            \"falundafamuseum.org\",\n            \"falungong.club\",\n            \"falungong.de\",\n            \"falungong.org.uk\",\n            \"falunhr.org\",\n            \"faluninfo.de\",\n            \"faluninfo.net\",\n            \"falunpilipinas.net\",\n            \"falunworld.net\",\n            \"familyfed.org\",\n            \"famunion.com\",\n            \"fan-qiang.com\",\n            \"fanbox.cc\",\n            \"fandom.com\",\n            \"fangbinxing.com\",\n            \"fangeming.com\",\n            \"fangeqiang.com\",\n            \"fanglizhi.info\",\n            \"fangmincn.org\",\n            \"fangong.org\",\n            \"fangongheike.com\",\n            \"fanhaodang.com\",\n            \"fanhaolou.com\",\n            \"fanqiang.network\",\n            \"fanqiang.tk\",\n            \"fanqiangdang.com\",\n            \"fanqiangdang.org\",\n            \"fanqianghou.com\",\n            \"fanqiangyakexi.net\",\n            \"fanqiangzhe.com\",\n            \"fanswong.com\",\n            \"fantv.hk\",\n            \"fanyue.info\",\n            \"fapdu.com\",\n            \"faproxy.com\",\n            \"faqserv.com\",\n            \"fartit.com\",\n            \"farwestchina.com\",\n            \"fast.com\",\n            \"fastestvpn.com\",\n            \"fastly.net\",\n            \"fastpic.ru\",\n            \"fastssh.com\",\n            \"faststone.org\",\n            \"fatakat-n.club\",\n            \"fatbtc.com\",\n            \"favotter.net\",\n            \"favstar.fm\",\n            \"fawanghuihui.org\",\n            \"faydao.com\",\n            \"faz.net\",\n            \"fb.com\",\n            \"fb.me\",\n            \"fb.watch\",\n            \"fbaddins.com\",\n            \"fbcdn.net\",\n            \"fbsbx.com\",\n            \"fbworkmail.com\",\n            \"fc2.com\",\n            \"fc2blog.net\",\n            \"fc2china.com\",\n            \"fc2cn.com\",\n            \"fc2web.com\",\n            \"fda.gov.tw\",\n            \"fdc64.de\",\n            \"fdc64.jp\",\n            \"fdc64.org\",\n            \"fdc89.jp\",\n            \"feedburner.com\",\n            \"feeder.co\",\n            \"feedly.com\",\n            \"feedx.net\",\n            \"feelssh.com\",\n            \"feer.com\",\n            \"feifeiss.com\",\n            \"feitian-california.org\",\n            \"feitianacademy.org\",\n            \"feixiaohao.com\",\n            \"feministteacher.com\",\n            \"fengzhenghu.com\",\n            \"fengzhenghu.net\",\n            \"fevernet.com\",\n            \"ff.im\",\n            \"fffff.at\",\n            \"fflick.com\",\n            \"ffvpn.com\",\n            \"fgmtv.net\",\n            \"fgmtv.org\",\n            \"fhreports.net\",\n            \"figprayer.com\",\n            \"fileflyer.com\",\n            \"fileforum.com\",\n            \"files2me.com\",\n            \"fileserve.com\",\n            \"filesor.com\",\n            \"fillthesquare.org\",\n            \"filmingfortibet.org\",\n            \"filthdump.com\",\n            \"financetwitter.com\",\n            \"financialexpress.com\",\n            \"finchvpn.com\",\n            \"findbook.tw\",\n            \"findmespot.com\",\n            \"findyoutube.com\",\n            \"findyoutube.net\",\n            \"fingerdaily.com\",\n            \"finler.net\",\n            \"firearmsworld.net\",\n            \"firebaseio.com\",\n            \"firefox.com\",\n            \"fireofliberty.info\",\n            \"fireofliberty.org\",\n            \"firetweet.io\",\n            \"firstfivefollowers.com\",\n            \"firstory.me\",\n            \"firstpost.com\",\n            \"firstrade.com\",\n            \"fish.audio\",\n            \"fizzik.com\",\n            \"flagsonline.it\",\n            \"flecheinthepeche.fr\",\n            \"fleshbot.com\",\n            \"fleursdeslettres.com\",\n            \"flexpool.io\",\n            \"flgg.us\",\n            \"flgjustice.org\",\n            \"flickr.com\",\n            \"flickrhivemind.net\",\n            \"flickriver.com\",\n            \"fling.com\",\n            \"flipboard.com\",\n            \"flipkart.com\",\n            \"flitto.com\",\n            \"flnet.org\",\n            \"flog.tw\",\n            \"flowhongkong.net\",\n            \"flurry.com\",\n            \"flypool.org\",\n            \"flyvpn.com\",\n            \"flyzy2005.com\",\n            \"fmnnow.com\",\n            \"fnac.be\",\n            \"fnac.com\",\n            \"fochk.org\",\n            \"focustaiwan.tw\",\n            \"focusvpn.com\",\n            \"fofg-europe.net\",\n            \"fofg.org\",\n            \"fofldfradio.org\",\n            \"foolsmountain.com\",\n            \"fooooo.com\",\n            \"footprint.net\",\n            \"footwiball.com\",\n            \"forbes.com\",\n            \"foreignaffairs.com\",\n            \"foreignpolicy.com\",\n            \"form.new\",\n            \"forms.new\",\n            \"forum4hk.com\",\n            \"forums-free.com\",\n            \"fotile.me\",\n            \"fountmedia.io\",\n            \"fourthinternational.org\",\n            \"foxbusiness.com\",\n            \"foxgay.com\",\n            \"foxsub.com\",\n            \"foxtang.com\",\n            \"fpmt-osel.org\",\n            \"fpmt.org\",\n            \"fpmt.tw\",\n            \"fpmtmexico.org\",\n            \"fqok.org\",\n            \"fqrouter.com\",\n            \"frank2019.me\",\n            \"franklc.com\",\n            \"freakshare.com\",\n            \"free-gate.org\",\n            \"free-hada-now.org\",\n            \"free-proxy.cz\",\n            \"free-ss.site\",\n            \"free-ssh.com\",\n            \"free.bg\",\n            \"free.com.tw\",\n            \"free.fr\",\n            \"free4u.com.ar\",\n            \"freealim.com\",\n            \"freebeacon.com\",\n            \"freebearblog.org\",\n            \"freebrowser.org\",\n            \"freechal.com\",\n            \"freechina.net\",\n            \"freechina.news\",\n            \"freechinaforum.org\",\n            \"freechinaweibo.com\",\n            \"freeddns.com\",\n            \"freeddns.org\",\n            \"freedl.org\",\n            \"freedomchina.info\",\n            \"freedomcollection.org\",\n            \"freedomhongkong.org\",\n            \"freedomhouse.org\",\n            \"freedomsherald.org\",\n            \"freeforums.org\",\n            \"freefq.com\",\n            \"freefuckvids.com\",\n            \"freegao.com\",\n            \"freehongkong.org\",\n            \"freeilhamtohti.org\",\n            \"freekazakhs.org\",\n            \"freekwonpyong.org\",\n            \"freelotto.com\",\n            \"freeman2.com\",\n            \"freemoren.com\",\n            \"freemorenews.com\",\n            \"freemuse.org\",\n            \"freenet-china.org\",\n            \"freenetproject.org\",\n            \"freenewscn.com\",\n            \"freeones.com\",\n            \"freeopenvpn.com\",\n            \"freeoz.org\",\n            \"freeproxylists.net\",\n            \"freerk.com\",\n            \"freess.org\",\n            \"freessh.us\",\n            \"freetcp.com\",\n            \"freetibet.net\",\n            \"freetibet.org\",\n            \"freetibetanheroes.org\",\n            \"freetls.fastly.net\",\n            \"freetribe.me\",\n            \"freeviewmovies.com\",\n            \"freevpn.me\",\n            \"freevpn.nl\",\n            \"freewallpaper4.me\",\n            \"freewebs.com\",\n            \"freewechat.com\",\n            \"freeweibo.com\",\n            \"freewww.biz\",\n            \"freewww.info\",\n            \"freexinwen.com\",\n            \"freeyellow.com\",\n            \"freeyoutubeproxy.net\",\n            \"freezhihu.org\",\n            \"friday.tw\",\n            \"frienddy.com\",\n            \"friendfeed-media.com\",\n            \"friendfeed.com\",\n            \"friendfinder.com\",\n            \"friends-of-tibet.org\",\n            \"friendsoftibet.org\",\n            \"fril.jp\",\n            \"fring.com\",\n            \"fringenetwork.com\",\n            \"from-pr.com\",\n            \"from-sd.com\",\n            \"fromchinatousa.net\",\n            \"frommel.net\",\n            \"frontlinedefenders.org\",\n            \"frootvpn.com\",\n            \"froth.zone\",\n            \"fscked.org\",\n            \"fsurf.com\",\n            \"ft.com\",\n            \"ftchinese.com\",\n            \"ftp1.biz\",\n            \"ftpserver.biz\",\n            \"ftv.com.tw\",\n            \"ftvnews.com.tw\",\n            \"ftx.com\",\n            \"fucd.com\",\n            \"fuchsia.dev\",\n            \"fuckccp.com\",\n            \"fuckccp.xyz\",\n            \"fuckcnnic.net\",\n            \"fuckgfw.org\",\n            \"fuckgfw233.org\",\n            \"fulione.com\",\n            \"fullerconsideration.com\",\n            \"fullservicegame.com\",\n            \"fulue.com\",\n            \"funami.tech\",\n            \"funf.tw\",\n            \"funkyimg.com\",\n            \"funp.com\",\n            \"fuq.com\",\n            \"furbo.org\",\n            \"furhhdl.org\",\n            \"furinkan.com\",\n            \"furrybar.com\",\n            \"futurechinaforum.org\",\n            \"futuremessage.org\",\n            \"fux.com\",\n            \"fuyin.net\",\n            \"fuyindiantai.org\",\n            \"fuyu.org.tw\",\n            \"fw.cm\",\n            \"fxcm-chinese.com\",\n            \"fxnetworks.com\",\n            \"fzh999.com\",\n            \"fzh999.net\",\n            \"fzlm.com\",\n            \"g-area.org\",\n            \"g-desktop.ru\",\n            \"g-queen.com\",\n            \"g.co\",\n            \"g0v.social\",\n            \"g6hentai.com\",\n            \"gab.com\",\n            \"gabocorp.com\",\n            \"gaeproxy.com\",\n            \"gaforum.org\",\n            \"gagaoolala.com\",\n            \"galaxymacau.com\",\n            \"galenwu.com\",\n            \"gallup.com\",\n            \"galstars.net\",\n            \"game735.com\",\n            \"gamebase.com.tw\",\n            \"gamejolt.com\",\n            \"gamer.com.tw\",\n            \"gamerp.jp\",\n            \"gamez.com.tw\",\n            \"gamousa.com\",\n            \"ganges.com\",\n            \"ganjing.com\",\n            \"ganjing.world\",\n            \"ganjingworld.com\",\n            \"gaoming.net\",\n            \"gaopi.net\",\n            \"gaozhisheng.net\",\n            \"gaozhisheng.org\",\n            \"gardennetworks.com\",\n            \"gardennetworks.org\",\n            \"gartlive.com\",\n            \"garudalinux.org\",\n            \"gate-project.com\",\n            \"gate.io\",\n            \"gatecoin.com\",\n            \"gather.com\",\n            \"gatherproxy.com\",\n            \"gati.org.tw\",\n            \"gaybubble.com\",\n            \"gaycn.net\",\n            \"gayhub.com\",\n            \"gaymap.cc\",\n            \"gaymenring.com\",\n            \"gaytube.com\",\n            \"gaywatch.com\",\n            \"gazotube.com\",\n            \"gcc.org.hk\",\n            \"gclooney.com\",\n            \"gclubs.com\",\n            \"gcmasia.com\",\n            \"gcpnews.com\",\n            \"gcr.io\",\n            \"gdaily.org\",\n            \"gdbt.net\",\n            \"gdzf.org\",\n            \"geek-art.net\",\n            \"geekerhome.com\",\n            \"geekheart.info\",\n            \"gekikame.com\",\n            \"gelbooru.com\",\n            \"gemini.com\",\n            \"generated.photos\",\n            \"genius.com\",\n            \"geocities.co.jp\",\n            \"geocities.com\",\n            \"geocities.jp\",\n            \"geph.io\",\n            \"gerefoundation.org\",\n            \"get.app\",\n            \"get.dev\",\n            \"get.how\",\n            \"get.page\",\n            \"getastrill.com\",\n            \"getchu.com\",\n            \"getcloak.com\",\n            \"getfoxyproxy.org\",\n            \"getgom.com\",\n            \"geti2p.net\",\n            \"getiton.com\",\n            \"getjetso.com\",\n            \"getlantern.org\",\n            \"getmalus.com\",\n            \"getmdl.io\",\n            \"getoutline.org\",\n            \"getsession.org\",\n            \"getsocialscope.com\",\n            \"getsync.com\",\n            \"gettr.com\",\n            \"gettrials.com\",\n            \"gettyimages.hk\",\n            \"getuploader.com\",\n            \"gfbv.de\",\n            \"gfgold.com.hk\",\n            \"gfnormal05at.com\",\n            \"gfsale.com\",\n            \"gfw.org.ua\",\n            \"gfw.press\",\n            \"gfw.report\",\n            \"gfwatch.org\",\n            \"ggjav.com\",\n            \"ggpht.com\",\n            \"ggssl.com\",\n            \"ghanely.me\",\n            \"ghidra-sre.org\",\n            \"ghostpath.com\",\n            \"ghproxy.com\",\n            \"ghut.org\",\n            \"giantessnight.com\",\n            \"gifree.com\",\n            \"giga-web.jp\",\n            \"gigacircle.com\",\n            \"giganews.com\",\n            \"gigporno.ru\",\n            \"girlbanker.com\",\n            \"git.io\",\n            \"gitbook.io\",\n            \"gitbooks.io\",\n            \"githack.com\",\n            \"github.blog\",\n            \"github.com\",\n            \"github.io\",\n            \"githubassets.com\",\n            \"githubcopilot.com\",\n            \"githubusercontent.com\",\n            \"gitlab.com\",\n            \"gitlab.net\",\n            \"gizlen.net\",\n            \"gjczz.com\",\n            \"glarity.app\",\n            \"glass8.eu\",\n            \"global.ssl.fastly.net\",\n            \"globaljihad.net\",\n            \"globalmediaoutreach.com\",\n            \"globalmuseumoncommunism.org\",\n            \"globalrescue.net\",\n            \"globaltm.org\",\n            \"globalvoices.org\",\n            \"globalvoicesonline.org\",\n            \"globalvpn.net\",\n            \"glock.com\",\n            \"gloryhole.com\",\n            \"glorystar.me\",\n            \"gluckman.com\",\n            \"glype.com\",\n            \"gmail.com\",\n            \"gmgard.com\",\n            \"gmhz.org\",\n            \"gmiddle.com\",\n            \"gmiddle.net\",\n            \"gmll.org\",\n            \"gmodules.com\",\n            \"gmp4.com\",\n            \"gmx.net\",\n            \"gnci.org.hk\",\n            \"gnews.org\",\n            \"go-pki.com\",\n            \"go-to-zlibrary.se\",\n            \"go.com\",\n            \"go141.com\",\n            \"go5.dev\",\n            \"goagent.biz\",\n            \"goagentplus.com\",\n            \"goagle.de\",\n            \"gobet.cc\",\n            \"godaddy.com\",\n            \"godfootsteps.org\",\n            \"godns.work\",\n            \"godoc.org\",\n            \"godsdirectcontact.co.uk\",\n            \"godsdirectcontact.org\",\n            \"godsdirectcontact.org.tw\",\n            \"godsimmediatecontact.com\",\n            \"gofundme.com\",\n            \"gogle.de\",\n            \"gogole.com\",\n            \"gogotunnel.com\",\n            \"gohappy.com.tw\",\n            \"gokbayrak.com\",\n            \"golang.org\",\n            \"goldbet.com\",\n            \"goldbetsports.com\",\n            \"golden-ages.org\",\n            \"goldeneyevault.com\",\n            \"goldenfrog.com\",\n            \"goldjizz.com\",\n            \"goldstep.net\",\n            \"goldwave.com\",\n            \"gongm.in\",\n            \"gongmeng.info\",\n            \"gongminliliang.com\",\n            \"gongwt.com\",\n            \"goo.gl\",\n            \"goo.gle\",\n            \"goo.ne.jp\",\n            \"good.news\",\n            \"gooday.xyz\",\n            \"gooddns.info\",\n            \"goodhope.school\",\n            \"goodnewsnetwork.org\",\n            \"goodreaders.com\",\n            \"goodreads.com\",\n            \"goodtv.com.tw\",\n            \"goodtv.tv\",\n            \"goofind.com\",\n            \"googel.de\",\n            \"google-analytics.com\",\n            \"google-base.de\",\n            \"google.ad\",\n            \"google.ae\",\n            \"google.al\",\n            \"google.am\",\n            \"google.as\",\n            \"google.at\",\n            \"google.az\",\n            \"google.ba\",\n            \"google.be\",\n            \"google.bf\",\n            \"google.bg\",\n            \"google.bi\",\n            \"google.bj\",\n            \"google.bs\",\n            \"google.bt\",\n            \"google.by\",\n            \"google.ca\",\n            \"google.cat\",\n            \"google.cd\",\n            \"google.cf\",\n            \"google.cg\",\n            \"google.ch\",\n            \"google.ci\",\n            \"google.cl\",\n            \"google.cm\",\n            \"google.cn\",\n            \"google.co\",\n            \"google.co.ao\",\n            \"google.co.bw\",\n            \"google.co.ck\",\n            \"google.co.cr\",\n            \"google.co.id\",\n            \"google.co.il\",\n            \"google.co.in\",\n            \"google.co.jp\",\n            \"google.co.ke\",\n            \"google.co.kr\",\n            \"google.co.ls\",\n            \"google.co.ma\",\n            \"google.co.mz\",\n            \"google.co.nz\",\n            \"google.co.th\",\n            \"google.co.tz\",\n            \"google.co.ug\",\n            \"google.co.uk\",\n            \"google.co.uz\",\n            \"google.co.ve\",\n            \"google.co.vi\",\n            \"google.co.za\",\n            \"google.co.zm\",\n            \"google.co.zw\",\n            \"google.com\",\n            \"google.com.af\",\n            \"google.com.ag\",\n            \"google.com.ai\",\n            \"google.com.ar\",\n            \"google.com.au\",\n            \"google.com.bd\",\n            \"google.com.bh\",\n            \"google.com.bn\",\n            \"google.com.bo\",\n            \"google.com.br\",\n            \"google.com.bz\",\n            \"google.com.co\",\n            \"google.com.cu\",\n            \"google.com.cy\",\n            \"google.com.do\",\n            \"google.com.ec\",\n            \"google.com.eg\",\n            \"google.com.et\",\n            \"google.com.fj\",\n            \"google.com.gh\",\n            \"google.com.gi\",\n            \"google.com.gt\",\n            \"google.com.hk\",\n            \"google.com.jm\",\n            \"google.com.kh\",\n            \"google.com.kw\",\n            \"google.com.lb\",\n            \"google.com.ly\",\n            \"google.com.mm\",\n            \"google.com.mt\",\n            \"google.com.mx\",\n            \"google.com.my\",\n            \"google.com.na\",\n            \"google.com.nf\",\n            \"google.com.ng\",\n            \"google.com.ni\",\n            \"google.com.np\",\n            \"google.com.om\",\n            \"google.com.pa\",\n            \"google.com.pe\",\n            \"google.com.pg\",\n            \"google.com.ph\",\n            \"google.com.pk\",\n            \"google.com.pr\",\n            \"google.com.py\",\n            \"google.com.qa\",\n            \"google.com.sa\",\n            \"google.com.sb\",\n            \"google.com.sg\",\n            \"google.com.sl\",\n            \"google.com.sv\",\n            \"google.com.tj\",\n            \"google.com.tr\",\n            \"google.com.tw\",\n            \"google.com.ua\",\n            \"google.com.uy\",\n            \"google.com.vc\",\n            \"google.com.vn\",\n            \"google.cv\",\n            \"google.cz\",\n            \"google.de\",\n            \"google.dev\",\n            \"google.dj\",\n            \"google.dk\",\n            \"google.dm\",\n            \"google.dz\",\n            \"google.ee\",\n            \"google.es\",\n            \"google.fi\",\n            \"google.fm\",\n            \"google.fr\",\n            \"google.ga\",\n            \"google.ge\",\n            \"google.gg\",\n            \"google.gl\",\n            \"google.gm\",\n            \"google.gp\",\n            \"google.gr\",\n            \"google.gy\",\n            \"google.hn\",\n            \"google.hr\",\n            \"google.ht\",\n            \"google.hu\",\n            \"google.ie\",\n            \"google.im\",\n            \"google.iq\",\n            \"google.is\",\n            \"google.it\",\n            \"google.je\",\n            \"google.jo\",\n            \"google.kg\",\n            \"google.ki\",\n            \"google.kz\",\n            \"google.la\",\n            \"google.li\",\n            \"google.lk\",\n            \"google.lt\",\n            \"google.lu\",\n            \"google.lv\",\n            \"google.md\",\n            \"google.me\",\n            \"google.mg\",\n            \"google.mk\",\n            \"google.ml\",\n            \"google.mn\",\n            \"google.ms\",\n            \"google.mu\",\n            \"google.mv\",\n            \"google.mw\",\n            \"google.ne\",\n            \"google.nl\",\n            \"google.no\",\n            \"google.nr\",\n            \"google.nu\",\n            \"google.pl\",\n            \"google.pn\",\n            \"google.ps\",\n            \"google.pt\",\n            \"google.ro\",\n            \"google.rs\",\n            \"google.ru\",\n            \"google.rw\",\n            \"google.sc\",\n            \"google.se\",\n            \"google.sh\",\n            \"google.si\",\n            \"google.sk\",\n            \"google.sm\",\n            \"google.sn\",\n            \"google.so\",\n            \"google.sr\",\n            \"google.st\",\n            \"google.td\",\n            \"google.tg\",\n            \"google.tk\",\n            \"google.tl\",\n            \"google.tm\",\n            \"google.tn\",\n            \"google.to\",\n            \"google.tt\",\n            \"google.vg\",\n            \"google.vu\",\n            \"google.ws\",\n            \"googleanalytics.com\",\n            \"googleapis.com\",\n            \"googleapps.com\",\n            \"googlearth.com\",\n            \"googleartproject.com\",\n            \"googleblog.com\",\n            \"googlebot.com\",\n            \"googlechinawebmaster.com\",\n            \"googlecode.com\",\n            \"googlecommerce.com\",\n            \"googledomains.com\",\n            \"googledrive.com\",\n            \"googleearth.com\",\n            \"googlefiber.net\",\n            \"googlegroups.com\",\n            \"googlehosted.com\",\n            \"googleideas.com\",\n            \"googleinsidesearch.com\",\n            \"googlelocal.nl\",\n            \"googlemail.com\",\n            \"googlemaps.sv\",\n            \"googlemashups.com\",\n            \"googlepagecreator.com\",\n            \"googleplay.com\",\n            \"googleplus.com\",\n            \"googlescholar.com\",\n            \"googlesource.com\",\n            \"googlesyndication.com\",\n            \"googleusercontent.com\",\n            \"googlevideo.com\",\n            \"googleweblight.com\",\n            \"googlezip.net\",\n            \"gopetition.com\",\n            \"goproxing.net\",\n            \"goreforum.com\",\n            \"goregrish.com\",\n            \"gospelherald.com\",\n            \"got-game.org\",\n            \"gotdns.ch\",\n            \"gotgeeks.com\",\n            \"gotquestions.org\",\n            \"gotrusted.com\",\n            \"gotw.ca\",\n            \"gov.ir\",\n            \"gov.taipei\",\n            \"gov.tw\",\n            \"gr8domain.biz\",\n            \"gr8name.biz\",\n            \"gradconnection.com\",\n            \"grammaly.com\",\n            \"grandtrial.org\",\n            \"grangorz.org\",\n            \"graph.org\",\n            \"graphis.ne.jp\",\n            \"graphql.org\",\n            \"gravatar.com\",\n            \"greasespot.net\",\n            \"greasyfork.org\",\n            \"great-firewall.com\",\n            \"great-roc.org\",\n            \"greatfire.org\",\n            \"greatfirewall.biz\",\n            \"greatfirewallofchina.org\",\n            \"greatroc.org\",\n            \"greatroc.tw\",\n            \"greatzhonghua.org\",\n            \"greenfieldbookstore.com.hk\",\n            \"greenparty.org.tw\",\n            \"greenpeace.com.tw\",\n            \"greenpeace.org\",\n            \"greenreadings.com\",\n            \"greenvpn.net\",\n            \"greenvpn.org\",\n            \"grindr.com\",\n            \"grok.com\",\n            \"grotty-monday.com\",\n            \"ground.news\",\n            \"gs-discuss.com\",\n            \"gsearch.media\",\n            \"gstatic.com\",\n            \"gstf.org\",\n            \"gtricks.com\",\n            \"gts-vpn.com\",\n            \"gtv.org\",\n            \"gtv1.org\",\n            \"gu-chu-sum.org\",\n            \"guaguass.com\",\n            \"guaguass.org\",\n            \"guancha.org\",\n            \"guaneryu.com\",\n            \"guangming.com.my\",\n            \"guardster.com\",\n            \"guishan.org\",\n            \"gumroad.com\",\n            \"gun-world.net\",\n            \"gunsamerica.com\",\n            \"gunsandammo.com\",\n            \"guo.media\",\n            \"guruonline.hk\",\n            \"gutteruncensored.com\",\n            \"gvideo.de\",\n            \"gvlib.com\",\n            \"gvm.com.tw\",\n            \"gvt0.com\",\n            \"gvt1.com\",\n            \"gvt3.com\",\n            \"gwave.com\",\n            \"gwins.org\",\n            \"gwtproject.org\",\n            \"gyalwarinpoche.com\",\n            \"gyatsostudio.com\",\n            \"gzm.tv\",\n            \"gzone-anime.info\",\n            \"h-china.org\",\n            \"h-comic.com\",\n            \"h-moe.com\",\n            \"h1n1china.org\",\n            \"h528.com\",\n            \"h5dm.com\",\n            \"h5galgame.me\",\n            \"hacg.club\",\n            \"hacg.in\",\n            \"hacg.li\",\n            \"hacg.me\",\n            \"hacg.red\",\n            \"hacken.cc\",\n            \"hacker.org\",\n            \"hackmd.io\",\n            \"hackthatphone.net\",\n            \"hahlo.com\",\n            \"haijiao.com\",\n            \"haiwaikan.com\",\n            \"hakkatv.org.tw\",\n            \"halktv.com.tr\",\n            \"handcraftedsoftware.org\",\n            \"hanime.tv\",\n            \"hanime1.me\",\n            \"hanminzu.org\",\n            \"hanunyi.com\",\n            \"hao.news\",\n            \"hao123.com\",\n            \"hao123img.com\",\n            \"happy-vpn.com\",\n            \"haproxy.org\",\n            \"hardsextube.com\",\n            \"harunyahya.com\",\n            \"hasi.wang\",\n            \"hatena.ne.jp\",\n            \"hautelook.com\",\n            \"hautelookcdn.com\",\n            \"have8.com\",\n            \"hbg.com\",\n            \"hbo.com\",\n            \"hcaptcha.com\",\n            \"hclips.com\",\n            \"hdlt.me\",\n            \"hdsky.me\",\n            \"hdtvb.net\",\n            \"hdzog.com\",\n            \"he.net\",\n            \"heartyit.com\",\n            \"heavy-r.com\",\n            \"hec.su\",\n            \"hecaitou.net\",\n            \"hechaji.com\",\n            \"heeact.edu.tw\",\n            \"hegre-art.com\",\n            \"helixstudios.net\",\n            \"helloandroid.com\",\n            \"helloavgirls.com\",\n            \"helloqueer.com\",\n            \"helloss.pw\",\n            \"hellotxt.com\",\n            \"hellouk.org\",\n            \"helpeachpeople.com\",\n            \"helplinfen.com\",\n            \"helpster.de\",\n            \"helpzhuling.org\",\n            \"henduohao.com\",\n            \"hentai.to\",\n            \"hentaipaw.com\",\n            \"hentaitube.tv\",\n            \"hentaivideoworld.com\",\n            \"heqinglian.net\",\n            \"here.com\",\n            \"heritage.org\",\n            \"heroku.com\",\n            \"herokuapp.com\",\n            \"herominers.com\",\n            \"heungkongdiscuss.com\",\n            \"hexieshe.com\",\n            \"hexieshe.xyz\",\n            \"hexxeh.net\",\n            \"heyuedi.com\",\n            \"heyzo.com\",\n            \"hgamefree.info\",\n            \"hgseav.com\",\n            \"hhdcb3office.org\",\n            \"hhthesakyatrizin.org\",\n            \"hi-on.org.tw\",\n            \"hiccears.com\",\n            \"hidden-advent.org\",\n            \"hide.me\",\n            \"hidecloud.com\",\n            \"hidein.net\",\n            \"hideipvpn.com\",\n            \"hideman.net\",\n            \"hideme.nl\",\n            \"hidemy.name\",\n            \"hidemyass.com\",\n            \"hidemycomp.com\",\n            \"higfw.com\",\n            \"highpeakspureearth.com\",\n            \"highrockmedia.com\",\n            \"hightail.com\",\n            \"hihiforum.com\",\n            \"hihistory.net\",\n            \"hiitch.com\",\n            \"hikinggfw.org\",\n            \"hilive.tv\",\n            \"himalaya.exchange\",\n            \"himalayan-foundation.org\",\n            \"himalayanglacier.com\",\n            \"himemix.com\",\n            \"himemix.net\",\n            \"hindustantimes.com\",\n            \"hinet.net\",\n            \"hitbtc.com\",\n            \"hitomi.la\",\n            \"hiveon.net\",\n            \"hiwifi.com\",\n            \"hizb-ut-tahrir.info\",\n            \"hizb-ut-tahrir.org\",\n            \"hizbuttahrir.org\",\n            \"hjclub.info\",\n            \"hjd.tw\",\n            \"hjd2048.com\",\n            \"hk-pub.com\",\n            \"hk01.com\",\n            \"hk32168.com\",\n            \"hkacg.com\",\n            \"hkacg.net\",\n            \"hkatvnews.com\",\n            \"hkbc.net\",\n            \"hkbf.org\",\n            \"hkbookcity.com\",\n            \"hkchronicles.com\",\n            \"hkchurch.org\",\n            \"hkci.org.hk\",\n            \"hkcmi.edu\",\n            \"hkcnews.com\",\n            \"hkcoc.com\",\n            \"hkdailynews.com.hk\",\n            \"hkday.net\",\n            \"hkdc.us\",\n            \"hkdf.org\",\n            \"hkej.com\",\n            \"hkepc.com\",\n            \"hket.com\",\n            \"hkfaa.com\",\n            \"hkfreezone.com\",\n            \"hkfront.org\",\n            \"hkgalden.com\",\n            \"hkgolden.com\",\n            \"hkgpao.com\",\n            \"hkheadline.com\",\n            \"hkhkhk.com\",\n            \"hkhrc.org.hk\",\n            \"hkip.org.uk\",\n            \"hkjc.com\",\n            \"hkjp.org\",\n            \"hklft.com\",\n            \"hklts.org.hk\",\n            \"hkmap.live\",\n            \"hkopentv.com\",\n            \"hkpeanut.com\",\n            \"hkptu.org\",\n            \"hkreadingcity.net\",\n            \"hkreporter.com\",\n            \"hku.hk\",\n            \"hkusu.net\",\n            \"hkvwet.com\",\n            \"hkwcc.org.hk\",\n            \"hmoegirl.com\",\n            \"hmonghot.com\",\n            \"hmv.co.jp\",\n            \"hmvdigital.ca\",\n            \"hmvdigital.com\",\n            \"hnjhj.com\",\n            \"hnntube.com\",\n            \"ho5ho.com\",\n            \"hojemacau.com.mo\",\n            \"hola.com\",\n            \"hola.org\",\n            \"holymountaincn.com\",\n            \"holyspiritspeaks.org\",\n            \"home.saxo\",\n            \"homedepot.com\",\n            \"homeperversion.com\",\n            \"homeservershow.com\",\n            \"honeynet.org\",\n            \"hongkongfp.com\",\n            \"hongmeimei.com\",\n            \"hongzhi.li\",\n            \"honven.xyz\",\n            \"hootsuite.com\",\n            \"hoover.org\",\n            \"hoovers.com\",\n            \"hopedialogue.org\",\n            \"hopto.org\",\n            \"hornygamer.com\",\n            \"hornytrip.com\",\n            \"horrorporn.com\",\n            \"hostloc.com\",\n            \"hotair.com\",\n            \"hotav.tv\",\n            \"hotcoin.com\",\n            \"hotcool.tw\",\n            \"hotels.cn\",\n            \"hotfrog.com.tw\",\n            \"hotgoo.com\",\n            \"hotpornshow.com\",\n            \"hotpot.hk\",\n            \"hotshame.com\",\n            \"hotspotshield.com\",\n            \"hottg.com\",\n            \"hotvpn.com\",\n            \"hougaige.com\",\n            \"house.gov\",\n            \"howtoforge.com\",\n            \"hoxx.com\",\n            \"hoy.tv\",\n            \"hoyolab.com\",\n            \"hpa.gov.tw\",\n            \"hpjav.com\",\n            \"hqcdp.org\",\n            \"hqjapanesesex.com\",\n            \"hqmovies.com\",\n            \"hrcchina.org\",\n            \"hrcir.com\",\n            \"hrea.org\",\n            \"hrichina.org\",\n            \"hrntt.org\",\n            \"hrtsea.com\",\n            \"hrw.org\",\n            \"hrweb.org\",\n            \"hsex.men\",\n            \"hsjp.net\",\n            \"hsselite.com\",\n            \"hst.net.tw\",\n            \"hstern.net\",\n            \"hstt.net\",\n            \"ht.ly\",\n            \"htkou.net\",\n            \"htl.li\",\n            \"html5rocks.com\",\n            \"https443.net\",\n            \"https443.org\",\n            \"hua-yue.net\",\n            \"huaglad.com\",\n            \"huaibinmall.com\",\n            \"huanghuagang.org\",\n            \"huangyiyu.com\",\n            \"huaren.us\",\n            \"huaren4us.com\",\n            \"huashangnews.com\",\n            \"huasing.org\",\n            \"huaxia-news.com\",\n            \"huaxiabao.org\",\n            \"huaxin.ph\",\n            \"huayuworld.org\",\n            \"hudatoriq.web.id\",\n            \"hudson.org\",\n            \"huffingtonpost.com\",\n            \"huffpost.com\",\n            \"huggingface.co\",\n            \"hugoroy.eu\",\n            \"huhaitai.com\",\n            \"huhamhire.com\",\n            \"huhangfei.com\",\n            \"huigui.tw\",\n            \"huiyi.in\",\n            \"hulkshare.com\",\n            \"hulu.com\",\n            \"huluim.com\",\n            \"humanparty.me\",\n            \"humanrightsbriefing.org\",\n            \"humanrightspressawards.org\",\n            \"hung-ya.com\",\n            \"hungerstrikeforaids.org\",\n            \"huobi.co\",\n            \"huobi.com\",\n            \"huobi.me\",\n            \"huobi.pro\",\n            \"huobi.sc\",\n            \"huobi.vc\",\n            \"huobipool.com\",\n            \"huobipro.com\",\n            \"huping.net\",\n            \"hurgokbayrak.com\",\n            \"hurriyet.com.tr\",\n            \"hustler.com\",\n            \"hustlercash.com\",\n            \"hut2.ru\",\n            \"hutianyi.net\",\n            \"hutong9.net\",\n            \"huyandex.com\",\n            \"hwadzan.tw\",\n            \"hwayue.org.tw\",\n            \"hxwk.org\",\n            \"hxwq.org\",\n            \"hybrid-analysis.com\",\n            \"hyperrate.com\",\n            \"hypothes.is\",\n            \"hyread.com.tw\",\n            \"hysteria.network\",\n            \"i-cable.com\",\n            \"i-part.com.tw\",\n            \"i-scmp.com\",\n            \"i1.hk\",\n            \"i2p2.de\",\n            \"i2runner.com\",\n            \"i818hk.com\",\n            \"iam.soy\",\n            \"iamtopone.com\",\n            \"iask.bz\",\n            \"iask.ca\",\n            \"iav19.com\",\n            \"iavian.net\",\n            \"ibiblio.org\",\n            \"iblist.com\",\n            \"iblogserv-f.net\",\n            \"ibros.org\",\n            \"ibtimes.com\",\n            \"ibvpn.com\",\n            \"ibytedtos.com\",\n            \"icams.com\",\n            \"icedrive.net\",\n            \"icerocket.com\",\n            \"icij.org\",\n            \"icl-fi.org\",\n            \"icoco.com\",\n            \"iconpaper.org\",\n            \"icu-project.org\",\n            \"idaiwan.com\",\n            \"idemocracy.asia\",\n            \"identi.ca\",\n            \"idiomconnection.com\",\n            \"idlcoyote.com\",\n            \"idope.se\",\n            \"idouga.com\",\n            \"idreamx.com\",\n            \"idv.tw\",\n            \"ieasy5.com\",\n            \"ied2k.net\",\n            \"ienergy1.com\",\n            \"ifanqiang.com\",\n            \"ifcss.org\",\n            \"ifjc.org\",\n            \"ifreewares.com\",\n            \"ift.tt\",\n            \"ig.com\",\n            \"igcd.net\",\n            \"igfw.net\",\n            \"igfw.tech\",\n            \"igmg.de\",\n            \"ignitedetroit.net\",\n            \"igoogle.ae\",\n            \"igoogle.am\",\n            \"igoogle.as\",\n            \"igoogle.at\",\n            \"igoogle.az\",\n            \"igoogle.ba\",\n            \"igoogle.be\",\n            \"igoogle.bg\",\n            \"igoogle.ca\",\n            \"igoogle.cd\",\n            \"igoogle.ci\",\n            \"igoogle.co.id\",\n            \"igoogle.co.jp\",\n            \"igoogle.co.kr\",\n            \"igoogle.co.ma\",\n            \"igoogle.co.uk\",\n            \"igoogle.com\",\n            \"igoogle.de\",\n            \"igoogle.dj\",\n            \"igoogle.dk\",\n            \"igoogle.es\",\n            \"igoogle.fi\",\n            \"igoogle.fm\",\n            \"igoogle.fr\",\n            \"igoogle.gg\",\n            \"igoogle.gl\",\n            \"igoogle.gr\",\n            \"igoogle.ie\",\n            \"igoogle.is\",\n            \"igoogle.it\",\n            \"igoogle.jo\",\n            \"igoogle.kz\",\n            \"igoogle.mn\",\n            \"igoogle.ms\",\n            \"igoogle.nl\",\n            \"igoogle.no\",\n            \"igoogle.nu\",\n            \"igoogle.ro\",\n            \"igoogle.ru\",\n            \"igoogle.rw\",\n            \"igoogle.sc\",\n            \"igoogle.sh\",\n            \"igoogle.sm\",\n            \"igoogle.sn\",\n            \"igoogle.tk\",\n            \"igoogle.tm\",\n            \"igoogle.to\",\n            \"igoogle.tt\",\n            \"igoogle.vu\",\n            \"igoogle.ws\",\n            \"igotmail.com.tw\",\n            \"igvita.com\",\n            \"ihakka.net\",\n            \"ihao.org\",\n            \"iicns.com\",\n            \"ikstar.com\",\n            \"ikwb.com\",\n            \"ilbe.com\",\n            \"ilhamtohtiinstitute.org\",\n            \"illawarramercury.com.au\",\n            \"illusionfactory.com\",\n            \"ilove80.be\",\n            \"ilovelongtoes.com\",\n            \"im88.tw\",\n            \"imageab.com\",\n            \"imagefap.com\",\n            \"imageflea.com\",\n            \"imageglass.org\",\n            \"images-gaytube.com\",\n            \"imageshack.us\",\n            \"imagevenue.com\",\n            \"imagezilla.net\",\n            \"imago-images.com\",\n            \"imb.org\",\n            \"imdb.com\",\n            \"img.ly\",\n            \"imgasd.com\",\n            \"imgchili.net\",\n            \"imgmega.com\",\n            \"imgur.com\",\n            \"imkev.com\",\n            \"imlive.co\",\n            \"imlive.com\",\n            \"immigration.gov.tw\",\n            \"immoral.jp\",\n            \"impact.org.au\",\n            \"impp.mn\",\n            \"improd.works\",\n            \"in-disguise.com\",\n            \"in.com\",\n            \"in99.org\",\n            \"incapdns.net\",\n            \"incloak.com\",\n            \"incredibox.fr\",\n            \"independent.co.uk\",\n            \"india.com\",\n            \"indiablooms.com\",\n            \"indianarrative.com\",\n            \"indiandefensenews.in\",\n            \"indianexpress.com\",\n            \"indiatimes.com\",\n            \"indiatoday.in\",\n            \"indiemerch.com\",\n            \"indsr.org.tw\",\n            \"info-graf.fr\",\n            \"informer.com\",\n            \"infura.io\",\n            \"inherit.live\",\n            \"initiativesforchina.org\",\n            \"inkbunny.net\",\n            \"inkui.com\",\n            \"inlang.com\",\n            \"inmediahk.net\",\n            \"innermongolia.org\",\n            \"inoreader.com\",\n            \"inote.tw\",\n            \"insecam.org\",\n            \"inside.com.tw\",\n            \"insidevoa.com\",\n            \"instagram.com\",\n            \"instanthq.com\",\n            \"institut-tibetain.org\",\n            \"interactivebrokers.com\",\n            \"internet.org\",\n            \"internetdefenseleague.org\",\n            \"internetfreedom.org\",\n            \"internetpopculture.com\",\n            \"inthenameofconfuciusmovie.com\",\n            \"invidio.us\",\n            \"inxian.com\",\n            \"iownyour.org\",\n            \"ipalter.com\",\n            \"ipdefenseforum.com\",\n            \"ipfire.org\",\n            \"ipfs.io\",\n            \"iphone4hongkong.com\",\n            \"iphonehacks.com\",\n            \"iphonetaiwan.org\",\n            \"iphonix.fr\",\n            \"ipicture.ru\",\n            \"ipify.org\",\n            \"ipjetable.net\",\n            \"ipobar.com\",\n            \"ipoock.com\",\n            \"iportal.me\",\n            \"ippotv.com\",\n            \"ipredator.se\",\n            \"iptv.com.tw\",\n            \"iptvbin.com\",\n            \"ipvanish.com\",\n            \"irangov.ir\",\n            \"iredmail.org\",\n            \"irib.ir\",\n            \"irna.ir\",\n            \"ironpython.net\",\n            \"ironsocket.com\",\n            \"is-a-hunter.com\",\n            \"is.gd\",\n            \"isaacmao.com\",\n            \"isasecret.com\",\n            \"isgreat.org\",\n            \"ishr.ch\",\n            \"islahhaber.net\",\n            \"islam.org.hk\",\n            \"islamawareness.net\",\n            \"islamhouse.com\",\n            \"islamicity.com\",\n            \"islamicpluralism.org\",\n            \"islamtoday.net\",\n            \"ismaelan.com\",\n            \"ismalltits.com\",\n            \"ismprofessional.net\",\n            \"isohunt.com\",\n            \"israbox.com\",\n            \"issuu.com\",\n            \"istars.co.nz\",\n            \"istarshine.com\",\n            \"istef.info\",\n            \"istiqlalhewer.com\",\n            \"istockphoto.com\",\n            \"isunaffairs.com\",\n            \"isuntv.com\",\n            \"isupportuyghurs.org\",\n            \"itaboo.info\",\n            \"itaiwan.gov.tw\",\n            \"italiatibet.org\",\n            \"itasoftware.com\",\n            \"itch.io\",\n            \"itemdb.com\",\n            \"itemfix.com\",\n            \"ithome.com.tw\",\n            \"itiger.com\",\n            \"itsaol.com\",\n            \"itshidden.com\",\n            \"itsky.it\",\n            \"itweet.net\",\n            \"iu45.com\",\n            \"iuhrdf.org\",\n            \"iuksky.com\",\n            \"ivacy.com\",\n            \"iverycd.com\",\n            \"ivonblog.com\",\n            \"ivpn.net\",\n            \"iwara.tv\",\n            \"ixquick.com\",\n            \"ixxx.com\",\n            \"iyouport.com\",\n            \"iyouport.org\",\n            \"izaobao.us\",\n            \"izihost.org\",\n            \"izles.net\",\n            \"izlesem.org\",\n            \"j.mp\",\n            \"jable.tv\",\n            \"jackjia.com\",\n            \"jamaat.org\",\n            \"jamestown.org\",\n            \"jamyangnorbu.com\",\n            \"jan.ai\",\n            \"jandyx.com\",\n            \"janwongphoto.com\",\n            \"japan-whores.com\",\n            \"japanhdv.com\",\n            \"japantimes.co.jp\",\n            \"jav.com\",\n            \"jav101.com\",\n            \"jav321.com\",\n            \"jav68.tv\",\n            \"jav777.cc\",\n            \"javakiba.org\",\n            \"javbus.co\",\n            \"javbus.com\",\n            \"javbus.sbs\",\n            \"javdb.com\",\n            \"javfinder.ai\",\n            \"javfor.me\",\n            \"javfree.me\",\n            \"javhd.com\",\n            \"javhip.com\",\n            \"javhub.net\",\n            \"javhuge.com\",\n            \"javlibrary.com\",\n            \"javmobile.net\",\n            \"javmoo.com\",\n            \"javmoo.xyz\",\n            \"javseen.com\",\n            \"javtag.com\",\n            \"javtrailers.com\",\n            \"javzoo.com\",\n            \"javzz.com\",\n            \"jbtalks.cc\",\n            \"jbtalks.com\",\n            \"jbtalks.my\",\n            \"jcpenney.com\",\n            \"jdwsy.com\",\n            \"jeanyim.com\",\n            \"jetos.com\",\n            \"jex.com\",\n            \"jfqu36.club\",\n            \"jfqu37.xyz\",\n            \"jgoodies.com\",\n            \"jiangweiping.com\",\n            \"jiaoyou8.com\",\n            \"jichangtj.com\",\n            \"jiehua.cz\",\n            \"jiepang.com\",\n            \"jieshibaobao.com\",\n            \"jifangge.com\",\n            \"jigglegifs.com\",\n            \"jigong1024.com\",\n            \"jigsy.com\",\n            \"jihadology.net\",\n            \"jiji.com\",\n            \"jims.net\",\n            \"jinbushe.org\",\n            \"jingpin.org\",\n            \"jingsim.org\",\n            \"jinhai.de\",\n            \"jinpianwang.com\",\n            \"jinrizhiyi.news\",\n            \"jinroukong.com\",\n            \"jintian.net\",\n            \"jinx.com\",\n            \"jiruan.net\",\n            \"jitouch.com\",\n            \"jizzthis.com\",\n            \"jjgirls.com\",\n            \"jkb.cc\",\n            \"jkforum.net\",\n            \"jkub.com\",\n            \"jma.go.jp\",\n            \"jmcomic.me\",\n            \"jmscult.com\",\n            \"joachims.org\",\n            \"jobso.tv\",\n            \"joinbbs.net\",\n            \"joinclubhouse.com\",\n            \"joinmastodon.org\",\n            \"joinpeertube.org\",\n            \"joins.com\",\n            \"jornaldacidadeonline.com.br\",\n            \"jotform.com\",\n            \"journalchretien.net\",\n            \"journalofdemocracy.org\",\n            \"joymiihub.com\",\n            \"joyourself.com\",\n            \"jp1lib.org\",\n            \"jpopforum.net\",\n            \"jquery.com\",\n            \"jqueryui.com\",\n            \"jrf.org.tw\",\n            \"jsdelivr.net\",\n            \"jsfiddle.net\",\n            \"jshell.net\",\n            \"jtvnw.net\",\n            \"jubushoushen.com\",\n            \"judicial.gov.tw\",\n            \"juhuaren.com\",\n            \"jukujo-club.com\",\n            \"juliepost.com\",\n            \"juliereyc.com\",\n            \"junauza.com\",\n            \"june4commemoration.org\",\n            \"junefourth-20.net\",\n            \"jungleheart.com\",\n            \"junglobal.net\",\n            \"juoaa.com\",\n            \"justdied.com\",\n            \"justfreevpn.com\",\n            \"justhost.ru\",\n            \"justicefortenzin.org\",\n            \"justmysocks.net\",\n            \"justmysocks1.net\",\n            \"justmysockscn.com\",\n            \"justpaste.it\",\n            \"justtristan.com\",\n            \"juyuange.org\",\n            \"juziyue.com\",\n            \"jw.org\",\n            \"jwmusic.org\",\n            \"jwplayer.com\",\n            \"jyxf.net\",\n            \"ka-wai.com\",\n            \"kadokawa.co.jp\",\n            \"kagyu.org\",\n            \"kagyu.org.za\",\n            \"kagyumonlam.org\",\n            \"kagyunews.com.hk\",\n            \"kagyuoffice.org\",\n            \"kagyuoffice.org.tw\",\n            \"kaiyuan.de\",\n            \"kakao.com\",\n            \"kalachakralugano.org\",\n            \"kanald.com.tr\",\n            \"kangye.org\",\n            \"kankan.today\",\n            \"kannewyork.com\",\n            \"kanshifang.com\",\n            \"kantie.org\",\n            \"kanzhongguo.com\",\n            \"kanzhongguo.eu\",\n            \"kaotic.com\",\n            \"karayou.com\",\n            \"karkhung.com\",\n            \"karmapa-teachings.org\",\n            \"karmapa.org\",\n            \"kawaiikawaii.jp\",\n            \"kawase.com\",\n            \"kba-tx.org\",\n            \"kcoolonline.com\",\n            \"kebrum.com\",\n            \"kechara.com\",\n            \"keepandshare.com\",\n            \"keezmovies.com\",\n            \"kemono.party\",\n            \"kendatire.com\",\n            \"kendincos.net\",\n            \"kenengba.com\",\n            \"keontech.net\",\n            \"kepard.com\",\n            \"keso.cn\",\n            \"kex.com\",\n            \"keycdn.com\",\n            \"kfd.me\",\n            \"khabdha.org\",\n            \"khatrimaza.org\",\n            \"khmusic.com.tw\",\n            \"kichiku-doujinko.com\",\n            \"kik.com\",\n            \"killwall.com\",\n            \"kindle4rss.com\",\n            \"kindleren.com\",\n            \"kingdomsalvation.org\",\n            \"kinghost.com\",\n            \"kingkong.com.tw\",\n            \"kingstone.com.tw\",\n            \"kink.com\",\n            \"kinmen.org.tw\",\n            \"kinmen.travel\",\n            \"kinokuniya.com\",\n            \"kir.jp\",\n            \"kissbbao.cn\",\n            \"kissjav.com\",\n            \"kiwi.kz\",\n            \"kk-whys.co.jp\",\n            \"kkbox.com\",\n            \"kknews.cc\",\n            \"klip.me\",\n            \"kmuh.org.tw\",\n            \"knowledgerush.com\",\n            \"knowyourmeme.com\",\n            \"ko-fi.com\",\n            \"kobe-np.co.jp\",\n            \"kobo.com\",\n            \"kobobooks.com\",\n            \"kodingen.com\",\n            \"kompozer.net\",\n            \"konachan.com\",\n            \"kone.com\",\n            \"koolsolutions.com\",\n            \"koornk.com\",\n            \"koranmandarin.com\",\n            \"korea.net\",\n            \"korenan2.com\",\n            \"kpkuang.org\",\n            \"kqes.net\",\n            \"kraken.com\",\n            \"krtc.com.tw\",\n            \"krtco.com.tw\",\n            \"ksdl.org\",\n            \"ksnews.com.tw\",\n            \"kspcoin.com\",\n            \"ktzhk.com\",\n            \"kuaichedao.co\",\n            \"kucoin.com\",\n            \"kui.name\",\n            \"kukuku.uk\",\n            \"kun.im\",\n            \"kurashsultan.com\",\n            \"kurtmunger.com\",\n            \"kusocity.com\",\n            \"kwcg.ca\",\n            \"kwongwah.com.my\",\n            \"kxsw.life\",\n            \"kyofun.com\",\n            \"kyohk.net\",\n            \"kyoyue.com\",\n            \"kyzyhello.com\",\n            \"kzaobao.com\",\n            \"kzeng.info\",\n            \"la-forum.org\",\n            \"labiennale.org\",\n            \"ladbrokes.com\",\n            \"lagranepoca.com\",\n            \"lala.im\",\n            \"lalulalu.com\",\n            \"lama.com.tw\",\n            \"lamayeshe.com\",\n            \"lamenhu.com\",\n            \"lamnia.co.uk\",\n            \"lamrim.com\",\n            \"landofhope.tv\",\n            \"lanterncn.cn\",\n            \"lantosfoundation.org\",\n            \"laod.cn\",\n            \"laogai.org\",\n            \"laogairesearch.org\",\n            \"laomiu.com\",\n            \"laowang.vip\",\n            \"laoyang.info\",\n            \"laqingdan.net\",\n            \"larsgeorge.com\",\n            \"lastcombat.com\",\n            \"lastfm.es\",\n            \"latelinenews.com\",\n            \"latibet.org\",\n            \"lausan.hk\",\n            \"law.com\",\n            \"lbank.info\",\n            \"ldplayer.net\",\n            \"ldplayer.tw\",\n            \"le-vpn.com\",\n            \"leafyvpn.net\",\n            \"lecloud.net\",\n            \"ledger.com\",\n            \"leeao.com.cn\",\n            \"lefora.com\",\n            \"left21.hk\",\n            \"legalporno.com\",\n            \"legra.ph\",\n            \"legsjapan.com\",\n            \"leirentv.ca\",\n            \"leisurecafe.ca\",\n            \"leisurepro.com\",\n            \"lematin.ch\",\n            \"lemonde.fr\",\n            \"lenwhite.com\",\n            \"lerosua.org\",\n            \"lesoir.be\",\n            \"lester850.info\",\n            \"letou.com\",\n            \"letscorp.net\",\n            \"lflink.com\",\n            \"lflinkup.com\",\n            \"lflinkup.net\",\n            \"lflinkup.org\",\n            \"lfpcontent.com\",\n            \"lhakar.org\",\n            \"lhasocialwork.org\",\n            \"li.taipei\",\n            \"liangyou.net\",\n            \"liangzhichuanmei.com\",\n            \"lianyue.net\",\n            \"liaowangxizang.net\",\n            \"liberal.org.hk\",\n            \"libertysculpturepark.com\",\n            \"libertytimes.com.tw\",\n            \"libraryinformationtechnology.com\",\n            \"libredd.it\",\n            \"lidecheng.com\",\n            \"lifemiles.com\",\n            \"lighten.org.tw\",\n            \"lighti.me\",\n            \"lightnovel.cn\",\n            \"lightyearvpn.com\",\n            \"lih.kg\",\n            \"lihkg.com\",\n            \"like.com\",\n            \"lilaoshibushinilaoshi.com\",\n            \"limelight.moe\",\n            \"limiao.net\",\n            \"line-apps.com\",\n            \"line-scdn.net\",\n            \"line.me\",\n            \"linglingfa.com\",\n            \"lingualeo.com\",\n            \"lingvodics.com\",\n            \"link-o-rama.com\",\n            \"linkedin.com\",\n            \"linkideo.com\",\n            \"linksalpha.com\",\n            \"linktr.ee\",\n            \"linkuswell.com\",\n            \"linpie.com\",\n            \"linux.org.hk\",\n            \"linuxtoy.org\",\n            \"lionsroar.com\",\n            \"lipuman.com\",\n            \"liquiditytp.com\",\n            \"liquidvpn.com\",\n            \"list-manage.com\",\n            \"listennotes.com\",\n            \"listentoyoutube.com\",\n            \"listorious.com\",\n            \"litenews.hk\",\n            \"lithium.com\",\n            \"liu-xiaobo.org\",\n            \"liuhanyu.com\",\n            \"liujianshu.com\",\n            \"liuxiaobo.net\",\n            \"liuxiaotong.com\",\n            \"live.com\",\n            \"livecoin.net\",\n            \"livedoor.jp\",\n            \"liveleak.com\",\n            \"livemint.com\",\n            \"livestation.com\",\n            \"livestream.com\",\n            \"livevideo.com\",\n            \"livingonline.us\",\n            \"livingstream.com\",\n            \"liwangyang.com\",\n            \"lizhizhuangbi.com\",\n            \"lkcn.net\",\n            \"llss.me\",\n            \"lmsys.org\",\n            \"load.to\",\n            \"lobsangwangyal.com\",\n            \"localbitcoins.com\",\n            \"localdomain.ws\",\n            \"localpresshk.com\",\n            \"lockestek.com\",\n            \"logbot.net\",\n            \"logiqx.com\",\n            \"logmein.com\",\n            \"logos.com.hk\",\n            \"londonchinese.ca\",\n            \"longhair.hk\",\n            \"longmusic.com\",\n            \"longtermly.net\",\n            \"longtoes.com\",\n            \"lookpic.com\",\n            \"looktoronto.com\",\n            \"loongese.com\",\n            \"lorenzetti.com.br\",\n            \"lotsawahouse.org\",\n            \"lotuslight.org.hk\",\n            \"lotuslight.org.tw\",\n            \"loukky.com\",\n            \"loved.hk\",\n            \"lovetvshow.com\",\n            \"lpsg.com\",\n            \"lrfz.com\",\n            \"lrip.org\",\n            \"lsd.org.hk\",\n            \"lsforum.net\",\n            \"lsm.org\",\n            \"lsmchinese.org\",\n            \"lsmkorean.org\",\n            \"lsmradio.com\",\n            \"lsmwebcast.com\",\n            \"lsxszzg.com\",\n            \"ltn.com.tw\",\n            \"luckydesigner.space\",\n            \"luckymobile.ca\",\n            \"ludepress.com\",\n            \"luke54.com\",\n            \"luke54.org\",\n            \"lupm.org\",\n            \"lushstories.com\",\n            \"luxebc.com\",\n            \"lvhai.org\",\n            \"lvv2.com\",\n            \"ly.gov.tw\",\n            \"lyfhk.net\",\n            \"lzjscript.com\",\n            \"lzmtnews.org\",\n            \"m-sport.co.uk\",\n            \"m-team.cc\",\n            \"m.me\",\n            \"m8008.com\",\n            \"macgamestore.com\",\n            \"machbbs.com\",\n            \"macrovpn.com\",\n            \"macts.com.tw\",\n            \"mad-ar.ch\",\n            \"madewithcode.com\",\n            \"madonna-av.com\",\n            \"madou.club\",\n            \"madrau.com\",\n            \"madthumbs.com\",\n            \"magic-net.info\",\n            \"mahabodhi.org\",\n            \"mahjongsoul.com\",\n            \"maiio.net\",\n            \"mail-archive.com\",\n            \"mail.ru\",\n            \"mailchimp.com\",\n            \"maildns.xyz\",\n            \"mainichi.jp\",\n            \"maiplus.com\",\n            \"maizhong.org\",\n            \"makemymood.com\",\n            \"makkahnewspaper.com\",\n            \"malaysiakini.com\",\n            \"mamingzhe.com\",\n            \"manchukuo.net\",\n            \"manchustate.org\",\n            \"mandiant.com\",\n            \"mangabz.com\",\n            \"mangafox.com\",\n            \"mangafox.me\",\n            \"mangmang.run\",\n            \"manhuabika.com\",\n            \"manhuache.com\",\n            \"manhuagui.com\",\n            \"maniash.com\",\n            \"manicur4ik.ru\",\n            \"mansion.com\",\n            \"mansionpoker.com\",\n            \"manta.com\",\n            \"manyvoices.news\",\n            \"maplew.com\",\n            \"marc.info\",\n            \"marguerite.su\",\n            \"martau.com\",\n            \"martincartoons.com\",\n            \"martinoei.com\",\n            \"martsangkagyuofficial.org\",\n            \"maruta.be\",\n            \"marxist.com\",\n            \"marxist.net\",\n            \"marxists.org\",\n            \"mash.to\",\n            \"mashash.com\",\n            \"maskedip.com\",\n            \"mastodon.cloud\",\n            \"mastodon.host\",\n            \"mastodon.online\",\n            \"mastodon.social\",\n            \"mastodon.xyz\",\n            \"matainja.com\",\n            \"material.io\",\n            \"mathable.io\",\n            \"mathiew-badimon.com\",\n            \"matome-plus.com\",\n            \"matome-plus.net\",\n            \"matrix.org\",\n            \"matters.news\",\n            \"matters.town\",\n            \"mattwilcox.net\",\n            \"maxai.co\",\n            \"maxing.jp\",\n            \"mayimayi.com\",\n            \"mcadforums.com\",\n            \"mcaf.ee\",\n            \"mcfog.com\",\n            \"mcreasite.com\",\n            \"mcusercontent.com\",\n            \"md-t.org\",\n            \"me.com\",\n            \"me.me\",\n            \"meansys.com\",\n            \"media.org.hk\",\n            \"mediachinese.com\",\n            \"mediafire.com\",\n            \"mediafreakcity.com\",\n            \"mediawiki.org\",\n            \"medicalnewstoday.com\",\n            \"medium.com\",\n            \"mee6.xyz\",\n            \"meetav.com\",\n            \"meetup.com\",\n            \"mefeedia.com\",\n            \"meforum.org\",\n            \"mefound.com\",\n            \"mega.co.nz\",\n            \"mega.io\",\n            \"mega.nz\",\n            \"megalodon.jp\",\n            \"megaproxy.com\",\n            \"megarotic.com\",\n            \"megavideo.com\",\n            \"megurineluka.com\",\n            \"meirixiaochao.com\",\n            \"meizhong.blog\",\n            \"meizhong.report\",\n            \"melon365.com\",\n            \"meltoday.com\",\n            \"memehk.com\",\n            \"memes.tw\",\n            \"memorybbs.com\",\n            \"memri.org\",\n            \"memrijttm.org\",\n            \"mercari.com\",\n            \"mercari.jp\",\n            \"mercatox.com\",\n            \"mercdn.net\",\n            \"mercyprophet.org\",\n            \"mergersandinquisitions.com\",\n            \"mergersandinquisitions.org\",\n            \"meridian-trust.org\",\n            \"meripet.biz\",\n            \"meripet.com\",\n            \"merit-times.com.tw\",\n            \"merlinblog.xyz\",\n            \"meshrep.com\",\n            \"mesotw.com\",\n            \"messenger.com\",\n            \"meta.com\",\n            \"metacafe.com\",\n            \"metacubex.one\",\n            \"metafilter.com\",\n            \"metamask.io\",\n            \"metart.com\",\n            \"metarthunter.com\",\n            \"meteorshowersonline.com\",\n            \"metro.taipei\",\n            \"metrohk.com.hk\",\n            \"metrolife.ca\",\n            \"metroradio.com.hk\",\n            \"mewe.com\",\n            \"meyou.jp\",\n            \"meyul.com\",\n            \"mfxmedia.com\",\n            \"mgoon.com\",\n            \"mgstage.com\",\n            \"mh4u.org\",\n            \"mhradio.org\",\n            \"mi.com\",\n            \"miami-airport.com\",\n            \"michaelmarketl.com\",\n            \"microsoft.com\",\n            \"microvpn.com\",\n            \"middle-way.net\",\n            \"mihk.hk\",\n            \"mihr.com\",\n            \"mihua.org\",\n            \"mikanani.me\",\n            \"mikesoltys.com\",\n            \"mikocon.com\",\n            \"milph.net\",\n            \"milsurps.com\",\n            \"mimiai.net\",\n            \"mimivip.com\",\n            \"mimivv.com\",\n            \"mindrolling.org\",\n            \"mingdemedia.org\",\n            \"minghui-a.org\",\n            \"minghui-b.org\",\n            \"minghui-school.org\",\n            \"minghui.or.kr\",\n            \"minghui.org\",\n            \"mingjinglishi.com\",\n            \"mingjingnews.com\",\n            \"mingjingtimes.com\",\n            \"mingpao.com\",\n            \"mingpaocanada.com\",\n            \"mingpaomonthly.com\",\n            \"mingpaonews.com\",\n            \"mingpaony.com\",\n            \"mingpaosf.com\",\n            \"mingpaotor.com\",\n            \"mingpaovan.com\",\n            \"mingshengbao.com\",\n            \"minhhue.net\",\n            \"miniforum.org\",\n            \"miningpoolhub.com\",\n            \"ministrybooks.org\",\n            \"minjian-danganguan.org\",\n            \"minzhuhua.net\",\n            \"minzhuzhanxian.com\",\n            \"minzhuzhongguo.org\",\n            \"miraheze.org\",\n            \"miroguide.com\",\n            \"mirror.xyz\",\n            \"mirrorbooks.com\",\n            \"mirrormedia.com.tw\",\n            \"mirrormedia.mg\",\n            \"missav.com\",\n            \"missav.ws\",\n            \"mist.vip\",\n            \"mit.edu\",\n            \"mitao.com.tw\",\n            \"mitbbs.com\",\n            \"mitbbsau.com\",\n            \"miuipolska.pl\",\n            \"mixero.com\",\n            \"mixi.jp\",\n            \"mixpod.com\",\n            \"mixx.com\",\n            \"mizzmona.com\",\n            \"mjib.gov.tw\",\n            \"mk5000.com\",\n            \"mlc.ai\",\n            \"mlcool.com\",\n            \"mlzs.work\",\n            \"mm-cg.com\",\n            \"mmaaxx.com\",\n            \"mmmca.com\",\n            \"mnewstv.com\",\n            \"mobatek.net\",\n            \"mobile01.com\",\n            \"mobileways.de\",\n            \"moby.to\",\n            \"mobypicture.com\",\n            \"mod.io\",\n            \"modernchinastudies.org\",\n            \"moeaic.gov.tw\",\n            \"moeerolibrary.com\",\n            \"moegirl.org\",\n            \"moeshare.cc\",\n            \"moeyy.xyz\",\n            \"mofa.gov.tw\",\n            \"mofaxiehui.com\",\n            \"mofos.com\",\n            \"mog.com\",\n            \"mohu.club\",\n            \"mohu.rocks\",\n            \"moj.gov.tw\",\n            \"mojim.com\",\n            \"mol.gov.tw\",\n            \"molihua.org\",\n            \"momoshop.com.tw\",\n            \"mondex.org\",\n            \"money-link.com.tw\",\n            \"moneydj.com\",\n            \"moneyhome.biz\",\n            \"monica.im\",\n            \"monitorchina.org\",\n            \"monitorware.com\",\n            \"monlamit.org\",\n            \"monocloud.me\",\n            \"monster.com\",\n            \"moodyz.com\",\n            \"moomoo.com\",\n            \"moon.fm\",\n            \"moonbbs.com\",\n            \"moonbbs.info\",\n            \"moonbingo.com\",\n            \"mooo.com\",\n            \"moptt.tw\",\n            \"morbell.com\",\n            \"moresci.sale\",\n            \"morningsun.org\",\n            \"moroneta.com\",\n            \"mos.ru\",\n            \"mosucloud.site\",\n            \"motherless.com\",\n            \"motor4ik.ru\",\n            \"mousebreaker.com\",\n            \"movements.org\",\n            \"moviefap.com\",\n            \"mozilla.org\",\n            \"moztw.org\",\n            \"mp3buscador.com\",\n            \"mp3ye.eu\",\n            \"mpettis.com\",\n            \"mpfinance.com\",\n            \"mpinews.com\",\n            \"mponline.hk\",\n            \"mqxd.org\",\n            \"mrbasic.com\",\n            \"mrbonus.com\",\n            \"mrface.com\",\n            \"mrslove.com\",\n            \"mrtweet.com\",\n            \"msa-it.org\",\n            \"msguancha.com\",\n            \"msha.gov\",\n            \"msn.com\",\n            \"msn.com.tw\",\n            \"mstdn.social\",\n            \"mswe1.org\",\n            \"mt.co.kr\",\n            \"mthruf.com\",\n            \"mtw.tl\",\n            \"mtzfile.pw\",\n            \"mubi.com\",\n            \"muchosucko.com\",\n            \"mullvad.net\",\n            \"multiply.com\",\n            \"multiproxy.org\",\n            \"multiupload.com\",\n            \"mummysgold.com\",\n            \"murmur.tw\",\n            \"muscdn.com\",\n            \"musicade.net\",\n            \"musical.ly\",\n            \"musixmatch.com\",\n            \"muslimvideo.com\",\n            \"muzi.com\",\n            \"muzi.net\",\n            \"muzu.tv\",\n            \"mvdis.gov.tw\",\n            \"mvg.jp\",\n            \"mx981.com\",\n            \"my-formosa.com\",\n            \"my-private-network.co.uk\",\n            \"my-proxy.com\",\n            \"my03.com\",\n            \"myactimes.com\",\n            \"myanniu.com\",\n            \"myaudiocast.com\",\n            \"myav.com.tw\",\n            \"mybbs.us\",\n            \"mybet.com\",\n            \"myca168.com\",\n            \"mycanadanow.com\",\n            \"mychat.to\",\n            \"mychinamyhome.com\",\n            \"mychinanet.com\",\n            \"mychinanews.com\",\n            \"mychinese.news\",\n            \"mycnnews.com\",\n            \"mycould.com\",\n            \"mydad.info\",\n            \"mydati.com\",\n            \"myddns.com\",\n            \"myeasytv.com\",\n            \"myeclipseide.com\",\n            \"myforum.com.hk\",\n            \"myfreecams.com\",\n            \"myfreepaysite.com\",\n            \"myfreshnet.com\",\n            \"myftp.info\",\n            \"myip.com\",\n            \"myiphide.com\",\n            \"myiphider.com\",\n            \"myjs.tw\",\n            \"mykomica.org\",\n            \"mylftv.com\",\n            \"mymaji.com\",\n            \"mymediarom.com\",\n            \"mymoe.moe\",\n            \"mymom.info\",\n            \"mymusic.net.tw\",\n            \"mynetav.net\",\n            \"mynetav.org\",\n            \"mynumber.org\",\n            \"myparagliding.com\",\n            \"mypicasa.com\",\n            \"mypicture.info\",\n            \"mypikpak.com\",\n            \"mypop3.net\",\n            \"mypop3.org\",\n            \"mypopescu.com\",\n            \"myradio.hk\",\n            \"myreadingmanga.info\",\n            \"mysecondarydns.com\",\n            \"mysinablog.com\",\n            \"myspace.com\",\n            \"myspacecdn.com\",\n            \"mytalkbox.com\",\n            \"mytizi.com\",\n            \"mywife.cc\",\n            \"mywww.biz\",\n            \"myz.info\",\n            \"naacoalition.org\",\n            \"naitik.net\",\n            \"naixi.net\",\n            \"nakido.com\",\n            \"nakuz.com\",\n            \"nalandabodhi.org\",\n            \"nalandawest.org\",\n            \"namgyal.org\",\n            \"namgyalmonastery.org\",\n            \"nanhuyt.com\",\n            \"nanopool.org\",\n            \"nanyang.com\",\n            \"nanyangpost.com\",\n            \"nanzao.com\",\n            \"naol.ca\",\n            \"naol.cc\",\n            \"narod.ru\",\n            \"nasa.gov\",\n            \"nat.gov.tw\",\n            \"nat.moe\",\n            \"natado.com\",\n            \"national-lottery.co.uk\",\n            \"nationalawakening.org\",\n            \"nationalgeographic.com\",\n            \"nationalinterest.org\",\n            \"nationalreview.com\",\n            \"nationsonline.org\",\n            \"nationwide.com\",\n            \"naughtyamerica.com\",\n            \"naver.com\",\n            \"naver.jp\",\n            \"navy.mil\",\n            \"naweeklytimes.com\",\n            \"nbc.com\",\n            \"nbcnews.com\",\n            \"nbtvpn.com\",\n            \"nbyy.tv\",\n            \"nccwatch.org.tw\",\n            \"nch.com.tw\",\n            \"nchrd.org\",\n            \"ncn.org\",\n            \"ncol.com\",\n            \"nde.de\",\n            \"ndi.org\",\n            \"ndr.de\",\n            \"ndtv.com\",\n            \"ned.org\",\n            \"nekoslovakia.net\",\n            \"nengcard.com\",\n            \"neo-miracle.com\",\n            \"neoforged.net\",\n            \"neowin.net\",\n            \"nesnode.com\",\n            \"netalert.me\",\n            \"netbirds.com\",\n            \"netcolony.com\",\n            \"netfirms.com\",\n            \"netflav.com\",\n            \"netflix.com\",\n            \"netflix.net\",\n            \"netlify.app\",\n            \"netme.cc\",\n            \"netsarang.com\",\n            \"netsneak.com\",\n            \"network54.com\",\n            \"networkedblogs.com\",\n            \"networktunnel.net\",\n            \"neverforget8964.org\",\n            \"new-3lunch.net\",\n            \"new-akiba.com\",\n            \"new96.ca\",\n            \"newcenturymc.com\",\n            \"newcenturynews.com\",\n            \"newchen.com\",\n            \"newgrounds.com\",\n            \"newhighlandvision.com\",\n            \"newindianexpress.com\",\n            \"newipnow.com\",\n            \"newlandmagazine.com.au\",\n            \"newmitbbs.com\",\n            \"newnews.ca\",\n            \"news.com.au\",\n            \"news1.kr\",\n            \"news100.com.tw\",\n            \"news18.com\",\n            \"newsancai.com\",\n            \"newsblur.com\",\n            \"newschinacomment.org\",\n            \"newscn.org\",\n            \"newsdetox.ca\",\n            \"newsdh.com\",\n            \"newsmagazine.asia\",\n            \"newsmax.com\",\n            \"newspeak.cc\",\n            \"newstamago.com\",\n            \"newstapa.org\",\n            \"newstarnet.com\",\n            \"newstatesman.com\",\n            \"newsweek.com\",\n            \"newtaiwan.com.tw\",\n            \"newtalk.tw\",\n            \"newthuhole.com\",\n            \"newyorker.com\",\n            \"newyorktimes.com\",\n            \"nexon.com\",\n            \"next11.co.jp\",\n            \"nextapple.com\",\n            \"nextapple.tw\",\n            \"nextdigital.com.hk\",\n            \"nextmag.com.tw\",\n            \"nextmedia.com\",\n            \"nexton-net.jp\",\n            \"nexttv.com.tw\",\n            \"nf.id.au\",\n            \"nfjtyd.com\",\n            \"nflxext.com\",\n            \"nflximg.com\",\n            \"nflximg.net\",\n            \"nflxso.net\",\n            \"nflxvideo.net\",\n            \"nftstorage.link\",\n            \"ng.mil\",\n            \"nga.mil\",\n            \"ngensis.com\",\n            \"nhentai.net\",\n            \"nhi.gov.tw\",\n            \"nhk-ondemand.jp\",\n            \"nic.gov\",\n            \"nicovideo.jp\",\n            \"nighost.org\",\n            \"nightlife141.com\",\n            \"nightswatch.top\",\n            \"nike.com\",\n            \"nikke-en.com\",\n            \"nikke-jp.com\",\n            \"nikke-kr.com\",\n            \"nikkei.com\",\n            \"ninecommentaries.com\",\n            \"ning.com\",\n            \"ninjacloak.com\",\n            \"ninjaproxy.ninja\",\n            \"nintendium.com\",\n            \"nirsoft.net\",\n            \"nitter.cc\",\n            \"nitter.net\",\n            \"niu.moe\",\n            \"niusnews.com\",\n            \"njactb.org\",\n            \"njav.tv\",\n            \"njuice.com\",\n            \"nlfreevpn.com\",\n            \"nmsl.website\",\n            \"nnews.eu\",\n            \"no-ip.com\",\n            \"no-ip.org\",\n            \"nobel.se\",\n            \"nobelprize.org\",\n            \"nobodycanstop.us\",\n            \"nodeseek.com\",\n            \"nodesnoop.com\",\n            \"nokogiri.org\",\n            \"nokola.com\",\n            \"noodlevpn.com\",\n            \"norbulingka.org\",\n            \"nordcdn.com\",\n            \"nordstrom.com\",\n            \"nordstromimage.com\",\n            \"nordstrommedia.com\",\n            \"nordstromrack.com\",\n            \"nordvpn.com\",\n            \"nos.nl\",\n            \"note.com\",\n            \"notepad-plus-plus.org\",\n            \"notion.site\",\n            \"nottinghampost.com\",\n            \"novelasia.com\",\n            \"now.com\",\n            \"now.im\",\n            \"nownews.com\",\n            \"nowtorrents.com\",\n            \"noxinfluencer.com\",\n            \"noypf.com\",\n            \"npa.go.jp\",\n            \"npa.gov.tw\",\n            \"npm.edu.tw\",\n            \"npm.gov.tw\",\n            \"npnt.me\",\n            \"npsboost.com\",\n            \"nradio.me\",\n            \"nrk.no\",\n            \"ns.ci\",\n            \"ns01.biz\",\n            \"ns01.info\",\n            \"ns01.us\",\n            \"ns02.biz\",\n            \"ns02.info\",\n            \"ns02.us\",\n            \"ns1.name\",\n            \"ns2.name\",\n            \"ns3.name\",\n            \"nsc.gov.tw\",\n            \"ntbk.gov.tw\",\n            \"ntbna.gov.tw\",\n            \"ntbt.gov.tw\",\n            \"ntd.tv\",\n            \"ntdsf.tv\",\n            \"ntdtv.ca\",\n            \"ntdtv.co.kr\",\n            \"ntdtv.com\",\n            \"ntdtv.com.tw\",\n            \"ntdtv.cz\",\n            \"ntdtv.jp\",\n            \"ntdtv.org\",\n            \"ntdtv.ru\",\n            \"ntdtvla.com\",\n            \"ntrfun.com\",\n            \"ntu.edu.tw\",\n            \"nu.nl\",\n            \"nubiles.net\",\n            \"nudezz.com\",\n            \"nuexpo.com\",\n            \"nukistream.com\",\n            \"nurgo-software.com\",\n            \"nusatrip.com\",\n            \"nutaku.net\",\n            \"nutsvpn.work\",\n            \"nuuvem.com\",\n            \"nuvid.com\",\n            \"nvdst.com\",\n            \"nvquan.org\",\n            \"nvtongzhisheng.org\",\n            \"nwtca.org\",\n            \"nyaa.eu\",\n            \"nyaa.si\",\n            \"nybooks.com\",\n            \"nydailynews.com\",\n            \"nydus.ca\",\n            \"nyinfor.com\",\n            \"nylon-angel.com\",\n            \"nylonstockingsonline.com\",\n            \"nypost.com\",\n            \"nyt.com\",\n            \"nytchina.com\",\n            \"nytcn.me\",\n            \"nytco.com\",\n            \"nyti.ms\",\n            \"nytimes.com\",\n            \"nytimes.map.fastly.net\",\n            \"nytimg.com\",\n            \"nytstyle.com\",\n            \"nzchinese.com\",\n            \"nzchinese.net.nz\",\n            \"o3o.ca\",\n            \"oaistatic.com\",\n            \"oaiusercontent.com\",\n            \"oanda.com\",\n            \"oann.com\",\n            \"oauth.net\",\n            \"observechina.net\",\n            \"obutu.com\",\n            \"obyte.org\",\n            \"ocaspro.com\",\n            \"occupytiananmen.com\",\n            \"oclp.hk\",\n            \"ocreampies.com\",\n            \"ocry.com\",\n            \"october-review.org\",\n            \"oculus.com\",\n            \"oculuscdn.com\",\n            \"odysee.com\",\n            \"oex.com\",\n            \"offbeatchina.com\",\n            \"officeoftibet.com\",\n            \"ofile.org\",\n            \"ogaoga.org\",\n            \"ogate.org\",\n            \"ohchr.org\",\n            \"ohmyrss.com\",\n            \"oikos.com.tw\",\n            \"oiktv.com\",\n            \"oizoblog.com\",\n            \"ok.ru\",\n            \"ok.xxx\",\n            \"okayfreedom.com\",\n            \"okcoin.com\",\n            \"okex.com\",\n            \"okinawatimes.co.jp\",\n            \"okk.tw\",\n            \"okpool.me\",\n            \"okx.com\",\n            \"old-cat.net\",\n            \"olehdtv.com\",\n            \"olelive.com\",\n            \"olevod.com\",\n            \"olumpo.com\",\n            \"olympicwatch.org\",\n            \"omct.org\",\n            \"omgili.com\",\n            \"omni7.jp\",\n            \"omnitalk.com\",\n            \"omnitalk.org\",\n            \"omny.fm\",\n            \"omtrdc.net\",\n            \"omy.sg\",\n            \"on.cc\",\n            \"on2.com\",\n            \"onapp.com\",\n            \"one.one\",\n            \"onedrive.com\",\n            \"onedumb.com\",\n            \"onejav.com\",\n            \"onesto.re\",\n            \"onestore.co.kr\",\n            \"onevps.com\",\n            \"onion.city\",\n            \"onion.ly\",\n            \"onion666.com\",\n            \"onlinecha.com\",\n            \"onlineyoutube.com\",\n            \"onlygayvideo.com\",\n            \"onlytweets.com\",\n            \"onmoon.com\",\n            \"onmoon.net\",\n            \"onmypc.biz\",\n            \"onmypc.info\",\n            \"onmypc.net\",\n            \"onmypc.org\",\n            \"onthehunt.com\",\n            \"ontrac.com\",\n            \"oojj.de\",\n            \"open-assistant.io\",\n            \"open.com.hk\",\n            \"openai.com\",\n            \"openallweb.com\",\n            \"opendemocracy.net\",\n            \"opendesktop.org\",\n            \"opendn.xyz\",\n            \"openervpn.in\",\n            \"openid.net\",\n            \"openleaks.org\",\n            \"opensea.io\",\n            \"openstreetmap.org\",\n            \"opentech.fund\",\n            \"openvpn.net\",\n            \"openvpn.org\",\n            \"openwebster.com\",\n            \"openwrt.org.cn\",\n            \"opera-mini.net\",\n            \"opera.com\",\n            \"opus-gaming.com\",\n            \"organcare.org.tw\",\n            \"organharvestinvestigation.net\",\n            \"organiccrap.com\",\n            \"orgasm.com\",\n            \"orgfree.com\",\n            \"oricon.co.jp\",\n            \"orient-doll.com\",\n            \"orientaldaily.com.my\",\n            \"orn.jp\",\n            \"orzistic.org\",\n            \"osfoora.com\",\n            \"osm.tw\",\n            \"otcbtc.com\",\n            \"otnd.org\",\n            \"otto.de\",\n            \"otzo.com\",\n            \"ourdearamy.com\",\n            \"ourhobby.com\",\n            \"oursogo.com\",\n            \"oursteps.com.au\",\n            \"oursweb.net\",\n            \"ourtv.hk\",\n            \"over-blog.com\",\n            \"overcast.fm\",\n            \"overdaily.org\",\n            \"overplay.net\",\n            \"ovi.com\",\n            \"ovpn.com\",\n            \"ow.ly\",\n            \"owind.com\",\n            \"owl.li\",\n            \"owltail.com\",\n            \"oxfordscholarship.com\",\n            \"oxid.it\",\n            \"oyax.com\",\n            \"oyghan.com\",\n            \"ozchinese.com\",\n            \"ozvoice.org\",\n            \"ozxw.com\",\n            \"ozyoyo.com\",\n            \"pachosting.com\",\n            \"pacificpoker.com\",\n            \"packetix.net\",\n            \"pacom.mil\",\n            \"pacopacomama.com\",\n            \"padmanet.com\",\n            \"page.link\",\n            \"page.tl\",\n            \"page2rss.com\",\n            \"pages.dev\",\n            \"pagodabox.com\",\n            \"paimon.moe\",\n            \"palacemoon.com\",\n            \"paldengyal.com\",\n            \"paljorpublications.com\",\n            \"palmislife.com\",\n            \"paltalk.com\",\n            \"pancakeswap.finance\",\n            \"pandafan.pub\",\n            \"pandapow.co\",\n            \"pandapow.net\",\n            \"pandavpn-jp.com\",\n            \"pandavpnpro.com\",\n            \"pandora.com\",\n            \"pandora.tv\",\n            \"panluan.net\",\n            \"panoramio.com\",\n            \"pao-pao.net\",\n            \"paper.li\",\n            \"paperb.us\",\n            \"paperclip.tk\",\n            \"paradisehill.cc\",\n            \"paradisepoker.com\",\n            \"parkansky.com\",\n            \"parler.com\",\n            \"parse.com\",\n            \"parsevideo.com\",\n            \"partycasino.com\",\n            \"partypoker.com\",\n            \"passion.com\",\n            \"passiontimes.hk\",\n            \"paste.ee\",\n            \"pastebin.com\",\n            \"pastie.org\",\n            \"pathtosharepoint.com\",\n            \"patreon.com\",\n            \"patreonusercontent.com\",\n            \"pawoo.net\",\n            \"paxful.com\",\n            \"pbs.org\",\n            \"pbwiki.com\",\n            \"pbworks.com\",\n            \"pbxes.com\",\n            \"pbxes.org\",\n            \"pcanywhere.net\",\n            \"pcc.gov.tw\",\n            \"pcdvd.com.tw\",\n            \"pcgamestorrents.com\",\n            \"pchome.com.tw\",\n            \"pchomeec.tw\",\n            \"pcij.org\",\n            \"pcloud.com\",\n            \"pcmarket.com.hk\",\n            \"pcstore.com.tw\",\n            \"pct.org.tw\",\n            \"pdetails.com\",\n            \"pdproxy.com\",\n            \"peace.ca\",\n            \"peacefire.org\",\n            \"peacehall.com\",\n            \"peeasian.com\",\n            \"peing.net\",\n            \"pekingduck.org\",\n            \"pemulihan.or.id\",\n            \"pen.io\",\n            \"penchinese.com\",\n            \"penchinese.net\",\n            \"pendrivelinux.com\",\n            \"pentalogic.net\",\n            \"penthouse.com\",\n            \"pentoy.hk\",\n            \"peoplebookcafe.com\",\n            \"peoplenews.tw\",\n            \"peopo.org\",\n            \"percy.in\",\n            \"perfect-privacy.com\",\n            \"perfectgirls.net\",\n            \"perfectvpn.net\",\n            \"periscope.tv\",\n            \"perplexity.ai\",\n            \"persecutionblog.com\",\n            \"persiankitty.com\",\n            \"pewresearch.org\",\n            \"pfd.org.hk\",\n            \"phapluan.org\",\n            \"phayul.com\",\n            \"philborges.com\",\n            \"phmsociety.org\",\n            \"phncdn.com\",\n            \"phonegap.com\",\n            \"photodharma.net\",\n            \"photofocus.com\",\n            \"photonmedia.net\",\n            \"phprcdn.com\",\n            \"phptutorial.net\",\n            \"phuquocservices.com\",\n            \"piaotia.com\",\n            \"picacomic.com\",\n            \"picacomiccn.com\",\n            \"picasaweb.com\",\n            \"picgo.net\",\n            \"picidae.net\",\n            \"picturedip.com\",\n            \"picturesocial.com\",\n            \"picuki.com\",\n            \"pigav.com\",\n            \"pimg.tw\",\n            \"pin-cong.com\",\n            \"pin6.com\",\n            \"pincong.rocks\",\n            \"ping.fm\",\n            \"pinimg.com\",\n            \"pinkrod.com\",\n            \"pinoy-n.com\",\n            \"pinterest.at\",\n            \"pinterest.ca\",\n            \"pinterest.co.uk\",\n            \"pinterest.com\",\n            \"pinterest.de\",\n            \"pinterest.dk\",\n            \"pinterest.fr\",\n            \"pinterest.jp\",\n            \"pinterest.nl\",\n            \"pinterest.se\",\n            \"pionex.com\",\n            \"pipii.tv\",\n            \"piposay.com\",\n            \"piraattilahti.org\",\n            \"piring.com\",\n            \"pixeldrain.com\",\n            \"pixelqi.com\",\n            \"pixiv.net\",\n            \"pixiv.org\",\n            \"pixivsketch.net\",\n            \"pixnet.in\",\n            \"pixnet.net\",\n            \"pk.com\",\n            \"pki.goog\",\n            \"pkqjiasu.com\",\n            \"pkuanvil.com\",\n            \"placemix.com\",\n            \"play-asia.com\",\n            \"playbeasts.com\",\n            \"playboy.com\",\n            \"playboyplus.com\",\n            \"player.fm\",\n            \"playno1.com\",\n            \"playpcesor.com\",\n            \"plays.com.tw\",\n            \"plexvpn.pro\",\n            \"plixi.com\",\n            \"plm.org.hk\",\n            \"plunder.com\",\n            \"plurk.com\",\n            \"plus.codes\",\n            \"plus28.com\",\n            \"plusbb.com\",\n            \"pmatehunter.com\",\n            \"pmates.com\",\n            \"po2b.com\",\n            \"pobieramy.top\",\n            \"podbean.com\",\n            \"podcast.app\",\n            \"podcast.co\",\n            \"podictionary.com\",\n            \"poe.com\",\n            \"points-media.com\",\n            \"pokerstars.com\",\n            \"pokerstars.net\",\n            \"pokerstrategy.com\",\n            \"politicalchina.org\",\n            \"politicalconsultation.org\",\n            \"politico.eu\",\n            \"politiscales.net\",\n            \"poloniex.com\",\n            \"polymarket.com\",\n            \"polymer-project.org\",\n            \"polymerhk.com\",\n            \"poolbinance.com\",\n            \"poolin.com\",\n            \"popai.pro\",\n            \"popo.tw\",\n            \"popvote.hk\",\n            \"popxi.click\",\n            \"popyard.com\",\n            \"popyard.org\",\n            \"porn.biz\",\n            \"porn.com\",\n            \"porn2.com\",\n            \"porn5.com\",\n            \"pornbase.org\",\n            \"pornerbros.com\",\n            \"pornhd.com\",\n            \"pornhost.com\",\n            \"pornhub.com\",\n            \"pornhubdeutsch.net\",\n            \"pornhubpremium.com\",\n            \"pornmate.com\",\n            \"pornmm.net\",\n            \"pornoxo.com\",\n            \"pornrapidshare.com\",\n            \"pornsharing.com\",\n            \"pornsocket.com\",\n            \"pornstarbyface.com\",\n            \"pornstarclub.com\",\n            \"porntube.com\",\n            \"porntubenews.com\",\n            \"porntvblog.com\",\n            \"pornvisit.com\",\n            \"port25.biz\",\n            \"portablevpn.nl\",\n            \"poskotanews.com\",\n            \"post01.com\",\n            \"post76.com\",\n            \"post852.com\",\n            \"postadult.com\",\n            \"potato.im\",\n            \"potatso.com\",\n            \"potvpn.com\",\n            \"pourquoi.tw\",\n            \"power.com\",\n            \"powerapple.com\",\n            \"powercx.com\",\n            \"powerphoto.org\",\n            \"powerpointninja.com\",\n            \"pp.ru\",\n            \"ppy.sh\",\n            \"prayforchina.net\",\n            \"prcleader.org\",\n            \"premeforwindows7.com\",\n            \"premproxy.com\",\n            \"presentation.new\",\n            \"presentationzen.com\",\n            \"president.ir\",\n            \"presidentlee.tw\",\n            \"pressreader.com\",\n            \"prestige-av.com\",\n            \"prettyvirgin.com\",\n            \"primevideo.com\",\n            \"printfriendly.com\",\n            \"prism-break.org\",\n            \"prisoneralert.com\",\n            \"pritunl.com\",\n            \"privacybox.de\",\n            \"privacyguides.org\",\n            \"private.com\",\n            \"privateinternetaccess.com\",\n            \"privatepaste.com\",\n            \"privatetunnel.com\",\n            \"privatevpn.com\",\n            \"privoxy.org\",\n            \"procopytips.com\",\n            \"prohashing.com\",\n            \"project-syndicate.org\",\n            \"prosiben.de\",\n            \"proton.me\",\n            \"protonvpn.com\",\n            \"provideocoalition.com\",\n            \"provpnaccounts.com\",\n            \"proxfree.com\",\n            \"proxifier.com\",\n            \"proxlet.com\",\n            \"proxomitron.info\",\n            \"proxpn.com\",\n            \"proxy.org\",\n            \"proxy1.xyz\",\n            \"proxyanonimo.es\",\n            \"proxydns.com\",\n            \"proxylist.org.uk\",\n            \"proxynetwork.org.uk\",\n            \"proxyroad.com\",\n            \"proxytunnel.net\",\n            \"proxz.com\",\n            \"proyectoclubes.com\",\n            \"prozz.net\",\n            \"psblog.name\",\n            \"pscp.tv\",\n            \"pshvpn.com\",\n            \"psiphon.ca\",\n            \"psiphon3.com\",\n            \"psiphontoday.com\",\n            \"pstatic.net\",\n            \"pt.im\",\n            \"pts.org.tw\",\n            \"ptt.cc\",\n            \"pttgame.com\",\n            \"ptthito.com\",\n            \"pttvan.org\",\n            \"pttweb.cc\",\n            \"pttyes.com\",\n            \"ptwxz.com\",\n            \"pubu.com.tw\",\n            \"puffin.com\",\n            \"puffinbrowser.com\",\n            \"puffstore.com\",\n            \"pugpig.com\",\n            \"pullfolio.com\",\n            \"punjab.gov.in\",\n            \"punjab.gov.pk\",\n            \"punyu.com\",\n            \"pure18.com\",\n            \"pureapk.com\",\n            \"pureconcepts.net\",\n            \"puredns.org\",\n            \"pureinsight.org\",\n            \"purepdf.com\",\n            \"purevpn.com\",\n            \"purplelotus.org\",\n            \"pursuestar.com\",\n            \"pushchinawall.com\",\n            \"pussyspace.com\",\n            \"putihome.org\",\n            \"putlocker.com\",\n            \"putty.org\",\n            \"puuko.com\",\n            \"pwned.com\",\n            \"pximg.net\",\n            \"python.com\",\n            \"python.com.tw\",\n            \"pythonhackers.com\",\n            \"pythonic.life\",\n            \"pytorch.org\",\n            \"qanote.com\",\n            \"qbittorrent.org\",\n            \"qgirl.com.tw\",\n            \"qhigh.com\",\n            \"qi-gong.me\",\n            \"qianbai.tw\",\n            \"qiandao.today\",\n            \"qianglie.com\",\n            \"qiangwaikan.com\",\n            \"qiangyou.org\",\n            \"qianmo.tw\",\n            \"qidian.ca\",\n            \"qienkuen.org\",\n            \"qiwen.lu\",\n            \"qixianglu.cn\",\n            \"qkshare.com\",\n            \"qmp4.com\",\n            \"qoos.com\",\n            \"qpoe.com\",\n            \"qq.co.za\",\n            \"qstatus.com\",\n            \"qtrac.eu\",\n            \"qtweeter.com\",\n            \"quannengshen.org\",\n            \"questvisual.com\",\n            \"quitccp.net\",\n            \"quitccp.org\",\n            \"quiz.directory\",\n            \"quora.com\",\n            \"quoracdn.net\",\n            \"quran.com\",\n            \"quranexplorer.com\",\n            \"qusi8.net\",\n            \"qvodzy.org\",\n            \"qwant.com\",\n            \"qx.net\",\n            \"qxbbs.org\",\n            \"qz.com\",\n            \"r-pool.net\",\n            \"r0.ru\",\n            \"r10s.jp\",\n            \"r18.com\",\n            \"ra.gg\",\n            \"radicalparty.org\",\n            \"radiko.jp\",\n            \"radio-canada.ca\",\n            \"radio-en-ligne.fr\",\n            \"radio.garden\",\n            \"radioaustralia.net.au\",\n            \"radiohilight.net\",\n            \"radioline.co\",\n            \"radiotime.com\",\n            \"radiovaticana.org\",\n            \"radiovncr.com\",\n            \"radmin-vpn.com\",\n            \"rael.org\",\n            \"raggedbanner.com\",\n            \"raidcall.com.tw\",\n            \"rainbowplan.org\",\n            \"raindrop.io\",\n            \"raizoji.or.jp\",\n            \"rakuten.co.jp\",\n            \"rakuten.com.tw\",\n            \"ramcity.com.au\",\n            \"rangwang.biz\",\n            \"rangzen.com\",\n            \"rangzen.net\",\n            \"rangzen.org\",\n            \"ranxiang.com\",\n            \"ranyunfei.com\",\n            \"rapbull.net\",\n            \"rapidmoviez.com\",\n            \"rapidvpn.com\",\n            \"rarbgprx.org\",\n            \"raremovie.cc\",\n            \"raremovie.net\",\n            \"rateyourmusic.com\",\n            \"rationalwiki.org\",\n            \"ratx.com\",\n            \"rawgit.com\",\n            \"rawgithub.com\",\n            \"razyboard.com\",\n            \"rcinet.ca\",\n            \"rd.com\",\n            \"reabble.com\",\n            \"read01.com\",\n            \"read100.com\",\n            \"readingtimes.com.tw\",\n            \"readmoo.com\",\n            \"readydown.com\",\n            \"realcourage.org\",\n            \"realitykings.com\",\n            \"realraptalk.com\",\n            \"realsexpass.com\",\n            \"reason.com\",\n            \"rebatesrule.net\",\n            \"recaptcha.net\",\n            \"recordhistory.org\",\n            \"recovery.org.tw\",\n            \"recoveryversion.com.tw\",\n            \"recoveryversion.org\",\n            \"red-lang.org\",\n            \"redballoonsolidarity.org\",\n            \"redbubble.com\",\n            \"redchinacn.net\",\n            \"redchinacn.org\",\n            \"redd.it\",\n            \"reddit.com\",\n            \"reddithelp.com\",\n            \"redditlist.com\",\n            \"redditmedia.com\",\n            \"redditspace.com\",\n            \"redditstatic.com\",\n            \"redhotlabs.com\",\n            \"redtube.com\",\n            \"referer.us\",\n            \"reflectivecode.com\",\n            \"reimu.net\",\n            \"relaxbbs.com\",\n            \"relay.com.tw\",\n            \"releaseinternational.org\",\n            \"religionnews.com\",\n            \"religioustolerance.org\",\n            \"renminbao.com\",\n            \"renyurenquan.org\",\n            \"resilio.com\",\n            \"resistchina.org\",\n            \"retweeteffect.com\",\n            \"retweetist.com\",\n            \"retweetrank.com\",\n            \"reuters.com\",\n            \"reutersmedia.net\",\n            \"revleft.com\",\n            \"revocationcheck.com\",\n            \"revver.com\",\n            \"rfa.org\",\n            \"rfachina.com\",\n            \"rfamobile.org\",\n            \"rfaweb.org\",\n            \"rferl.org\",\n            \"rfi.fr\",\n            \"rfi.my\",\n            \"rigpa.org\",\n            \"riku.me\",\n            \"rileyguide.com\",\n            \"riseup.net\",\n            \"ritouki.jp\",\n            \"ritter.vg\",\n            \"rixcloud.com\",\n            \"rixcloud.us\",\n            \"rlcdn.com\",\n            \"rlwlw.com\",\n            \"rmbl.ws\",\n            \"rmjdw.com\",\n            \"rmjdw132.info\",\n            \"roadshow.hk\",\n            \"roboforex.com\",\n            \"robustnessiskey.com\",\n            \"rocket-inc.net\",\n            \"rocket.chat\",\n            \"rocketbbs.com\",\n            \"rocksdb.org\",\n            \"rojo.com\",\n            \"rolfoundation.org\",\n            \"rolia.net\",\n            \"rolsociety.org\",\n            \"ronjoneswriter.com\",\n            \"roodo.com\",\n            \"rosechina.net\",\n            \"rotten.com\",\n            \"rou.video\",\n            \"roucdn.link\",\n            \"rsdlmonitor.com\",\n            \"rsf-chinese.org\",\n            \"rsf.org\",\n            \"rsgamen.org\",\n            \"rsshub.app\",\n            \"rssing.com\",\n            \"rssmeme.com\",\n            \"rtalabel.org\",\n            \"rthk.hk\",\n            \"rthk.org.hk\",\n            \"rti.org.tw\",\n            \"rti.tw\",\n            \"rtycminnesota.org\",\n            \"ruanyifeng.com\",\n            \"rukor.org\",\n            \"rule34.xxx\",\n            \"rule34video.com\",\n            \"rumble.com\",\n            \"runbtx.com\",\n            \"rushbee.com\",\n            \"rusvpn.com\",\n            \"ruten.com.tw\",\n            \"rutracker.net\",\n            \"rutracker.org\",\n            \"rutube.ru\",\n            \"ruyiseek.com\",\n            \"rxhj.net\",\n            \"s-cute.com\",\n            \"s-dragon.org\",\n            \"s-nbcnews.com\",\n            \"s1heng.com\",\n            \"s1s1s1.com\",\n            \"s3-ap-northeast-1.amazonaws.com\",\n            \"s3-ap-northeast-2.amazonaws.com\",\n            \"s3-ap-southeast-1.amazonaws.com\",\n            \"s3-ap-southeast-2.amazonaws.com\",\n            \"s3-eu-central-1.amazonaws.com\",\n            \"s3.amazonaws.com\",\n            \"s3.ap-northeast-2.amazonaws.com\",\n            \"s3.eu-central-1.amazonaws.com\",\n            \"s3.us-east-1.amazonaws.com\",\n            \"s4miniarchive.com\",\n            \"s8forum.com\",\n            \"saboom.com\",\n            \"sacks.com\",\n            \"sacom.hk\",\n            \"sadistic-v.com\",\n            \"sadpanda.us\",\n            \"saeima.lv\",\n            \"safechat.com\",\n            \"safeguarddefenders.com\",\n            \"safervpn.com\",\n            \"sagernet.org\",\n            \"saintyculture.com\",\n            \"sakura-paris.org\",\n            \"sakuralive.com\",\n            \"sakya.org\",\n            \"salvation.org.hk\",\n            \"samair.ru\",\n            \"sambhota.org\",\n            \"sandscotaicentral.com\",\n            \"sankakucomplex.com\",\n            \"sankei.com\",\n            \"sanmin.com.tw\",\n            \"sans.edu\",\n            \"sapikachu.net\",\n            \"saveliuxiaobo.com\",\n            \"savemedia.com\",\n            \"savethedate.foo\",\n            \"savethesounds.info\",\n            \"savetibet.de\",\n            \"savetibet.fr\",\n            \"savetibet.nl\",\n            \"savetibet.org\",\n            \"savetibet.ru\",\n            \"savetibetstore.org\",\n            \"saveuighur.org\",\n            \"savevid.com\",\n            \"sbme.me\",\n            \"sbs.com.au\",\n            \"scasino.com\",\n            \"schema.org\",\n            \"sciencemag.org\",\n            \"sciencenets.com\",\n            \"scieron.com\",\n            \"sclub.com.tw\",\n            \"scmp.com\",\n            \"scmpchinese.com\",\n            \"scramble.io\",\n            \"scribd.com\",\n            \"scriptspot.com\",\n            \"seapuff.com\",\n            \"search.com\",\n            \"search.xxx\",\n            \"searchtruth.com\",\n            \"searx.me\",\n            \"seatguru.com\",\n            \"seattlefdc.com\",\n            \"secretchina.com\",\n            \"secretgarden.no\",\n            \"secretsline.biz\",\n            \"secureservercdn.net\",\n            \"securetunnel.com\",\n            \"securityinabox.org\",\n            \"securitykiss.com\",\n            \"see.xxx\",\n            \"seed4.me\",\n            \"seehua.com\",\n            \"seesmic.com\",\n            \"seevpn.com\",\n            \"seezone.net\",\n            \"sehuatang.net\",\n            \"sehuatang.org\",\n            \"sejie.com\",\n            \"seju.life\",\n            \"sellclassics.com\",\n            \"sendsmtp.com\",\n            \"sendspace.com\",\n            \"sensortower.com\",\n            \"servehttp.com\",\n            \"serveuser.com\",\n            \"serveusers.com\",\n            \"sesawe.net\",\n            \"sesawe.org\",\n            \"sethwklein.net\",\n            \"setn.com\",\n            \"settv.com.tw\",\n            \"sevenload.com\",\n            \"sex-11.com\",\n            \"sex.com\",\n            \"sex3.com\",\n            \"sex8.cc\",\n            \"sexandsubmission.com\",\n            \"sexbot.com\",\n            \"sexhu.com\",\n            \"sexhuang.com\",\n            \"sexidude.com\",\n            \"sexinsex.net\",\n            \"sextvx.com\",\n            \"sf.net\",\n            \"sfileydy.com\",\n            \"sfshibao.com\",\n            \"sftindia.org\",\n            \"sftuk.org\",\n            \"sgwritings.com\",\n            \"sgzhan.com\",\n            \"shadeyouvpn.com\",\n            \"shadow.ma\",\n            \"shadowsky.xyz\",\n            \"shadowsocks-r.com\",\n            \"shadowsocks.asia\",\n            \"shadowsocks.be\",\n            \"shadowsocks.com\",\n            \"shadowsocks.com.hk\",\n            \"shadowsocks.nu\",\n            \"shadowsocks.org\",\n            \"shafaqna.com\",\n            \"shahit.biz\",\n            \"shambalapost.com\",\n            \"shambhalasun.com\",\n            \"shangfang.org\",\n            \"shanxivideo.com\",\n            \"shapeservices.com\",\n            \"share-videos.se\",\n            \"sharebee.com\",\n            \"sharecool.org\",\n            \"sharpdaily.com.hk\",\n            \"sharpdaily.hk\",\n            \"sharpdaily.tw\",\n            \"shat-tibet.com\",\n            \"shattered.io\",\n            \"sheet.new\",\n            \"sheets.new\",\n            \"sheikyermami.com\",\n            \"shellfire.de\",\n            \"shemalez.com\",\n            \"shenshou.org\",\n            \"shenyun.com\",\n            \"shenyunperformingarts.org\",\n            \"shenyunshop.com\",\n            \"shenzhoufilm.com\",\n            \"shenzhouzhengdao.org\",\n            \"sherabgyaltsen.com\",\n            \"shiatv.net\",\n            \"shicheng.org\",\n            \"shiksha.com\",\n            \"shiksha.ws\",\n            \"shipcamouflage.com\",\n            \"shireyishunjian.com\",\n            \"shitaotv.org\",\n            \"shixiao.org\",\n            \"shizhao.org\",\n            \"shkspr.mobi\",\n            \"shodanhq.com\",\n            \"shooshtime.com\",\n            \"shop2000.com.tw\",\n            \"shopee.tw\",\n            \"shopping.com\",\n            \"showhaotu.com\",\n            \"showtime.jp\",\n            \"showwe.tw\",\n            \"shutterstock.com\",\n            \"shwchurch.org\",\n            \"shwchurch3.com\",\n            \"siddharthasintent.org\",\n            \"sidelinesnews.com\",\n            \"sidelinessportseatery.com\",\n            \"sierrafriendsoftibet.org\",\n            \"signal.org\",\n            \"sijihuisuo.club\",\n            \"sijihuisuo.com\",\n            \"silkbook.com\",\n            \"silvergatebank.com\",\n            \"simbolostwitter.com\",\n            \"simplecd.me\",\n            \"simplecd.org\",\n            \"simpleproductivityblog.com\",\n            \"simpleswap.io\",\n            \"simplex.chat\",\n            \"sina.com\",\n            \"sina.com.hk\",\n            \"sinchew.com.my\",\n            \"singaporepools.com.sg\",\n            \"singfortibet.com\",\n            \"singlelogin.me\",\n            \"singlelogin.se\",\n            \"singpao.com.hk\",\n            \"singtao.ca\",\n            \"singtao.com\",\n            \"singtaousa.com\",\n            \"sino-monthly.com\",\n            \"sinoants.com\",\n            \"sinoca.com\",\n            \"sinocast.com\",\n            \"sinocism.com\",\n            \"sinoinsider.com\",\n            \"sinomontreal.ca\",\n            \"sinonet.ca\",\n            \"sinopitt.info\",\n            \"sinoquebec.com\",\n            \"sipml5.org\",\n            \"sis.xxx\",\n            \"sis001.com\",\n            \"sis001.us\",\n            \"site.new\",\n            \"site2unblock.com\",\n            \"site90.net\",\n            \"sitebro.tw\",\n            \"sitekreator.com\",\n            \"sitemaps.org\",\n            \"sites.new\",\n            \"six-degrees.io\",\n            \"sixth.biz\",\n            \"sjrt.org\",\n            \"sjum.cn\",\n            \"sketchappsources.com\",\n            \"skimtube.com\",\n            \"skk.moe\",\n            \"skybet.com\",\n            \"skyking.com.tw\",\n            \"skykiwi.com\",\n            \"skynet.be\",\n            \"skype.com\",\n            \"skyvegas.com\",\n            \"skyxvpn.com\",\n            \"sl-reverse.com\",\n            \"slacker.com\",\n            \"slandr.net\",\n            \"slashine.onl\",\n            \"slaytizle.com\",\n            \"sleazydream.com\",\n            \"sleazyfork.org\",\n            \"slheng.com\",\n            \"slickvpn.com\",\n            \"slides.com\",\n            \"slides.new\",\n            \"slideshare.net\",\n            \"slime.com.tw\",\n            \"slinkset.com\",\n            \"slutload.com\",\n            \"slutmoonbeam.com\",\n            \"slyip.com\",\n            \"slyip.net\",\n            \"sm-miracle.com\",\n            \"sm3ha.ru\",\n            \"smartdnsproxy.com\",\n            \"smarthide.com\",\n            \"smartmailcloud.com\",\n            \"smashwords.com\",\n            \"smchbooks.com\",\n            \"smh.com.au\",\n            \"smhric.org\",\n            \"smith.edu\",\n            \"smn.news\",\n            \"smyxy.org\",\n            \"snapchat.com\",\n            \"snapseed.com\",\n            \"snaptu.com\",\n            \"sndcdn.com\",\n            \"sneakme.net\",\n            \"snow-plus.net\",\n            \"snowlionpub.com\",\n            \"so-net.net.tw\",\n            \"soav.com\",\n            \"sobees.com\",\n            \"soc.mil\",\n            \"social.edu.ci\",\n            \"socialblade.com\",\n            \"socks-proxy.net\",\n            \"sockscap64.com\",\n            \"sockslist.net\",\n            \"socrec.org\",\n            \"sod.co.jp\",\n            \"softether-download.com\",\n            \"softether.co.jp\",\n            \"softether.org\",\n            \"softfamous.com\",\n            \"softlayer.net\",\n            \"softonic.cn\",\n            \"softonic.com\",\n            \"softwarebychuck.com\",\n            \"sogclub.com\",\n            \"sogoo.org\",\n            \"sogrady.me\",\n            \"soh.tw\",\n            \"sohcradio.com\",\n            \"sohfrance.org\",\n            \"soifind.com\",\n            \"sokamonline.com\",\n            \"sokmil.com\",\n            \"solana.com\",\n            \"solidaritetibet.org\",\n            \"solidfiles.com\",\n            \"solv.finance\",\n            \"somee.com\",\n            \"songjianjun.com\",\n            \"sonicbbs.cc\",\n            \"sonidodelaesperanza.org\",\n            \"sony.com\",\n            \"sopcast.com\",\n            \"sopcast.org\",\n            \"sophos.com\",\n            \"sorazone.net\",\n            \"sorting-algorithms.com\",\n            \"sos.org\",\n            \"sosad.fun\",\n            \"sosreader.com\",\n            \"sostibet.org\",\n            \"sotwe.com\",\n            \"sou-tong.org\",\n            \"soubory.com\",\n            \"soul-plus.net\",\n            \"soulcaliburhentai.net\",\n            \"soundcloud.com\",\n            \"soundofhope.kr\",\n            \"soundofhope.org\",\n            \"soundon.fm\",\n            \"soup.io\",\n            \"soupofmedia.com\",\n            \"sourceforge.net\",\n            \"sourcewadio.com\",\n            \"south-plus.net\",\n            \"south-plus.org\",\n            \"southmongolia.org\",\n            \"southnews.com.tw\",\n            \"sowers.org.hk\",\n            \"sowiki.net\",\n            \"soylent.com\",\n            \"soylentnews.org\",\n            \"spankbang.com\",\n            \"spankingtube.com\",\n            \"spankwire.com\",\n            \"sparkpool.com\",\n            \"spatial.io\",\n            \"spb.com\",\n            \"speakerdeck.com\",\n            \"speedcat.me\",\n            \"speedify.com\",\n            \"spem.at\",\n            \"spencertipping.com\",\n            \"spendee.com\",\n            \"spicevpn.com\",\n            \"spideroak.com\",\n            \"spiderpool.com\",\n            \"spiegel.de\",\n            \"spike.com\",\n            \"spotflux.com\",\n            \"spotify.com\",\n            \"spreadsheet.new\",\n            \"spreadshirt.es\",\n            \"spreaker.com\",\n            \"spring-plus.net\",\n            \"spring4u.info\",\n            \"springboardplatform.com\",\n            \"springwood.me\",\n            \"sprite.org\",\n            \"sproutcore.com\",\n            \"sproxy.info\",\n            \"squirly.info\",\n            \"squirrelvpn.com\",\n            \"srocket.us\",\n            \"ss-link.com\",\n            \"ssglobal.co\",\n            \"ssglobal.me\",\n            \"ssh91.com\",\n            \"ssl443.org\",\n            \"sspanel.net\",\n            \"sspanel.org\",\n            \"sspro.ml\",\n            \"ssr.tools\",\n            \"ssrshare.com\",\n            \"ssrshare.us\",\n            \"ssrtool.com\",\n            \"sss.camp\",\n            \"sstm.moe\",\n            \"sstmlt.moe\",\n            \"sstmlt.net\",\n            \"stackcommerce.net\",\n            \"stackoverflow.com\",\n            \"stacksocial.com\",\n            \"stage64.hk\",\n            \"standard.co.uk\",\n            \"standupfortibet.org\",\n            \"standwithhk.org\",\n            \"stanford.edu\",\n            \"starfishfx.com\",\n            \"starp2p.com\",\n            \"startpage.com\",\n            \"startuplivingchina.com\",\n            \"stat.gov.tw\",\n            \"state.gov\",\n            \"statearmor.org\",\n            \"static-economist.com\",\n            \"statically.io\",\n            \"staticflickr.com\",\n            \"statsig.com\",\n            \"statueofdemocracy.org\",\n            \"stboy.net\",\n            \"stc.com.sa\",\n            \"steamcommunity.com\",\n            \"steampowered.com\",\n            \"steamstatic.com\",\n            \"steel-storm.com\",\n            \"steemit.com\",\n            \"steganos.com\",\n            \"steganos.net\",\n            \"stepchina.com\",\n            \"stephaniered.com\",\n            \"stgloballink.com\",\n            \"stheadline.com\",\n            \"sthoo.com\",\n            \"stickam.com\",\n            \"stickeraction.com\",\n            \"stileproject.com\",\n            \"stitcher.com\",\n            \"sto.cc\",\n            \"stoporganharvesting.org\",\n            \"stoptibetcrisis.net\",\n            \"storagenewsletter.com\",\n            \"storify.com\",\n            \"storj.io\",\n            \"storm.mg\",\n            \"stormmediagroup.com\",\n            \"storry.tv\",\n            \"stoweboyd.com\",\n            \"straitstimes.com\",\n            \"stranabg.com\",\n            \"straplessdildo.com\",\n            \"streamable.com\",\n            \"streamate.com\",\n            \"streamguys1.com\",\n            \"streamingthe.net\",\n            \"streema.com\",\n            \"streetvoice.com\",\n            \"striek.com\",\n            \"strikingly.com\",\n            \"strongvpn.com\",\n            \"strongwindpress.com\",\n            \"student.tw\",\n            \"studentsforafreetibet.org\",\n            \"studybuddhism.com\",\n            \"stumbleupon.com\",\n            \"stupidvideos.com\",\n            \"stweetly.com\",\n            \"subhd.tv\",\n            \"substack.com\",\n            \"successfn.com\",\n            \"sueddeutsche.de\",\n            \"sugarsync.com\",\n            \"sugobbs.com\",\n            \"sugumiru18.com\",\n            \"suissl.com\",\n            \"summify.com\",\n            \"sumrando.com\",\n            \"sun1911.com\",\n            \"sundayguardianlive.com\",\n            \"sunmedia.ca\",\n            \"suno.ai\",\n            \"suno.com\",\n            \"sunporno.com\",\n            \"sunskyforum.com\",\n            \"sunta.com.tw\",\n            \"sunvpn.net\",\n            \"suoluo.org\",\n            \"supchina.com\",\n            \"superfreevpn.com\",\n            \"superpages.com\",\n            \"supervpn.net\",\n            \"superzooi.com\",\n            \"supjav.com\",\n            \"suppig.net\",\n            \"suprememastertv.com\",\n            \"surfeasy.com\",\n            \"surfeasy.com.au\",\n            \"surfshark.com\",\n            \"suroot.com\",\n            \"surrenderat20.net\",\n            \"suyangg.com\",\n            \"svsfx.com\",\n            \"swagbucks.com\",\n            \"swapspace.co\",\n            \"swbusdev.com\",\n            \"swissinfo.ch\",\n            \"swissvpn.net\",\n            \"switch1.jp\",\n            \"switchvpn.net\",\n            \"sydneytoday.com\",\n            \"sylfoundation.org\",\n            \"synapse.org\",\n            \"syncback.com\",\n            \"synergyse.com\",\n            \"syosetu.com\",\n            \"sysresccd.org\",\n            \"sytes.net\",\n            \"syx86.com\",\n            \"szbbs.net\",\n            \"szetowah.org.hk\",\n            \"t-g.com\",\n            \"t.co\",\n            \"t.me\",\n            \"t35.com\",\n            \"t35hosting.com\",\n            \"t66y.com\",\n            \"t91y.com\",\n            \"taa-usa.org\",\n            \"taaze.tw\",\n            \"tablesgenerator.com\",\n            \"tabtter.jp\",\n            \"tacem.org\",\n            \"taconet.com.tw\",\n            \"taedp.org.tw\",\n            \"tafm.org\",\n            \"tagesschau.de\",\n            \"tagwa.org.au\",\n            \"tagwalk.com\",\n            \"tahr.org.tw\",\n            \"taipei.gov.tw\",\n            \"taipeisociety.org\",\n            \"taipeitimes.com\",\n            \"taisounds.com\",\n            \"taiwan-sex.com\",\n            \"taiwanbible.com\",\n            \"taiwancon.com\",\n            \"taiwandaily.net\",\n            \"taiwandc.org\",\n            \"taiwanhot.net\",\n            \"taiwanjobs.gov.tw\",\n            \"taiwanjustice.com\",\n            \"taiwanjustice.net\",\n            \"taiwankiss.com\",\n            \"taiwannation.com\",\n            \"taiwannation.com.tw\",\n            \"taiwanncf.org.tw\",\n            \"taiwannews.com.tw\",\n            \"taiwanonline.cc\",\n            \"taiwantp.net\",\n            \"taiwantt.org.tw\",\n            \"taiwanus.net\",\n            \"taiwanyes.com\",\n            \"talk853.com\",\n            \"talkatone.com\",\n            \"talkboxapp.com\",\n            \"talkcc.com\",\n            \"talkonly.net\",\n            \"tamiaode.tk\",\n            \"tampabay.com\",\n            \"tanc.org\",\n            \"tangben.com\",\n            \"tangren.us\",\n            \"tanks.gg\",\n            \"taoism.net\",\n            \"taolun.info\",\n            \"tapanwap.com\",\n            \"tapatalk.com\",\n            \"taragana.com\",\n            \"tardigrade.io\",\n            \"target.com\",\n            \"tascn.com.au\",\n            \"taup.net\",\n            \"taup.org.tw\",\n            \"taweet.com\",\n            \"tbcollege.org\",\n            \"tbi.org.hk\",\n            \"tbjyt.org\",\n            \"tbrc.org\",\n            \"tbs-rainbow.org\",\n            \"tbs.co.jp\",\n            \"tbsec.org\",\n            \"tbsn.org\",\n            \"tbsseattle.org\",\n            \"tbssqh.org\",\n            \"tbswd.org\",\n            \"tbtemple.org.uk\",\n            \"tbthouston.org\",\n            \"tccwonline.org\",\n            \"tcewf.org\",\n            \"tchrd.org\",\n            \"tcnynj.org\",\n            \"tcpspeed.co\",\n            \"tcpspeed.com\",\n            \"tcsofbc.org\",\n            \"tcsovi.org\",\n            \"tdesktop.com\",\n            \"tdm.com.mo\",\n            \"teachparentstech.org\",\n            \"teamamericany.com\",\n            \"techcrunch.com\",\n            \"technews.tw\",\n            \"techspot.com\",\n            \"techviz.net\",\n            \"teck.in\",\n            \"teco-hk.org\",\n            \"teco-mo.org\",\n            \"teddysun.com\",\n            \"teenfucks.org\",\n            \"teeniefuck.net\",\n            \"teensinasia.com\",\n            \"teepr.com\",\n            \"tehrantimes.com\",\n            \"telecomspace.com\",\n            \"telega.one\",\n            \"telegra.ph\",\n            \"telegram.dog\",\n            \"telegram.me\",\n            \"telegram.org\",\n            \"telegram.space\",\n            \"telegramdownload.com\",\n            \"telegraph.co.uk\",\n            \"telesco.pe\",\n            \"tellapart.com\",\n            \"tellme.pw\",\n            \"tenacy.com\",\n            \"tenor.com\",\n            \"tensorflow.org\",\n            \"tenzinpalmo.com\",\n            \"terabox.com\",\n            \"tew.org\",\n            \"textnow.com\",\n            \"textnow.me\",\n            \"tfc-taiwan.org.tw\",\n            \"tfhub.dev\",\n            \"tfiflve.com\",\n            \"tg-me.com\",\n            \"tg.dev\",\n            \"tgstat.com\",\n            \"thaicn.com\",\n            \"thb.gov.tw\",\n            \"theage.com.au\",\n            \"theatlantic.com\",\n            \"theatrum-belli.com\",\n            \"theaustralian.com.au\",\n            \"theb.ai\",\n            \"thebcomplex.com\",\n            \"theblaze.com\",\n            \"theblemish.com\",\n            \"thebobs.com\",\n            \"thebodyshop-usa.com\",\n            \"thechasernews.co.uk\",\n            \"thechinabeat.org\",\n            \"thechinacollection.org\",\n            \"thechinaproject.com\",\n            \"thechinastory.org\",\n            \"theconversation.com\",\n            \"thedalailamamovie.com\",\n            \"thediplomat.com\",\n            \"thedw.us\",\n            \"theepochtimes.com\",\n            \"thefacebook.com\",\n            \"thegay.com\",\n            \"thegioitinhoc.vn\",\n            \"thegly.com\",\n            \"theguardian.com\",\n            \"thehansindia.com\",\n            \"thehindu.com\",\n            \"thehots.info\",\n            \"thehousenews.com\",\n            \"thehun.net\",\n            \"theinitium.com\",\n            \"thenewslens.com\",\n            \"thepiratebay.ee\",\n            \"thepiratebay.org\",\n            \"theporndude.com\",\n            \"theportalwiki.com\",\n            \"theprint.in\",\n            \"therock.net.nz\",\n            \"thesaturdaypaper.com.au\",\n            \"thespeeder.com\",\n            \"thestandard.com.hk\",\n            \"thestandnews.com\",\n            \"thestar.com\",\n            \"thetatoken.org\",\n            \"thetibetcenter.org\",\n            \"thetibetconnection.org\",\n            \"thetibetmuseum.org\",\n            \"thetibetpost.com\",\n            \"thetrotskymovie.com\",\n            \"thetvdb.com\",\n            \"thewgo.org\",\n            \"thewirechina.com\",\n            \"theync.com\",\n            \"thinkgeek.com\",\n            \"thinkhk.com\",\n            \"thinkingtaiwan.com\",\n            \"thinkwithgoogle.com\",\n            \"thirdmill.org\",\n            \"thisav.com\",\n            \"thlib.org\",\n            \"thomasbernhard.org\",\n            \"thongdreams.com\",\n            \"threadreaderapp.com\",\n            \"threads.com\",\n            \"threads.net\",\n            \"threatchaos.com\",\n            \"throughnightsfire.com\",\n            \"thu.monster\",\n            \"thuhole.com\",\n            \"thumbzilla.com\",\n            \"thywords.com\",\n            \"thywords.com.tw\",\n            \"tiananmenduizhi.com\",\n            \"tiananmenmother.org\",\n            \"tiananmenuniv.com\",\n            \"tiananmenuniv.net\",\n            \"tiandixing.org\",\n            \"tianhuayuan.com\",\n            \"tianlawoffice.com\",\n            \"tianti.io\",\n            \"tiantibooks.org\",\n            \"tianyantong.org.cn\",\n            \"tianzhu.org\",\n            \"tibet-envoy.eu\",\n            \"tibet-foundation.org\",\n            \"tibet-house-trust.co.uk\",\n            \"tibet-info.net\",\n            \"tibet-initiative.de\",\n            \"tibet-munich.de\",\n            \"tibet.a.se\",\n            \"tibet.at\",\n            \"tibet.ca\",\n            \"tibet.com\",\n            \"tibet.fr\",\n            \"tibet.net\",\n            \"tibet.nu\",\n            \"tibet.org\",\n            \"tibet.org.tw\",\n            \"tibet.sk\",\n            \"tibet.to\",\n            \"tibet3rdpole.org\",\n            \"tibetaction.net\",\n            \"tibetaid.org\",\n            \"tibetalk.com\",\n            \"tibetan-alliance.org\",\n            \"tibetan.fr\",\n            \"tibetanaidproject.org\",\n            \"tibetanarts.org\",\n            \"tibetanbuddhistinstitute.org\",\n            \"tibetancommunity.org\",\n            \"tibetancommunityuk.net\",\n            \"tibetanculture.org\",\n            \"tibetanentrepreneurs.org\",\n            \"tibetanfeministcollective.org\",\n            \"tibetanhealth.org\",\n            \"tibetanjournal.com\",\n            \"tibetanlanguage.org\",\n            \"tibetanliberation.org\",\n            \"tibetanpaintings.com\",\n            \"tibetanphotoproject.com\",\n            \"tibetanpoliticalreview.org\",\n            \"tibetanreview.net\",\n            \"tibetansports.org\",\n            \"tibetanwomen.org\",\n            \"tibetanyouth.org\",\n            \"tibetanyouthcongress.org\",\n            \"tibetcharity.dk\",\n            \"tibetcharity.in\",\n            \"tibetchild.org\",\n            \"tibetcity.com\",\n            \"tibetcollection.com\",\n            \"tibetcorps.org\",\n            \"tibetexpress.net\",\n            \"tibetfocus.com\",\n            \"tibetfund.org\",\n            \"tibetgermany.com\",\n            \"tibetgermany.de\",\n            \"tibethaus.com\",\n            \"tibetheritagefund.org\",\n            \"tibethouse.jp\",\n            \"tibethouse.org\",\n            \"tibethouse.us\",\n            \"tibetinfonet.net\",\n            \"tibetjustice.org\",\n            \"tibetkomite.dk\",\n            \"tibetmuseum.org\",\n            \"tibetnetwork.org\",\n            \"tibetoffice.ch\",\n            \"tibetoffice.com.au\",\n            \"tibetoffice.eu\",\n            \"tibetoffice.org\",\n            \"tibetonline.com\",\n            \"tibetonline.tv\",\n            \"tibetoralhistory.org\",\n            \"tibetpolicy.eu\",\n            \"tibetrelieffund.co.uk\",\n            \"tibetsites.com\",\n            \"tibetsociety.com\",\n            \"tibetsun.com\",\n            \"tibetsupportgroup.org\",\n            \"tibetswiss.ch\",\n            \"tibettelegraph.com\",\n            \"tibettimes.net\",\n            \"tibettruth.com\",\n            \"tibetwrites.org\",\n            \"ticket.com.tw\",\n            \"tigervpn.com\",\n            \"tiktok.com\",\n            \"tiktokcdn-eu.com\",\n            \"tiktokcdn-us.com\",\n            \"tiktokcdn.com\",\n            \"tiktokv.com\",\n            \"tiktokv.us\",\n            \"tiktokw.us\",\n            \"tiltbrush.com\",\n            \"timdir.com\",\n            \"time.com\",\n            \"timesnownews.com\",\n            \"timsah.com\",\n            \"timtales.com\",\n            \"tinc-vpn.org\",\n            \"tiney.com\",\n            \"tineye.com\",\n            \"tingtalk.me\",\n            \"tiny.cc\",\n            \"tinychat.com\",\n            \"tinypaste.com\",\n            \"tinyurl.com\",\n            \"tipas.net\",\n            \"tipo.gov.tw\",\n            \"tistory.com\",\n            \"tkcs-collins.com\",\n            \"tl.gd\",\n            \"tma.co.jp\",\n            \"tmagazine.com\",\n            \"tmi.me\",\n            \"tmpp.org\",\n            \"tnaflix.com\",\n            \"tnp.org\",\n            \"tnt-ea.com\",\n            \"to-porno.com\",\n            \"togetter.com\",\n            \"toh.info\",\n            \"token.im\",\n            \"tokenlon.im\",\n            \"tokyo-247.com\",\n            \"tokyo-hot.com\",\n            \"tokyo-porn-tube.com\",\n            \"tokyocn.com\",\n            \"tomonews.net\",\n            \"tomp3.cc\",\n            \"tongil.or.kr\",\n            \"tonyyan.net\",\n            \"toodoc.com\",\n            \"toonel.net\",\n            \"top.tv\",\n            \"top10vpn.com\",\n            \"top81.ws\",\n            \"topbtc.com\",\n            \"topnews.in\",\n            \"toppornsites.com\",\n            \"topshareware.com\",\n            \"topsy.com\",\n            \"toptip.ca\",\n            \"toptoon.net\",\n            \"tora.to\",\n            \"torcn.com\",\n            \"torguard.net\",\n            \"torlock.com\",\n            \"torproject.org\",\n            \"torrentgalaxy.to\",\n            \"torrentkitty.tv\",\n            \"torrentprivacy.com\",\n            \"torrentproject.se\",\n            \"torrenty.org\",\n            \"torrentz.eu\",\n            \"tortoisesvn.net\",\n            \"torvpn.com\",\n            \"totalvpn.com\",\n            \"tou.tv\",\n            \"toutiaoabc.com\",\n            \"towngain.com\",\n            \"toypark.in\",\n            \"toythieves.com\",\n            \"toytractorshow.com\",\n            \"tparents.org\",\n            \"tpi.org.tw\",\n            \"tracfone.com\",\n            \"tradingview.com\",\n            \"traffichaus.com\",\n            \"translate.goog\",\n            \"transparency.org\",\n            \"travelinkcard.com\",\n            \"treemall.com.tw\",\n            \"trendsmap.com\",\n            \"trialofccp.org\",\n            \"trickip.net\",\n            \"trickip.org\",\n            \"trimondi.de\",\n            \"tron.network\",\n            \"tronscan.org\",\n            \"trouw.nl\",\n            \"trt.net.tr\",\n            \"trtc.com.tw\",\n            \"truebuddha-md.org\",\n            \"trulyergonomic.com\",\n            \"truthontour.org\",\n            \"truthsocial.com\",\n            \"truveo.com\",\n            \"tryheart.jp\",\n            \"tsctv.net\",\n            \"tsemtulku.com\",\n            \"tsquare.tv\",\n            \"tsu.org.tw\",\n            \"tsunagarumon.com\",\n            \"tt1069.com\",\n            \"tttan.com\",\n            \"ttv.com.tw\",\n            \"ttvnw.net\",\n            \"ttwstatic.com\",\n            \"tu8964.com\",\n            \"tubaholic.com\",\n            \"tube.com\",\n            \"tube8.com\",\n            \"tube911.com\",\n            \"tubecup.com\",\n            \"tubegals.com\",\n            \"tubeislam.com\",\n            \"tubepornclassic.com\",\n            \"tubestack.com\",\n            \"tubewolf.com\",\n            \"tuibeitu.net\",\n            \"tuidang.net\",\n            \"tuidang.org\",\n            \"tuidang.se\",\n            \"tuitwit.com\",\n            \"tukaani.org\",\n            \"tumblr.com\",\n            \"tumutanzi.com\",\n            \"tumview.com\",\n            \"tunein.com\",\n            \"tunnelbear.com\",\n            \"tunnelblick.net\",\n            \"tunnelr.com\",\n            \"tunsafe.com\",\n            \"tuo8.blue\",\n            \"tuo8.cc\",\n            \"tuo8.club\",\n            \"tuo8.fit\",\n            \"tuo8.hk\",\n            \"tuo8.in\",\n            \"tuo8.ninja\",\n            \"tuo8.org\",\n            \"tuo8.pw\",\n            \"tuo8.red\",\n            \"tuo8.space\",\n            \"turansam.org\",\n            \"turbobit.net\",\n            \"turbohide.com\",\n            \"turbotwitter.com\",\n            \"turkistantimes.com\",\n            \"turntable.fm\",\n            \"tushycash.com\",\n            \"tuvpn.com\",\n            \"tuzaijidi.com\",\n            \"tv.com\",\n            \"tvants.com\",\n            \"tvb.com\",\n            \"tvboxnow.com\",\n            \"tvbs.com.tw\",\n            \"tvider.com\",\n            \"tvmost.com.hk\",\n            \"tvplayvideos.com\",\n            \"tvunetworks.com\",\n            \"tw-blog.com\",\n            \"tw-npo.org\",\n            \"tw01.org\",\n            \"twaitter.com\",\n            \"twapperkeeper.com\",\n            \"twaud.io\",\n            \"twavi.com\",\n            \"twbbs.net.tw\",\n            \"twbbs.org\",\n            \"twbbs.tw\",\n            \"twblogger.com\",\n            \"twcomix.com\",\n            \"tweepguide.com\",\n            \"tweeplike.me\",\n            \"tweepmag.com\",\n            \"tweepml.org\",\n            \"tweetbackup.com\",\n            \"tweetboard.com\",\n            \"tweetboner.biz\",\n            \"tweetcs.com\",\n            \"tweetdeck.com\",\n            \"tweetedtimes.com\",\n            \"tweetmylast.fm\",\n            \"tweetphoto.com\",\n            \"tweetrans.com\",\n            \"tweetree.com\",\n            \"tweettunnel.com\",\n            \"tweetwally.com\",\n            \"tweetymail.com\",\n            \"tweez.net\",\n            \"twelve.today\",\n            \"twerkingbutt.com\",\n            \"twftp.org\",\n            \"twgreatdaily.com\",\n            \"twibase.com\",\n            \"twibble.de\",\n            \"twibbon.com\",\n            \"twibs.com\",\n            \"twicountry.org\",\n            \"twicsy.com\",\n            \"twiends.com\",\n            \"twifan.com\",\n            \"twiffo.com\",\n            \"twiggit.org\",\n            \"twilightsex.com\",\n            \"twilio.com\",\n            \"twilog.org\",\n            \"twimbow.com\",\n            \"twimg.com\",\n            \"twindexx.com\",\n            \"twip.me\",\n            \"twipple.jp\",\n            \"twishort.com\",\n            \"twistar.cc\",\n            \"twister.net.co\",\n            \"twisterio.com\",\n            \"twisternow.com\",\n            \"twistory.net\",\n            \"twit2d.com\",\n            \"twitch.tv\",\n            \"twitchcdn.net\",\n            \"twitgoo.com\",\n            \"twitiq.com\",\n            \"twitlonger.com\",\n            \"twitmania.com\",\n            \"twitoaster.com\",\n            \"twitonmsn.com\",\n            \"twitpic.com\",\n            \"twitstat.com\",\n            \"twittbot.net\",\n            \"twitter.com\",\n            \"twitter.jp\",\n            \"twitter4j.org\",\n            \"twittercounter.com\",\n            \"twitterfeed.com\",\n            \"twittergadget.com\",\n            \"twitterkr.com\",\n            \"twittermail.com\",\n            \"twitterrific.com\",\n            \"twittertim.es\",\n            \"twitthat.com\",\n            \"twitturk.com\",\n            \"twitturly.com\",\n            \"twitvid.com\",\n            \"twitzap.com\",\n            \"twiyia.com\",\n            \"twkan.com\",\n            \"twnorth.org.tw\",\n            \"twreporter.org\",\n            \"twskype.com\",\n            \"twstar.net\",\n            \"twt.tl\",\n            \"twtkr.com\",\n            \"twtrland.com\",\n            \"twttr.com\",\n            \"twurl.nl\",\n            \"twyac.org\",\n            \"tx.me\",\n            \"txxx.com\",\n            \"tycool.com\",\n            \"typekit.net\",\n            \"typepad.com\",\n            \"typeset.io\",\n            \"typora.io\",\n            \"u15.info\",\n            \"u9un.com\",\n            \"ua5v.com\",\n            \"ub0.cc\",\n            \"ubddns.org\",\n            \"uberproxy.net\",\n            \"uc-japan.org\",\n            \"ucam.org\",\n            \"ucanews.com\",\n            \"ucdc1998.org\",\n            \"uchicago.edu\",\n            \"uderzo.it\",\n            \"udn.com\",\n            \"udn.com.tw\",\n            \"udnbkk.com\",\n            \"udndata.com\",\n            \"udomain.hk\",\n            \"uforadio.com.tw\",\n            \"ufreevpn.com\",\n            \"ugo.com\",\n            \"uhdwallpapers.org\",\n            \"uhrp.org\",\n            \"uighur.nl\",\n            \"uighurbiz.net\",\n            \"uk.to\",\n            \"ukcdp.co.uk\",\n            \"ukliferadio.co.uk\",\n            \"uku.im\",\n            \"ulifestyle.com.hk\",\n            \"ulike.net\",\n            \"ulop.net\",\n            \"ultrasurf.us\",\n            \"ultravpn.com\",\n            \"ultravpn.fr\",\n            \"ultraxs.com\",\n            \"umich.edu\",\n            \"unblock-us.com\",\n            \"unblock.cn.com\",\n            \"unblockdmm.com\",\n            \"unblocker.yt\",\n            \"unblocksit.es\",\n            \"uncyclomedia.org\",\n            \"uncyclopedia.hk\",\n            \"uncyclopedia.tw\",\n            \"underwoodammo.com\",\n            \"unholyknight.com\",\n            \"uni.cc\",\n            \"unicode.org\",\n            \"unification.net\",\n            \"unification.org.tw\",\n            \"unirule.cloud\",\n            \"unitedsocialpress.com\",\n            \"unix100.com\",\n            \"unknownspace.org\",\n            \"unlock-music.dev\",\n            \"unmineable.com\",\n            \"unodedos.com\",\n            \"unpo.org\",\n            \"unseen.is\",\n            \"unstable.icu\",\n            \"untraceable.us\",\n            \"unwire.hk\",\n            \"uocn.org\",\n            \"upbit.com\",\n            \"updatestar.com\",\n            \"upghsbc.com\",\n            \"upholdjustice.org\",\n            \"upload4u.info\",\n            \"uploaded.net\",\n            \"uploaded.to\",\n            \"uploadstation.com\",\n            \"upmedia.mg\",\n            \"upornia.com\",\n            \"uproxy.org\",\n            \"uptodown.com\",\n            \"upwill.org\",\n            \"ur7s.com\",\n            \"uraban.me\",\n            \"urbandictionary.com\",\n            \"urbansurvival.com\",\n            \"urchin.com\",\n            \"url.com.tw\",\n            \"urlborg.com\",\n            \"urlparser.com\",\n            \"us.to\",\n            \"usacn.com\",\n            \"usaip.eu\",\n            \"usc.edu\",\n            \"uscardforum.com\",\n            \"uscg.mil\",\n            \"uscnpm.org\",\n            \"usefreevpn.com\",\n            \"usembassy.gov\",\n            \"usercontent.goog\",\n            \"usfk.mil\",\n            \"usma.edu\",\n            \"usmc.mil\",\n            \"usocctn.com\",\n            \"uspto.gov\",\n            \"ustibetcommittee.org\",\n            \"ustream.tv\",\n            \"usunitednews.com\",\n            \"usus.cc\",\n            \"utopianpal.com\",\n            \"uu-gg.com\",\n            \"uujiasu.com\",\n            \"uukanshu.com\",\n            \"uupool.cn\",\n            \"uvwxyz.xyz\",\n            \"uwants.com\",\n            \"uwants.net\",\n            \"uyghur-archive.com\",\n            \"uyghur-j.org\",\n            \"uyghur.co.uk\",\n            \"uyghuraa.org\",\n            \"uyghuramerican.org\",\n            \"uyghurbiz.org\",\n            \"uyghurcanadiansociety.org\",\n            \"uyghurcongress.org\",\n            \"uyghurensemble.co.uk\",\n            \"uyghurpen.org\",\n            \"uyghurpress.com\",\n            \"uyghurstudies.org\",\n            \"uyghurtribunal.com\",\n            \"uygur.org\",\n            \"uymaarip.com\",\n            \"v2.help\",\n            \"v2board.com\",\n            \"v2ex.com\",\n            \"v2fly.org\",\n            \"v2mm.tech\",\n            \"v2ray.com\",\n            \"v2raya.org\",\n            \"v2raycn.com\",\n            \"valeursactuelles.com\",\n            \"van001.com\",\n            \"van698.com\",\n            \"vanemu.cn\",\n            \"vanilla-jp.com\",\n            \"vanpeople.com\",\n            \"vansky.com\",\n            \"vaticannews.va\",\n            \"vatn.org\",\n            \"vcf-online.org\",\n            \"vcfbuilder.org\",\n            \"vegasred.com\",\n            \"velkaepocha.sk\",\n            \"venbbs.com\",\n            \"venchina.com\",\n            \"venetianmacao.com\",\n            \"ventureswell.com\",\n            \"veoh.com\",\n            \"vercel.app\",\n            \"vercel.com\",\n            \"verizon.net\",\n            \"vermonttibet.org\",\n            \"vern.cc\",\n            \"versavpn.com\",\n            \"verybs.com\",\n            \"vevo.com\",\n            \"vewas.net\",\n            \"vft.com.tw\",\n            \"viber.com\",\n            \"vica.info\",\n            \"victimsofcommunism.org\",\n            \"vid.me\",\n            \"vidble.com\",\n            \"videobam.com\",\n            \"videodetective.com\",\n            \"videomega.tv\",\n            \"videomo.com\",\n            \"videopediaworld.com\",\n            \"videopress.com\",\n            \"vidinfo.org\",\n            \"vietdaikynguyen.com\",\n            \"vijayatemple.org\",\n            \"vilanet.me\",\n            \"vilavpn.com\",\n            \"vimeo.com\",\n            \"vimeocdn.com\",\n            \"vimperator.org\",\n            \"vincnd.com\",\n            \"vine.co\",\n            \"vinniev.com\",\n            \"vip-enterprise.com\",\n            \"virginia.edu\",\n            \"virtualrealporn.com\",\n            \"visibletweets.com\",\n            \"visualstudio.com\",\n            \"vital247.org\",\n            \"viu.com\",\n            \"viu.tv\",\n            \"vivahentai4u.net\",\n            \"vivaldi.com\",\n            \"vivatube.com\",\n            \"vivthomas.com\",\n            \"vizvaz.com\",\n            \"vjav.com\",\n            \"vjmedia.com.hk\",\n            \"vllcs.org\",\n            \"vmixcore.com\",\n            \"vmpsoft.com\",\n            \"vnet.link\",\n            \"voa.mobi\",\n            \"voacambodia.com\",\n            \"voacantonese.com\",\n            \"voachinese.com\",\n            \"voachineseblog.com\",\n            \"voagd.com\",\n            \"voaindonesia.com\",\n            \"voanews.com\",\n            \"voatibetan.com\",\n            \"voatibetanenglish.com\",\n            \"vocaroo.com\",\n            \"vocativ.com\",\n            \"vocn.tv\",\n            \"vocus.cc\",\n            \"voi.id\",\n            \"voicettank.org\",\n            \"vot.org\",\n            \"vovo2000.com\",\n            \"vox.com\",\n            \"voxer.com\",\n            \"voy.com\",\n            \"vpn.ac\",\n            \"vpn.net\",\n            \"vpn4all.com\",\n            \"vpnaccount.org\",\n            \"vpnaccounts.com\",\n            \"vpnbook.com\",\n            \"vpncomparison.org\",\n            \"vpncoupons.com\",\n            \"vpncup.com\",\n            \"vpndada.com\",\n            \"vpnfan.com\",\n            \"vpnfire.com\",\n            \"vpnfires.biz\",\n            \"vpnforgame.net\",\n            \"vpngate.jp\",\n            \"vpngate.net\",\n            \"vpngratis.net\",\n            \"vpnhq.com\",\n            \"vpnhub.com\",\n            \"vpninja.net\",\n            \"vpnintouch.com\",\n            \"vpnintouch.net\",\n            \"vpnjack.com\",\n            \"vpnmaster.com\",\n            \"vpnmentor.com\",\n            \"vpnpick.com\",\n            \"vpnpop.com\",\n            \"vpnpronet.com\",\n            \"vpnproxymaster.com\",\n            \"vpnreactor.com\",\n            \"vpnreviewz.com\",\n            \"vpnsecure.me\",\n            \"vpnshazam.com\",\n            \"vpnshieldapp.com\",\n            \"vpnsp.com\",\n            \"vpntraffic.com\",\n            \"vpntunnel.com\",\n            \"vpnuk.info\",\n            \"vpnunlimitedapp.com\",\n            \"vpnvip.com\",\n            \"vpnworldwide.com\",\n            \"vporn.com\",\n            \"vpser.net\",\n            \"vpsxb.net\",\n            \"vraiesagesse.net\",\n            \"vrchat.com\",\n            \"vrmtr.com\",\n            \"vrporn.com\",\n            \"vrsmash.com\",\n            \"vtunnel.com\",\n            \"vuku.cc\",\n            \"vultryhw.com\",\n            \"vyprvpn.com\",\n            \"vzw.com\",\n            \"w-pool.com\",\n            \"w.wiki\",\n            \"w3.org\",\n            \"w3s.link\",\n            \"waffle1999.com\",\n            \"wahas.com\",\n            \"waigaobu.com\",\n            \"waikeung.org\",\n            \"wailaike.net\",\n            \"wainao.me\",\n            \"waiwaier.com\",\n            \"walletconnect.com\",\n            \"wallhaven.cc\",\n            \"wallmama.com\",\n            \"wallornot.org\",\n            \"wallpapercasa.com\",\n            \"wallproxy.com\",\n            \"wallsttv.com\",\n            \"waltermartin.com\",\n            \"waltermartin.org\",\n            \"wan-press.org\",\n            \"wanderinghorse.net\",\n            \"wangafu.net\",\n            \"wangjinbo.org\",\n            \"wanglixiong.com\",\n            \"wango.org\",\n            \"wangruoshui.net\",\n            \"wangruowang.org\",\n            \"want-daily.com\",\n            \"wanz-factory.com\",\n            \"wapedia.mobi\",\n            \"warroom.org\",\n            \"waselpro.com\",\n            \"washeng.net\",\n            \"washingtonpost.com\",\n            \"watch8x.com\",\n            \"watchinese.com\",\n            \"watchmygf.net\",\n            \"watchout.tw\",\n            \"wattpad.com\",\n            \"wav.tv\",\n            \"waveprotocol.org\",\n            \"waybig.com\",\n            \"waymo.com\",\n            \"wd.bible\",\n            \"wda.gov.tw\",\n            \"wdf5.com\",\n            \"wealth.com.tw\",\n            \"wearehairy.com\",\n            \"wearn.com\",\n            \"weather.com.hk\",\n            \"web.dev\",\n            \"web2project.net\",\n            \"webbang.net\",\n            \"webevader.org\",\n            \"webfreer.com\",\n            \"webjb.org\",\n            \"weblagu.com\",\n            \"webmproject.org\",\n            \"webpack.de\",\n            \"webpkgcache.com\",\n            \"webrtc.org\",\n            \"webrush.net\",\n            \"webs-tv.net\",\n            \"website.new\",\n            \"websitepulse.com\",\n            \"websnapr.com\",\n            \"webwarper.net\",\n            \"webworkerdaily.com\",\n            \"wechatlawsuit.com\",\n            \"weebly.com\",\n            \"wefightcensorship.org\",\n            \"wefong.com\",\n            \"weiboleak.com\",\n            \"weihuo.org\",\n            \"weijingsheng.org\",\n            \"weiming.info\",\n            \"weiquanwang.org\",\n            \"weisuo.ws\",\n            \"weitt.us\",\n            \"welovecock.com\",\n            \"welt.de\",\n            \"wemigrate.org\",\n            \"wengewang.com\",\n            \"wengewang.org\",\n            \"wenhui.ch\",\n            \"wenxuecity.com\",\n            \"wenyunchao.com\",\n            \"wenzhao.ca\",\n            \"westca.com\",\n            \"westernshugdensociety.org\",\n            \"westernwolves.com\",\n            \"westkit.net\",\n            \"westpoint.edu\",\n            \"wetplace.com\",\n            \"wetpussygames.com\",\n            \"wexiaobo.org\",\n            \"wezhiyong.org\",\n            \"wezone.net\",\n            \"wforum.com\",\n            \"whatblocked.com\",\n            \"whatbrowser.org\",\n            \"whats.new\",\n            \"whatsapp.com\",\n            \"whatsapp.net\",\n            \"whatsonweibo.com\",\n            \"wheatseeds.org\",\n            \"wheelockslatin.com\",\n            \"whereiswerner.com\",\n            \"wheretowatch.com\",\n            \"whichav.com\",\n            \"whichav.video\",\n            \"whippedass.com\",\n            \"whispersystems.org\",\n            \"who.is\",\n            \"whodns.xyz\",\n            \"whoer.net\",\n            \"whotalking.com\",\n            \"whylover.com\",\n            \"whyx.org\",\n            \"widevine.com\",\n            \"wikaba.com\",\n            \"wikia.com\",\n            \"wikia.org\",\n            \"wikibooks.org\",\n            \"wikidata.org\",\n            \"wikileaks-forum.com\",\n            \"wikileaks.ch\",\n            \"wikileaks.com\",\n            \"wikileaks.de\",\n            \"wikileaks.eu\",\n            \"wikileaks.lu\",\n            \"wikileaks.org\",\n            \"wikileaks.pl\",\n            \"wikilivres.info\",\n            \"wikimapia.org\",\n            \"wikimedia.org\",\n            \"wikinews.org\",\n            \"wikipedia-on-ipfs.org\",\n            \"wikipedia.org\",\n            \"wikiquote.org\",\n            \"wikisource.org\",\n            \"wikiversity.org\",\n            \"wikivoyage.org\",\n            \"wikiwand.com\",\n            \"wiktionary.org\",\n            \"wildammo.com\",\n            \"williamhill.com\",\n            \"willw.net\",\n            \"wilsoncenter.org\",\n            \"windscribe.com\",\n            \"wingamestore.com\",\n            \"wingy.site\",\n            \"winning11.com\",\n            \"winwhispers.info\",\n            \"wionews.com\",\n            \"wire.com\",\n            \"wiredbytes.com\",\n            \"wiredpen.com\",\n            \"wireguard.com\",\n            \"wisdompubs.org\",\n            \"wisevid.com\",\n            \"wistia.com\",\n            \"withgoogle.com\",\n            \"withyoutube.com\",\n            \"witnessleeteaching.com\",\n            \"witopia.net\",\n            \"wixsite.com\",\n            \"wizcrafts.net\",\n            \"wjbk.org\",\n            \"wmflabs.org\",\n            \"wmfusercontent.org\",\n            \"wn.com\",\n            \"wnacg.com\",\n            \"wnacg.org\",\n            \"wo.tc\",\n            \"woeser.com\",\n            \"wokar.org\",\n            \"wolfax.com\",\n            \"wombo.ai\",\n            \"woolyss.com\",\n            \"woopie.jp\",\n            \"woopie.tv\",\n            \"wordpress.com\",\n            \"work2icu.org\",\n            \"workatruna.com\",\n            \"workerdemo.org.hk\",\n            \"workerempowerment.org\",\n            \"workers.dev\",\n            \"workersthebig.net\",\n            \"worldcat.org\",\n            \"worldjournal.com\",\n            \"worldpopulationreview.com\",\n            \"worldvpn.net\",\n            \"wow-life.net\",\n            \"wow.com\",\n            \"wowgirls.com\",\n            \"wowhead.com\",\n            \"wowlegacy.ml\",\n            \"wowporn.com\",\n            \"wowrk.com\",\n            \"woxinghuiguo.com\",\n            \"woyaolian.org\",\n            \"wozy.in\",\n            \"wp.com\",\n            \"wpoforum.com\",\n            \"wqyd.org\",\n            \"wrchina.org\",\n            \"wretch.cc\",\n            \"writesonic.com\",\n            \"wsimg.com\",\n            \"wsj.com\",\n            \"wsj.net\",\n            \"wsjhk.com\",\n            \"wtbn.org\",\n            \"wtfpeople.com\",\n            \"wuerkaixi.com\",\n            \"wufafangwen.com\",\n            \"wufi.org.tw\",\n            \"wuguoguang.com\",\n            \"wujie.net\",\n            \"wujieliulan.com\",\n            \"wukangrui.net\",\n            \"wunderground.com\",\n            \"wuw.red\",\n            \"wuyanblog.com\",\n            \"wwe.com\",\n            \"wwitv.com\",\n            \"www1.biz\",\n            \"wwwhost.biz\",\n            \"wxw.cat\",\n            \"wxw.moe\",\n            \"wzyboy.im\",\n            \"x-art.com\",\n            \"x-berry.com\",\n            \"x-wall.org\",\n            \"x.ai\",\n            \"x.co\",\n            \"x.com\",\n            \"x.company\",\n            \"x1949x.com\",\n            \"x24hr.com\",\n            \"x365x.com\",\n            \"x3guide.com\",\n            \"xaislam.com\",\n            \"xanga.com\",\n            \"xbabe.com\",\n            \"xbookcn.com\",\n            \"xbtce.com\",\n            \"xcafe.in\",\n            \"xchina.co\",\n            \"xcity.jp\",\n            \"xcritic.com\",\n            \"xerotica.com\",\n            \"xfiles.to\",\n            \"xfinity.com\",\n            \"xfxssr.me\",\n            \"xgmyd.com\",\n            \"xhamster.com\",\n            \"xhcdn.com\",\n            \"xianba.net\",\n            \"xianchawang.net\",\n            \"xianjian.tw\",\n            \"xianqiao.net\",\n            \"xiaobaiwu.com\",\n            \"xiaochuncnjp.com\",\n            \"xiaod.in\",\n            \"xiaohexie.com\",\n            \"xiaolan.me\",\n            \"xiaoma.org\",\n            \"xiaomi.eu\",\n            \"xiaxiaoqiang.net\",\n            \"xicons.org\",\n            \"xiezhua.com\",\n            \"xihua.es\",\n            \"xinbao.de\",\n            \"xing.com\",\n            \"xinhuanet.org\",\n            \"xinjiangpolicefiles.org\",\n            \"xinmiao.com.hk\",\n            \"xinsheng.net\",\n            \"xinshijue.com\",\n            \"xinyubbs.net\",\n            \"xiongpian.com\",\n            \"xiuren.org\",\n            \"xizang-zhiye.org\",\n            \"xjp.cc\",\n            \"xjtravelguide.com\",\n            \"xkiwi.tk\",\n            \"xlfmtalk.com\",\n            \"xlfmwz.info\",\n            \"xm.com\",\n            \"xml-training-guide.com\",\n            \"xmonk.net\",\n            \"xmovies.com\",\n            \"xn--11xs86f.icu\",\n            \"xn--4gq171p.com\",\n            \"xn--90wwvt03e.com\",\n            \"xn--9pr62r24a.com\",\n            \"xn--czq75pvv1aj5c.org\",\n            \"xn--i2ru8q2qg.com\",\n            \"xn--ngstr-lra8j.com\",\n            \"xn--noss43i.com\",\n            \"xn--oiq.cc\",\n            \"xnpool.com\",\n            \"xnxx-cdn.com\",\n            \"xnxx.com\",\n            \"xpdo.net\",\n            \"xpud.org\",\n            \"xrentdvd.com\",\n            \"xsden.info\",\n            \"xsden.org\",\n            \"xskywalker.com\",\n            \"xt.com\",\n            \"xt.pub\",\n            \"xtube.com\",\n            \"xuchao.net\",\n            \"xuchao.org\",\n            \"xuehua.us\",\n            \"xuite.net\",\n            \"xuzhiyong.net\",\n            \"xvbelink.com\",\n            \"xvideo.cc\",\n            \"xvideos-cdn.com\",\n            \"xvideos.com\",\n            \"xvideos.es\",\n            \"xvideos2.com\",\n            \"xvinlink.com\",\n            \"xxbbx.com\",\n            \"xxlmovies.com\",\n            \"xxuz.com\",\n            \"xxx.com\",\n            \"xxx.xxx\",\n            \"xxxfuckmom.com\",\n            \"xxxx.com.au\",\n            \"xxxy.info\",\n            \"xxxymovies.com\",\n            \"xys.org\",\n            \"xysblogs.org\",\n            \"xyy69.com\",\n            \"xyy69.info\",\n            \"y2mate.com\",\n            \"yadi.sk\",\n            \"yahoo.co.jp\",\n            \"yahoo.com\",\n            \"yahoo.com.hk\",\n            \"yahoo.com.tw\",\n            \"yahoo.net\",\n            \"yahooinc.com\",\n            \"yahoosandbox.com\",\n            \"yakbutterblues.com\",\n            \"yam.com\",\n            \"yam.org.tw\",\n            \"yande.re\",\n            \"yandex.com\",\n            \"yandex.net\",\n            \"yandex.ru\",\n            \"yanghengjun.com\",\n            \"yangjianli.com\",\n            \"yangzhi.org\",\n            \"yasni.co.uk\",\n            \"yasukuni.or.jp\",\n            \"yayabay.com\",\n            \"ycombinator.com\",\n            \"ydy.com\",\n            \"yeahteentube.com\",\n            \"yecl.net\",\n            \"yeelou.com\",\n            \"yeeyi.com\",\n            \"yegle.net\",\n            \"yes-news.com\",\n            \"yes.xxx\",\n            \"yes123.com.tw\",\n            \"yesasia.com\",\n            \"yesasia.com.hk\",\n            \"yespornplease.com\",\n            \"yeyeclub.com\",\n            \"ygto.com\",\n            \"yhcw.net\",\n            \"yibada.com\",\n            \"yibaochina.com\",\n            \"yidio.com\",\n            \"yigeni.com\",\n            \"yilubbs.com\",\n            \"yimg.com\",\n            \"yingsuoss.com\",\n            \"yinlei.org\",\n            \"yipub.com\",\n            \"yizhihongxing.com\",\n            \"ylive.jp\",\n            \"yobit.net\",\n            \"yobt.com\",\n            \"yobt.tv\",\n            \"yodobashi.com\",\n            \"yogichen.org\",\n            \"yolasite.com\",\n            \"yomiuri.co.jp\",\n            \"yong.hu\",\n            \"yorkbbs.ca\",\n            \"you-get.org\",\n            \"you.com\",\n            \"youdontcare.com\",\n            \"youjizz.com\",\n            \"youlucky.com\",\n            \"youmaker.com\",\n            \"youngpornvideos.com\",\n            \"youngspiration.hk\",\n            \"youpai.org\",\n            \"youporn.com\",\n            \"youporngay.com\",\n            \"your-freedom.net\",\n            \"yourepeat.com\",\n            \"yourlisten.com\",\n            \"yourlust.com\",\n            \"yourprivatevpn.com\",\n            \"yourtrap.com\",\n            \"yousendit.com\",\n            \"youshun12.com\",\n            \"youthnetradio.org\",\n            \"youthwant.com.tw\",\n            \"youtu.be\",\n            \"youtube-nocookie.com\",\n            \"youtube.com\",\n            \"youtubecn.com\",\n            \"youtubeeducation.com\",\n            \"youtubegaming.com\",\n            \"youtubekids.com\",\n            \"youversion.com\",\n            \"youwin.com\",\n            \"youxu.info\",\n            \"yt.be\",\n            \"ytht.net\",\n            \"ytimg.com\",\n            \"ytn.co.kr\",\n            \"yts.ag\",\n            \"yts.am\",\n            \"yts.lt\",\n            \"yts.mx\",\n            \"yuanming.net\",\n            \"yuanzhengtang.org\",\n            \"yulghun.com\",\n            \"yunchao.net\",\n            \"yunomi.tokyo\",\n            \"yuntipub.com\",\n            \"yuvutu.com\",\n            \"yvesgeleyn.com\",\n            \"ywpw.com\",\n            \"yx51.net\",\n            \"yyii.org\",\n            \"yyjlymb.xyz\",\n            \"yysub.net\",\n            \"yzzk.com\",\n            \"z-lib.fm\",\n            \"z-lib.fo\",\n            \"z-lib.gd\",\n            \"z-lib.gl\",\n            \"z-lib.io\",\n            \"z-lib.org\",\n            \"z-library.sk\",\n            \"zacebook.com\",\n            \"zalmos.com\",\n            \"zamimg.com\",\n            \"zannel.com\",\n            \"zaobao.com.sg\",\n            \"zaozon.com\",\n            \"zapto.org\",\n            \"zattoo.com\",\n            \"zb.com\",\n            \"zdnet.com.tw\",\n            \"zello.com\",\n            \"zengjinyan.org\",\n            \"zenmate.com\",\n            \"zenmate.com.ru\",\n            \"zergpool.com\",\n            \"zerohedge.com\",\n            \"zeronet.io\",\n            \"zeutch.com\",\n            \"zfreet.com\",\n            \"zgsddh.com\",\n            \"zgzcjj.net\",\n            \"zhanbin.net\",\n            \"zhangboli.net\",\n            \"zhangtianliang.com\",\n            \"zhanlve.org\",\n            \"zhenghui.org\",\n            \"zhengjian.org\",\n            \"zhengwunet.org\",\n            \"zhenlibu.info\",\n            \"zhenlibu1984.com\",\n            \"zhenxiang.biz\",\n            \"zhinengluyou.com\",\n            \"zhizhu.top\",\n            \"zhongguo.ca\",\n            \"zhongguorenquan.org\",\n            \"zhongguotese.net\",\n            \"zhongzidi.com\",\n            \"zhoushuguang.com\",\n            \"zhreader.com\",\n            \"zhuanxing.cn\",\n            \"zhuatieba.com\",\n            \"zhuichaguoji.org\",\n            \"zhujiget.com\",\n            \"zi.media\",\n            \"zi5.me\",\n            \"ziddu.com\",\n            \"zillionk.com\",\n            \"zim.vn\",\n            \"zinio.com\",\n            \"ziporn.com\",\n            \"zippyshare.com\",\n            \"zkaip.com\",\n            \"zkiz.com\",\n            \"zmedia.com.tw\",\n            \"zmw.cn\",\n            \"zodgame.us\",\n            \"zodgame.xyz\",\n            \"zoho.com\",\n            \"zomobo.net\",\n            \"zonaeuropa.com\",\n            \"zonghexinwen.com\",\n            \"zonghexinwen.net\",\n            \"zoogvpn.com\",\n            \"zoominfo.com\",\n            \"zooqle.com\",\n            \"zootool.com\",\n            \"zoozle.net\",\n            \"zophar.net\",\n            \"zorrovpn.com\",\n            \"zozotown.com\",\n            \"zpn.im\",\n            \"zsdxzk.com\",\n            \"zspeeder.me\",\n            \"zsrhao.com\",\n            \"zuo.la\",\n            \"zuobiao.me\",\n            \"zuola.com\",\n            \"zvereff.com\",\n            \"zynamics.com\",\n            \"zyns.com\",\n            \"zyxel.com\",\n            \"zzcartoon.com\",\n            \"zzcloud.me\",\n            \"zzux.com\"\n        ]\n    ],\n    [\n        [],\n        []\n    ]\n];\n\nvar lastRule = '';\n\nfunction FindProxyForURL(url, host) {\n    for (var i = 0; i < rules.length; i++) {\n        ret = testHost(host, i);\n        if (ret != undefined)\n            return ret;\n    }\n    return 'DIRECT';\n}\n\nfunction testHost(host, index) {\n    for (var i = 0; i < rules[index].length; i++) {\n        for (var j = 0; j < rules[index][i].length; j++) {\n            lastRule = rules[index][i][j]\n            if (host == lastRule || host.endsWith('.' + lastRule))\n                return i % 2 == 0 ? 'DIRECT' : proxy;\n        }\n    }\n    lastRule = '';\n}\n\n// REF: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith\nif (!String.prototype.endsWith) {\n    String.prototype.endsWith = function(searchString, position) {\n        var subjectString = this.toString();\n        if (typeof position !== 'number' || !isFinite(position) || Math.floor(position) !== position || position > subjectString.length) {\n            position = subjectString.length;\n        }\n        position -= searchString.length;\n        var lastIndex = subjectString.indexOf(searchString, position);\n        return lastIndex !== -1 && lastIndex === position;\n  };\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/proxy_set_linux_sh",
    "content": "#!/bin/bash\n\n# Function to set proxy for GNOME\nset_gnome_proxy() {\n    local MODE=$1\n    local PROXY_IP=$2\n    local PROXY_PORT=$3\n    local IGNORE_HOSTS=$4\n\n    # Set the proxy mode\n    gsettings set org.gnome.system.proxy mode \"$MODE\"\n\n    if [ \"$MODE\" == \"manual\" ]; then\n        # List of protocols\n        local PROTOCOLS=(\"http\" \"https\" \"ftp\" \"socks\")\n\n        # Loop through protocols to set the proxy\n        for PROTOCOL in \"${PROTOCOLS[@]}\"; do\n            gsettings set org.gnome.system.proxy.$PROTOCOL host \"$PROXY_IP\"\n            gsettings set org.gnome.system.proxy.$PROTOCOL port \"$PROXY_PORT\"\n        done\n\n        # Set ignored hosts\n        gsettings set org.gnome.system.proxy ignore-hosts \"['$IGNORE_HOSTS']\"\n\n        echo \"GNOME: Manual proxy settings applied.\"\n        echo \"Proxy IP: $PROXY_IP\"\n        echo \"Proxy Port: $PROXY_PORT\"\n        echo \"Ignored Hosts: $IGNORE_HOSTS\"\n    elif [ \"$MODE\" == \"none\" ]; then\n        echo \"GNOME: Proxy disabled.\"\n    fi\n}\n\n# Function to set proxy for KDE\nset_kde_proxy() {\n    local MODE=$1\n    local PROXY_IP=$2\n    local PROXY_PORT=$3\n    local IGNORE_HOSTS=$4\n\n    # Determine the correct kwriteconfig command based on KDE_SESSION_VERSION\n    if [ \"$KDE_SESSION_VERSION\" == \"6\" ]; then\n        KWRITECONFIG=\"kwriteconfig6\"\n    else\n        KWRITECONFIG=\"kwriteconfig5\"\n    fi\n\n    # KDE uses kwriteconfig to modify proxy settings\n    if [ \"$MODE\" == \"manual\" ]; then\n        # Set proxy for all protocols\n        $KWRITECONFIG --file kioslaverc --group \"Proxy Settings\" --key ProxyType 1\n        $KWRITECONFIG --file kioslaverc --group \"Proxy Settings\" --key httpProxy \"http://$PROXY_IP:$PROXY_PORT\"\n        $KWRITECONFIG --file kioslaverc --group \"Proxy Settings\" --key httpsProxy \"http://$PROXY_IP:$PROXY_PORT\"\n        $KWRITECONFIG --file kioslaverc --group \"Proxy Settings\" --key ftpProxy \"http://$PROXY_IP:$PROXY_PORT\"\n        $KWRITECONFIG --file kioslaverc --group \"Proxy Settings\" --key socksProxy \"http://$PROXY_IP:$PROXY_PORT\"\n\n        # Set ignored hosts\n        $KWRITECONFIG --file kioslaverc --group \"Proxy Settings\" --key NoProxyFor \"$IGNORE_HOSTS\"\n\n        echo \"KDE: Manual proxy settings applied.\"\n        echo \"Proxy IP: $PROXY_IP\"\n        echo \"Proxy Port: $PROXY_PORT\"\n        echo \"Ignored Hosts: $IGNORE_HOSTS\"\n    elif [ \"$MODE\" == \"none\" ]; then\n        # Disable proxy\n        $KWRITECONFIG --file kioslaverc --group \"Proxy Settings\" --key ProxyType 0\n        echo \"KDE: Proxy disabled.\"\n    fi\n\n    # Apply changes by restarting KDE's network settings\n    dbus-send --type=signal /KIO/Scheduler org.kde.KIO.Scheduler.reparseSlaveConfiguration string:\"\"\n}\n\n# Detect the current desktop environment\ndetect_desktop_environment() {\n    if [[ \"$XDG_CURRENT_DESKTOP\" == *\"GNOME\"* ]] || [[ \"$XDG_SESSION_DESKTOP\" == *\"GNOME\"* ]]; then\n        echo \"gnome\"\n        return\n    fi\n\n    if [[ \"$XDG_CURRENT_DESKTOP\" == *\"XFCE\"* ]] || [[ \"$XDG_SESSION_DESKTOP\" == *\"XFCE\"* ]]; then\n        echo \"gnome\"\n        return\n    fi\n\n    if [[ \"$XDG_CURRENT_DESKTOP\" == *\"X-Cinnamon\"* ]] || [[ \"$XDG_SESSION_DESKTOP\" == *\"cinnamon\"* ]]; then\n        echo \"gnome\"\n        return\n    fi\n\n    if [[ \"$XDG_CURRENT_DESKTOP\" == *\"UKUI\"* ]] || [[ \"$XDG_SESSION_DESKTOP\" == *\"ukui\"* ]]; then\n        echo \"gnome\"\n        return\n    fi\n\n    if [[ \"$XDG_CURRENT_DESKTOP\" == *\"DDE\"* ]] || [[ \"$XDG_SESSION_DESKTOP\" == *\"dde\"* ]]; then\n        echo \"gnome\"\n        return\n    fi\n\n    if [[ \"$XDG_CURRENT_DESKTOP\" == *\"MATE\"* ]] || [[ \"$XDG_SESSION_DESKTOP\" == *\"mate\"* ]]; then\n        echo \"gnome\"\n        return\n    fi\n\n    local KDE_ENVIRONMENTS=(\"KDE\" \"plasma\")\n    for ENV in \"${KDE_ENVIRONMENTS[@]}\"; do\n        if [ \"$XDG_CURRENT_DESKTOP\" == \"$ENV\" ] || [ \"$XDG_SESSION_DESKTOP\" == \"$ENV\" ]; then\n            echo \"kde\"\n            return\n        fi\n    done\n\n    # Fallback to GNOME method if CLI utility is available. This solves the\n    # proxy configuration issues on minimal installation systems, like setups\n    # with only window managers, that borrow some parts from big DEs.\n    if command -v gsettings >/dev/null 2>&1; then\n        echo \"gnome\"\n        return\n    fi\n\n    echo \"unsupported\"\n}\n\n# Main script logic\nif [ \"$#\" -lt 1 ]; then\n    echo \"Usage: $0 <mode> [proxy_ip proxy_port ignore_hosts]\"\n    echo \"  mode: 'none' or 'manual'\"\n    echo \"  If mode is 'manual', provide proxy IP, port, and ignore hosts.\"\n    exit 1\nfi\n\n# Get the mode\nMODE=$1\nPROXY_IP=$2\nPROXY_PORT=$3\nIGNORE_HOSTS=$4\n\nif ! [[ \"$MODE\" =~ ^(manual|none)$ ]]; then\n    echo \"Invalid mode. Use 'none' or 'manual'.\" >&2\n    exit 1\nfi\n\n# Detect desktop environment\nDE=$(detect_desktop_environment)\n\n# Apply settings based on the desktop environment\nif [ \"$DE\" == \"gnome\" ]; then\n    set_gnome_proxy \"$MODE\" \"$PROXY_IP\" \"$PROXY_PORT\" \"$IGNORE_HOSTS\"\nelif [ \"$DE\" == \"kde\" ]; then\n    set_gnome_proxy \"$MODE\" \"$PROXY_IP\" \"$PROXY_PORT\" \"$IGNORE_HOSTS\"\n    set_kde_proxy \"$MODE\" \"$PROXY_IP\" \"$PROXY_PORT\" \"$IGNORE_HOSTS\"\nelse\n    echo \"Unsupported desktop environment: $DE\" >&2\n    exit 1\nfi\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/proxy_set_osx_sh",
    "content": "#!/bin/bash\n\n# Function to set proxy\nset_proxy() {\n    PROXY_IP=$1\n    PROXY_PORT=$2\n\n    shift 2\n    BYPASS_DOMAINS=(\"$@\")\n    # If no bypass domains are provided, set it to empty by default\n    if [ ${#BYPASS_DOMAINS[@]} -eq 0 ]; then\n        BYPASS_DOMAINS=(\"\")\n    fi\n\n    # Get all network service names\n    SERVICES=$(networksetup -listallnetworkservices | grep -v '*')\n\n    # Loop through each network service\n    echo \"$SERVICES\" | while read -r SERVICE; do\n        echo \"Setting proxy for network service '$SERVICE'...\"\n        # Set HTTP proxy\n        networksetup -setwebproxy \"$SERVICE\" \"$PROXY_IP\" \"$PROXY_PORT\"\n\n        # Set HTTPS proxy\n        networksetup -setsecurewebproxy \"$SERVICE\" \"$PROXY_IP\" \"$PROXY_PORT\"\n\n        # Set SOCKS proxy\n        networksetup -setsocksfirewallproxy \"$SERVICE\" \"$PROXY_IP\" \"$PROXY_PORT\"\n\n        # Set bypass domains\n        networksetup -setproxybypassdomains \"$SERVICE\" \"${BYPASS_DOMAINS[@]}\"\n        echo \"Proxy for network service '$SERVICE' has been set to $PROXY_IP:$PROXY_PORT\"\n    done\n    echo \"Proxy settings for all network services are complete!\"\n}\n\n# Function to disable proxy\nclear_proxy() {\n    # Get all network service names\n    SERVICES=$(networksetup -listallnetworkservices | grep -v '*')\n\n    # Loop through each network service\n    echo \"$SERVICES\" | while read -r SERVICE; do\n        echo \"Disabling proxy and clearing bypass domains for network service '$SERVICE'...\"\n        # Disable HTTP proxy\n        networksetup -setwebproxystate \"$SERVICE\" off\n\n        # Disable HTTPS proxy\n        networksetup -setsecurewebproxystate \"$SERVICE\" off\n\n        # Disable SOCKS proxy\n        networksetup -setsocksfirewallproxystate \"$SERVICE\" off\n\n        echo \"Proxy for network service '$SERVICE' has been disabled\"\n    done\n    echo \"Proxy for all network services has been disabled!\"\n}\n\n# Main script logic\nif [ \"$1\" == \"set\" ]; then\n    # Check if enough parameters are passed for setting proxy\n    if [ \"$#\" -lt 3 ]; then\n        echo \"Usage: $0 set <IP Address> <Port> [Bypass Domain 1 Bypass Domain 2 ...]\"\n        exit 1\n    fi\n    set_proxy \"$2\" \"$3\" \"${@:4}\"\nelif [ \"$1\" == \"clear\" ]; then\n    clear_proxy\nelse\n    echo \"Usage:\"\n    echo \"  To set proxy:    $0 set <IP Address> <Port> [Bypass Domain 1 Bypass Domain 2 ...]\"\n    echo \"  To clear proxy: $0 clear\"\n    exit 1\nfi\n"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/singbox_fakeip_filter",
    "content": "{\n  \"domain\": [\n    \"amobile.music.tc.qq.com\",\n    \"api-jooxtt.sanook.com\",\n    \"api.joox.com\",\n    \"aqqmusic.tc.qq.com\",\n    \"dl.stream.qqmusic.qq.com\",\n    \"ff.dorado.sdo.com\",\n    \"heartbeat.belkin.com\",\n    \"isure.stream.qqmusic.qq.com\",\n    \"joox.com\",\n    \"lens.l.google.com\",\n    \"localhost.ptlogin2.qq.com\",\n    \"localhost.sec.qq.com\",\n    \"mesu.apple.com\",\n    \"mobileoc.music.tc.qq.com\",\n    \"music.taihe.com\",\n    \"musicapi.taihe.com\",\n    \"na.b.g-tun.com\",\n    \"proxy.golang.org\",\n    \"ps.res.netease.com\",\n    \"shark007.net\",\n    \"songsearch.kugou.com\",\n    \"static.adtidy.org\",\n    \"streamoc.music.tc.qq.com\",\n    \"swcdn.apple.com\",\n    \"swdist.apple.com\",\n    \"swdownload.apple.com\",\n    \"swquery.apple.com\",\n    \"swscan.apple.com\",\n    \"turn.cloudflare.com\",\n    \"trackercdn.kugou.com\",\n    \"xnotify.xboxlive.com\"\n  ],\n  \"domain_keyword\": [\n    \"ntp\",\n    \"stun\",\n    \"time\"\n  ],\n  \"domain_regex\": [\n    \"^[^.]+$\",\n    \"^[^.]+\\\\.[^.]+\\\\.xboxlive\\\\.com$\",\n    \"^localhost\\\\.[^.]+\\\\.weixin\\\\.qq\\\\.com$\",\n    \"^mijia\\\\scloud$\",\n    \"^xbox\\\\.[^.]+\\\\.microsoft\\\\.com$\",\n    \"^xbox\\\\.[^.]+\\\\.[^.]+\\\\.microsoft\\\\.com$\"\n  ],\n  \"domain_suffix\": [\n    \"126.net\",\n    \"3gppnetwork.org\",\n    \"battle.net\",\n    \"battlenet.com.cn\",\n    \"cdn.nintendo.net\",\n    \"cmbchina.com\",\n    \"cmbimg.com\",\n    \"ff14.sdo.com\",\n    \"ffxiv.com\",\n    \"finalfantasyxiv.com\",\n    \"gcloudcs.com\",\n    \"home.arpa\",\n    \"invalid\",\n    \"kuwo.cn\",\n    \"lan\",\n    \"linksys.com\",\n    \"linksyssmartwifi.com\",\n    \"local\",\n    \"localdomain\",\n    \"localhost\",\n    \"market.xiaomi.com\",\n    \"mcdn.bilivideo.cn\",\n    \"media.dssott.com\",\n    \"msftconnecttest.com\",\n    \"msftncsi.com\",\n    \"music.163.com\",\n    \"music.migu.cn\",\n    \"n0808.com\",\n    \"nflxvideo.net\",\n    \"oray.com\",\n    \"orayimg.com\",\n    \"router.asus.com\",\n    \"sandai.net\",\n    \"square-enix.com\",\n    \"srv.nintendo.net\",\n    \"steamcontent.com\",\n    \"uu.163.com\",\n    \"wargaming.net\",\n    \"wggames.cn\",\n    \"wotgame.cn\",\n    \"wowsgame.cn\",\n    \"xiami.com\",\n    \"y.qq.com\"\n  ]\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/tun_singbox_dns",
    "content": "{\n  \"servers\": [\n    {\n      \"tag\": \"remote\",\n      \"type\": \"tcp\",\n      \"server\": \"8.8.8.8\",\n      \"detour\": \"proxy\"\n    },\n    {\n      \"tag\": \"local\",\n      \"type\": \"udp\",\n      \"server\": \"223.5.5.5\"\n    }\n  ],\n  \"rules\": [\n    {\n      \"rule_set\": [\n        \"geosite-google\"\n      ],\n      \"server\": \"remote\",\n      \"strategy\": \"prefer_ipv4\"\n    },\n    {\n      \"rule_set\": [\n        \"geosite-cn\"\n      ],\n      \"server\": \"local\",\n      \"strategy\": \"prefer_ipv4\"\n    }\n  ],\n  \"final\": \"remote\",\n  \"strategy\": \"prefer_ipv4\"\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/tun_singbox_inbound",
    "content": "{\n  \"type\": \"tun\",\n  \"tag\": \"tun-in\",\n  \"interface_name\": \"singbox_tun\",\n  \"address\": [\n    \"172.18.0.1/30\",\n    \"fdfe:dcba:9876::1/126\"\n  ],\n  \"mtu\": 9000,\n  \"auto_route\": true,\n  \"strict_route\": false,\n  \"stack\": \"system\",\n  \"sniff\": true\n}"
  },
  {
    "path": "v2rayN/ServiceLib/Sample/tun_singbox_rules",
    "content": "[\n  {\n    \"network\": \"udp\",\n    \"port\": [\n      135,\n      137,\n      138,\n      139,\n      5353\n    ],\n    \"action\": \"reject\"\n  },\n  {\n    \"ip_cidr\": [\n      \"224.0.0.0/3\",\n      \"ff00::/8\"\n    ],\n    \"action\": \"reject\"\n  }\n]"
  },
  {
    "path": "v2rayN/ServiceLib/ServiceLib.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>Library</OutputType>\n\t</PropertyGroup>\n\n\t<ItemGroup>\n\t\t<PackageReference Include=\"Downloader\" />\n\t\t<PackageReference Include=\"ReactiveUI\">\n\t\t\t<TreatAsUsed>true</TreatAsUsed>\n\t\t</PackageReference>\n\t\t<PackageReference Include=\"ReactiveUI.Fody\" />\n\t\t<PackageReference Include=\"sqlite-net-pcl\" />\n\t\t<PackageReference Include=\"NLog\" />\n\t\t<PackageReference Include=\"WebDav.Client\" />\n\t\t<PackageReference Include=\"YamlDotNet\" />\n\t\t<PackageReference Include=\"QRCoder\" />\n\t\t<PackageReference Include=\"CliWrap\" />\n\t\t<PackageReference Include=\"ZXing.Net.Bindings.SkiaSharp\" />\n\t\t<PackageReference Include=\"TaskScheduler\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<EmbeddedResource Include=\"Sample\\clash_mixin_yaml\" />\n\t\t<EmbeddedResource Include=\"Sample\\clash_tun_yaml\" />\n\t\t<EmbeddedResource Include=\"Sample\\custom_routing_black\" />\n\t\t<EmbeddedResource Include=\"Sample\\custom_routing_global\" />\n\t\t<EmbeddedResource Include=\"Sample\\custom_routing_white\" />\n\t\t<EmbeddedResource Include=\"Sample\\dns_singbox_normal\" />\n\t\t<EmbeddedResource Include=\"Sample\\dns_v2ray_normal\" />\n\t\t<EmbeddedResource Include=\"Sample\\kill_as_sudo_linux_sh\" />\n\t\t<EmbeddedResource Include=\"Sample\\kill_as_sudo_osx_sh\" />\n\t\t<EmbeddedResource Include=\"Sample\\pac\" />\n\t\t<EmbeddedResource Include=\"Sample\\proxy_set_linux_sh\" /> \n\t\t<EmbeddedResource Include=\"Sample\\proxy_set_osx_sh\" />\n\t\t<EmbeddedResource Include=\"Sample\\SampleClientConfig\" />\n\t\t<EmbeddedResource Include=\"Sample\\SampleHttpRequest\" />\n\t\t<EmbeddedResource Include=\"Sample\\SampleHttpResponse\" />\n\t\t<EmbeddedResource Include=\"Sample\\SampleInbound\" />\n\t\t<EmbeddedResource Include=\"Sample\\SampleOutbound\" />\n\t\t<EmbeddedResource Include=\"Sample\\SingboxSampleClientConfig\" />\n\t\t<EmbeddedResource Include=\"Sample\\SingboxSampleOutbound\" />\n\t\t<EmbeddedResource Include=\"Sample\\tun_singbox_dns\" />\n\t\t<EmbeddedResource Include=\"Sample\\tun_singbox_inbound\" />\n\t\t<EmbeddedResource Include=\"Sample\\tun_singbox_rules\" />\n\t\t<EmbeddedResource Include=\"Sample\\linux_autostart_config\" />\n        <EmbeddedResource Include=\"Sample\\singbox_fakeip_filter\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<Compile Update=\"Resx\\ResUI.Designer.cs\">\n\t\t\t<DependentUpon>ResUI.resx</DependentUpon>\n\t\t\t<DesignTime>True</DesignTime>\n\t\t\t<AutoGen>True</AutoGen>\n\t\t</Compile>\n\t\t<EmbeddedResource Update=\"Resx\\ResUI.fa-Ir.resx\">\n\t\t\t<SubType>Designer</SubType>\n\t\t\t<Generator>PublicResXFileCodeGenerator</Generator>\n\t\t</EmbeddedResource>\n        <EmbeddedResource Update=\"Resx\\ResUI.fr.resx\">\n\t\t\t<Generator>PublicResXFileCodeGenerator</Generator>\n\t\t</EmbeddedResource>\n\t\t<EmbeddedResource Update=\"Resx\\ResUI.hu.resx\">\n\t\t\t<Generator>PublicResXFileCodeGenerator</Generator>\n\t\t</EmbeddedResource>\n\t\t<EmbeddedResource Update=\"Resx\\ResUI.resx\">\n\t\t\t<SubType>Designer</SubType>\n\t\t\t<LastGenOutput>ResUI.Designer.cs</LastGenOutput>\n\t\t\t<Generator>PublicResXFileCodeGenerator</Generator>\n\t\t</EmbeddedResource>\n\t\t<EmbeddedResource Update=\"Resx\\ResUI.ru.resx\">\n\t\t\t<SubType>Designer</SubType>\n\t\t\t<Generator>PublicResXFileCodeGenerator</Generator>\n\t\t</EmbeddedResource>\n\t\t<EmbeddedResource Update=\"Resx\\ResUI.zh-Hans.resx\">\n\t\t\t<SubType>Designer</SubType>\n\t\t\t<Generator>PublicResXFileCodeGenerator</Generator>\n\t\t</EmbeddedResource>\n\t\t<EmbeddedResource Update=\"Resx\\ResUI.zh-Hant.resx\">\n\t\t\t<SubType>Designer</SubType>\n\t\t\t<Generator>PublicResXFileCodeGenerator</Generator>\n\t\t</EmbeddedResource>\n\t</ItemGroup>\n\n</Project>\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/CoreConfigClashService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\n/// <summary>\n/// Core configuration file processing class\n/// </summary>\npublic class CoreConfigClashService\n{\n    private Config _config;\n    private static readonly string _tag = \"CoreConfigClashService\";\n\n    public CoreConfigClashService(Config config)\n    {\n        _config = config;\n    }\n\n    public async Task<RetResult> GenerateClientCustomConfig(ProfileItem node, string? fileName)\n    {\n        var ret = new RetResult();\n        if (node == null || fileName is null)\n        {\n            ret.Msg = ResUI.CheckServerSettings;\n            return ret;\n        }\n\n        ret.Msg = ResUI.InitialConfiguration;\n\n        try\n        {\n            if (node == null)\n            {\n                ret.Msg = ResUI.CheckServerSettings;\n                return ret;\n            }\n\n            if (File.Exists(fileName))\n            {\n                File.Delete(fileName);\n            }\n\n            var addressFileName = node.Address;\n            if (addressFileName.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n            if (!File.Exists(addressFileName))\n            {\n                addressFileName = Path.Combine(Utils.GetConfigPath(), addressFileName);\n            }\n            if (!File.Exists(addressFileName))\n            {\n                ret.Msg = ResUI.FailedReadConfiguration + \"1\";\n                return ret;\n            }\n\n            var tagYamlStr1 = \"!<str>\";\n            var tagYamlStr2 = \"__strn__\";\n            var tagYamlStr3 = \"!!str\";\n            var txtFile = File.ReadAllText(addressFileName);\n            txtFile = txtFile.Replace(tagYamlStr1, tagYamlStr2);\n\n            //YAML anchors\n            if (txtFile.Contains(\"<<:\") && txtFile.Contains('*') && txtFile.Contains('&'))\n            {\n                txtFile = YamlUtils.PreprocessYaml(txtFile);\n            }\n\n            var fileContent = YamlUtils.FromYaml<Dictionary<string, object>>(txtFile);\n            if (fileContent == null)\n            {\n                ret.Msg = ResUI.FailedConversionConfiguration;\n                return ret;\n            }\n\n            //mixed-port\n            fileContent[\"mixed-port\"] = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);\n            //log-level\n            fileContent[\"log-level\"] = GetLogLevel(_config.CoreBasicItem.Loglevel);\n\n            //external-controller\n            fileContent[\"external-controller\"] = $\"{Global.Loopback}:{AppManager.Instance.StatePort2}\";\n            fileContent.Remove(\"secret\");\n            //allow-lan\n            if (_config.Inbound.First().AllowLANConn)\n            {\n                fileContent[\"allow-lan\"] = \"true\";\n                fileContent[\"bind-address\"] = \"*\";\n            }\n            else\n            {\n                fileContent[\"allow-lan\"] = \"false\";\n            }\n\n            //ipv6\n            fileContent[\"ipv6\"] = _config.ClashUIItem.EnableIPv6;\n\n            //mode\n            if (!fileContent.ContainsKey(\"mode\"))\n            {\n                fileContent[\"mode\"] = ERuleMode.Rule.ToString().ToLower();\n            }\n            else\n            {\n                if (_config.ClashUIItem.RuleMode != ERuleMode.Unchanged)\n                {\n                    fileContent[\"mode\"] = _config.ClashUIItem.RuleMode.ToString().ToLower();\n                }\n            }\n\n            //enable tun mode\n            if (_config.TunModeItem.EnableTun)\n            {\n                var tun = EmbedUtils.GetEmbedText(Global.ClashTunYaml);\n                if (tun.IsNotEmpty())\n                {\n                    var tunContent = YamlUtils.FromYaml<Dictionary<string, object>>(tun);\n                    if (tunContent != null)\n                    {\n                        fileContent[\"tun\"] = tunContent[\"tun\"];\n                    }\n                }\n            }\n\n            //Mixin\n            try\n            {\n                await MixinContent(fileContent, node);\n            }\n            catch (Exception ex)\n            {\n                Logging.SaveLog($\"{_tag}-Mixin\", ex);\n            }\n\n            var txtFileNew = YamlUtils.ToYaml(fileContent).Replace(tagYamlStr2, tagYamlStr3);\n            await File.WriteAllTextAsync(fileName, txtFileNew);\n            //check again\n            if (!File.Exists(fileName))\n            {\n                ret.Msg = ResUI.FailedReadConfiguration + \"2\";\n                return ret;\n            }\n\n            ClashApiManager.Instance.ProfileContent = fileContent;\n\n            ret.Msg = string.Format(ResUI.SuccessfulConfiguration, $\"{node.GetSummary()}\");\n            ret.Success = true;\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    private async Task MixinContent(Dictionary<string, object> fileContent, ProfileItem node)\n    {\n        if (!_config.ClashUIItem.EnableMixinContent)\n        {\n            return;\n        }\n\n        var path = Utils.GetConfigPath(Global.ClashMixinConfigFileName);\n        if (!File.Exists(path))\n        {\n            var mixin = EmbedUtils.GetEmbedText(Global.ClashMixinYaml);\n            await File.AppendAllTextAsync(path, mixin);\n        }\n\n        var txtFile = await File.ReadAllTextAsync(Utils.GetConfigPath(Global.ClashMixinConfigFileName));\n\n        var mixinContent = YamlUtils.FromYaml<Dictionary<string, object>>(txtFile);\n        if (mixinContent == null)\n        {\n            return;\n        }\n        foreach (var item in mixinContent)\n        {\n            if (!_config.TunModeItem.EnableTun && item.Key == \"tun\")\n            {\n                continue;\n            }\n\n            if (item.Key.StartsWith(\"prepend-\")\n                || item.Key.StartsWith(\"append-\")\n                || item.Key.StartsWith(\"removed-\"))\n            {\n                ModifyContentMerge(fileContent, item.Key, item.Value);\n            }\n            else\n            {\n                fileContent[item.Key] = item.Value;\n            }\n        }\n        return;\n    }\n\n    private void ModifyContentMerge(Dictionary<string, object> fileContent, string key, object value)\n    {\n        var blPrepend = false;\n        var blRemoved = false;\n        if (key.StartsWith(\"prepend-\"))\n        {\n            blPrepend = true;\n            key = key.Replace(\"prepend-\", \"\");\n        }\n        else if (key.StartsWith(\"append-\"))\n        {\n            blPrepend = false;\n            key = key.Replace(\"append-\", \"\");\n        }\n        else if (key.StartsWith(\"removed-\"))\n        {\n            blRemoved = true;\n            key = key.Replace(\"removed-\", \"\");\n        }\n        else\n        {\n            return;\n        }\n\n        if (!blRemoved && !fileContent.ContainsKey(key))\n        {\n            fileContent.Add(key, value);\n            return;\n        }\n        var lstOri = (List<object>)fileContent[key];\n        var lstValue = (List<object>)value;\n\n        if (blRemoved)\n        {\n            foreach (var item in lstValue)\n            {\n                lstOri.RemoveAll(t => t.ToString().StartsWith(item.ToString()));\n            }\n            return;\n        }\n\n        if (blPrepend)\n        {\n            lstValue.Reverse();\n            lstValue.ForEach(item => lstOri.Insert(0, item));\n        }\n        else\n        {\n            lstValue.ForEach(item => lstOri.Add(item));\n        }\n    }\n\n    private string GetLogLevel(string level)\n    {\n        if (level == \"none\")\n        {\n            return \"silent\";\n        }\n        else\n        {\n            return level;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/CoreConfigSingboxService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService(CoreConfigContext context)\n{\n    private static readonly string _tag = \"CoreConfigSingboxService\";\n    private readonly Config _config = context.AppConfig;\n    private readonly ProfileItem _node = context.Node;\n\n    private SingboxConfig _coreConfig = new();\n\n    #region public gen function\n\n    public RetResult GenerateClientConfigContent()\n    {\n        var ret = new RetResult();\n        try\n        {\n            if (_node == null\n                || !_node.IsValid())\n            {\n                ret.Msg = ResUI.CheckServerSettings;\n                return ret;\n            }\n            if (_node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))\n            {\n                ret.Msg = ResUI.Incorrectconfiguration + $\" - {_node.GetNetwork()}\";\n                return ret;\n            }\n\n            ret.Msg = ResUI.InitialConfiguration;\n\n            var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);\n            if (result.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n\n            _coreConfig = JsonUtils.Deserialize<SingboxConfig>(result);\n            if (_coreConfig == null)\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            GenLog();\n\n            GenInbounds();\n\n            GenOutbounds();\n\n            GenRouting();\n\n            GenDns();\n\n            GenExperimental();\n\n            ConvertGeo2Ruleset();\n\n            ret.Msg = string.Format(ResUI.SuccessfulConfiguration, \"\");\n            ret.Success = true;\n\n            ret.Data = ApplyFullConfigTemplate();\n            if (context.TunProtectSsPort is > 0 and <= 65535)\n            {\n                var ssInbound = new\n                {\n                    type = \"shadowsocks\",\n                    tag = \"tun-protect-ss\",\n                    listen = Global.Loopback,\n                    listen_port = context.TunProtectSsPort,\n                    method = \"none\",\n                    password = \"none\",\n                };\n                var directRule = new Rule4Sbox()\n                {\n                    inbound = new List<string> { ssInbound.tag },\n                    outbound = Global.DirectTag,\n                };\n                var singboxConfigNode = JsonUtils.ParseJson(ret.Data.ToString())!.AsObject();\n                var inboundsNode = singboxConfigNode[\"inbounds\"]!.AsArray();\n                inboundsNode.Add(JsonUtils.SerializeToNode(ssInbound, new JsonSerializerOptions\n                {\n                    DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull\n                }));\n                var routeNode = singboxConfigNode[\"route\"]?.AsObject();\n                var rulesNode = routeNode?[\"rules\"]?.AsArray();\n                var protectRuleNode = JsonUtils.SerializeToNode(directRule,\n                    new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });\n                if (rulesNode != null)\n                {\n                    rulesNode.Insert(0, protectRuleNode);\n                }\n                else\n                {\n                    var newRulesNode = new JsonArray() { protectRuleNode };\n                    if (routeNode is null)\n                    {\n                        var newRouteNode = new JsonObject() { [\"rules\"] = newRulesNode };\n                        singboxConfigNode[\"route\"] = newRouteNode;\n                    }\n                    else\n                    {\n                        routeNode[\"rules\"] = newRulesNode;\n                    }\n                }\n                ret.Data = JsonUtils.Serialize(singboxConfigNode);\n            }\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    public RetResult GenerateClientSpeedtestConfig(List<ServerTestItem> selecteds)\n    {\n        var ret = new RetResult();\n        try\n        {\n            ret.Msg = ResUI.InitialConfiguration;\n\n            var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);\n            var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);\n            if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n\n            _coreConfig = JsonUtils.Deserialize<SingboxConfig>(result);\n            if (_coreConfig == null)\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            var (lstIpEndPoints, lstTcpConns) = Utils.GetActiveNetworkInfo();\n\n            GenLog();\n            GenMinimizedDns();\n            _coreConfig.inbounds.Clear();\n            _coreConfig.outbounds.RemoveAt(0);\n\n            var initPort = AppManager.Instance.GetLocalPort(EInboundProtocol.speedtest);\n\n            foreach (var it in selecteds)\n            {\n                if (!(Global.SingboxSupportConfigType.Contains(it.ConfigType) || it.ConfigType.IsGroupType()))\n                {\n                    continue;\n                }\n                if (!it.ConfigType.IsComplexType() && it.Port <= 0)\n                {\n                    continue;\n                }\n                var actIndexId = context.ServerTestItemMap.GetValueOrDefault(it.IndexId, it.IndexId);\n                var item = context.AllProxiesMap.GetValueOrDefault(actIndexId);\n                if (item is null || item.ConfigType is EConfigType.Custom || !item.IsValid())\n                {\n                    continue;\n                }\n\n                //find unused port\n                var port = initPort;\n                for (var k = initPort; k < Global.MaxPort; k++)\n                {\n                    if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)\n                    {\n                        continue;\n                    }\n                    if (lstTcpConns?.FindIndex(_it => _it.LocalEndPoint.Port == k) >= 0)\n                    {\n                        continue;\n                    }\n                    //found\n                    port = k;\n                    initPort = port + 1;\n                    break;\n                }\n\n                //Port In Used\n                if (lstIpEndPoints?.FindIndex(_it => _it.Port == port) >= 0)\n                {\n                    continue;\n                }\n                it.Port = port;\n                it.AllowTest = true;\n\n                //inbound\n                Inbound4Sbox inbound = new()\n                {\n                    listen = Global.Loopback,\n                    listen_port = port,\n                    type = EInboundProtocol.mixed.ToString(),\n                };\n                inbound.tag = inbound.type + inbound.listen_port.ToString();\n                _coreConfig.inbounds.Add(inbound);\n\n                var tag = Global.ProxyTag + inbound.listen_port.ToString();\n                var serverList = new CoreConfigSingboxService(context with { Node = item }).BuildAllProxyOutbounds(tag);\n                FillRangeProxy(serverList, _coreConfig, false);\n\n                //rule\n                Rule4Sbox rule = new()\n                {\n                    inbound = new List<string> { inbound.tag },\n                    outbound = tag\n                };\n                _coreConfig.route.rules.Add(rule);\n            }\n\n            ret.Success = true;\n            ret.Data = JsonUtils.Serialize(_coreConfig);\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    public RetResult GenerateClientSpeedtestConfig(int port)\n    {\n        var ret = new RetResult();\n        try\n        {\n            if (_node == null\n                || !_node.IsValid())\n            {\n                ret.Msg = ResUI.CheckServerSettings;\n                return ret;\n            }\n            if (_node.GetNetwork() is nameof(ETransport.kcp) or nameof(ETransport.xhttp))\n            {\n                ret.Msg = ResUI.Incorrectconfiguration + $\" - {_node.GetNetwork()}\";\n                return ret;\n            }\n\n            ret.Msg = ResUI.InitialConfiguration;\n\n            var result = EmbedUtils.GetEmbedText(Global.SingboxSampleClient);\n            if (result.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n\n            _coreConfig = JsonUtils.Deserialize<SingboxConfig>(result);\n            if (_coreConfig == null)\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            GenLog();\n            GenOutbounds();\n            GenMinimizedDns();\n\n            _coreConfig.route.rules.Clear();\n            _coreConfig.inbounds.Clear();\n            _coreConfig.inbounds.Add(new()\n            {\n                tag = $\"{EInboundProtocol.mixed}{port}\",\n                listen = Global.Loopback,\n                listen_port = port,\n                type = EInboundProtocol.mixed.ToString(),\n            });\n\n            ret.Msg = string.Format(ResUI.SuccessfulConfiguration, \"\");\n            ret.Success = true;\n            ret.Data = JsonUtils.Serialize(_coreConfig);\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    #endregion public gen function\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxConfigTemplateService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private string ApplyFullConfigTemplate()\n    {\n        var fullConfigTemplate = context.FullConfigTemplate;\n        if (fullConfigTemplate is not { Enabled: true })\n        {\n            return JsonUtils.Serialize(_coreConfig);\n        }\n\n        var fullConfigTemplateItem = context.IsTunEnabled ? fullConfigTemplate.TunConfig : fullConfigTemplate.Config;\n        if (fullConfigTemplateItem.IsNullOrEmpty())\n        {\n            return JsonUtils.Serialize(_coreConfig);\n        }\n\n        var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplateItem);\n        if (fullConfigTemplateNode == null)\n        {\n            return JsonUtils.Serialize(_coreConfig);\n        }\n\n        // Process outbounds\n        var customOutboundsNode = fullConfigTemplateNode[\"outbounds\"] is JsonArray outbounds ? outbounds : [];\n        foreach (var outbound in _coreConfig.outbounds)\n        {\n            if (outbound.type.ToLower() is \"direct\" or \"block\")\n            {\n                if (fullConfigTemplate.AddProxyOnly == true)\n                {\n                    continue;\n                }\n            }\n            else if (outbound.detour.IsNullOrEmpty() && !fullConfigTemplate.ProxyDetour.IsNullOrEmpty() && !Utils.IsPrivateNetwork(outbound.server ?? string.Empty))\n            {\n                outbound.detour = fullConfigTemplate.ProxyDetour;\n            }\n            customOutboundsNode.Add(JsonUtils.DeepCopy(outbound));\n        }\n        fullConfigTemplateNode[\"outbounds\"] = customOutboundsNode;\n\n        // Process endpoints\n        if (_coreConfig.endpoints != null && _coreConfig.endpoints.Count > 0)\n        {\n            var customEndpointsNode = fullConfigTemplateNode[\"endpoints\"] is JsonArray endpoints ? endpoints : [];\n            foreach (var endpoint in _coreConfig.endpoints)\n            {\n                if (endpoint.detour.IsNullOrEmpty() && !fullConfigTemplate.ProxyDetour.IsNullOrEmpty())\n                {\n                    endpoint.detour = fullConfigTemplate.ProxyDetour;\n                }\n                customEndpointsNode.Add(JsonUtils.DeepCopy(endpoint));\n            }\n            fullConfigTemplateNode[\"endpoints\"] = customEndpointsNode;\n        }\n\n        return JsonUtils.Serialize(fullConfigTemplateNode);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxDnsService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private void GenDns()\n    {\n        try\n        {\n            var item = context.RawDnsItem;\n            if (item is { Enabled: true })\n            {\n                GenDnsCustom();\n                return;\n            }\n\n            GenDnsServers();\n            GenDnsRules();\n\n            _coreConfig.dns ??= new Dns4Sbox();\n            _coreConfig.dns.independent_cache = true;\n\n            // final dns\n            var routing = context.RoutingItem;\n            var useDirectDns = false;\n            if (routing != null)\n            {\n                var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];\n\n                if (rules?.LastOrDefault() is { } lastRule && lastRule.OutboundTag == Global.DirectTag)\n                {\n                    var noDomain = lastRule.Domain == null || lastRule.Domain.Count == 0;\n                    var noProcess = lastRule.Process == null || lastRule.Process.Count == 0;\n                    var isAnyIp = lastRule.Ip == null || lastRule.Ip.Count == 0 || lastRule.Ip.Contains(\"0.0.0.0/0\");\n                    var isAnyPort = string.IsNullOrEmpty(lastRule.Port) || lastRule.Port == \"0-65535\";\n                    var isAnyNetwork = string.IsNullOrEmpty(lastRule.Network) || lastRule.Network == \"tcp,udp\";\n                    useDirectDns = noDomain && noProcess && isAnyIp && isAnyPort && isAnyNetwork;\n                }\n            }\n            _coreConfig.dns.final = useDirectDns ? Global.SingboxDirectDNSTag : Global.SingboxRemoteDNSTag;\n            var simpleDnsItem = context.SimpleDnsItem;\n            if ((!useDirectDns) && simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == false)\n            {\n                _coreConfig.dns.rules.Add(new()\n                {\n                    server = Global.SingboxFakeDNSTag,\n                    query_type = new List<int> { 1, 28 }, // A and AAAA\n                    rewrite_ttl = 1,\n                });\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void GenDnsServers()\n    {\n        var simpleDnsItem = context.SimpleDnsItem;\n        var finalDns = GenBootstrapDns();\n\n        var directDns = ParseDnsAddress(simpleDnsItem.DirectDNS ?? Global.DomainDirectDNSAddress.First());\n        directDns.tag = Global.SingboxDirectDNSTag;\n        directDns.domain_resolver = Global.SingboxLocalDNSTag;\n\n        var remoteDns = ParseDnsAddress(simpleDnsItem.RemoteDNS ?? Global.DomainRemoteDNSAddress.First());\n        remoteDns.tag = Global.SingboxRemoteDNSTag;\n        remoteDns.detour = Global.ProxyTag;\n        remoteDns.domain_resolver = Global.SingboxLocalDNSTag;\n\n        var hostsDns = new Server4Sbox\n        {\n            tag = Global.SingboxHostsDNSTag,\n            type = \"hosts\",\n            predefined = new(),\n        };\n        if (simpleDnsItem.AddCommonHosts == true)\n        {\n            hostsDns.predefined = Global.PredefinedHosts;\n        }\n\n        if (simpleDnsItem.UseSystemHosts == true)\n        {\n            var systemHosts = Utils.GetSystemHosts();\n            if (systemHosts != null && systemHosts.Count > 0)\n            {\n                foreach (var host in systemHosts)\n                {\n                    hostsDns.predefined.TryAdd(host.Key, new List<string> { host.Value });\n                }\n            }\n        }\n\n        foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))\n        {\n            // only allow full match\n            // like example.com and full:example.com,\n            // but not domain:example.com, keyword:example.com or regex:example.com etc.\n            var testRule = new Rule4Sbox();\n            if (!ParseV2Domain(kvp.Key, testRule))\n            {\n                continue;\n            }\n            if (testRule.domain_keyword?.Count > 0 && !kvp.Key.Contains(':'))\n            {\n                testRule.domain = testRule.domain_keyword;\n                testRule.domain_keyword = null;\n            }\n            if (testRule.domain?.Count == 1)\n            {\n                hostsDns.predefined[testRule.domain.First()] = kvp.Value.Where(Utils.IsIpAddress).ToList();\n            }\n        }\n\n        foreach (var host in hostsDns.predefined)\n        {\n            if (finalDns.server == host.Key)\n            {\n                finalDns.domain_resolver = Global.SingboxHostsDNSTag;\n            }\n            if (remoteDns.server == host.Key)\n            {\n                remoteDns.domain_resolver = Global.SingboxHostsDNSTag;\n            }\n            if (directDns.server == host.Key)\n            {\n                directDns.domain_resolver = Global.SingboxHostsDNSTag;\n            }\n        }\n\n        _coreConfig.dns ??= new Dns4Sbox();\n        _coreConfig.dns.servers ??= [];\n        _coreConfig.dns.servers.Add(remoteDns);\n        _coreConfig.dns.servers.Add(directDns);\n        _coreConfig.dns.servers.Add(hostsDns);\n\n        // fake ip\n        if (simpleDnsItem.FakeIP == true)\n        {\n            var fakeip = new Server4Sbox\n            {\n                tag = Global.SingboxFakeDNSTag,\n                type = \"fakeip\",\n                inet4_range = \"198.18.0.0/15\",\n                inet6_range = \"fc00::/18\",\n            };\n            _coreConfig.dns.servers.Add(fakeip);\n        }\n    }\n\n    private Server4Sbox GenBootstrapDns()\n    {\n        var finalDns = ParseDnsAddress(context.SimpleDnsItem?.BootstrapDNS ?? Global.DomainPureIPDNSAddress.First());\n        finalDns.tag = Global.SingboxLocalDNSTag;\n        _coreConfig.dns ??= new Dns4Sbox();\n        _coreConfig.dns.servers ??= [];\n        _coreConfig.dns.servers.Add(finalDns);\n        return finalDns;\n    }\n\n    private void GenDnsRules()\n    {\n        var simpleDnsItem = context.SimpleDnsItem;\n        _coreConfig.dns ??= new Dns4Sbox();\n        _coreConfig.dns.rules ??= [];\n\n        _coreConfig.dns.rules.Add(new() { ip_accept_any = true, server = Global.SingboxHostsDNSTag });\n\n        if (context.ProtectDomainList.Count > 0)\n        {\n            _coreConfig.dns.rules.Add(new()\n            {\n                server = Global.SingboxDirectDNSTag,\n                strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom),\n                domain = context.ProtectDomainList.ToList(),\n            });\n        }\n\n        _coreConfig.dns.rules.AddRange(new[]\n        {\n            new Rule4Sbox\n            {\n                server = Global.SingboxRemoteDNSTag,\n                strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Proxy),\n                clash_mode = ERuleMode.Global.ToString()\n            },\n            new Rule4Sbox\n            {\n                server = Global.SingboxDirectDNSTag,\n                strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom),\n                clash_mode = ERuleMode.Direct.ToString()\n            }\n        });\n\n        foreach (var kvp in Utils.ParseHostsToDictionary(simpleDnsItem.Hosts))\n        {\n            var predefined = kvp.Value.First();\n            if (predefined.IsNullOrEmpty())\n            {\n                continue;\n            }\n            var rule = new Rule4Sbox()\n            {\n                query_type = [1, 5, 28], // A, CNAME and AAAA\n                action = \"predefined\",\n                rcode = \"NOERROR\",\n            };\n            if (!ParseV2Domain(kvp.Key, rule))\n            {\n                continue;\n            }\n            // see: https://xtls.github.io/en/config/dns.html#dnsobject\n            // The matching format (domain:, full:, etc.) is the same as the domain\n            // in the commonly used Routing System. The difference is that without a prefix,\n            // it defaults to using the full: prefix (similar to the common hosts file syntax).\n            if (rule.domain_keyword?.Count > 0 && !kvp.Key.Contains(':'))\n            {\n                rule.domain = rule.domain_keyword;\n                rule.domain_keyword = null;\n            }\n            // example.com #0 -> example.com with NOERROR\n            if (predefined.StartsWith('#') && int.TryParse(predefined.AsSpan(1), out var rcode))\n            {\n                rule.rcode = rcode switch\n                {\n                    0 => \"NOERROR\",\n                    1 => \"FORMERR\",\n                    2 => \"SERVFAIL\",\n                    3 => \"NXDOMAIN\",\n                    4 => \"NOTIMP\",\n                    5 => \"REFUSED\",\n                    _ => \"NOERROR\",\n                };\n            }\n            else if (Utils.IsDomain(predefined))\n            {\n                // example.com CNAME target.com -> example.com with CNAME target.com\n                rule.answer = new List<string> { $\"*. IN CNAME {predefined}.\" };\n            }\n            else if (Utils.IsIpAddress(predefined) && (rule.domain?.Count ?? 0) == 0)\n            {\n                // not full match, but an IP address, treat it as predefined answer\n                if (Utils.IsIpv6(predefined))\n                {\n                    rule.answer = new List<string> { $\"*. IN AAAA {predefined}\" };\n                }\n                else\n                {\n                    rule.answer = new List<string> { $\"*. IN A {predefined}\" };\n                }\n            }\n            else\n            {\n                continue;\n            }\n            _coreConfig.dns.rules.Add(rule);\n        }\n\n        if (simpleDnsItem.BlockBindingQuery == true)\n        {\n            _coreConfig.dns.rules.Add(new()\n            {\n                query_type = [64, 65],\n                action = \"predefined\",\n                rcode = \"NOERROR\"\n            });\n        }\n\n        if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == true)\n        {\n            var fakeipFilterRule = JsonUtils.Deserialize<Rule4Sbox>(EmbedUtils.GetEmbedText(Global.SingboxFakeIPFilterFileName));\n            fakeipFilterRule.invert = true;\n            var rule4Fake = new Rule4Sbox\n            {\n                server = Global.SingboxFakeDNSTag,\n                type = \"logical\",\n                mode = \"and\",\n                rewrite_ttl = 1,\n                rules =\n                [\n                    new()\n                    {\n                        query_type = [1, 28], // A and AAAA\n                    },\n                    fakeipFilterRule\n                ]\n            };\n\n            _coreConfig.dns.rules.Add(rule4Fake);\n        }\n\n        var routing = context.RoutingItem;\n        if (routing == null)\n        {\n            return;\n        }\n\n        var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet) ?? [];\n        var expectedIPCidr = new List<string>();\n        var expectedIPsRegions = new List<string>();\n        var regionNames = new HashSet<string>();\n\n        if (!string.IsNullOrEmpty(simpleDnsItem?.DirectExpectedIPs))\n        {\n            var ipItems = simpleDnsItem.DirectExpectedIPs\n                .Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)\n                .Select(s => s.Trim())\n                .Where(s => !string.IsNullOrEmpty(s))\n                .ToList();\n\n            foreach (var ip in ipItems)\n            {\n                if (ip.StartsWith(\"geoip:\", StringComparison.OrdinalIgnoreCase))\n                {\n                    var region = ip[\"geoip:\".Length..];\n                    if (!string.IsNullOrEmpty(region))\n                    {\n                        expectedIPsRegions.Add(region);\n                        regionNames.Add(region);\n                        regionNames.Add($\"geolocation-{region}\");\n                        regionNames.Add($\"tld-{region}\");\n                    }\n                }\n                else\n                {\n                    expectedIPCidr.Add(ip);\n                }\n            }\n        }\n\n        foreach (var item in rules)\n        {\n            if (!item.Enabled || item.Domain is null || item.Domain.Count == 0)\n            {\n                continue;\n            }\n\n            if (item.RuleType == ERuleType.Routing)\n            {\n                continue;\n            }\n\n            var rule = new Rule4Sbox();\n            var validDomains = item.Domain.Count(it => ParseV2Domain(it, rule));\n            if (validDomains <= 0)\n            {\n                continue;\n            }\n\n            if (item.OutboundTag == Global.DirectTag)\n            {\n                rule.server = Global.SingboxDirectDNSTag;\n                rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom);\n\n                if (expectedIPsRegions.Count > 0 && rule.geosite?.Count > 0)\n                {\n                    var geositeSet = new HashSet<string>(rule.geosite);\n                    if (regionNames.Intersect(geositeSet).Any())\n                    {\n                        if (expectedIPsRegions.Count > 0)\n                        {\n                            rule.geoip = expectedIPsRegions;\n                        }\n                        if (expectedIPCidr.Count > 0)\n                        {\n                            rule.ip_cidr = expectedIPCidr;\n                        }\n                    }\n                }\n            }\n            else if (item.OutboundTag == Global.BlockTag)\n            {\n                rule.action = \"predefined\";\n                rule.rcode = \"NXDOMAIN\";\n            }\n            else\n            {\n                if (simpleDnsItem.FakeIP == true && simpleDnsItem.GlobalFakeIp == false)\n                {\n                    var rule4Fake = JsonUtils.DeepCopy(rule);\n                    rule4Fake.server = Global.SingboxFakeDNSTag;\n                    rule4Fake.query_type = new List<int> { 1, 28 }; // A and AAAA\n                    rule4Fake.rewrite_ttl = 1;\n                    _coreConfig.dns.rules.Add(rule4Fake);\n                }\n                rule.server = Global.SingboxRemoteDNSTag;\n                rule.strategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Proxy);\n            }\n\n            _coreConfig.dns.rules.Add(rule);\n        }\n    }\n\n    private void GenMinimizedDns()\n    {\n        GenDnsServers();\n        foreach (var server in _coreConfig.dns!.servers.Where(s => !string.IsNullOrEmpty(s.detour)).ToList())\n        {\n            _coreConfig.dns.servers.Remove(server);\n        }\n        _coreConfig.dns ??= new();\n        _coreConfig.dns.rules ??= [];\n        _coreConfig.dns.rules.Clear();\n        _coreConfig.dns.final = Global.SingboxDirectDNSTag;\n        _coreConfig.route.default_domain_resolver = new()\n        {\n            server = Global.SingboxDirectDNSTag,\n        };\n    }\n\n    private void GenDnsCustom()\n    {\n        try\n        {\n            var item = context.RawDnsItem;\n            var strDNS = string.Empty;\n            if (context.IsTunEnabled)\n            {\n                strDNS = string.IsNullOrEmpty(item?.TunDNS) ? EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName) : item?.TunDNS;\n            }\n            else\n            {\n                strDNS = string.IsNullOrEmpty(item?.NormalDNS) ? EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName) : item?.NormalDNS;\n            }\n\n            var dns4Sbox = JsonUtils.Deserialize<Dns4Sbox>(strDNS);\n            if (dns4Sbox is null)\n            {\n                return;\n            }\n            _coreConfig.dns = dns4Sbox;\n            if (dns4Sbox.servers?.Count > 0 &&\n                dns4Sbox.servers.First().address.IsNullOrEmpty())\n            {\n                GenDnsProtectCustom();\n            }\n            else\n            {\n                GenDnsProtectCustomLegacy();\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void GenDnsProtectCustom()\n    {\n        var dnsItem = context.RawDnsItem;\n        var dns4Sbox = _coreConfig.dns ?? new();\n        dns4Sbox.servers ??= [];\n        dns4Sbox.rules ??= [];\n\n        var tag = Global.SingboxLocalDNSTag;\n        dns4Sbox.rules.Insert(0, new()\n        {\n            server = tag,\n            clash_mode = ERuleMode.Direct.ToString()\n        });\n        dns4Sbox.rules.Insert(0, new()\n        {\n            server = dns4Sbox.servers.Where(t => t.detour == Global.ProxyTag).Select(t => t.tag).FirstOrDefault() ?? \"remote\",\n            clash_mode = ERuleMode.Global.ToString()\n        });\n\n        var finalDnsAddress = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dnsItem?.DomainDNSAddress;\n\n        var localDnsServer = ParseDnsAddress(finalDnsAddress);\n        localDnsServer.tag = tag;\n\n        dns4Sbox.servers.Add(localDnsServer);\n        var protectDomainRule = BuildProtectDomainRule();\n        if (protectDomainRule != null)\n        {\n            dns4Sbox.rules.Insert(0, protectDomainRule);\n        }\n\n        _coreConfig.dns = dns4Sbox;\n    }\n\n    private void GenDnsProtectCustomLegacy()\n    {\n        GenDnsProtectCustom();\n\n        _coreConfig.dns?.servers?.RemoveAll(s => s.tag == Global.SingboxLocalDNSTag);\n        var dnsItem = context.RawDnsItem;\n        var localDnsServer = new Server4Sbox()\n        {\n            address = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress)\n                ? Global.DomainPureIPDNSAddress.FirstOrDefault()\n                : dnsItem?.DomainDNSAddress,\n            tag = Global.SingboxLocalDNSTag,\n            detour = Global.DirectTag,\n        };\n        _coreConfig.dns?.servers?.Add(localDnsServer);\n    }\n\n    private Rule4Sbox? BuildProtectDomainRule()\n    {\n        if (context.ProtectDomainList.Count == 0)\n        {\n            return null;\n        }\n        return new()\n        {\n            server = Global.SingboxLocalDNSTag,\n            domain = context.ProtectDomainList.ToList(),\n        };\n    }\n\n    private static Server4Sbox? ParseDnsAddress(string address)\n    {\n        var addressFirst = address?.Split(address.Contains(',') ? ',' : ';').FirstOrDefault()?.Trim();\n        if (string.IsNullOrEmpty(addressFirst))\n        {\n            return null;\n        }\n\n        var server = new Server4Sbox();\n\n        if (addressFirst is \"local\" or \"localhost\")\n        {\n            server.type = \"local\";\n            return server;\n        }\n\n        var (domain, scheme, port, path) = Utils.ParseUrl(addressFirst);\n\n        if (scheme.Equals(\"dhcp\", StringComparison.OrdinalIgnoreCase))\n        {\n            server.type = \"dhcp\";\n            if ((!domain.IsNullOrEmpty()) && domain != \"auto\")\n            {\n                server.server = domain;\n            }\n            return server;\n        }\n\n        if (scheme.IsNullOrEmpty())\n        {\n            // udp dns\n            server.type = \"udp\";\n        }\n        else\n        {\n            // server.type = scheme.ToLower();\n\n            // remove \"+local\" suffix\n            // TODO: \"+local\" suffix decide server.detour = \"direct\" ?\n            server.type = scheme.Replace(\"+local\", \"\", StringComparison.OrdinalIgnoreCase).ToLower();\n        }\n\n        server.server = domain;\n        if (port != 0)\n        {\n            server.server_port = port;\n        }\n        if ((server.type == \"https\" || server.type == \"h3\") && !string.IsNullOrEmpty(path) && path != \"/\")\n        {\n            server.path = path;\n        }\n        return server;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxInboundService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private void GenInbounds()\n    {\n        try\n        {\n            var listen = \"0.0.0.0\";\n            var listenPort = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);\n            _coreConfig.inbounds = [];\n\n            if (!context.IsTunEnabled\n                || (context.IsTunEnabled && _node.Port != listenPort))\n            {\n                var inbound = new Inbound4Sbox()\n                {\n                    type = EInboundProtocol.mixed.ToString(),\n                    tag = EInboundProtocol.socks.ToString(),\n                    listen = Global.Loopback,\n                };\n                _coreConfig.inbounds.Add(inbound);\n\n                inbound.listen_port = listenPort;\n\n                if (_config.Inbound.First().SecondLocalPortEnabled)\n                {\n                    var inbound2 = BuildInbound(inbound, EInboundProtocol.socks2, true);\n                    _coreConfig.inbounds.Add(inbound2);\n                }\n\n                if (_config.Inbound.First().AllowLANConn)\n                {\n                    if (_config.Inbound.First().NewPort4LAN)\n                    {\n                        var inbound3 = BuildInbound(inbound, EInboundProtocol.socks3, true);\n                        inbound3.listen = listen;\n                        _coreConfig.inbounds.Add(inbound3);\n\n                        //auth\n                        if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty())\n                        {\n                            inbound3.users = new() { new() { username = _config.Inbound.First().User, password = _config.Inbound.First().Pass } };\n                        }\n                    }\n                    else\n                    {\n                        inbound.listen = listen;\n                    }\n                }\n            }\n\n            if (context.IsTunEnabled)\n            {\n                if (_config.TunModeItem.Mtu <= 0)\n                {\n                    _config.TunModeItem.Mtu = Global.TunMtus.First();\n                }\n                if (_config.TunModeItem.Stack.IsNullOrEmpty())\n                {\n                    _config.TunModeItem.Stack = Global.TunStacks.First();\n                }\n\n                var tunInbound = JsonUtils.Deserialize<Inbound4Sbox>(EmbedUtils.GetEmbedText(Global.TunSingboxInboundFileName)) ?? new Inbound4Sbox { };\n                tunInbound.interface_name = Utils.IsMacOS() ? $\"utun{new Random().Next(99)}\" : \"singbox_tun\";\n                tunInbound.mtu = _config.TunModeItem.Mtu;\n                tunInbound.auto_route = _config.TunModeItem.AutoRoute;\n                tunInbound.strict_route = _config.TunModeItem.StrictRoute;\n                tunInbound.stack = _config.TunModeItem.Stack;\n                if (_config.TunModeItem.EnableIPv6Address == false)\n                {\n                    tunInbound.address = [\"172.18.0.1/30\"];\n                }\n\n                _coreConfig.inbounds.Add(tunInbound);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private Inbound4Sbox BuildInbound(Inbound4Sbox inItem, EInboundProtocol protocol, bool bSocks)\n    {\n        var inbound = JsonUtils.DeepCopy(inItem);\n        inbound.tag = protocol.ToString();\n        inbound.listen_port = inItem.listen_port + (int)protocol;\n        inbound.type = EInboundProtocol.mixed.ToString();\n        return inbound;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxLogService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private void GenLog()\n    {\n        try\n        {\n            switch (_config.CoreBasicItem.Loglevel)\n            {\n                case \"debug\":\n                case \"info\":\n                case \"error\":\n                    _coreConfig.log.level = _config.CoreBasicItem.Loglevel;\n                    break;\n\n                case \"warning\":\n                    _coreConfig.log.level = \"warn\";\n                    break;\n\n                default:\n                    break;\n            }\n            if (_config.CoreBasicItem.Loglevel == Global.None)\n            {\n                _coreConfig.log.disabled = true;\n            }\n            if (_config.CoreBasicItem.LogEnabled)\n            {\n                var dtNow = DateTime.Now;\n                _coreConfig.log.output = Utils.GetLogPath($\"sbox_{dtNow:yyyy-MM-dd}.txt\");\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxOutboundService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private void GenOutbounds()\n    {\n        var proxyOutbounds = BuildAllProxyOutbounds();\n        FillRangeProxy(proxyOutbounds, _coreConfig, true);\n    }\n\n    private List<BaseServer4Sbox> BuildAllProxyOutbounds(string baseTagName = Global.ProxyTag, bool withSelector = true)\n    {\n        var proxyOutboundList = new List<BaseServer4Sbox>();\n        if (!_node.ConfigType.IsComplexType())\n        {\n            var outbound = BuildProxyOutbound(baseTagName);\n            proxyOutboundList.Add(outbound);\n        }\n        else\n        {\n            proxyOutboundList.AddRange(BuildGroupProxyOutbounds(baseTagName));\n        }\n        if (withSelector)\n        {\n            var proxyTags = proxyOutboundList.Where(n => n.tag.StartsWith(Global.ProxyTag)).Select(n => n.tag).ToList();\n            if (proxyTags.Count > 1)\n            {\n                proxyOutboundList.InsertRange(0, BuildSelectorOutbounds(proxyTags, baseTagName));\n            }\n        }\n        return proxyOutboundList;\n    }\n\n    private BaseServer4Sbox BuildProxyOutbound(string baseTagName = Global.ProxyTag)\n    {\n        var outbound = BuildProxyServer();\n        outbound.tag = baseTagName;\n        return outbound;\n    }\n\n    private List<BaseServer4Sbox> BuildGroupProxyOutbounds(string baseTagName = Global.ProxyTag)\n    {\n        var proxyOutboundList = new List<BaseServer4Sbox>();\n        switch (_node.ConfigType)\n        {\n            case EConfigType.PolicyGroup:\n                proxyOutboundList = BuildOutboundsList(baseTagName);\n                break;\n\n            case EConfigType.ProxyChain:\n                proxyOutboundList = BuildChainOutboundsList(baseTagName);\n                break;\n        }\n        return proxyOutboundList;\n    }\n\n    private BaseServer4Sbox BuildProxyServer()\n    {\n        try\n        {\n            var txtOutbound = EmbedUtils.GetEmbedText(Global.SingboxSampleOutbound);\n            if (_node.ConfigType == EConfigType.WireGuard)\n            {\n                var endpoint = JsonUtils.Deserialize<Endpoints4Sbox>(txtOutbound);\n                FillEndpoint(endpoint);\n                return endpoint;\n            }\n            else\n            {\n                var outbound = JsonUtils.Deserialize<Outbound4Sbox>(txtOutbound);\n                FillOutbound(outbound);\n                return outbound;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        throw new InvalidOperationException();\n    }\n\n    private void FillOutbound(Outbound4Sbox outbound)\n    {\n        try\n        {\n            var protocolExtra = _node.GetProtocolExtra();\n            outbound.server = _node.Address;\n            outbound.server_port = _node.Port;\n            outbound.type = Global.ProtocolTypes[_node.ConfigType];\n\n            switch (_node.ConfigType)\n            {\n                case EConfigType.VMess:\n                    {\n                        outbound.uuid = _node.Password;\n                        outbound.alter_id = int.TryParse(protocolExtra.AlterId, out var result) ? result : 0;\n                        if (Global.VmessSecurities.Contains(protocolExtra.VmessSecurity))\n                        {\n                            outbound.security = protocolExtra.VmessSecurity;\n                        }\n                        else\n                        {\n                            outbound.security = Global.DefaultSecurity;\n                        }\n\n                        FillOutboundMux(outbound);\n                        FillOutboundTransport(outbound);\n                        break;\n                    }\n                case EConfigType.Shadowsocks:\n                    {\n                        outbound.method = AppManager.Instance.GetShadowsocksSecurities(_node).Contains(protocolExtra.SsMethod)\n                            ? protocolExtra.SsMethod : Global.None;\n                        outbound.password = _node.Password;\n\n                        if (_node.Network == nameof(ETransport.tcp) && _node.HeaderType == Global.TcpHeaderHttp)\n                        {\n                            outbound.plugin = \"obfs-local\";\n                            outbound.plugin_opts = $\"obfs=http;obfs-host={_node.RequestHost};\";\n                        }\n                        else\n                        {\n                            var pluginArgs = string.Empty;\n                            if (_node.Network == nameof(ETransport.ws))\n                            {\n                                pluginArgs += \"mode=websocket;\";\n                                pluginArgs += $\"host={_node.RequestHost};\";\n                                // https://github.com/shadowsocks/v2ray-plugin/blob/e9af1cdd2549d528deb20a4ab8d61c5fbe51f306/args.go#L172\n                                // Equal signs and commas [and backslashes] must be escaped with a backslash.\n                                var path = _node.Path.Replace(\"\\\\\", \"\\\\\\\\\").Replace(\"=\", \"\\\\=\").Replace(\",\", \"\\\\,\");\n                                pluginArgs += $\"path={path};\";\n                            }\n                            else if (_node.Network == nameof(ETransport.quic))\n                            {\n                                pluginArgs += \"mode=quic;\";\n                            }\n                            if (_node.StreamSecurity == Global.StreamSecurity)\n                            {\n                                pluginArgs += \"tls;\";\n                                var certs = CertPemManager.ParsePemChain(_node.Cert);\n                                if (certs.Count > 0)\n                                {\n                                    var cert = certs.First();\n                                    const string beginMarker = \"-----BEGIN CERTIFICATE-----\\n\";\n                                    const string endMarker = \"\\n-----END CERTIFICATE-----\";\n\n                                    var base64Content = cert.Replace(beginMarker, \"\").Replace(endMarker, \"\").Trim();\n\n                                    base64Content = base64Content.Replace(\"=\", \"\\\\=\");\n\n                                    pluginArgs += $\"certRaw={base64Content};\";\n                                }\n                            }\n                            if (pluginArgs.Length > 0)\n                            {\n                                outbound.plugin = \"v2ray-plugin\";\n                                pluginArgs += \"mux=0;\";\n                                // pluginStr remove last ';'\n                                pluginArgs = pluginArgs[..^1];\n                                outbound.plugin_opts = pluginArgs;\n                            }\n                        }\n\n                        FillOutboundMux(outbound);\n                        break;\n                    }\n                case EConfigType.SOCKS:\n                    {\n                        outbound.version = \"5\";\n                        if (_node.Username.IsNotEmpty()\n                            && _node.Password.IsNotEmpty())\n                        {\n                            outbound.username = _node.Username;\n                            outbound.password = _node.Password;\n                        }\n                        break;\n                    }\n                case EConfigType.HTTP:\n                    {\n                        if (_node.Username.IsNotEmpty()\n                            && _node.Password.IsNotEmpty())\n                        {\n                            outbound.username = _node.Username;\n                            outbound.password = _node.Password;\n                        }\n                        break;\n                    }\n                case EConfigType.VLESS:\n                    {\n                        outbound.uuid = _node.Password;\n\n                        outbound.packet_encoding = \"xudp\";\n\n                        if (!protocolExtra.Flow.IsNullOrEmpty())\n                        {\n                            outbound.flow = protocolExtra.Flow;\n                        }\n                        else\n                        {\n                            FillOutboundMux(outbound);\n                        }\n\n                        FillOutboundTransport(outbound);\n                        break;\n                    }\n                case EConfigType.Trojan:\n                    {\n                        outbound.password = _node.Password;\n\n                        FillOutboundMux(outbound);\n                        FillOutboundTransport(outbound);\n                        break;\n                    }\n                case EConfigType.Hysteria2:\n                    {\n                        outbound.password = _node.Password;\n\n                        if (!protocolExtra.SalamanderPass.IsNullOrEmpty())\n                        {\n                            outbound.obfs = new()\n                            {\n                                type = \"salamander\",\n                                password = protocolExtra.SalamanderPass.TrimEx(),\n                            };\n                        }\n\n                        outbound.up_mbps = protocolExtra?.UpMbps is { } su and >= 0\n                            ? su\n                            : _config.HysteriaItem.UpMbps;\n                        outbound.down_mbps = protocolExtra?.DownMbps is { } sd and >= 0\n                            ? sd\n                            : _config.HysteriaItem.DownMbps;\n                        var ports = protocolExtra?.Ports?.IsNullOrEmpty() == false ? protocolExtra.Ports : null;\n                        if ((!ports.IsNullOrEmpty()) && (ports.Contains(':') || ports.Contains('-') || ports.Contains(',')))\n                        {\n                            outbound.server_port = null;\n                            outbound.server_ports = ports.Split(',')\n                                .Select(p => p.Trim())\n                                .Where(p => p.IsNotEmpty())\n                                .Select(p =>\n                                {\n                                    var port = p.Replace('-', ':');\n                                    return port.Contains(':') ? port : $\"{port}:{port}\";\n                                })\n                                .ToList();\n                            outbound.hop_interval = _config.HysteriaItem.HopInterval >= 5\n                                ? $\"{_config.HysteriaItem.HopInterval}s\"\n                                : $\"{Global.Hysteria2DefaultHopInt}s\";\n                            if (int.TryParse(protocolExtra.HopInterval, out var hiResult))\n                            {\n                                outbound.hop_interval = hiResult >= 5 ? $\"{hiResult}s\" : outbound.hop_interval;\n                            }\n                            else if (protocolExtra.HopInterval?.Contains('-') ?? false)\n                            {\n                                // may be a range like 5-10\n                                var parts = protocolExtra.HopInterval.Split('-');\n                                if (parts.Length == 2 && int.TryParse(parts[0], out var hiL) &&\n                                    int.TryParse(parts[0], out var hiH))\n                                {\n                                    var hi = (hiL + hiH) / 2;\n                                    outbound.hop_interval = hi >= 5 ? $\"{hi}s\" : outbound.hop_interval;\n                                }\n                            }\n                        }\n\n                        break;\n                    }\n                case EConfigType.TUIC:\n                    {\n                        outbound.uuid = _node.Username;\n                        outbound.password = _node.Password;\n                        outbound.congestion_control = _node.HeaderType;\n                        break;\n                    }\n                case EConfigType.Anytls:\n                    {\n                        outbound.password = _node.Password;\n                        break;\n                    }\n            }\n\n            FillOutboundTls(outbound);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillEndpoint(Endpoints4Sbox endpoint)\n    {\n        try\n        {\n            var protocolExtra = _node.GetProtocolExtra();\n\n            endpoint.address = Utils.String2List(protocolExtra.WgInterfaceAddress);\n            endpoint.type = Global.ProtocolTypes[_node.ConfigType];\n\n            switch (_node.ConfigType)\n            {\n                case EConfigType.WireGuard:\n                    {\n                        var peer = new Peer4Sbox\n                        {\n                            public_key = protocolExtra.WgPublicKey,\n                            pre_shared_key = protocolExtra.WgPresharedKey,\n                            reserved = Utils.String2List(protocolExtra.WgReserved)?.Select(int.Parse).ToList(),\n                            address = _node.Address,\n                            port = _node.Port,\n                            // TODO default [\"0.0.0.0/0\", \"::/0\"]\n                            allowed_ips = new() { \"0.0.0.0/0\", \"::/0\" },\n                        };\n                        endpoint.private_key = _node.Password;\n                        endpoint.mtu = protocolExtra.WgMtu > 0 ? protocolExtra.WgMtu : Global.TunMtus.First();\n                        endpoint.peers = [peer];\n                        break;\n                    }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillOutboundMux(Outbound4Sbox outbound)\n    {\n        try\n        {\n            var muxEnabled = _node.MuxEnabled ?? _config.CoreBasicItem.MuxEnabled;\n            if (muxEnabled && _config.Mux4SboxItem.Protocol.IsNotEmpty())\n            {\n                var mux = new Multiplex4Sbox()\n                {\n                    enabled = true,\n                    protocol = _config.Mux4SboxItem.Protocol,\n                    max_connections = _config.Mux4SboxItem.MaxConnections,\n                    padding = _config.Mux4SboxItem.Padding,\n                };\n                outbound.multiplex = mux;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillOutboundTls(Outbound4Sbox outbound)\n    {\n        try\n        {\n            if (_node.StreamSecurity is not (Global.StreamSecurityReality or Global.StreamSecurity))\n            {\n                return;\n            }\n            if (_node.ConfigType is EConfigType.Shadowsocks or EConfigType.SOCKS or EConfigType.WireGuard)\n            {\n                return;\n            }\n            var serverName = string.Empty;\n            if (_node.Sni.IsNotEmpty())\n            {\n                serverName = _node.Sni;\n            }\n            else if (_node.RequestHost.IsNotEmpty())\n            {\n                serverName = Utils.String2List(_node.RequestHost)?.First();\n            }\n            var tls = new Tls4Sbox()\n            {\n                enabled = true,\n                record_fragment = _config.CoreBasicItem.EnableFragment ? true : null,\n                server_name = serverName,\n                insecure = Utils.ToBool(_node.AllowInsecure.IsNullOrEmpty() ? _config.CoreBasicItem.DefAllowInsecure.ToString().ToLower() : _node.AllowInsecure),\n                alpn = _node.GetAlpn(),\n            };\n            if (_node.Fingerprint.IsNotEmpty())\n            {\n                tls.utls = new Utls4Sbox()\n                {\n                    enabled = true,\n                    fingerprint = _node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : _node.Fingerprint\n                };\n            }\n            if (_node.StreamSecurity == Global.StreamSecurity)\n            {\n                var certs = CertPemManager.ParsePemChain(_node.Cert);\n                if (certs.Count > 0)\n                {\n                    tls.certificate = certs;\n                    tls.insecure = false;\n                }\n            }\n            else if (_node.StreamSecurity == Global.StreamSecurityReality)\n            {\n                tls.reality = new Reality4Sbox()\n                {\n                    enabled = true,\n                    public_key = _node.PublicKey,\n                    short_id = _node.ShortId\n                };\n                tls.insecure = false;\n            }\n            var (ech, _) = ParseEchParam(_node.EchConfigList);\n            if (ech is not null)\n            {\n                tls.ech = ech;\n            }\n            outbound.tls = tls;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillOutboundTransport(Outbound4Sbox outbound)\n    {\n        try\n        {\n            var transport = new Transport4Sbox();\n\n            switch (_node.GetNetwork())\n            {\n                case nameof(ETransport.h2):\n                    transport.type = nameof(ETransport.http);\n                    transport.host = _node.RequestHost.IsNullOrEmpty() ? null : Utils.String2List(_node.RequestHost);\n                    transport.path = _node.Path.NullIfEmpty();\n                    break;\n\n                case nameof(ETransport.tcp):   //http\n                    if (_node.HeaderType == Global.TcpHeaderHttp)\n                    {\n                        transport.type = nameof(ETransport.http);\n                        transport.host = _node.RequestHost.IsNullOrEmpty() ? null : Utils.String2List(_node.RequestHost);\n                        transport.path = _node.Path.NullIfEmpty();\n                    }\n                    break;\n\n                case nameof(ETransport.ws):\n                    transport.type = nameof(ETransport.ws);\n                    var wsPath = _node.Path;\n\n                    // Parse eh and ed parameters from path using regex\n                    if (!wsPath.IsNullOrEmpty())\n                    {\n                        var edRegex = new Regex(@\"[?&]ed=(\\d+)\");\n                        var edMatch = edRegex.Match(wsPath);\n                        if (edMatch.Success && int.TryParse(edMatch.Groups[1].Value, out var edValue))\n                        {\n                            transport.max_early_data = edValue;\n                            transport.early_data_header_name = \"Sec-WebSocket-Protocol\";\n\n                            wsPath = edRegex.Replace(wsPath, \"\");\n                            wsPath = wsPath.Replace(\"?&\", \"?\");\n                            if (wsPath.EndsWith('?'))\n                            {\n                                wsPath = wsPath.TrimEnd('?');\n                            }\n                        }\n\n                        var ehRegex = new Regex(@\"[?&]eh=([^&]+)\");\n                        var ehMatch = ehRegex.Match(wsPath);\n                        if (ehMatch.Success)\n                        {\n                            transport.early_data_header_name = Uri.UnescapeDataString(ehMatch.Groups[1].Value);\n                        }\n                    }\n\n                    transport.path = wsPath.NullIfEmpty();\n                    if (_node.RequestHost.IsNotEmpty())\n                    {\n                        transport.headers = new()\n                        {\n                            Host = _node.RequestHost\n                        };\n                    }\n                    break;\n\n                case nameof(ETransport.httpupgrade):\n                    transport.type = nameof(ETransport.httpupgrade);\n                    transport.path = _node.Path.NullIfEmpty();\n                    transport.host = _node.RequestHost.NullIfEmpty();\n\n                    break;\n\n                case nameof(ETransport.quic):\n                    transport.type = nameof(ETransport.quic);\n                    break;\n\n                case nameof(ETransport.grpc):\n                    transport.type = nameof(ETransport.grpc);\n                    transport.service_name = _node.Path;\n                    transport.idle_timeout = _config.GrpcItem.IdleTimeout?.ToString(\"##s\");\n                    transport.ping_timeout = _config.GrpcItem.HealthCheckTimeout?.ToString(\"##s\");\n                    transport.permit_without_stream = _config.GrpcItem.PermitWithoutStream;\n                    break;\n\n                default:\n                    break;\n            }\n            if (transport.type != null)\n            {\n                outbound.transport = transport;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private List<Outbound4Sbox> BuildSelectorOutbounds(List<string> proxyTags, string baseTagName = Global.ProxyTag)\n    {\n        var multipleLoad = _node.GetProtocolExtra().MultipleLoad ?? EMultipleLoad.LeastPing;\n        var outUrltest = new Outbound4Sbox\n        {\n            type = \"urltest\",\n            tag = $\"{baseTagName}-auto\",\n            outbounds = proxyTags,\n            interrupt_exist_connections = false,\n        };\n\n        if (multipleLoad == EMultipleLoad.Fallback)\n        {\n            outUrltest.tolerance = 5000;\n        }\n\n        // Add selector outbound (manual selection)\n        var outSelector = new Outbound4Sbox\n        {\n            type = \"selector\",\n            tag = baseTagName,\n            outbounds = JsonUtils.DeepCopy(proxyTags),\n            interrupt_exist_connections = false,\n        };\n        outSelector.outbounds.Insert(0, outUrltest.tag);\n\n        return [outSelector, outUrltest];\n    }\n\n    private List<BaseServer4Sbox> BuildOutboundsList(string baseTagName = Global.ProxyTag)\n    {\n        var nodes = new List<ProfileItem>();\n        foreach (var nodeId in Utils.String2List(_node.GetProtocolExtra().ChildItems) ?? [])\n        {\n            if (context.AllProxiesMap.TryGetValue(nodeId, out var node))\n            {\n                nodes.Add(node);\n            }\n        }\n        var resultOutbounds = new List<BaseServer4Sbox>();\n        for (var i = 0; i < nodes.Count; i++)\n        {\n            var node = nodes[i];\n            var currentTag = $\"{baseTagName}-{i + 1}\";\n\n            if (node.ConfigType.IsGroupType())\n            {\n                var childProfiles = new CoreConfigSingboxService(context with { Node = node, }).BuildGroupProxyOutbounds(currentTag);\n                resultOutbounds.AddRange(childProfiles);\n                continue;\n            }\n            var outbound = new CoreConfigSingboxService(context with { Node = node, }).BuildProxyOutbound();\n            outbound.tag = currentTag;\n            resultOutbounds.Add(outbound);\n        }\n        return resultOutbounds;\n    }\n\n    private List<BaseServer4Sbox> BuildChainOutboundsList(string baseTagName = Global.ProxyTag)\n    {\n        var nodes = new List<ProfileItem>();\n        foreach (var nodeId in Utils.String2List(_node.GetProtocolExtra().ChildItems) ?? [])\n        {\n            if (context.AllProxiesMap.TryGetValue(nodeId, out var node))\n            {\n                nodes.Add(node);\n            }\n        }\n        // Based on actual network flow instead of data packets\n        var nodesReverse = nodes.AsEnumerable().Reverse().ToList();\n        var resultOutbounds = new List<BaseServer4Sbox>();\n        for (var i = 0; i < nodesReverse.Count; i++)\n        {\n            var node = nodesReverse[i];\n            var currentTag = i == 0 ? baseTagName : $\"chain-{baseTagName}-{i}\";\n            var dialerProxyTag = i != nodesReverse.Count - 1 ? $\"chain-{baseTagName}-{i + 1}\" : null;\n            if (node.ConfigType.IsGroupType())\n            {\n                var childProfiles = new CoreConfigSingboxService(context with { Node = node, }).BuildGroupProxyOutbounds(currentTag);\n                if (!dialerProxyTag.IsNullOrEmpty())\n                {\n                    var chainEndNodes =\n                        childProfiles.Where(n => n?.detour.IsNullOrEmpty() ?? true);\n                    foreach (var chainEndNode in chainEndNodes)\n                    {\n                        chainEndNode.detour = dialerProxyTag;\n                    }\n                }\n                if (i != 0)\n                {\n                    var chainStartNodes = childProfiles.Where(n => n.tag.StartsWith(currentTag)).ToList();\n                    if (chainStartNodes.Count == 1)\n                    {\n                        foreach (var existedChainEndNode in resultOutbounds.Where(n => n.detour == currentTag))\n                        {\n                            existedChainEndNode.detour = chainStartNodes.First().tag;\n                        }\n                    }\n                    else if (chainStartNodes.Count > 1)\n                    {\n                        var existedChainNodes = CloneOutbounds(resultOutbounds);\n                        resultOutbounds.Clear();\n                        var j = 0;\n                        foreach (var chainStartNode in chainStartNodes)\n                        {\n                            var existedChainNodesClone = CloneOutbounds(existedChainNodes);\n                            foreach (var existedChainNode in existedChainNodesClone)\n                            {\n                                var cloneTag = $\"{existedChainNode.tag}-clone-{j + 1}\";\n                                existedChainNode.tag = cloneTag;\n                            }\n                            for (var k = 0; k < existedChainNodesClone.Count; k++)\n                            {\n                                var existedChainNode = existedChainNodesClone[k];\n                                var previousDialerProxyTag = existedChainNode.detour;\n                                var nextTag = k + 1 < existedChainNodesClone.Count\n                                    ? existedChainNodesClone[k + 1].tag\n                                    : chainStartNode.tag;\n                                existedChainNode.detour = (previousDialerProxyTag == currentTag)\n                                    ? chainStartNode.tag\n                                    : nextTag;\n                                resultOutbounds.Add(existedChainNode);\n                            }\n                            j++;\n                        }\n                    }\n                }\n                resultOutbounds.AddRange(childProfiles);\n                continue;\n            }\n            var outbound = new CoreConfigSingboxService(context with { Node = node, }).BuildProxyOutbound();\n\n            outbound.tag = currentTag;\n\n            if (!dialerProxyTag.IsNullOrEmpty())\n            {\n                outbound.detour = dialerProxyTag;\n            }\n\n            resultOutbounds.Add(outbound);\n        }\n        return resultOutbounds;\n    }\n\n    private static List<BaseServer4Sbox> CloneOutbounds(List<BaseServer4Sbox> source)\n    {\n        if (source is null || source.Count == 0)\n        {\n            return [];\n        }\n\n        var result = new List<BaseServer4Sbox>(source.Count);\n        foreach (var item in source)\n        {\n            BaseServer4Sbox? clone = null;\n            if (item is Outbound4Sbox outbound)\n            {\n                clone = JsonUtils.DeepCopy(outbound);\n            }\n            else if (item is Endpoints4Sbox endpoint)\n            {\n                clone = JsonUtils.DeepCopy(endpoint);\n            }\n            if (clone is not null)\n            {\n                result.Add(clone);\n            }\n        }\n        return result;\n    }\n\n    private static void FillRangeProxy(List<BaseServer4Sbox> servers, SingboxConfig singboxConfig, bool prepend = true)\n    {\n        try\n        {\n            if (servers is null || servers.Count <= 0)\n            {\n                return;\n            }\n            var outbounds = servers.Where(s => s is Outbound4Sbox).Cast<Outbound4Sbox>().ToList();\n            var endpoints = servers.Where(s => s is Endpoints4Sbox).Cast<Endpoints4Sbox>().ToList();\n            singboxConfig.endpoints ??= [];\n            if (prepend)\n            {\n                singboxConfig.outbounds.InsertRange(0, outbounds);\n                singboxConfig.endpoints.InsertRange(0, endpoints);\n            }\n            else\n            {\n                singboxConfig.outbounds.AddRange(outbounds);\n                singboxConfig.endpoints.AddRange(endpoints);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private static (Ech4Sbox? ech, Server4Sbox? dnsServer) ParseEchParam(string? echConfig)\n    {\n        if (echConfig.IsNullOrEmpty())\n        {\n            return (null, null);\n        }\n        if (!echConfig.Contains(\"://\"))\n        {\n            return (new Ech4Sbox()\n            {\n                enabled = true,\n                config = [$\"-----BEGIN ECH CONFIGS-----\\n\" +\n                          $\"{echConfig}\\n\" +\n                          $\"-----END ECH CONFIGS-----\"],\n            }, null);\n        }\n        var idx = echConfig.IndexOf('+');\n        // NOTE: query_server_name, since sing-box 1.13.0\n        //var queryServerName = idx > 0 ? echConfig[..idx] : null;\n        var echDnsServer = idx > 0 ? echConfig[(idx + 1)..] : echConfig;\n        return (new Ech4Sbox()\n        {\n            enabled = true,\n            query_server_name = null,\n        }, ParseDnsAddress(echDnsServer));\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRoutingService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private void GenRouting()\n    {\n        try\n        {\n            _coreConfig.route.final = Global.ProxyTag;\n            var simpleDnsItem = context.SimpleDnsItem;\n\n            var defaultDomainResolverTag = Global.SingboxDirectDNSTag;\n            var directDnsStrategy = Utils.DomainStrategy4Sbox(simpleDnsItem.Strategy4Freedom);\n\n            var rawDNSItem = context.RawDnsItem;\n            if (rawDNSItem is { Enabled: true })\n            {\n                defaultDomainResolverTag = Global.SingboxLocalDNSTag;\n                directDnsStrategy = rawDNSItem.DomainStrategy4Freedom.IsNullOrEmpty() ? null : rawDNSItem.DomainStrategy4Freedom;\n            }\n            _coreConfig.route.default_domain_resolver = new()\n            {\n                server = defaultDomainResolverTag,\n                strategy = directDnsStrategy\n            };\n\n            if (_config.TunModeItem.EnableTun)\n            {\n                _coreConfig.route.auto_detect_interface = true;\n\n                var tunRules = JsonUtils.Deserialize<List<Rule4Sbox>>(EmbedUtils.GetEmbedText(Global.TunSingboxRulesFileName));\n                if (tunRules != null)\n                {\n                    _coreConfig.route.rules.AddRange(tunRules);\n                }\n\n                var (lstDnsExe, lstDirectExe) = BuildRoutingDirectExe();\n                _coreConfig.route.rules.Add(new()\n                {\n                    port = [53],\n                    action = \"hijack-dns\",\n                    process_name = lstDnsExe\n                });\n\n                _coreConfig.route.rules.Add(new()\n                {\n                    outbound = Global.DirectTag,\n                    process_name = lstDirectExe\n                });\n            }\n\n            if (_config.Inbound.First().SniffingEnabled)\n            {\n                _coreConfig.route.rules.Add(new()\n                {\n                    action = \"sniff\"\n                });\n                _coreConfig.route.rules.Add(new()\n                {\n                    protocol = [\"dns\"],\n                    action = \"hijack-dns\"\n                });\n            }\n            else\n            {\n                _coreConfig.route.rules.Add(new()\n                {\n                    port = [53],\n                    network = [\"udp\"],\n                    action = \"hijack-dns\"\n                });\n            }\n\n            var hostsDomains = new List<string>();\n            if (rawDNSItem is not { Enabled: true })\n            {\n                var userHostsMap = Utils.ParseHostsToDictionary(simpleDnsItem.Hosts);\n                hostsDomains.AddRange(userHostsMap.Select(kvp => kvp.Key));\n                if (simpleDnsItem.UseSystemHosts == true)\n                {\n                    var systemHostsMap = Utils.GetSystemHosts();\n                    hostsDomains.AddRange(systemHostsMap.Select(kvp => kvp.Key));\n                }\n            }\n            if (hostsDomains.Count > 0)\n            {\n                var hostsResolveRule = new Rule4Sbox\n                {\n                    action = \"resolve\",\n                };\n                var hostsCounter = 0;\n                foreach (var host in hostsDomains)\n                {\n                    var domainRule = new Rule4Sbox();\n                    if (!ParseV2Domain(host, domainRule))\n                    {\n                        continue;\n                    }\n                    if (domainRule.domain_keyword?.Count > 0 && !host.Contains(':'))\n                    {\n                        domainRule.domain = domainRule.domain_keyword;\n                        domainRule.domain_keyword = null;\n                    }\n                    if (domainRule.domain?.Count > 0)\n                    {\n                        hostsResolveRule.domain ??= [];\n                        hostsResolveRule.domain.AddRange(domainRule.domain);\n                        hostsCounter++;\n                    }\n                    else if (domainRule.domain_keyword?.Count > 0)\n                    {\n                        hostsResolveRule.domain_keyword ??= [];\n                        hostsResolveRule.domain_keyword.AddRange(domainRule.domain_keyword);\n                        hostsCounter++;\n                    }\n                    else if (domainRule.domain_suffix?.Count > 0)\n                    {\n                        hostsResolveRule.domain_suffix ??= [];\n                        hostsResolveRule.domain_suffix.AddRange(domainRule.domain_suffix);\n                        hostsCounter++;\n                    }\n                    else if (domainRule.domain_regex?.Count > 0)\n                    {\n                        hostsResolveRule.domain_regex ??= [];\n                        hostsResolveRule.domain_regex.AddRange(domainRule.domain_regex);\n                        hostsCounter++;\n                    }\n                    else if (domainRule.geosite?.Count > 0)\n                    {\n                        hostsResolveRule.geosite ??= [];\n                        hostsResolveRule.geosite.AddRange(domainRule.geosite);\n                        hostsCounter++;\n                    }\n                }\n                if (hostsCounter > 0)\n                {\n                    _coreConfig.route.rules.Add(hostsResolveRule);\n                }\n            }\n\n            _coreConfig.route.rules.Add(new()\n            {\n                outbound = Global.DirectTag,\n                clash_mode = ERuleMode.Direct.ToString()\n            });\n            _coreConfig.route.rules.Add(new()\n            {\n                outbound = Global.ProxyTag,\n                clash_mode = ERuleMode.Global.ToString()\n            });\n\n            var domainStrategy = _config.RoutingBasicItem.DomainStrategy4Singbox.NullIfEmpty();\n            var routing = context.RoutingItem;\n            if (routing.DomainStrategy4Singbox.IsNotEmpty())\n            {\n                domainStrategy = routing.DomainStrategy4Singbox;\n            }\n            var resolveRule = new Rule4Sbox\n            {\n                action = \"resolve\",\n                strategy = domainStrategy\n            };\n            if (_config.RoutingBasicItem.DomainStrategy == Global.IPOnDemand)\n            {\n                _coreConfig.route.rules.Add(resolveRule);\n            }\n\n            var ipRules = new List<RulesItem>();\n            if (routing != null)\n            {\n                var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);\n                foreach (var item1 in rules ?? [])\n                {\n                    if (!item1.Enabled)\n                    {\n                        continue;\n                    }\n\n                    if (item1.RuleType == ERuleType.DNS)\n                    {\n                        continue;\n                    }\n\n                    GenRoutingUserRule(item1);\n\n                    if (item1.Ip?.Count > 0)\n                    {\n                        ipRules.Add(item1);\n                    }\n                }\n            }\n            if (_config.RoutingBasicItem.DomainStrategy == Global.IPIfNonMatch)\n            {\n                _coreConfig.route.rules.Add(resolveRule);\n                foreach (var item2 in ipRules)\n                {\n                    GenRoutingUserRule(item2);\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private static (List<string> lstDnsExe, List<string> lstDirectExe) BuildRoutingDirectExe()\n    {\n        var dnsExeSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n        var directExeSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);\n\n        var coreInfoResult = CoreInfoManager.Instance.GetCoreInfo();\n\n        foreach (var coreConfig in coreInfoResult)\n        {\n            if (coreConfig.CoreType == ECoreType.v2rayN)\n            {\n                continue;\n            }\n\n            foreach (var baseExeName in coreConfig.CoreExes)\n            {\n                if (coreConfig.CoreType != ECoreType.sing_box)\n                {\n                    dnsExeSet.Add(Utils.GetExeName(baseExeName));\n                }\n                directExeSet.Add(Utils.GetExeName(baseExeName));\n            }\n        }\n\n        var lstDnsExe = new List<string>(dnsExeSet);\n        var lstDirectExe = new List<string>(directExeSet);\n\n        return (lstDnsExe, lstDirectExe);\n    }\n\n    private void GenRoutingUserRule(RulesItem? item)\n    {\n        try\n        {\n            if (item == null)\n            {\n                return;\n            }\n            item.OutboundTag = GenRoutingUserRuleOutbound(item.OutboundTag ?? Global.ProxyTag);\n            var rules = _coreConfig.route.rules;\n\n            var rule = new Rule4Sbox();\n            if (item.OutboundTag == \"block\")\n            {\n                rule.action = \"reject\";\n            }\n            else\n            {\n                rule.outbound = item.OutboundTag;\n            }\n\n            if (item.Port.IsNotEmpty())\n            {\n                var portRanges = item.Port.Split(',').Where(it => it.Contains('-')).Select(it => it.Replace(\"-\", \":\")).ToList();\n                var ports = item.Port.Split(',').Where(it => !it.Contains('-')).Select(it => it.ToInt()).ToList();\n\n                rule.port_range = portRanges.Count > 0 ? portRanges : null;\n                rule.port = ports.Count > 0 ? ports : null;\n            }\n            if (item.Network.IsNotEmpty())\n            {\n                rule.network = Utils.String2List(item.Network);\n            }\n            if (item.Protocol?.Count > 0)\n            {\n                rule.protocol = item.Protocol;\n            }\n            if (item.InboundTag?.Count >= 0)\n            {\n                rule.inbound = item.InboundTag;\n            }\n            var rule1 = JsonUtils.DeepCopy(rule);\n            var rule2 = JsonUtils.DeepCopy(rule);\n            var rule3 = JsonUtils.DeepCopy(rule);\n\n            var hasDomainIp = false;\n            if (item.Domain?.Count > 0)\n            {\n                var countDomain = 0;\n                foreach (var it in item.Domain)\n                {\n                    if (ParseV2Domain(it, rule1))\n                    {\n                        countDomain++;\n                    }\n                }\n                if (countDomain > 0)\n                {\n                    rules.Add(rule1);\n                    hasDomainIp = true;\n                }\n            }\n\n            if (item.Ip?.Count > 0)\n            {\n                var countIp = 0;\n                foreach (var it in item.Ip)\n                {\n                    if (ParseV2Address(it, rule2))\n                    {\n                        countIp++;\n                    }\n                }\n                if (countIp > 0)\n                {\n                    rules.Add(rule2);\n                    hasDomainIp = true;\n                }\n            }\n\n            if (item.Process?.Count > 0)\n            {\n                var ruleProcName = JsonUtils.DeepCopy(rule3);\n                ruleProcName.process_name ??= [];\n                var ruleProcPath = JsonUtils.DeepCopy(rule3);\n                ruleProcPath.process_path ??= [];\n                foreach (var process in item.Process)\n                {\n                    // sing-box doesn't support this, fall back to process name match\n                    if (process is \"self/\" or \"xray/\")\n                    {\n                        ruleProcName.process_name.Add(Utils.GetExeName(\"sing-box\"));\n                        continue;\n                    }\n\n                    if (process.Contains('/') || process.Contains('\\\\'))\n                    {\n                        var procPath = process;\n                        if (Utils.IsWindows())\n                        {\n                            procPath = procPath.Replace('/', '\\\\');\n                        }\n                        ruleProcPath.process_path.Add(procPath);\n                        continue;\n                    }\n\n                    // sing-box strictly matches the exe suffix on Windows\n                    var procName = Utils.GetExeName(process);\n\n                    ruleProcName.process_name.Add(procName);\n                }\n\n                if (ruleProcName.process_name.Count > 0)\n                {\n                    rules.Add(ruleProcName);\n                    hasDomainIp = true;\n                }\n\n                if (ruleProcPath.process_path.Count > 0)\n                {\n                    rules.Add(ruleProcPath);\n                    hasDomainIp = true;\n                }\n            }\n\n            if (!hasDomainIp\n                && (rule.port != null || rule.port_range != null || rule.protocol != null || rule.inbound != null || rule.network != null))\n            {\n                rules.Add(rule);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private static bool ParseV2Domain(string domain, Rule4Sbox rule)\n    {\n        if (domain.StartsWith('#') || domain.StartsWith(\"ext:\") || domain.StartsWith(\"ext-domain:\"))\n        {\n            return false;\n        }\n        else if (domain.StartsWith(\"geosite:\"))\n        {\n            rule.geosite ??= [];\n            rule.geosite?.Add(domain.Substring(8));\n        }\n        else if (domain.StartsWith(\"regexp:\"))\n        {\n            rule.domain_regex ??= [];\n            rule.domain_regex?.Add(domain.Replace(Global.RoutingRuleComma, \",\").Substring(7));\n        }\n        else if (domain.StartsWith(\"domain:\"))\n        {\n            rule.domain_suffix ??= [];\n            rule.domain_suffix?.Add(domain.Substring(7));\n        }\n        else if (domain.StartsWith(\"full:\"))\n        {\n            rule.domain ??= [];\n            rule.domain?.Add(domain.Substring(5));\n        }\n        else if (domain.StartsWith(\"keyword:\"))\n        {\n            rule.domain_keyword ??= [];\n            rule.domain_keyword?.Add(domain.Substring(8));\n        }\n        else if (domain.StartsWith(\"dotless:\"))\n        {\n            rule.domain_keyword ??= [];\n            rule.domain_keyword?.Add(domain.Substring(8));\n        }\n        else\n        {\n            rule.domain_keyword ??= [];\n            rule.domain_keyword?.Add(domain);\n        }\n        return true;\n    }\n\n    private static bool ParseV2Address(string address, Rule4Sbox rule)\n    {\n        if (address.StartsWith(\"ext:\") || address.StartsWith(\"ext-ip:\"))\n        {\n            return false;\n        }\n        else if (address.Equals(\"geoip:private\"))\n        {\n            rule.ip_is_private = true;\n        }\n        else if (address.StartsWith(\"geoip:\"))\n        {\n            rule.geoip ??= new();\n            rule.geoip?.Add(address.Substring(6));\n        }\n        else if (address.Equals(\"geoip:!private\"))\n        {\n            rule.ip_is_private = false;\n        }\n        else if (address.StartsWith(\"geoip:!\"))\n        {\n            rule.geoip ??= new();\n            rule.geoip?.Add(address.Substring(6));\n            rule.invert = true;\n        }\n        else\n        {\n            rule.ip_cidr ??= new();\n            rule.ip_cidr?.Add(address);\n        }\n        return true;\n    }\n\n    private string GenRoutingUserRuleOutbound(string outboundTag)\n    {\n        if (Global.OutboundTags.Contains(outboundTag))\n        {\n            return outboundTag;\n        }\n\n        var node = context.AllProxiesMap.GetValueOrDefault($\"remark:{outboundTag}\");\n\n        if (node == null\n            || (!Global.SingboxSupportConfigType.Contains(node.ConfigType)\n            && !node.ConfigType.IsGroupType()))\n        {\n            return Global.ProxyTag;\n        }\n\n        var tag = $\"{node.IndexId}-{Global.ProxyTag}\";\n        if (_coreConfig.outbounds.Any(o => o.tag.StartsWith(tag))\n            || (_coreConfig.endpoints != null && _coreConfig.endpoints.Any(e => e.tag.StartsWith(tag))))\n        {\n            return tag;\n        }\n\n        var proxyOutbounds = new CoreConfigSingboxService(context with { Node = node, }).BuildAllProxyOutbounds(tag);\n        FillRangeProxy(proxyOutbounds, _coreConfig, false);\n\n        return tag;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxRulesetService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private void ConvertGeo2Ruleset()\n    {\n        static void AddRuleSets(List<string> ruleSets, List<string>? rule_set)\n        {\n            if (rule_set != null)\n            {\n                ruleSets.AddRange(rule_set);\n            }\n        }\n        var geosite = \"geosite\";\n        var geoip = \"geoip\";\n        var ruleSets = new List<string>();\n\n        //convert route geosite & geoip to ruleset\n        foreach (var rule in _coreConfig.route.rules.Where(t => t.geosite?.Count > 0).ToList() ?? [])\n        {\n            rule.rule_set ??= new List<string>();\n            rule.rule_set.AddRange(rule?.geosite?.Select(t => $\"{geosite}-{t}\").ToList());\n            rule.geosite = null;\n            AddRuleSets(ruleSets, rule.rule_set);\n        }\n        foreach (var rule in _coreConfig.route.rules.Where(t => t.geoip?.Count > 0).ToList() ?? [])\n        {\n            rule.rule_set ??= new List<string>();\n            rule.rule_set.AddRange(rule?.geoip?.Select(t => $\"{geoip}-{t}\").ToList());\n            rule.geoip = null;\n            AddRuleSets(ruleSets, rule.rule_set);\n        }\n\n        //convert dns geosite & geoip to ruleset\n        foreach (var rule in _coreConfig.dns?.rules.Where(t => t.geosite?.Count > 0).ToList() ?? [])\n        {\n            rule.rule_set ??= new List<string>();\n            rule.rule_set.AddRange(rule?.geosite?.Select(t => $\"{geosite}-{t}\").ToList());\n            rule.geosite = null;\n        }\n        foreach (var rule in _coreConfig.dns?.rules.Where(t => t.geoip?.Count > 0).ToList() ?? [])\n        {\n            rule.rule_set ??= new List<string>();\n            rule.rule_set.AddRange(rule?.geoip?.Select(t => $\"{geoip}-{t}\").ToList());\n            rule.geoip = null;\n        }\n        foreach (var dnsRule in _coreConfig.dns?.rules.Where(t => t.rule_set?.Count > 0).ToList() ?? [])\n        {\n            AddRuleSets(ruleSets, dnsRule.rule_set);\n        }\n        //rules in rules\n        foreach (var item in _coreConfig.dns?.rules.Where(t => t.rules?.Count > 0).Select(t => t.rules).ToList() ?? [])\n        {\n            foreach (var item2 in item ?? [])\n            {\n                AddRuleSets(ruleSets, item2.rule_set);\n            }\n        }\n\n        //load custom ruleset file\n        List<Ruleset4Sbox> customRulesets = [];\n\n        var routing = context.RoutingItem;\n        if (routing.CustomRulesetPath4Singbox.IsNotEmpty())\n        {\n            var result = EmbedUtils.LoadResource(routing.CustomRulesetPath4Singbox);\n            if (result.IsNotEmpty())\n            {\n                customRulesets = (JsonUtils.Deserialize<List<Ruleset4Sbox>>(result) ?? [])\n                    .Where(t => t.tag != null)\n                    .Where(t => t.type != null)\n                    .Where(t => t.format != null)\n                    .ToList();\n            }\n        }\n\n        //Local srs files address\n        var localSrss = Utils.GetBinPath(\"srss\");\n\n        //Add ruleset srs\n        _coreConfig.route.rule_set = [];\n        foreach (var item in new HashSet<string>(ruleSets))\n        {\n            if (item.IsNullOrEmpty())\n            { continue; }\n            var customRuleset = customRulesets.FirstOrDefault(t => t.tag != null && t.tag.Equals(item));\n            if (customRuleset is null)\n            {\n                var pathSrs = Path.Combine(localSrss, $\"{item}.srs\");\n                if (File.Exists(pathSrs))\n                {\n                    customRuleset = new()\n                    {\n                        type = \"local\",\n                        format = \"binary\",\n                        tag = item,\n                        path = pathSrs\n                    };\n                }\n                else\n                {\n                    var srsUrl = string.IsNullOrEmpty(_config.ConstItem.SrsSourceUrl)\n                        ? Global.SingboxRulesetUrl\n                        : _config.ConstItem.SrsSourceUrl;\n\n                    customRuleset = new()\n                    {\n                        type = \"remote\",\n                        format = \"binary\",\n                        tag = item,\n                        url = string.Format(srsUrl, item.StartsWith(geosite) ? geosite : geoip, item),\n                        download_detour = Global.ProxyTag\n                    };\n                }\n            }\n            _coreConfig.route.rule_set.Add(customRuleset);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/Singbox/SingboxStatisticService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigSingboxService\n{\n    private void GenExperimental()\n    {\n        //if (_config.guiItem.enableStatistics)\n        {\n            _coreConfig.experimental ??= new Experimental4Sbox();\n            _coreConfig.experimental.clash_api = new Clash_Api4Sbox()\n            {\n                external_controller = $\"{Global.Loopback}:{AppManager.Instance.StatePort2}\",\n            };\n        }\n\n        if (_config.CoreBasicItem.EnableCacheFile4Sbox)\n        {\n            _coreConfig.experimental ??= new Experimental4Sbox();\n            _coreConfig.experimental.cache_file = new CacheFile4Sbox()\n            {\n                enabled = true,\n                path = Utils.GetBinPath(\"cache.db\"),\n                store_fakeip = context.SimpleDnsItem.FakeIP == true\n            };\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/CoreConfigV2rayService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService(CoreConfigContext context)\n{\n    private static readonly string _tag = \"CoreConfigV2rayService\";\n    private readonly Config _config = context.AppConfig;\n    private readonly ProfileItem _node = context.Node;\n\n    private V2rayConfig _coreConfig = new();\n\n    #region public gen function\n\n    public RetResult GenerateClientConfigContent()\n    {\n        var ret = new RetResult();\n        try\n        {\n            if (context.IsTunEnabled && context.TunProtectSsPort > 0 && context.ProxyRelaySsPort > 0)\n            {\n                return GenerateClientProxyRelayConfig();\n            }\n            if (_node == null\n                || !_node.IsValid())\n            {\n                ret.Msg = ResUI.CheckServerSettings;\n                return ret;\n            }\n\n            if (_node.GetNetwork() is nameof(ETransport.quic))\n            {\n                ret.Msg = ResUI.Incorrectconfiguration + $\" - {_node.GetNetwork()}\";\n                return ret;\n            }\n\n            ret.Msg = ResUI.InitialConfiguration;\n\n            var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);\n            if (result.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n\n            _coreConfig = JsonUtils.Deserialize<V2rayConfig>(result);\n            if (_coreConfig == null)\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            GenLog();\n\n            GenInbounds();\n\n            GenOutbounds();\n\n            GenRouting();\n\n            GenDns();\n\n            GenStatistic();\n\n            var finalRule = BuildFinalRule();\n            if (!string.IsNullOrEmpty(finalRule?.balancerTag))\n            {\n                _coreConfig.routing.rules.Add(finalRule);\n            }\n\n            ret.Msg = string.Format(ResUI.SuccessfulConfiguration, \"\");\n            ret.Success = true;\n            ret.Data = ApplyFullConfigTemplate();\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    public RetResult GenerateClientSpeedtestConfig(List<ServerTestItem> selecteds)\n    {\n        var ret = new RetResult();\n        try\n        {\n            ret.Msg = ResUI.InitialConfiguration;\n\n            var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);\n            var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);\n            if (result.IsNullOrEmpty() || txtOutbound.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n\n            _coreConfig = JsonUtils.Deserialize<V2rayConfig>(result);\n            if (_coreConfig == null)\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            var (lstIpEndPoints, lstTcpConns) = Utils.GetActiveNetworkInfo();\n\n            GenLog();\n            _coreConfig.inbounds.Clear();\n            _coreConfig.outbounds.Clear();\n            _coreConfig.routing.rules.Clear();\n\n            var initPort = AppManager.Instance.GetLocalPort(EInboundProtocol.speedtest);\n\n            foreach (var it in selecteds)\n            {\n                if (!(Global.XraySupportConfigType.Contains(it.ConfigType) || it.ConfigType.IsGroupType()))\n                {\n                    continue;\n                }\n                if (!it.ConfigType.IsComplexType() && it.Port <= 0)\n                {\n                    continue;\n                }\n                var actIndexId = context.ServerTestItemMap.GetValueOrDefault(it.IndexId, it.IndexId);\n                var item = context.AllProxiesMap.GetValueOrDefault(actIndexId);\n                if (item is null || item.ConfigType is EConfigType.Custom || !item.IsValid())\n                {\n                    continue;\n                }\n\n                //find unused port\n                var port = initPort;\n                for (var k = initPort; k < Global.MaxPort; k++)\n                {\n                    if (lstIpEndPoints?.FindIndex(_it => _it.Port == k) >= 0)\n                    {\n                        continue;\n                    }\n                    if (lstTcpConns?.FindIndex(_it => _it.LocalEndPoint.Port == k) >= 0)\n                    {\n                        continue;\n                    }\n                    //found\n                    port = k;\n                    initPort = port + 1;\n                    break;\n                }\n\n                //Port In Used\n                if (lstIpEndPoints?.FindIndex(_it => _it.Port == port) >= 0)\n                {\n                    continue;\n                }\n                it.Port = port;\n                it.AllowTest = true;\n\n                //inbound\n                Inbounds4Ray inbound = new()\n                {\n                    listen = Global.Loopback,\n                    port = port,\n                    protocol = EInboundProtocol.mixed.ToString(),\n                };\n                inbound.tag = inbound.protocol + inbound.port.ToString();\n                _coreConfig.inbounds.Add(inbound);\n\n                var tag = Global.ProxyTag + inbound.port.ToString();\n                var isBalancer = false;\n                //outbound\n                var proxyOutbounds =\n                    new CoreConfigV2rayService(context with { Node = item }).BuildAllProxyOutbounds(tag);\n                _coreConfig.outbounds.AddRange(proxyOutbounds);\n                if (proxyOutbounds.Count(n => n.tag.StartsWith(tag)) > 1)\n                {\n                    isBalancer = true;\n                    var multipleLoad = _node.GetProtocolExtra().MultipleLoad ?? EMultipleLoad.LeastPing;\n                    GenObservatory(multipleLoad, tag);\n                    GenBalancer(multipleLoad, tag);\n                }\n\n                //rule\n                RulesItem4Ray rule = new()\n                {\n                    inboundTag = [inbound.tag],\n                    outboundTag = tag,\n                    type = \"field\"\n                };\n                if (isBalancer)\n                {\n                    rule.balancerTag = tag + Global.BalancerTagSuffix;\n                    rule.outboundTag = null;\n                }\n                _coreConfig.routing.rules.Add(rule);\n            }\n\n            //ret.Msg =string.Format(ResUI.SuccessfulConfiguration\"), node.getSummary());\n            ret.Success = true;\n            ret.Data = JsonUtils.Serialize(_coreConfig);\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    public RetResult GenerateClientSpeedtestConfig(int port)\n    {\n        var ret = new RetResult();\n        try\n        {\n            if (_node == null\n                || !_node.IsValid())\n            {\n                ret.Msg = ResUI.CheckServerSettings;\n                return ret;\n            }\n\n            if (_node.GetNetwork() is nameof(ETransport.quic))\n            {\n                ret.Msg = ResUI.Incorrectconfiguration + $\" - {_node.GetNetwork()}\";\n                return ret;\n            }\n\n            var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);\n            if (result.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n\n            _coreConfig = JsonUtils.Deserialize<V2rayConfig>(result);\n            if (_coreConfig == null)\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            GenLog();\n            GenOutbounds();\n\n            _coreConfig.routing.domainStrategy = Global.AsIs;\n            _coreConfig.routing.rules.Clear();\n            _coreConfig.inbounds.Clear();\n            _coreConfig.inbounds.Add(new()\n            {\n                tag = $\"{EInboundProtocol.socks}{port}\",\n                listen = Global.Loopback,\n                port = port,\n                protocol = EInboundProtocol.mixed.ToString(),\n            });\n\n            _coreConfig.routing.rules.Add(BuildFinalRule());\n\n            ret.Msg = string.Format(ResUI.SuccessfulConfiguration, \"\");\n            ret.Success = true;\n            ret.Data = JsonUtils.Serialize(_coreConfig);\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    public RetResult GenerateClientProxyRelayConfig()\n    {\n        var ret = new RetResult();\n        try\n        {\n            if (_node == null\n                || !_node.IsValid())\n            {\n                ret.Msg = ResUI.CheckServerSettings;\n                return ret;\n            }\n\n            if (_node.GetNetwork() is nameof(ETransport.quic))\n            {\n                ret.Msg = ResUI.Incorrectconfiguration + $\" - {_node.GetNetwork()}\";\n                return ret;\n            }\n\n            var result = EmbedUtils.GetEmbedText(Global.V2raySampleClient);\n            if (result.IsNullOrEmpty())\n            {\n                ret.Msg = ResUI.FailedGetDefaultConfiguration;\n                return ret;\n            }\n\n            _coreConfig = JsonUtils.Deserialize<V2rayConfig>(result);\n            if (_coreConfig == null)\n            {\n                ret.Msg = ResUI.FailedGenDefaultConfiguration;\n                return ret;\n            }\n\n            GenLog();\n            _coreConfig.outbounds.Clear();\n            GenOutbounds();\n            GenStatistic();\n\n            var protectNode = new ProfileItem()\n            {\n                CoreType = ECoreType.Xray,\n                ConfigType = EConfigType.Shadowsocks,\n                Address = Global.Loopback,\n                Port = context.TunProtectSsPort,\n                Password = Global.None,\n            };\n            protectNode.SetProtocolExtra(protectNode.GetProtocolExtra() with\n            {\n                SsMethod = Global.None,\n            });\n\n            foreach (var outbound in _coreConfig.outbounds\n                .Where(o => o.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true))\n            {\n                outbound.streamSettings ??= new();\n                outbound.streamSettings.sockopt ??= new();\n                outbound.streamSettings.sockopt.dialerProxy = \"tun-protect-ss\";\n            }\n            // ech protected\n            foreach (var outbound in _coreConfig.outbounds\n                .Where(outbound => outbound.streamSettings?.tlsSettings?.echConfigList?.IsNullOrEmpty() == false))\n            {\n                outbound.streamSettings!.tlsSettings!.echSockopt ??= new();\n                outbound.streamSettings.tlsSettings.echSockopt.dialerProxy = \"tun-protect-ss\";\n            }\n            _coreConfig.outbounds.Add(new CoreConfigV2rayService(context with\n            {\n                Node = protectNode,\n            }).BuildProxyOutbound(\"tun-protect-ss\"));\n\n            _coreConfig.routing.rules ??= [];\n            var hasBalancer = _coreConfig.routing.balancers is { Count: > 0 };\n            _coreConfig.routing.rules.Add(new()\n            {\n                inboundTag = [\"proxy-relay-ss\"],\n                outboundTag = hasBalancer ? null : Global.ProxyTag,\n                balancerTag = hasBalancer ? Global.ProxyTag + Global.BalancerTagSuffix : null,\n                type = \"field\"\n            });\n\n            //_coreConfig.inbounds.Clear();\n\n            var configNode = JsonUtils.ParseJson(JsonUtils.Serialize(_coreConfig))!;\n            configNode[\"inbounds\"]!.AsArray().Add(new\n            {\n                listen = Global.Loopback,\n                port = context.ProxyRelaySsPort,\n                protocol = \"shadowsocks\",\n                settings = new\n                {\n                    network = \"tcp,udp\",\n                    method = Global.None,\n                    password = Global.None,\n                },\n                tag = \"proxy-relay-ss\",\n            });\n\n            ret.Msg = string.Format(ResUI.SuccessfulConfiguration, \"\");\n            ret.Success = true;\n            ret.Data = JsonUtils.Serialize(configNode);\n            return ret;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            ret.Msg = ResUI.FailedGenDefaultConfiguration;\n            return ret;\n        }\n    }\n\n    #endregion public gen function\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayBalancerService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private void GenObservatory(EMultipleLoad multipleLoad, string baseTagName = Global.ProxyTag)\n    {\n        // Collect all existing subject selectors from both observatories\n        var subjectSelectors = new List<string>();\n        subjectSelectors.AddRange(_coreConfig.burstObservatory?.subjectSelector ?? []);\n        subjectSelectors.AddRange(_coreConfig.observatory?.subjectSelector ?? []);\n\n        // Case 1: exact match already exists -> nothing to do\n        if (subjectSelectors.Any(baseTagName.StartsWith))\n        {\n            return;\n        }\n\n        // Case 2: prefix match exists -> reuse it and move to the first position\n        var matched = subjectSelectors.FirstOrDefault(s => s.StartsWith(baseTagName));\n        if (matched is not null)\n        {\n            baseTagName = matched;\n\n            if (_coreConfig.burstObservatory?.subjectSelector?.Contains(baseTagName) == true)\n            {\n                _coreConfig.burstObservatory.subjectSelector.Remove(baseTagName);\n                _coreConfig.burstObservatory.subjectSelector.Insert(0, baseTagName);\n            }\n\n            if (_coreConfig.observatory?.subjectSelector?.Contains(baseTagName) == true)\n            {\n                _coreConfig.observatory.subjectSelector.Remove(baseTagName);\n                _coreConfig.observatory.subjectSelector.Insert(0, baseTagName);\n            }\n\n            return;\n        }\n\n        // Case 3: need to create or insert based on multipleLoad type\n        if (multipleLoad is EMultipleLoad.LeastLoad or EMultipleLoad.Fallback)\n        {\n            if (_coreConfig.burstObservatory is null)\n            {\n                // Create new burst observatory with default ping config\n                _coreConfig.burstObservatory = new BurstObservatory4Ray\n                {\n                    subjectSelector = [baseTagName],\n                    pingConfig = new()\n                    {\n                        destination = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl,\n                        interval = \"5m\",\n                        timeout = \"30s\",\n                        sampling = 2,\n                    }\n                };\n            }\n            else\n            {\n                _coreConfig.burstObservatory.subjectSelector ??= new();\n                _coreConfig.burstObservatory.subjectSelector.Add(baseTagName);\n            }\n        }\n        else if (multipleLoad is EMultipleLoad.LeastPing)\n        {\n            if (_coreConfig.observatory is null)\n            {\n                // Create new observatory with default probe config\n                _coreConfig.observatory = new Observatory4Ray\n                {\n                    subjectSelector = [baseTagName],\n                    probeUrl = AppManager.Instance.Config.SpeedTestItem.SpeedPingTestUrl,\n                    probeInterval = \"3m\",\n                    enableConcurrency = true,\n                };\n            }\n            else\n            {\n                _coreConfig.observatory.subjectSelector ??= new();\n                _coreConfig.observatory.subjectSelector.Add(baseTagName);\n            }\n        }\n    }\n\n    private void GenBalancer(EMultipleLoad multipleLoad, string selector = Global.ProxyTag)\n    {\n        var strategyType = multipleLoad switch\n        {\n            EMultipleLoad.Random => \"random\",\n            EMultipleLoad.RoundRobin => \"roundRobin\",\n            EMultipleLoad.LeastPing => \"leastPing\",\n            EMultipleLoad.LeastLoad => \"leastLoad\",\n            _ => \"roundRobin\",\n        };\n        var balancerTag = $\"{selector}{Global.BalancerTagSuffix}\";\n        var balancer = new BalancersItem4Ray\n        {\n            selector = [selector],\n            strategy = new()\n            {\n                type = strategyType,\n                settings = new()\n                {\n                    expected = 1,\n                },\n            },\n            tag = balancerTag,\n        };\n        _coreConfig.routing.balancers ??= new();\n        _coreConfig.routing.balancers.Add(balancer);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayConfigTemplateService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private string ApplyFullConfigTemplate()\n    {\n        var fullConfigTemplate = context.FullConfigTemplate;\n        if (fullConfigTemplate == null || !fullConfigTemplate.Enabled || fullConfigTemplate.Config.IsNullOrEmpty())\n        {\n            return JsonUtils.Serialize(_coreConfig);\n        }\n\n        var fullConfigTemplateNode = JsonNode.Parse(fullConfigTemplate.Config);\n        if (fullConfigTemplateNode == null)\n        {\n            return JsonUtils.Serialize(_coreConfig);\n        }\n\n        // Handle balancer and rules modifications (for multiple load scenarios)\n        if (_coreConfig.routing?.balancers?.Count > 0)\n        {\n            var balancer =\n                _coreConfig.routing.balancers.FirstOrDefault(b => b.tag == Global.ProxyTag + Global.BalancerTagSuffix, null);\n\n            // Modify existing rules in custom config\n            if (balancer != null)\n            {\n                var rulesNode = fullConfigTemplateNode[\"routing\"]?[\"rules\"];\n                if (rulesNode != null)\n                {\n                    foreach (var rule in rulesNode.AsArray())\n                    {\n                        if (rule[\"outboundTag\"]?.GetValue<string>() == Global.ProxyTag)\n                        {\n                            rule.AsObject().Remove(\"outboundTag\");\n                            rule[\"balancerTag\"] = balancer.tag;\n                        }\n                    }\n                }\n            }\n\n            // Ensure routing node exists\n            if (fullConfigTemplateNode[\"routing\"] == null)\n            {\n                fullConfigTemplateNode[\"routing\"] = new JsonObject();\n            }\n\n            // Handle balancers - append instead of override\n            if (fullConfigTemplateNode[\"routing\"][\"balancers\"] is JsonArray customBalancersNode)\n            {\n                if (JsonNode.Parse(JsonUtils.Serialize(_coreConfig.routing.balancers)) is JsonArray newBalancers)\n                {\n                    foreach (var balancerNode in newBalancers)\n                    {\n                        customBalancersNode.Add(balancerNode?.DeepClone());\n                    }\n                }\n            }\n            else\n            {\n                fullConfigTemplateNode[\"routing\"][\"balancers\"] = JsonNode.Parse(JsonUtils.Serialize(_coreConfig.routing.balancers));\n            }\n        }\n\n        if (_coreConfig.observatory != null)\n        {\n            if (fullConfigTemplateNode[\"observatory\"] == null)\n            {\n                fullConfigTemplateNode[\"observatory\"] = JsonNode.Parse(JsonUtils.Serialize(_coreConfig.observatory));\n            }\n            else\n            {\n                var subjectSelector = _coreConfig.observatory.subjectSelector;\n                subjectSelector.AddRange(fullConfigTemplateNode[\"observatory\"]?[\"subjectSelector\"]?.AsArray()?.Select(x => x?.GetValue<string>()) ?? []);\n                fullConfigTemplateNode[\"observatory\"][\"subjectSelector\"] = JsonNode.Parse(JsonUtils.Serialize(subjectSelector.Distinct().ToList()));\n            }\n        }\n\n        if (_coreConfig.burstObservatory != null)\n        {\n            if (fullConfigTemplateNode[\"burstObservatory\"] == null)\n            {\n                fullConfigTemplateNode[\"burstObservatory\"] = JsonNode.Parse(JsonUtils.Serialize(_coreConfig.burstObservatory));\n            }\n            else\n            {\n                var subjectSelector = _coreConfig.burstObservatory.subjectSelector;\n                subjectSelector.AddRange(fullConfigTemplateNode[\"burstObservatory\"]?[\"subjectSelector\"]?.AsArray()?.Select(x => x?.GetValue<string>()) ?? []);\n                fullConfigTemplateNode[\"burstObservatory\"][\"subjectSelector\"] = JsonNode.Parse(JsonUtils.Serialize(subjectSelector.Distinct().ToList()));\n            }\n        }\n\n        var customOutboundsNode = new JsonArray();\n\n        foreach (var outbound in _coreConfig.outbounds)\n        {\n            if (outbound.protocol.ToLower() is \"blackhole\" or \"dns\" or \"freedom\")\n            {\n                if (fullConfigTemplate.AddProxyOnly == true)\n                {\n                    continue;\n                }\n            }\n            else if (!fullConfigTemplate.ProxyDetour.IsNullOrEmpty()\n                && (outbound.streamSettings?.sockopt?.dialerProxy.IsNullOrEmpty() ?? true))\n            {\n                var outboundAddress = outbound.settings?.servers?.FirstOrDefault()?.address\n                    ?? outbound.settings?.vnext?.FirstOrDefault()?.address\n                    ?? string.Empty;\n                if (!Utils.IsPrivateNetwork(outboundAddress))\n                {\n                    outbound.streamSettings ??= new StreamSettings4Ray();\n                    outbound.streamSettings.sockopt ??= new Sockopt4Ray();\n                    outbound.streamSettings.sockopt.dialerProxy = fullConfigTemplate.ProxyDetour;\n                }\n            }\n            customOutboundsNode.Add(JsonUtils.DeepCopy(outbound));\n        }\n\n        if (fullConfigTemplateNode[\"outbounds\"] is JsonArray templateOutbounds)\n        {\n            foreach (var outbound in templateOutbounds)\n            {\n                customOutboundsNode.Add(outbound?.DeepClone());\n            }\n        }\n\n        fullConfigTemplateNode[\"outbounds\"] = customOutboundsNode;\n\n        return JsonUtils.Serialize(fullConfigTemplateNode);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayDnsService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private void GenDns()\n    {\n        try\n        {\n            var item = context.RawDnsItem;\n            if (item is { Enabled: true })\n            {\n                GenDnsCustom();\n\n                if (_coreConfig.routing.domainStrategy != Global.IPIfNonMatch)\n                {\n                    return;\n                }\n\n                // DNS routing\n                var dnsObj = JsonUtils.SerializeToNode(_coreConfig.dns);\n                if (dnsObj == null)\n                {\n                    return;\n                }\n\n                dnsObj[\"tag\"] = Global.DnsTag;\n                _coreConfig.dns = JsonUtils.Deserialize<Dns4Ray>(JsonUtils.Serialize(dnsObj));\n                _coreConfig.routing.rules.Add(new RulesItem4Ray\n                {\n                    type = \"field\",\n                    inboundTag = new List<string> { Global.DnsTag },\n                    outboundTag = Global.ProxyTag,\n                });\n                return;\n            }\n            var simpleDnsItem = context.SimpleDnsItem;\n            var dnsItem = _coreConfig.dns is Dns4Ray dns4Ray ? dns4Ray : new Dns4Ray();\n\n            var strategy4Freedom = simpleDnsItem?.Strategy4Freedom ?? Global.AsIs;\n            //Outbound Freedom domainStrategy\n            if (strategy4Freedom.IsNotEmpty() && strategy4Freedom != Global.AsIs)\n            {\n                var outbound = _coreConfig.outbounds.FirstOrDefault(t => t is { protocol: \"freedom\", tag: Global.DirectTag });\n                if (outbound != null)\n                {\n                    outbound.settings = new()\n                    {\n                        domainStrategy = strategy4Freedom,\n                        userLevel = 0\n                    };\n                }\n            }\n\n            var strategy4Proxy = simpleDnsItem?.Strategy4Proxy ?? Global.AsIs;\n            //Outbound Proxy domainStrategy\n            if (strategy4Proxy.IsNotEmpty() && strategy4Proxy != Global.AsIs)\n            {\n                var xraySupportConfigTypeNames = Global.XraySupportConfigType\n                        .Select(x => x == EConfigType.Hysteria2 ? \"hysteria\" : Global.ProtocolTypes[x])\n                        .ToHashSet();\n                _coreConfig.outbounds\n                    .Where(t => xraySupportConfigTypeNames.Contains(t.protocol))\n                    .ToList()\n                    .ForEach(outbound => outbound.targetStrategy = strategy4Proxy);\n            }\n\n            FillDnsServers(dnsItem);\n            FillDnsHosts(dnsItem);\n\n            dnsItem.serveStale = simpleDnsItem?.ServeStale is true ? true : null;\n            dnsItem.enableParallelQuery = simpleDnsItem?.ParallelQuery is true ? true : null;\n\n            // DNS routing\n            var directDnsTags = dnsItem.servers\n                .Select(server =>\n                {\n                    var tagNode = (server as JsonObject)?[\"tag\"];\n                    return tagNode is JsonValue value && value.TryGetValue<string>(out var tag) ? tag : null;\n                })\n                .Where(tag => tag is not null && tag.StartsWith(Global.DirectDnsTag, StringComparison.Ordinal))\n                .Select(tag => tag!)\n                .ToList();\n            if (directDnsTags.Count > 0)\n            {\n                _coreConfig.routing.rules.Add(new()\n                {\n                    type = \"field\",\n                    inboundTag = directDnsTags,\n                    outboundTag = Global.DirectTag,\n                });\n            }\n\n            var finalRule = BuildFinalRule();\n            dnsItem.tag = Global.DnsTag;\n            _coreConfig.routing.rules.Add(new()\n            {\n                type = \"field\",\n                inboundTag = [Global.DnsTag],\n                outboundTag = finalRule.outboundTag,\n                balancerTag = finalRule.balancerTag,\n            });\n\n            _coreConfig.dns = dnsItem;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillDnsServers(Dns4Ray dnsItem)\n    {\n        var simpleDNSItem = context.SimpleDnsItem;\n\n        var directDNSAddress = ParseDnsAddresses(simpleDNSItem?.DirectDNS, Global.DomainDirectDNSAddress.First());\n        var remoteDNSAddress = ParseDnsAddresses(simpleDNSItem?.RemoteDNS, Global.DomainRemoteDNSAddress.First());\n\n        var directDomainList = new List<string>();\n        var directGeositeList = new List<string>();\n        var proxyDomainList = new List<string>();\n        var proxyGeositeList = new List<string>();\n        var expectedDomainList = new List<string>();\n        var expectedIPs = new List<string>();\n        var regionNames = new HashSet<string>();\n\n        var bootstrapDNSAddress = ParseDnsAddresses(simpleDNSItem?.BootstrapDNS, Global.DomainPureIPDNSAddress.First());\n        var dnsServerDomains = new List<string>();\n\n        foreach (var dns in directDNSAddress)\n        {\n            var (domain, _, _, _) = Utils.ParseUrl(dns);\n            if (domain == \"localhost\")\n            {\n                continue;\n            }\n            if (Utils.IsDomain(domain))\n            {\n                dnsServerDomains.Add($\"full:{domain}\");\n            }\n        }\n        foreach (var dns in remoteDNSAddress)\n        {\n            var (domain, _, _, _) = Utils.ParseUrl(dns);\n            if (domain == \"localhost\")\n            {\n                continue;\n            }\n            if (Utils.IsDomain(domain))\n            {\n                dnsServerDomains.Add($\"full:{domain}\");\n            }\n        }\n        dnsServerDomains = dnsServerDomains.Distinct().ToList();\n\n        if (!string.IsNullOrEmpty(simpleDNSItem?.DirectExpectedIPs))\n        {\n            expectedIPs = simpleDNSItem.DirectExpectedIPs\n                .Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries)\n                .Select(s => s.Trim())\n                .Where(s => !string.IsNullOrEmpty(s))\n                .ToList();\n\n            foreach (var ip in expectedIPs)\n            {\n                if (ip.StartsWith(\"geoip:\", StringComparison.OrdinalIgnoreCase))\n                {\n                    var region = ip[\"geoip:\".Length..];\n                    if (!string.IsNullOrEmpty(region))\n                    {\n                        regionNames.Add($\"geosite:{region}\");\n                        regionNames.Add($\"geosite:geolocation-{region}\");\n                        regionNames.Add($\"geosite:tld-{region}\");\n                    }\n                }\n            }\n        }\n\n        var routing = context.RoutingItem;\n        List<RulesItem>? rules = null;\n        rules = JsonUtils.Deserialize<List<RulesItem>>(routing?.RuleSet) ?? [];\n        foreach (var item in rules)\n        {\n            if (!item.Enabled || item.Domain is null || item.Domain.Count == 0)\n            {\n                continue;\n            }\n\n            if (item.RuleType == ERuleType.Routing)\n            {\n                continue;\n            }\n\n            foreach (var domain in item.Domain)\n            {\n                if (domain.StartsWith('#'))\n                {\n                    continue;\n                }\n\n                var normalizedDomain = domain.Replace(Global.RoutingRuleComma, \",\");\n\n                if (item.OutboundTag == Global.DirectTag)\n                {\n                    if (normalizedDomain.StartsWith(\"geosite:\") || normalizedDomain.StartsWith(\"ext:\"))\n                    {\n                        (regionNames.Contains(normalizedDomain) ? expectedDomainList : directGeositeList).Add(normalizedDomain);\n                    }\n                    else\n                    {\n                        directDomainList.Add(normalizedDomain);\n                    }\n                }\n                else if (item.OutboundTag != Global.BlockTag)\n                {\n                    if (normalizedDomain.StartsWith(\"geosite:\") || normalizedDomain.StartsWith(\"ext:\"))\n                    {\n                        proxyGeositeList.Add(normalizedDomain);\n                    }\n                    else\n                    {\n                        proxyDomainList.Add(normalizedDomain);\n                    }\n                }\n            }\n        }\n\n        if (context.ProtectDomainList.Count > 0)\n        {\n            directDomainList.AddRange(context.ProtectDomainList);\n        }\n\n        dnsItem.servers ??= [];\n\n        var directDnsTagIndex = 1;\n\n        AddDnsServers(remoteDNSAddress, proxyDomainList);\n        AddDnsServers(directDNSAddress, directDomainList, true);\n        AddDnsServers(remoteDNSAddress, proxyGeositeList);\n        AddDnsServers(directDNSAddress, directGeositeList, true);\n        AddDnsServers(directDNSAddress, expectedDomainList, true, expectedIPs);\n        if (dnsServerDomains.Count > 0)\n        {\n            AddDnsServers(bootstrapDNSAddress, dnsServerDomains);\n        }\n\n        var useDirectDns = false;\n\n        if (rules?.LastOrDefault() is { } lastRule && lastRule.OutboundTag == Global.DirectTag)\n        {\n            var noDomain = lastRule.Domain == null || lastRule.Domain.Count == 0;\n            var noProcess = lastRule.Process == null || lastRule.Process.Count == 0;\n            var isAnyIp = lastRule.Ip == null || lastRule.Ip.Count == 0 || lastRule.Ip.Contains(\"0.0.0.0/0\");\n            var isAnyPort = string.IsNullOrEmpty(lastRule.Port) || lastRule.Port == \"0-65535\";\n            var isAnyNetwork = string.IsNullOrEmpty(lastRule.Network) || lastRule.Network == \"tcp,udp\";\n            useDirectDns = noDomain && noProcess && isAnyIp && isAnyPort && isAnyNetwork;\n        }\n\n        if (!useDirectDns)\n        {\n            dnsItem.servers.AddRange(remoteDNSAddress);\n        }\n        else\n        {\n            foreach (var dns in directDNSAddress)\n            {\n                var dnsServer = CreateDnsServer(dns, []);\n                dnsServer.tag = $\"{Global.DirectDnsTag}-{directDnsTagIndex++}\";\n                dnsServer.skipFallback = false;\n                dnsItem.servers.Add(JsonUtils.SerializeToNode(dnsServer,\n                    new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }));\n            }\n        }\n        return;\n\n        static List<string> ParseDnsAddresses(string? dnsInput, string defaultAddress)\n        {\n            var addresses = dnsInput?.Split(dnsInput.Contains(',') ? ',' : ';')\n                .Select(addr => addr.Trim())\n                .Where(addr => !string.IsNullOrEmpty(addr))\n                .Select(addr => addr.StartsWith(\"dhcp\", StringComparison.OrdinalIgnoreCase) ? \"localhost\" : addr)\n                .Distinct()\n                .ToList() ?? [defaultAddress];\n            return addresses.Count > 0 ? addresses : new List<string> { defaultAddress };\n        }\n\n        static DnsServer4Ray CreateDnsServer(string dnsAddress, List<string> domains, List<string>? expectedIPs = null)\n        {\n            var (domain, scheme, port, path) = Utils.ParseUrl(dnsAddress);\n            var domainFinal = dnsAddress;\n            int? portFinal = null;\n            if (scheme.IsNullOrEmpty() || scheme.StartsWith(\"udp\", StringComparison.OrdinalIgnoreCase))\n            {\n                domainFinal = domain;\n                portFinal = port > 0 ? port : null;\n            }\n            else if (scheme.StartsWith(\"tcp\", StringComparison.OrdinalIgnoreCase))\n            {\n                domainFinal = scheme + \"://\" + domain;\n                portFinal = port > 0 ? port : null;\n            }\n            var dnsServer = new DnsServer4Ray\n            {\n                address = domainFinal,\n                port = portFinal,\n                skipFallback = true,\n                domains = domains.Count > 0 ? domains : null,\n                expectedIPs = expectedIPs?.Count > 0 ? expectedIPs : null\n            };\n            return dnsServer;\n        }\n\n        void AddDnsServers(List<string> dnsAddresses, List<string> domains, bool isDirectDns = false, List<string>? expectedIPs = null)\n        {\n            if (domains.Count <= 0)\n            {\n                return;\n            }\n            foreach (var dnsAddress in dnsAddresses)\n            {\n                var dnsServer = CreateDnsServer(dnsAddress, domains, expectedIPs);\n                if (isDirectDns)\n                {\n                    dnsServer.tag = $\"{Global.DirectDnsTag}-{directDnsTagIndex++}\";\n                }\n                var dnsServerNode = JsonUtils.SerializeToNode(dnsServer,\n                    new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull });\n                dnsItem.servers.Add(dnsServerNode);\n            }\n        }\n    }\n\n    private void FillDnsHosts(Dns4Ray dnsItem)\n    {\n        var simpleDNSItem = context.SimpleDnsItem;\n        if (simpleDNSItem.AddCommonHosts == false && simpleDNSItem.UseSystemHosts == false && simpleDNSItem.Hosts.IsNullOrEmpty())\n        {\n            return;\n        }\n        dnsItem.hosts ??= new Dictionary<string, object>();\n        if (simpleDNSItem.AddCommonHosts == true)\n        {\n            dnsItem.hosts = Global.PredefinedHosts.ToDictionary(\n                kvp => kvp.Key,\n                kvp => (object)kvp.Value\n            );\n        }\n\n        if (simpleDNSItem.UseSystemHosts == true)\n        {\n            var systemHosts = Utils.GetSystemHosts();\n            var normalHost = dnsItem.hosts;\n\n            if (normalHost != null && systemHosts?.Count > 0)\n            {\n                foreach (var host in systemHosts)\n                {\n                    normalHost.TryAdd(host.Key, new List<string> { host.Value });\n                }\n            }\n        }\n\n        foreach (var kvp in Utils.ParseHostsToDictionary(simpleDNSItem.Hosts))\n        {\n            dnsItem.hosts[kvp.Key] = kvp.Value;\n        }\n    }\n\n    private void GenDnsCustom()\n    {\n        try\n        {\n            var item = context.RawDnsItem;\n            var normalDNS = item?.NormalDNS;\n            var domainStrategy4Freedom = item?.DomainStrategy4Freedom;\n            if (normalDNS.IsNullOrEmpty())\n            {\n                normalDNS = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);\n            }\n\n            //Outbound Freedom domainStrategy\n            if (domainStrategy4Freedom.IsNotEmpty())\n            {\n                var outbound = _coreConfig.outbounds.FirstOrDefault(t => t is { protocol: \"freedom\", tag: Global.DirectTag });\n                if (outbound != null)\n                {\n                    outbound.settings = new();\n                    outbound.settings.domainStrategy = domainStrategy4Freedom;\n                    outbound.settings.userLevel = 0;\n                }\n            }\n\n            var obj = JsonUtils.ParseJson(normalDNS);\n            if (obj is null)\n            {\n                List<string> servers = [];\n                var arrDNS = normalDNS.Split(',');\n                foreach (var str in arrDNS)\n                {\n                    servers.Add(str);\n                }\n                obj = JsonUtils.ParseJson(\"{}\");\n                obj[\"servers\"] = JsonUtils.SerializeToNode(servers);\n            }\n\n            // Append to dns settings\n            if (item.UseSystemHosts)\n            {\n                var systemHosts = Utils.GetSystemHosts();\n                if (systemHosts.Count > 0)\n                {\n                    var normalHost1 = obj[\"hosts\"];\n                    if (normalHost1 != null)\n                    {\n                        foreach (var host in systemHosts)\n                        {\n                            if (normalHost1[host.Key] != null)\n                            {\n                                continue;\n                            }\n\n                            normalHost1[host.Key] = host.Value;\n                        }\n                    }\n                }\n            }\n            var normalHost = obj[\"hosts\"];\n            if (normalHost != null)\n            {\n                foreach (var hostProp in normalHost.AsObject().ToList())\n                {\n                    if (hostProp.Value is JsonValue value && value.TryGetValue<string>(out var ip))\n                    {\n                        normalHost[hostProp.Key] = new JsonArray(ip);\n                    }\n                }\n            }\n\n            FillDnsDomainsCustom(obj);\n\n            _coreConfig.dns = obj;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillDnsDomainsCustom(JsonNode dns)\n    {\n        var servers = dns[\"servers\"];\n        if (servers == null)\n        {\n            return;\n        }\n\n        var domainList = context.ProtectDomainList;\n        if (domainList.Count <= 0)\n        {\n            return;\n        }\n\n        var dnsItem = context.RawDnsItem;\n        var dnsServer = new DnsServer4Ray()\n        {\n            address = string.IsNullOrEmpty(dnsItem?.DomainDNSAddress) ? Global.DomainPureIPDNSAddress.FirstOrDefault() : dnsItem?.DomainDNSAddress,\n            skipFallback = true,\n            domains = domainList.ToList(),\n        };\n        servers.AsArray().Add(JsonUtils.SerializeToNode(dnsServer));\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayInboundService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private void GenInbounds()\n    {\n        try\n        {\n            var listen = \"0.0.0.0\";\n            _coreConfig.inbounds = [];\n\n            var inbound = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks, true);\n            _coreConfig.inbounds.Add(inbound);\n\n            if (_config.Inbound.First().SecondLocalPortEnabled)\n            {\n                var inbound2 = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks2, true);\n                _coreConfig.inbounds.Add(inbound2);\n            }\n\n            if (_config.Inbound.First().AllowLANConn)\n            {\n                if (_config.Inbound.First().NewPort4LAN)\n                {\n                    var inbound3 = BuildInbound(_config.Inbound.First(), EInboundProtocol.socks3, true);\n                    inbound3.listen = listen;\n                    _coreConfig.inbounds.Add(inbound3);\n\n                    //auth\n                    if (_config.Inbound.First().User.IsNotEmpty() && _config.Inbound.First().Pass.IsNotEmpty())\n                    {\n                        inbound3.settings.auth = \"password\";\n                        inbound3.settings.accounts = new List<AccountsItem4Ray> { new() { user = _config.Inbound.First().User, pass = _config.Inbound.First().Pass } };\n                    }\n                }\n                else\n                {\n                    inbound.listen = listen;\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private Inbounds4Ray BuildInbound(InItem inItem, EInboundProtocol protocol, bool bSocks)\n    {\n        var result = EmbedUtils.GetEmbedText(Global.V2raySampleInbound);\n        if (result.IsNullOrEmpty())\n        {\n            return new();\n        }\n\n        var inbound = JsonUtils.Deserialize<Inbounds4Ray>(result);\n        if (inbound == null)\n        {\n            return new();\n        }\n        inbound.tag = protocol.ToString();\n        inbound.port = inItem.LocalPort + (int)protocol;\n        inbound.protocol = EInboundProtocol.mixed.ToString();\n        inbound.settings.udp = inItem.UdpEnabled;\n        inbound.sniffing.enabled = inItem.SniffingEnabled;\n        inbound.sniffing.destOverride = inItem.DestOverride;\n        inbound.sniffing.routeOnly = inItem.RouteOnly;\n\n        return inbound;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayLogService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private void GenLog()\n    {\n        try\n        {\n            if (_config.CoreBasicItem.LogEnabled)\n            {\n                var dtNow = DateTime.Now;\n                _coreConfig.log.loglevel = _config.CoreBasicItem.Loglevel;\n                _coreConfig.log.access = Utils.GetLogPath($\"Vaccess_{dtNow:yyyy-MM-dd}.txt\");\n                _coreConfig.log.error = Utils.GetLogPath($\"Verror_{dtNow:yyyy-MM-dd}.txt\");\n            }\n            else\n            {\n                _coreConfig.log.loglevel = _config.CoreBasicItem.Loglevel;\n                _coreConfig.log.access = null;\n                _coreConfig.log.error = null;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayOutboundService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private void GenOutbounds()\n    {\n        var proxyOutboundList = BuildAllProxyOutbounds();\n        _coreConfig.outbounds.InsertRange(0, proxyOutboundList);\n        if (proxyOutboundList.Count(n => n.tag.StartsWith(Global.ProxyTag)) > 1)\n        {\n            var multipleLoad = _node.GetProtocolExtra().MultipleLoad ?? EMultipleLoad.LeastPing;\n            GenObservatory(multipleLoad);\n            GenBalancer(multipleLoad);\n        }\n    }\n\n    private List<Outbounds4Ray> BuildAllProxyOutbounds(string baseTagName = Global.ProxyTag)\n    {\n        var proxyOutboundList = new List<Outbounds4Ray>();\n        if (_node.ConfigType.IsGroupType())\n        {\n            proxyOutboundList.AddRange(BuildGroupProxyOutbounds(baseTagName));\n        }\n        else\n        {\n            proxyOutboundList.Add(BuildProxyOutbound(baseTagName));\n        }\n\n        if (_config.CoreBasicItem.EnableFragment)\n        {\n            var fragmentOutbound = new Outbounds4Ray\n            {\n                protocol = \"freedom\",\n                tag = $\"frag-{baseTagName}\",\n                settings = new()\n                {\n                    fragment = new()\n                    {\n                        packets = _config.Fragment4RayItem?.Packets,\n                        length = _config.Fragment4RayItem?.Length,\n                        interval = _config.Fragment4RayItem?.Interval\n                    }\n                }\n            };\n            var actOutboundWithTlsList =\n                proxyOutboundList.Where(n => n.streamSettings?.security.IsNullOrEmpty() == false\n                                             && (n.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true)).ToList();\n            if (actOutboundWithTlsList.Count > 0)\n            {\n                proxyOutboundList.Add(fragmentOutbound);\n            }\n            foreach (var outbound in actOutboundWithTlsList)\n            {\n                outbound.streamSettings.sockopt = new()\n                {\n                    dialerProxy = fragmentOutbound.tag\n                };\n            }\n        }\n        return proxyOutboundList;\n    }\n\n    private List<Outbounds4Ray> BuildGroupProxyOutbounds(string baseTagName = Global.ProxyTag)\n    {\n        var proxyOutboundList = new List<Outbounds4Ray>();\n        switch (_node.ConfigType)\n        {\n            case EConfigType.PolicyGroup:\n                proxyOutboundList.AddRange(BuildOutboundsList(baseTagName));\n                break;\n\n            case EConfigType.ProxyChain:\n                proxyOutboundList.AddRange(BuildChainOutboundsList(baseTagName));\n                break;\n        }\n        return proxyOutboundList;\n    }\n\n    private Outbounds4Ray BuildProxyOutbound(string baseTagName = Global.ProxyTag)\n    {\n        var txtOutbound = EmbedUtils.GetEmbedText(Global.V2raySampleOutbound);\n        var outbound = JsonUtils.Deserialize<Outbounds4Ray>(txtOutbound);\n        FillOutbound(outbound);\n        outbound.tag = baseTagName;\n        return outbound;\n    }\n\n    private void FillOutbound(Outbounds4Ray outbound)\n    {\n        try\n        {\n            var protocolExtra = _node.GetProtocolExtra();\n            var muxEnabled = _node.MuxEnabled ?? _config.CoreBasicItem.MuxEnabled;\n            switch (_node.ConfigType)\n            {\n                case EConfigType.VMess:\n                    {\n                        VnextItem4Ray vnextItem;\n                        if (outbound.settings.vnext.Count <= 0)\n                        {\n                            vnextItem = new VnextItem4Ray();\n                            outbound.settings.vnext.Add(vnextItem);\n                        }\n                        else\n                        {\n                            vnextItem = outbound.settings.vnext.First();\n                        }\n                        vnextItem.address = _node.Address;\n                        vnextItem.port = _node.Port;\n\n                        UsersItem4Ray usersItem;\n                        if (vnextItem.users.Count <= 0)\n                        {\n                            usersItem = new UsersItem4Ray();\n                            vnextItem.users.Add(usersItem);\n                        }\n                        else\n                        {\n                            usersItem = vnextItem.users.First();\n                        }\n\n                        usersItem.id = _node.Password;\n                        usersItem.alterId = int.TryParse(protocolExtra?.AlterId, out var result) ? result : 0;\n                        usersItem.email = Global.UserEMail;\n                        if (Global.VmessSecurities.Contains(protocolExtra.VmessSecurity))\n                        {\n                            usersItem.security = protocolExtra.VmessSecurity;\n                        }\n                        else\n                        {\n                            usersItem.security = Global.DefaultSecurity;\n                        }\n\n                        FillOutboundMux(outbound, muxEnabled, muxEnabled);\n\n                        outbound.settings.servers = null;\n                        break;\n                    }\n                case EConfigType.Shadowsocks:\n                    {\n                        ServersItem4Ray serversItem;\n                        if (outbound.settings.servers.Count <= 0)\n                        {\n                            serversItem = new ServersItem4Ray();\n                            outbound.settings.servers.Add(serversItem);\n                        }\n                        else\n                        {\n                            serversItem = outbound.settings.servers.First();\n                        }\n                        serversItem.address = _node.Address;\n                        serversItem.port = _node.Port;\n                        serversItem.password = _node.Password;\n                        serversItem.method = AppManager.Instance.GetShadowsocksSecurities(_node).Contains(protocolExtra.SsMethod)\n                            ? protocolExtra.SsMethod : \"none\";\n\n                        serversItem.ota = false;\n                        serversItem.level = 1;\n\n                        FillOutboundMux(outbound);\n\n                        outbound.settings.vnext = null;\n                        break;\n                    }\n                case EConfigType.SOCKS:\n                case EConfigType.HTTP:\n                    {\n                        ServersItem4Ray serversItem;\n                        if (outbound.settings.servers.Count <= 0)\n                        {\n                            serversItem = new ServersItem4Ray();\n                            outbound.settings.servers.Add(serversItem);\n                        }\n                        else\n                        {\n                            serversItem = outbound.settings.servers.First();\n                        }\n                        serversItem.address = _node.Address;\n                        serversItem.port = _node.Port;\n                        serversItem.method = null;\n                        serversItem.password = null;\n\n                        if (_node.Username.IsNotEmpty()\n                            && _node.Password.IsNotEmpty())\n                        {\n                            SocksUsersItem4Ray socksUsersItem = new()\n                            {\n                                user = _node.Username ?? \"\",\n                                pass = _node.Password,\n                                level = 1\n                            };\n\n                            serversItem.users = new List<SocksUsersItem4Ray>() { socksUsersItem };\n                        }\n\n                        FillOutboundMux(outbound);\n\n                        outbound.settings.vnext = null;\n                        break;\n                    }\n                case EConfigType.VLESS:\n                    {\n                        VnextItem4Ray vnextItem;\n                        if (outbound.settings.vnext?.Count <= 0)\n                        {\n                            vnextItem = new VnextItem4Ray();\n                            outbound.settings.vnext.Add(vnextItem);\n                        }\n                        else\n                        {\n                            vnextItem = outbound.settings.vnext.First();\n                        }\n                        vnextItem.address = _node.Address;\n                        vnextItem.port = _node.Port;\n\n                        UsersItem4Ray usersItem;\n                        if (vnextItem.users.Count <= 0)\n                        {\n                            usersItem = new UsersItem4Ray();\n                            vnextItem.users.Add(usersItem);\n                        }\n                        else\n                        {\n                            usersItem = vnextItem.users.First();\n                        }\n                        usersItem.id = _node.Password;\n                        usersItem.email = Global.UserEMail;\n                        usersItem.encryption = protocolExtra.VlessEncryption;\n\n                        if (!protocolExtra.Flow.IsNullOrEmpty())\n                        {\n                            usersItem.flow = protocolExtra.Flow;\n                        }\n                        else\n                        {\n                            FillOutboundMux(outbound, false, muxEnabled);\n                        }\n                        outbound.settings.servers = null;\n                        break;\n                    }\n                case EConfigType.Trojan:\n                    {\n                        ServersItem4Ray serversItem;\n                        if (outbound.settings.servers.Count <= 0)\n                        {\n                            serversItem = new ServersItem4Ray();\n                            outbound.settings.servers.Add(serversItem);\n                        }\n                        else\n                        {\n                            serversItem = outbound.settings.servers.First();\n                        }\n                        serversItem.address = _node.Address;\n                        serversItem.port = _node.Port;\n                        serversItem.password = _node.Password;\n\n                        serversItem.ota = false;\n                        serversItem.level = 1;\n\n                        FillOutboundMux(outbound);\n\n                        outbound.settings.vnext = null;\n                        break;\n                    }\n                case EConfigType.Hysteria2:\n                    {\n                        outbound.settings = new()\n                        {\n                            version = 2,\n                            address = _node.Address,\n                            port = _node.Port,\n                        };\n                        outbound.settings.vnext = null;\n                        outbound.settings.servers = null;\n                        break;\n                    }\n                case EConfigType.WireGuard:\n                    {\n                        var address = _node.Address;\n                        if (Utils.IsIpv6(address))\n                        {\n                            address = $\"[{address}]\";\n                        }\n                        var peer = new WireguardPeer4Ray\n                        {\n                            publicKey = protocolExtra.WgPublicKey ?? \"\",\n                            endpoint = address + \":\" + _node.Port.ToString()\n                        };\n                        var setting = new Outboundsettings4Ray\n                        {\n                            address = Utils.String2List(protocolExtra.WgInterfaceAddress),\n                            secretKey = _node.Password,\n                            reserved = Utils.String2List(protocolExtra.WgReserved)?.Select(int.Parse).ToList(),\n                            mtu = protocolExtra.WgMtu > 0 ? protocolExtra.WgMtu : Global.TunMtus.First(),\n                            peers = [peer]\n                        };\n                        outbound.settings = setting;\n                        outbound.settings.vnext = null;\n                        outbound.settings.servers = null;\n                        break;\n                    }\n            }\n\n            outbound.protocol = Global.ProtocolTypes[_node.ConfigType];\n            if (_node.ConfigType == EConfigType.Hysteria2)\n            {\n                outbound.protocol = \"hysteria\";\n            }\n            FillBoundStreamSettings(outbound);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillOutboundMux(Outbounds4Ray outbound, bool enabledTCP = false, bool enabledUDP = false)\n    {\n        try\n        {\n            outbound.mux.enabled = false;\n            outbound.mux.concurrency = -1;\n\n            if (enabledTCP)\n            {\n                outbound.mux.enabled = true;\n                outbound.mux.concurrency = _config.Mux4RayItem.Concurrency;\n            }\n            else if (enabledUDP)\n            {\n                outbound.mux.enabled = true;\n                outbound.mux.xudpConcurrency = _config.Mux4RayItem.XudpConcurrency;\n                outbound.mux.xudpProxyUDP443 = _config.Mux4RayItem.XudpProxyUDP443;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void FillBoundStreamSettings(Outbounds4Ray outbound)\n    {\n        try\n        {\n            var streamSettings = outbound.streamSettings;\n            var network = _node.GetNetwork();\n            if (_node.ConfigType == EConfigType.Hysteria2)\n            {\n                network = \"hysteria\";\n            }\n            streamSettings.network = network;\n            var host = _node.RequestHost.TrimEx();\n            var path = _node.Path.TrimEx();\n            var sni = _node.Sni.TrimEx();\n            var useragent = \"\";\n            if (!_config.CoreBasicItem.DefUserAgent.IsNullOrEmpty())\n            {\n                useragent = Global.UserAgentTexts.GetValueOrDefault(_config.CoreBasicItem.DefUserAgent, _config.CoreBasicItem.DefUserAgent);\n            }\n\n            //if tls\n            if (_node.StreamSecurity == Global.StreamSecurity)\n            {\n                streamSettings.security = _node.StreamSecurity;\n\n                TlsSettings4Ray tlsSettings = new()\n                {\n                    allowInsecure = Utils.ToBool(_node.AllowInsecure.IsNullOrEmpty() ? _config.CoreBasicItem.DefAllowInsecure.ToString().ToLower() : _node.AllowInsecure),\n                    alpn = _node.GetAlpn(),\n                    fingerprint = _node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : _node.Fingerprint,\n                    echConfigList = _node.EchConfigList.NullIfEmpty(),\n                    echForceQuery = _node.EchForceQuery.NullIfEmpty()\n                };\n                if (sni.IsNotEmpty())\n                {\n                    tlsSettings.serverName = sni;\n                }\n                else if (host.IsNotEmpty())\n                {\n                    tlsSettings.serverName = Utils.String2List(host)?.First();\n                }\n                var certs = CertPemManager.ParsePemChain(_node.Cert);\n                if (certs.Count > 0)\n                {\n                    var certsettings = new List<CertificateSettings4Ray>();\n                    foreach (var cert in certs)\n                    {\n                        var certPerLine = cert.Split(\"\\n\").ToList();\n                        certsettings.Add(new CertificateSettings4Ray\n                        {\n                            certificate = certPerLine,\n                            usage = \"verify\",\n                        });\n                    }\n                    tlsSettings.certificates = certsettings;\n                    tlsSettings.disableSystemRoot = true;\n                    tlsSettings.allowInsecure = false;\n                }\n                else if (!_node.CertSha.IsNullOrEmpty())\n                {\n                    tlsSettings.pinnedPeerCertSha256 = _node.CertSha;\n                    tlsSettings.allowInsecure = false;\n                }\n                streamSettings.tlsSettings = tlsSettings;\n            }\n\n            //if Reality\n            if (_node.StreamSecurity == Global.StreamSecurityReality)\n            {\n                streamSettings.security = _node.StreamSecurity;\n\n                TlsSettings4Ray realitySettings = new()\n                {\n                    fingerprint = _node.Fingerprint.IsNullOrEmpty() ? _config.CoreBasicItem.DefFingerprint : _node.Fingerprint,\n                    serverName = sni,\n                    publicKey = _node.PublicKey,\n                    shortId = _node.ShortId,\n                    spiderX = _node.SpiderX,\n                    mldsa65Verify = _node.Mldsa65Verify,\n                    show = false,\n                };\n\n                streamSettings.realitySettings = realitySettings;\n            }\n\n            //streamSettings\n            switch (network)\n            {\n                case nameof(ETransport.kcp):\n                    KcpSettings4Ray kcpSettings = new()\n                    {\n                        mtu = _config.KcpItem.Mtu,\n                        tti = _config.KcpItem.Tti\n                    };\n\n                    kcpSettings.uplinkCapacity = _config.KcpItem.UplinkCapacity;\n                    kcpSettings.downlinkCapacity = _config.KcpItem.DownlinkCapacity;\n\n                    kcpSettings.congestion = _config.KcpItem.Congestion;\n                    kcpSettings.readBufferSize = _config.KcpItem.ReadBufferSize;\n                    kcpSettings.writeBufferSize = _config.KcpItem.WriteBufferSize;\n                    streamSettings.finalmask ??= new();\n                    if (Global.KcpHeaderMaskMap.TryGetValue(_node.HeaderType, out var header))\n                    {\n                        streamSettings.finalmask.udp =\n                        [\n                            new Mask4Ray\n                            {\n                                type = header,\n                                settings = _node.HeaderType == \"dns\" && !host.IsNullOrEmpty() ? new MaskSettings4Ray { domain = host } : null\n                            }\n                        ];\n                    }\n                    streamSettings.finalmask.udp ??= [];\n                    if (path.IsNullOrEmpty())\n                    {\n                        streamSettings.finalmask.udp.Add(new Mask4Ray\n                        {\n                            type = \"mkcp-original\"\n                        });\n                    }\n                    else\n                    {\n                        streamSettings.finalmask.udp.Add(new Mask4Ray\n                        {\n                            type = \"mkcp-aes128gcm\",\n                            settings = new MaskSettings4Ray { password = path }\n                        });\n                    }\n                    streamSettings.kcpSettings = kcpSettings;\n                    break;\n                //ws\n                case nameof(ETransport.ws):\n                    WsSettings4Ray wsSettings = new();\n                    wsSettings.headers = new Headers4Ray();\n\n                    if (host.IsNotEmpty())\n                    {\n                        wsSettings.host = host;\n                    }\n                    if (path.IsNotEmpty())\n                    {\n                        wsSettings.path = path;\n                    }\n                    if (useragent.IsNotEmpty())\n                    {\n                        wsSettings.headers.UserAgent = useragent;\n                    }\n                    streamSettings.wsSettings = wsSettings;\n\n                    break;\n                //httpupgrade\n                case nameof(ETransport.httpupgrade):\n                    HttpupgradeSettings4Ray httpupgradeSettings = new();\n\n                    if (path.IsNotEmpty())\n                    {\n                        httpupgradeSettings.path = path;\n                    }\n                    if (host.IsNotEmpty())\n                    {\n                        httpupgradeSettings.host = host;\n                    }\n                    streamSettings.httpupgradeSettings = httpupgradeSettings;\n\n                    break;\n                //xhttp\n                case nameof(ETransport.xhttp):\n                    streamSettings.network = ETransport.xhttp.ToString();\n                    XhttpSettings4Ray xhttpSettings = new();\n\n                    if (path.IsNotEmpty())\n                    {\n                        xhttpSettings.path = path;\n                    }\n                    if (host.IsNotEmpty())\n                    {\n                        xhttpSettings.host = host;\n                    }\n                    if (_node.HeaderType.IsNotEmpty() && Global.XhttpMode.Contains(_node.HeaderType))\n                    {\n                        xhttpSettings.mode = _node.HeaderType;\n                    }\n                    if (_node.Extra.IsNotEmpty())\n                    {\n                        xhttpSettings.extra = JsonUtils.ParseJson(_node.Extra);\n                    }\n\n                    streamSettings.xhttpSettings = xhttpSettings;\n                    FillOutboundMux(outbound);\n\n                    break;\n                //h2\n                case nameof(ETransport.h2):\n                    HttpSettings4Ray httpSettings = new();\n\n                    if (host.IsNotEmpty())\n                    {\n                        httpSettings.host = Utils.String2List(host);\n                    }\n                    httpSettings.path = path;\n\n                    streamSettings.httpSettings = httpSettings;\n\n                    break;\n                //quic\n                case nameof(ETransport.quic):\n                    QuicSettings4Ray quicsettings = new()\n                    {\n                        security = host,\n                        key = path,\n                        header = new Header4Ray\n                        {\n                            type = _node.HeaderType\n                        }\n                    };\n                    streamSettings.quicSettings = quicsettings;\n                    if (_node.StreamSecurity == Global.StreamSecurity)\n                    {\n                        if (sni.IsNotEmpty())\n                        {\n                            streamSettings.tlsSettings.serverName = sni;\n                        }\n                        else\n                        {\n                            streamSettings.tlsSettings.serverName = _node.Address;\n                        }\n                    }\n                    break;\n\n                case nameof(ETransport.grpc):\n                    GrpcSettings4Ray grpcSettings = new()\n                    {\n                        authority = host.NullIfEmpty(),\n                        serviceName = path,\n                        multiMode = _node.HeaderType == Global.GrpcMultiMode,\n                        idle_timeout = _config.GrpcItem.IdleTimeout,\n                        health_check_timeout = _config.GrpcItem.HealthCheckTimeout,\n                        permit_without_stream = _config.GrpcItem.PermitWithoutStream,\n                        initial_windows_size = _config.GrpcItem.InitialWindowsSize,\n                    };\n                    streamSettings.grpcSettings = grpcSettings;\n                    break;\n\n                case \"hysteria\":\n                    var protocolExtra = _node.GetProtocolExtra();\n                    var ports = protocolExtra?.Ports;\n                    int? upMbps = protocolExtra?.UpMbps is { } su and >= 0\n                        ? su\n                        : _config.HysteriaItem.UpMbps;\n                    int? downMbps = protocolExtra?.DownMbps is { } sd and >= 0\n                        ? sd\n                        : _config.HysteriaItem.UpMbps;\n                    var hopInterval = !protocolExtra.HopInterval.IsNullOrEmpty()\n                        ? protocolExtra.HopInterval\n                        : (_config.HysteriaItem.HopInterval >= 5\n                            ? _config.HysteriaItem.HopInterval\n                            : Global.Hysteria2DefaultHopInt).ToString();\n                    HysteriaUdpHop4Ray? udpHop = null;\n                    if (!ports.IsNullOrEmpty() &&\n                        (ports.Contains(':') || ports.Contains('-') || ports.Contains(',')))\n                    {\n                        udpHop = new HysteriaUdpHop4Ray\n                        {\n                            port = ports.Replace(':', '-'),\n                            interval = hopInterval,\n                        };\n                    }\n                    streamSettings.hysteriaSettings = new()\n                    {\n                        version = 2,\n                        auth = _node.Password,\n                        up = upMbps > 0 ? $\"{upMbps}mbps\" : null,\n                        down = downMbps > 0 ? $\"{downMbps}mbps\" : null,\n                        udphop = udpHop,\n                    };\n                    if (!protocolExtra.SalamanderPass.IsNullOrEmpty())\n                    {\n                        streamSettings.finalmask ??= new();\n                        streamSettings.finalmask.udp =\n                        [\n                            new Mask4Ray\n                            {\n                                type = \"salamander\",\n                                settings = new MaskSettings4Ray { password = protocolExtra.SalamanderPass.TrimEx(), }\n                            }\n                        ];\n                    }\n                    break;\n\n                default:\n                    //tcp\n                    if (_node.HeaderType == Global.TcpHeaderHttp)\n                    {\n                        TcpSettings4Ray tcpSettings = new()\n                        {\n                            header = new Header4Ray\n                            {\n                                type = _node.HeaderType\n                            }\n                        };\n\n                        //request Host\n                        var request = EmbedUtils.GetEmbedText(Global.V2raySampleHttpRequestFileName);\n                        var arrHost = host.Split(',');\n                        var host2 = string.Join(\",\".AppendQuotes(), arrHost);\n                        request = request.Replace(\"$requestHost$\", $\"{host2.AppendQuotes()}\");\n                        request = request.Replace(\"$requestUserAgent$\", $\"{useragent.AppendQuotes()}\");\n                        //Path\n                        var pathHttp = @\"/\";\n                        if (path.IsNotEmpty())\n                        {\n                            var arrPath = path.Split(',');\n                            pathHttp = string.Join(\",\".AppendQuotes(), arrPath);\n                        }\n                        request = request.Replace(\"$requestPath$\", $\"{pathHttp.AppendQuotes()}\");\n                        tcpSettings.header.request = JsonUtils.Deserialize<object>(request);\n\n                        streamSettings.tcpSettings = tcpSettings;\n                    }\n                    break;\n            }\n\n            if (!_node.Finalmask.IsNullOrEmpty())\n            {\n                streamSettings.finalmask = JsonUtils.Deserialize<Finalmask4Ray>(_node.Finalmask);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private List<Outbounds4Ray> BuildOutboundsList(string baseTagName = Global.ProxyTag)\n    {\n        var nodes = new List<ProfileItem>();\n        foreach (var nodeId in Utils.String2List(_node.GetProtocolExtra().ChildItems) ?? [])\n        {\n            if (context.AllProxiesMap.TryGetValue(nodeId, out var node))\n            {\n                nodes.Add(node);\n            }\n        }\n        var resultOutbounds = new List<Outbounds4Ray>();\n        for (var i = 0; i < nodes.Count; i++)\n        {\n            var node = nodes[i];\n            var currentTag = $\"{baseTagName}-{i + 1}\";\n\n            if (node.ConfigType.IsGroupType())\n            {\n                var childProfiles = new CoreConfigV2rayService(context with { Node = node, }).BuildGroupProxyOutbounds(currentTag);\n                resultOutbounds.AddRange(childProfiles);\n                continue;\n            }\n            var outbound = new CoreConfigV2rayService(context with { Node = node, }).BuildProxyOutbound();\n            outbound.tag = currentTag;\n            resultOutbounds.Add(outbound);\n        }\n        return resultOutbounds;\n    }\n\n    private List<Outbounds4Ray> BuildChainOutboundsList(string baseTagName = Global.ProxyTag)\n    {\n        var nodes = new List<ProfileItem>();\n        foreach (var nodeId in Utils.String2List(_node.GetProtocolExtra().ChildItems) ?? [])\n        {\n            if (context.AllProxiesMap.TryGetValue(nodeId, out var node))\n            {\n                nodes.Add(node);\n            }\n        }\n        // Based on actual network flow instead of data packets\n        var nodesReverse = nodes.AsEnumerable().Reverse().ToList();\n        var resultOutbounds = new List<Outbounds4Ray>();\n        for (var i = 0; i < nodesReverse.Count; i++)\n        {\n            var node = nodesReverse[i];\n            var currentTag = i == 0 ? baseTagName : $\"chain-{baseTagName}-{i}\";\n            var dialerProxyTag = i != nodesReverse.Count - 1 ? $\"chain-{baseTagName}-{i + 1}\" : null;\n            if (node.ConfigType.IsGroupType())\n            {\n                var childProfiles = new CoreConfigV2rayService(context with { Node = node, }).BuildGroupProxyOutbounds(currentTag);\n                if (!dialerProxyTag.IsNullOrEmpty())\n                {\n                    var chainEndNodes =\n                        childProfiles.Where(n => n?.streamSettings?.sockopt?.dialerProxy?.IsNullOrEmpty() ?? true);\n                    foreach (var chainEndNode in chainEndNodes)\n                    {\n                        chainEndNode.streamSettings.sockopt = new()\n                        {\n                            dialerProxy = dialerProxyTag\n                        };\n                    }\n                }\n                if (i != 0)\n                {\n                    var chainStartNodes = childProfiles.Where(n => n.tag.StartsWith(currentTag)).ToList();\n                    if (chainStartNodes.Count == 1)\n                    {\n                        foreach (var existedChainEndNode in resultOutbounds.Where(n => n.streamSettings?.sockopt?.dialerProxy == currentTag))\n                        {\n                            existedChainEndNode.streamSettings.sockopt = new()\n                            {\n                                dialerProxy = chainStartNodes.First().tag\n                            };\n                        }\n                    }\n                    else if (chainStartNodes.Count > 1)\n                    {\n                        var existedChainNodes = JsonUtils.DeepCopy(resultOutbounds);\n                        resultOutbounds.Clear();\n                        var j = 0;\n                        foreach (var chainStartNode in chainStartNodes)\n                        {\n                            var existedChainNodesClone = JsonUtils.DeepCopy(existedChainNodes);\n                            foreach (var existedChainNode in existedChainNodesClone)\n                            {\n                                var cloneTag = $\"{existedChainNode.tag}-clone-{j + 1}\";\n                                existedChainNode.tag = cloneTag;\n                            }\n                            for (var k = 0; k < existedChainNodesClone.Count; k++)\n                            {\n                                var existedChainNode = existedChainNodesClone[k];\n                                var previousDialerProxyTag = existedChainNode.streamSettings?.sockopt?.dialerProxy;\n                                var nextTag = k + 1 < existedChainNodesClone.Count\n                                    ? existedChainNodesClone[k + 1].tag\n                                    : chainStartNode.tag;\n                                existedChainNode.streamSettings.sockopt = new()\n                                {\n                                    dialerProxy = (previousDialerProxyTag == currentTag)\n                                        ? chainStartNode.tag\n                                        : nextTag\n                                };\n                                resultOutbounds.Add(existedChainNode);\n                            }\n                            j++;\n                        }\n                    }\n                }\n                resultOutbounds.AddRange(childProfiles);\n                continue;\n            }\n            var outbound = new CoreConfigV2rayService(context with { Node = node, }).BuildProxyOutbound();\n\n            outbound.tag = currentTag;\n\n            if (!dialerProxyTag.IsNullOrEmpty())\n            {\n                outbound.streamSettings.sockopt = new()\n                {\n                    dialerProxy = dialerProxyTag\n                };\n            }\n\n            resultOutbounds.Add(outbound);\n        }\n        return resultOutbounds;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayRoutingService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private void GenRouting()\n    {\n        try\n        {\n            if (_coreConfig.routing?.rules != null)\n            {\n                _coreConfig.routing.domainStrategy = _config.RoutingBasicItem.DomainStrategy;\n\n                var routing = context.RoutingItem;\n                if (routing != null)\n                {\n                    if (routing.DomainStrategy.IsNotEmpty())\n                    {\n                        _coreConfig.routing.domainStrategy = routing.DomainStrategy;\n                    }\n                    var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);\n                    foreach (var item in rules)\n                    {\n                        if (!item.Enabled)\n                        {\n                            continue;\n                        }\n\n                        if (item.RuleType == ERuleType.DNS)\n                        {\n                            continue;\n                        }\n\n                        var item2 = JsonUtils.Deserialize<RulesItem4Ray>(JsonUtils.Serialize(item));\n                        GenRoutingUserRule(item2);\n                    }\n                }\n                var balancerTagList = _coreConfig.routing.balancers\n                    ?.Select(p => p.tag)\n                    .ToList() ?? [];\n                if (balancerTagList.Count > 0)\n                {\n                    foreach (var rulesItem in _coreConfig.routing.rules.Where(r => balancerTagList.Contains(r.outboundTag + Global.BalancerTagSuffix)))\n                    {\n                        rulesItem.balancerTag = rulesItem.outboundTag + Global.BalancerTagSuffix;\n                        rulesItem.outboundTag = null;\n                    }\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void GenRoutingUserRule(RulesItem4Ray? userRule)\n    {\n        try\n        {\n            if (userRule == null)\n            {\n                return;\n            }\n            userRule.outboundTag = GenRoutingUserRuleOutbound(userRule.outboundTag ?? Global.ProxyTag);\n\n            if (userRule.port.IsNullOrEmpty())\n            {\n                userRule.port = null;\n            }\n            if (userRule.network.IsNullOrEmpty())\n            {\n                userRule.network = null;\n            }\n            if (userRule.domain?.Count == 0)\n            {\n                userRule.domain = null;\n            }\n            if (userRule.ip?.Count == 0)\n            {\n                userRule.ip = null;\n            }\n            if (userRule.protocol?.Count == 0)\n            {\n                userRule.protocol = null;\n            }\n            if (userRule.inboundTag?.Count == 0)\n            {\n                userRule.inboundTag = null;\n            }\n            if (userRule.process?.Count == 0)\n            {\n                userRule.process = null;\n            }\n\n            var hasDomainIp = false;\n            if (userRule.domain?.Count > 0)\n            {\n                var it = JsonUtils.DeepCopy(userRule);\n                it.ip = null;\n                it.process = null;\n                it.type = \"field\";\n                for (var k = it.domain.Count - 1; k >= 0; k--)\n                {\n                    if (it.domain[k].StartsWith('#'))\n                    {\n                        it.domain.RemoveAt(k);\n                    }\n                    it.domain[k] = it.domain[k].Replace(Global.RoutingRuleComma, \",\");\n                }\n                _coreConfig.routing.rules.Add(it);\n                hasDomainIp = true;\n            }\n            if (userRule.ip?.Count > 0)\n            {\n                var it = JsonUtils.DeepCopy(userRule);\n                it.domain = null;\n                it.process = null;\n                it.type = \"field\";\n                _coreConfig.routing.rules.Add(it);\n                hasDomainIp = true;\n            }\n            if (userRule.process?.Count > 0)\n            {\n                var it = JsonUtils.DeepCopy(userRule);\n                it.domain = null;\n                it.ip = null;\n                it.type = \"field\";\n                _coreConfig.routing.rules.Add(it);\n                hasDomainIp = true;\n            }\n            if (!hasDomainIp)\n            {\n                if (userRule.port.IsNotEmpty()\n                    || userRule.protocol?.Count > 0\n                    || userRule.inboundTag?.Count > 0\n                    || userRule.network != null\n                    )\n                {\n                    var it = JsonUtils.DeepCopy(userRule);\n                    it.type = \"field\";\n                    _coreConfig.routing.rules.Add(it);\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private string GenRoutingUserRuleOutbound(string outboundTag)\n    {\n        if (Global.OutboundTags.Contains(outboundTag))\n        {\n            return outboundTag;\n        }\n\n        var node = context.AllProxiesMap.GetValueOrDefault($\"remark:{outboundTag}\");\n\n        if (node == null\n            || (!Global.XraySupportConfigType.Contains(node.ConfigType)\n            && !node.ConfigType.IsGroupType()))\n        {\n            return Global.ProxyTag;\n        }\n\n        var tag = $\"{node.IndexId}-{Global.ProxyTag}\";\n        if (_coreConfig.outbounds.Any(p => p.tag.StartsWith(tag)))\n        {\n            return tag;\n        }\n\n        var proxyOutbounds = new CoreConfigV2rayService(context with { Node = node, }).BuildAllProxyOutbounds(tag);\n        _coreConfig.outbounds.AddRange(proxyOutbounds);\n        if (proxyOutbounds.Count(n => n.tag.StartsWith(tag)) > 1)\n        {\n            var multipleLoad = node.GetProtocolExtra().MultipleLoad ?? EMultipleLoad.LeastPing;\n            GenObservatory(multipleLoad, tag);\n            GenBalancer(multipleLoad, tag);\n        }\n\n        return tag;\n    }\n\n    private RulesItem4Ray BuildFinalRule()\n    {\n        var finalRule = new RulesItem4Ray()\n        {\n            type = \"field\",\n            network = \"tcp,udp\",\n            outboundTag = Global.ProxyTag,\n        };\n        var balancer =\n            _coreConfig?.routing?.balancers?.FirstOrDefault(b => b.tag == Global.ProxyTag + Global.BalancerTagSuffix, null);\n        var domainStrategy = _coreConfig.routing?.domainStrategy ?? Global.AsIs;\n        if (balancer is not null)\n        {\n            finalRule.outboundTag = null;\n            finalRule.balancerTag = balancer.tag;\n        }\n        if (domainStrategy == Global.IPIfNonMatch)\n        {\n            finalRule.network = null;\n            finalRule.ip = [\"0.0.0.0/0\", \"::/0\"];\n        }\n        return finalRule;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/CoreConfig/V2ray/V2rayStatisticService.cs",
    "content": "namespace ServiceLib.Services.CoreConfig;\n\npublic partial class CoreConfigV2rayService\n{\n    private void GenStatistic()\n    {\n        if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)\n        {\n            var tag = EInboundProtocol.api.ToString();\n            Metrics4Ray apiObj = new();\n            Policy4Ray policyObj = new();\n            SystemPolicy4Ray policySystemSetting = new();\n\n            _coreConfig.stats = new Stats4Ray();\n\n            apiObj.tag = tag;\n            _coreConfig.metrics = apiObj;\n\n            policySystemSetting.statsOutboundDownlink = true;\n            policySystemSetting.statsOutboundUplink = true;\n            policyObj.system = policySystemSetting;\n            _coreConfig.policy = policyObj;\n\n            if (!_coreConfig.inbounds.Exists(item => item.tag == tag))\n            {\n                Inbounds4Ray apiInbound = new();\n                Inboundsettings4Ray apiInboundSettings = new();\n                apiInbound.tag = tag;\n                apiInbound.listen = Global.Loopback;\n                apiInbound.port = AppManager.Instance.StatePort;\n                apiInbound.protocol = Global.InboundAPIProtocol;\n                apiInboundSettings.address = Global.Loopback;\n                apiInbound.settings = apiInboundSettings;\n                _coreConfig.inbounds.Add(apiInbound);\n            }\n\n            if (!_coreConfig.routing.rules.Exists(item => item.outboundTag == tag))\n            {\n                RulesItem4Ray apiRoutingRule = new()\n                {\n                    inboundTag = new List<string> { tag },\n                    outboundTag = tag,\n                    type = \"field\"\n                };\n\n                _coreConfig.routing.rules.Add(apiRoutingRule);\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/DownloadService.cs",
    "content": "using System.Net.Http.Headers;\n\nnamespace ServiceLib.Services;\n\n/// <summary>\n///Download\n/// </summary>\npublic class DownloadService\n{\n    public event EventHandler<UpdateResult>? UpdateCompleted;\n\n    public event ErrorEventHandler? Error;\n\n    private static readonly string _tag = \"DownloadService\";\n\n    public async Task<int> DownloadDataAsync(string url, WebProxy webProxy, int downloadTimeout, Func<bool, string, Task> updateFunc)\n    {\n        try\n        {\n            var progress = new Progress<string>();\n            progress.ProgressChanged += (sender, value) => updateFunc?.Invoke(false, $\"{value}\");\n\n            await DownloaderHelper.Instance.DownloadDataAsync4Speed(webProxy,\n                  url,\n                  progress,\n                  downloadTimeout);\n        }\n        catch (Exception ex)\n        {\n            await updateFunc?.Invoke(false, ex.Message);\n            if (ex.InnerException != null)\n            {\n                await updateFunc?.Invoke(false, ex.InnerException.Message);\n            }\n        }\n        return 0;\n    }\n\n    public async Task DownloadFileAsync(string url, string fileName, bool blProxy, int downloadTimeout)\n    {\n        try\n        {\n            UpdateCompleted?.Invoke(this, new UpdateResult(false, $\"{ResUI.Downloading}   {url}\"));\n\n            var progress = new Progress<double>();\n            progress.ProgressChanged += (sender, value) => UpdateCompleted?.Invoke(this, new UpdateResult(value > 100, $\"...{value}%\"));\n\n            var webProxy = await GetWebProxy(blProxy);\n            await DownloaderHelper.Instance.DownloadFileAsync(webProxy,\n                url,\n                fileName,\n                progress,\n                downloadTimeout);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n\n            Error?.Invoke(this, new ErrorEventArgs(ex));\n            if (ex.InnerException != null)\n            {\n                Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));\n            }\n        }\n    }\n\n    public async Task<string?> UrlRedirectAsync(string url, bool blProxy)\n    {\n        var webRequestHandler = new SocketsHttpHandler\n        {\n            AllowAutoRedirect = false,\n            Proxy = await GetWebProxy(blProxy)\n        };\n        var client = new HttpClient(webRequestHandler);\n\n        var response = await client.GetAsync(url);\n        if (response.StatusCode == HttpStatusCode.Redirect && response.Headers.Location is not null)\n        {\n            return response.Headers.Location.ToString();\n        }\n        else\n        {\n            Error?.Invoke(this, new ErrorEventArgs(new Exception(\"StatusCode error: \" + response.StatusCode)));\n            Logging.SaveLog(\"StatusCode error: \" + url);\n            return null;\n        }\n    }\n\n    public async Task<string?> TryDownloadString(string url, bool blProxy, string userAgent)\n    {\n        try\n        {\n            var result1 = await DownloadStringAsync(url, blProxy, userAgent, 15);\n            if (result1.IsNotEmpty())\n            {\n                return result1;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            Error?.Invoke(this, new ErrorEventArgs(ex));\n            if (ex.InnerException != null)\n            {\n                Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));\n            }\n        }\n\n        try\n        {\n            var result2 = await DownloadStringViaDownloader(url, blProxy, userAgent, 15);\n            if (result2.IsNotEmpty())\n            {\n                return result2;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            Error?.Invoke(this, new ErrorEventArgs(ex));\n            if (ex.InnerException != null)\n            {\n                Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));\n            }\n        }\n\n        return null;\n    }\n\n    /// <summary>\n    /// DownloadString\n    /// </summary>\n    /// <param name=\"url\"></param>\n    private async Task<string?> DownloadStringAsync(string url, bool blProxy, string userAgent, int timeout)\n    {\n        try\n        {\n            var webProxy = await GetWebProxy(blProxy);\n            var client = new HttpClient(new SocketsHttpHandler()\n            {\n                Proxy = webProxy,\n                UseProxy = webProxy != null\n            });\n\n            if (userAgent.IsNullOrEmpty())\n            {\n                userAgent = Utils.GetVersion(false);\n            }\n            client.DefaultRequestHeaders.UserAgent.TryParseAdd(userAgent);\n\n            Uri uri = new(url);\n            //Authorization Header\n            if (uri.UserInfo.IsNotEmpty())\n            {\n                client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(\"Basic\", Utils.Base64Encode(uri.UserInfo));\n            }\n\n            using var cts = new CancellationTokenSource();\n            var result = await client.GetStringAsync(url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);\n            return result;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            Error?.Invoke(this, new ErrorEventArgs(ex));\n            if (ex.InnerException != null)\n            {\n                Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));\n            }\n        }\n        return null;\n    }\n\n    /// <summary>\n    /// DownloadString\n    /// </summary>\n    /// <param name=\"url\"></param>\n    private async Task<string?> DownloadStringViaDownloader(string url, bool blProxy, string userAgent, int timeout)\n    {\n        try\n        {\n            var webProxy = await GetWebProxy(blProxy);\n\n            if (userAgent.IsNullOrEmpty())\n            {\n                userAgent = Utils.GetVersion(false);\n            }\n            var result = await DownloaderHelper.Instance.DownloadStringAsync(webProxy, url, userAgent, timeout);\n            return result;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            Error?.Invoke(this, new ErrorEventArgs(ex));\n            if (ex.InnerException != null)\n            {\n                Error?.Invoke(this, new ErrorEventArgs(ex.InnerException));\n            }\n        }\n        return null;\n    }\n\n    private async Task<WebProxy?> GetWebProxy(bool blProxy)\n    {\n        if (!blProxy)\n        {\n            return null;\n        }\n        var port = AppManager.Instance.GetLocalPort(EInboundProtocol.socks);\n        if (await SocketCheck(Global.Loopback, port) == false)\n        {\n            return null;\n        }\n\n        return new WebProxy($\"socks5://{Global.Loopback}:{port}\");\n    }\n\n    private async Task<bool> SocketCheck(string ip, int port)\n    {\n        try\n        {\n            IPEndPoint point = new(IPAddress.Parse(ip), port);\n            using Socket? sock = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);\n            await sock.ConnectAsync(point);\n            return true;\n        }\n        catch (Exception)\n        {\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/ProcessService.cs",
    "content": "namespace ServiceLib.Services;\n\npublic class ProcessService : IDisposable\n{\n    private readonly Process _process;\n    private readonly Func<bool, string, Task>? _updateFunc;\n    private bool _isDisposed;\n\n    public int Id => _process.Id;\n    public IntPtr Handle => _process.Handle;\n    public bool HasExited => _process.HasExited;\n\n    public ProcessService(\n        string fileName,\n        string arguments,\n        string workingDirectory,\n        bool displayLog,\n        bool redirectInput,\n        Dictionary<string, string>? environmentVars,\n        Func<bool, string, Task>? updateFunc)\n    {\n        _updateFunc = updateFunc;\n\n        _process = new Process\n        {\n            StartInfo = new ProcessStartInfo\n            {\n                FileName = fileName,\n                Arguments = arguments,\n                WorkingDirectory = workingDirectory,\n                UseShellExecute = false,\n                RedirectStandardInput = redirectInput,\n                RedirectStandardOutput = displayLog,\n                RedirectStandardError = displayLog,\n                CreateNoWindow = true,\n                StandardOutputEncoding = displayLog ? Encoding.UTF8 : null,\n                StandardErrorEncoding = displayLog ? Encoding.UTF8 : null,\n            },\n            EnableRaisingEvents = true\n        };\n\n        if (environmentVars != null)\n        {\n            foreach (var kv in environmentVars)\n            {\n                _process.StartInfo.Environment[kv.Key] = kv.Value;\n            }\n        }\n\n        if (displayLog)\n        {\n            RegisterEventHandlers();\n        }\n    }\n\n    public async Task StartAsync(string pwd = null)\n    {\n        _process.Start();\n\n        if (_process.StartInfo.RedirectStandardOutput)\n        {\n            _process.BeginOutputReadLine();\n            _process.BeginErrorReadLine();\n        }\n\n        if (_process.StartInfo.RedirectStandardInput)\n        {\n            await Task.Delay(10);\n            await _process.StandardInput.WriteLineAsync(pwd);\n        }\n    }\n\n    public async Task StopAsync()\n    {\n        if (_process.HasExited)\n        {\n            return;\n        }\n\n        try\n        {\n            if (_process.StartInfo.RedirectStandardOutput)\n            {\n                try\n                {\n                    _process.CancelOutputRead();\n                }\n                catch { }\n                try\n                {\n                    _process.CancelErrorRead();\n                }\n                catch { }\n            }\n\n            try\n            {\n                if (Utils.IsNonWindows())\n                {\n                    _process.Kill(true);\n                }\n            }\n            catch { }\n\n            try\n            {\n                _process.Kill();\n            }\n            catch { }\n\n            await Task.Delay(100);\n        }\n        catch (Exception ex)\n        {\n            await _updateFunc?.Invoke(true, ex.Message);\n        }\n    }\n\n    private void RegisterEventHandlers()\n    {\n        void dataHandler(object sender, DataReceivedEventArgs e)\n        {\n            if (e.Data.IsNotEmpty())\n            {\n                _ = _updateFunc?.Invoke(false, e.Data + Environment.NewLine);\n            }\n        }\n\n        _process.OutputDataReceived += dataHandler;\n        _process.ErrorDataReceived += dataHandler;\n\n        _process.Exited += (s, e) =>\n        {\n            try\n            {\n                _process.OutputDataReceived -= dataHandler;\n                _process.ErrorDataReceived -= dataHandler;\n            }\n            catch\n            {\n            }\n        };\n    }\n\n    public void Dispose()\n    {\n        if (_isDisposed)\n        {\n            return;\n        }\n\n        try\n        {\n            if (!_process.HasExited)\n            {\n                try\n                {\n                    _process.CancelOutputRead();\n                }\n                catch { }\n                try\n                {\n                    _process.CancelErrorRead();\n                }\n                catch { }\n\n                _process.Kill();\n            }\n\n            _process.Dispose();\n        }\n        catch (Exception ex)\n        {\n            _updateFunc?.Invoke(true, ex.Message);\n        }\n\n        _isDisposed = true;\n        GC.SuppressFinalize(this);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/SpeedtestService.cs",
    "content": "namespace ServiceLib.Services;\n\npublic class SpeedtestService(Config config, Func<SpeedTestResult, Task> updateFunc)\n{\n    private static readonly string _tag = \"SpeedtestService\";\n    private readonly Config? _config = config;\n    private readonly Func<SpeedTestResult, Task>? _updateFunc = updateFunc;\n    private static readonly ConcurrentBag<string> _lstExitLoop = new();\n\n    public void RunLoop(ESpeedActionType actionType, List<ProfileItem> selecteds)\n    {\n        Task.Run(async () =>\n        {\n            await RunAsync(actionType, selecteds);\n            await ProfileExManager.Instance.SaveTo();\n            await UpdateFunc(\"\", ResUI.SpeedtestingCompleted);\n        });\n    }\n\n    public void ExitLoop()\n    {\n        if (!_lstExitLoop.IsEmpty)\n        {\n            _ = UpdateFunc(\"\", ResUI.SpeedtestingStop);\n\n            _lstExitLoop.Clear();\n        }\n    }\n\n    private static bool ShouldStopTest(string exitLoopKey)\n    {\n        return !_lstExitLoop.Any(p => p == exitLoopKey);\n    }\n\n    private async Task RunAsync(ESpeedActionType actionType, List<ProfileItem> selecteds)\n    {\n        var exitLoopKey = Utils.GetGuid(false);\n        _lstExitLoop.Add(exitLoopKey);\n\n        var lstSelected = await GetClearItem(actionType, selecteds);\n\n        switch (actionType)\n        {\n            case ESpeedActionType.Tcping:\n                await RunTcpingAsync(lstSelected);\n                break;\n\n            case ESpeedActionType.Realping:\n                await RunRealPingBatchAsync(lstSelected, exitLoopKey);\n                break;\n\n            case ESpeedActionType.Speedtest:\n                await RunMixedTestAsync(lstSelected, 1, true, exitLoopKey);\n                break;\n\n            case ESpeedActionType.Mixedtest:\n                await RunMixedTestAsync(lstSelected, _config.SpeedTestItem.MixedConcurrencyCount, true, exitLoopKey);\n                break;\n        }\n    }\n\n    private async Task<List<ServerTestItem>> GetClearItem(ESpeedActionType actionType, List<ProfileItem> selecteds)\n    {\n        var lstSelected = new List<ServerTestItem>(selecteds.Count);\n        var ids = selecteds.Where(it => !it.IndexId.IsNullOrEmpty()\n            && it.ConfigType != EConfigType.Custom\n            && (it.ConfigType.IsComplexType() || it.Port > 0))\n            .Select(it => it.IndexId)\n            .ToList();\n        var profileMap = await AppManager.Instance.GetProfileItemsByIndexIdsAsMap(ids);\n        for (var i = 0; i < selecteds.Count; i++)\n        {\n            var it = selecteds[i];\n            if (it.ConfigType == EConfigType.Custom)\n            {\n                continue;\n            }\n\n            if (!it.ConfigType.IsComplexType() && it.Port <= 0)\n            {\n                continue;\n            }\n\n            var profile = profileMap.GetValueOrDefault(it.IndexId, it);\n            lstSelected.Add(new ServerTestItem()\n            {\n                IndexId = it.IndexId,\n                Address = it.Address,\n                Port = it.Port,\n                ConfigType = it.ConfigType,\n                QueueNum = i,\n                Profile = profile,\n                CoreType = AppManager.Instance.GetCoreType(profile, it.ConfigType),\n            });\n        }\n\n        //clear test result\n        foreach (var it in lstSelected)\n        {\n            switch (actionType)\n            {\n                case ESpeedActionType.Tcping:\n                case ESpeedActionType.Realping:\n                    await UpdateFunc(it.IndexId, ResUI.Speedtesting, \"\");\n                    ProfileExManager.Instance.SetTestDelay(it.IndexId, 0);\n                    break;\n\n                case ESpeedActionType.Speedtest:\n                    await UpdateFunc(it.IndexId, \"\", ResUI.SpeedtestingWait);\n                    ProfileExManager.Instance.SetTestSpeed(it.IndexId, 0);\n                    break;\n\n                case ESpeedActionType.Mixedtest:\n                    await UpdateFunc(it.IndexId, ResUI.Speedtesting, ResUI.SpeedtestingWait);\n                    ProfileExManager.Instance.SetTestDelay(it.IndexId, 0);\n                    ProfileExManager.Instance.SetTestSpeed(it.IndexId, 0);\n                    break;\n            }\n        }\n\n        if (lstSelected.Count > 1 && (actionType == ESpeedActionType.Speedtest || actionType == ESpeedActionType.Mixedtest))\n        {\n            NoticeManager.Instance.Enqueue(ResUI.SpeedtestingPressEscToExit);\n        }\n\n        return lstSelected;\n    }\n\n    private async Task RunTcpingAsync(List<ServerTestItem> selecteds)\n    {\n        List<Task> tasks = [];\n        foreach (var it in selecteds)\n        {\n            tasks.Add(Task.Run(async () =>\n            {\n                try\n                {\n                    var responseTime = await GetTcpingTime(it.Address, it.Port);\n\n                    ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);\n                    await UpdateFunc(it.IndexId, responseTime.ToString());\n                }\n                catch (Exception ex)\n                {\n                    Logging.SaveLog(_tag, ex);\n                }\n            }));\n        }\n        await Task.WhenAll(tasks);\n    }\n\n    private async Task RunRealPingBatchAsync(List<ServerTestItem> lstSelected, string exitLoopKey, int pageSize = 0)\n    {\n        if (pageSize <= 0)\n        {\n            pageSize = lstSelected.Count < Global.SpeedTestPageSize ? lstSelected.Count : Global.SpeedTestPageSize;\n        }\n        var lstTest = GetTestBatchItem(lstSelected, pageSize);\n\n        List<ServerTestItem> lstFailed = new();\n        foreach (var lst in lstTest)\n        {\n            var ret = await RunRealPingAsync(lst, exitLoopKey);\n            if (ret == false)\n            {\n                lstFailed.AddRange(lst);\n            }\n            await Task.Delay(100);\n        }\n\n        //Retest the failed part\n        var pageSizeNext = pageSize / 2;\n        if (lstFailed.Count > 0 && pageSizeNext > 0)\n        {\n            if (ShouldStopTest(exitLoopKey))\n            {\n                await UpdateFunc(\"\", ResUI.SpeedtestingSkip);\n                return;\n            }\n\n            await UpdateFunc(\"\", string.Format(ResUI.SpeedtestingTestFailedPart, lstFailed.Count));\n\n            if (pageSizeNext > _config.SpeedTestItem.MixedConcurrencyCount)\n            {\n                await RunRealPingBatchAsync(lstFailed, exitLoopKey, pageSizeNext);\n            }\n            else\n            {\n                await RunMixedTestAsync(lstSelected, _config.SpeedTestItem.MixedConcurrencyCount, false, exitLoopKey);\n            }\n        }\n    }\n\n    private async Task<bool> RunRealPingAsync(List<ServerTestItem> selecteds, string exitLoopKey)\n    {\n        ProcessService processService = null;\n        try\n        {\n            processService = await CoreManager.Instance.LoadCoreConfigSpeedtest(selecteds);\n            if (processService is null)\n            {\n                return false;\n            }\n            await Task.Delay(1000);\n\n            List<Task> tasks = new();\n            foreach (var it in selecteds)\n            {\n                if (!it.AllowTest)\n                {\n                    await UpdateFunc(it.IndexId, ResUI.SpeedtestingSkip);\n                    continue;\n                }\n\n                if (ShouldStopTest(exitLoopKey))\n                {\n                    return false;\n                }\n\n                tasks.Add(Task.Run(async () =>\n                {\n                    await DoRealPing(it);\n                }));\n            }\n            await Task.WhenAll(tasks);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        finally\n        {\n            if (processService != null)\n            {\n                await processService?.StopAsync();\n            }\n        }\n        return true;\n    }\n\n    private async Task RunMixedTestAsync(List<ServerTestItem> selecteds, int concurrencyCount, bool blSpeedTest, string exitLoopKey)\n    {\n        using var concurrencySemaphore = new SemaphoreSlim(concurrencyCount);\n        var downloadHandle = new DownloadService();\n        List<Task> tasks = new();\n        foreach (var it in selecteds)\n        {\n            if (ShouldStopTest(exitLoopKey))\n            {\n                await UpdateFunc(it.IndexId, \"\", ResUI.SpeedtestingSkip);\n                continue;\n            }\n            await concurrencySemaphore.WaitAsync();\n\n            tasks.Add(Task.Run(async () =>\n            {\n                ProcessService processService = null;\n                try\n                {\n                    processService = await CoreManager.Instance.LoadCoreConfigSpeedtest(it);\n                    if (processService is null)\n                    {\n                        await UpdateFunc(it.IndexId, \"\", ResUI.FailedToRunCore);\n                        return;\n                    }\n\n                    await Task.Delay(1000);\n\n                    var delay = await DoRealPing(it);\n                    if (blSpeedTest)\n                    {\n                        if (ShouldStopTest(exitLoopKey))\n                        {\n                            await UpdateFunc(it.IndexId, \"\", ResUI.SpeedtestingSkip);\n                            return;\n                        }\n\n                        if (delay > 0)\n                        {\n                            await DoSpeedTest(downloadHandle, it);\n                        }\n                        else\n                        {\n                            await UpdateFunc(it.IndexId, \"\", ResUI.SpeedtestingSkip);\n                        }\n                    }\n                }\n                catch (Exception ex)\n                {\n                    Logging.SaveLog(_tag, ex);\n                }\n                finally\n                {\n                    if (processService != null)\n                    {\n                        await processService?.StopAsync();\n                    }\n                    concurrencySemaphore.Release();\n                }\n            }));\n        }\n        await Task.WhenAll(tasks);\n    }\n\n    private async Task<int> DoRealPing(ServerTestItem it)\n    {\n        var webProxy = new WebProxy($\"socks5://{Global.Loopback}:{it.Port}\");\n        var responseTime = await ConnectionHandler.GetRealPingTime(_config.SpeedTestItem.SpeedPingTestUrl, webProxy, 10);\n\n        ProfileExManager.Instance.SetTestDelay(it.IndexId, responseTime);\n        await UpdateFunc(it.IndexId, responseTime.ToString());\n        return responseTime;\n    }\n\n    private async Task DoSpeedTest(DownloadService downloadHandle, ServerTestItem it)\n    {\n        await UpdateFunc(it.IndexId, \"\", ResUI.Speedtesting);\n\n        var webProxy = new WebProxy($\"socks5://{Global.Loopback}:{it.Port}\");\n        var url = _config.SpeedTestItem.SpeedTestUrl;\n        var timeout = _config.SpeedTestItem.SpeedTestTimeout;\n        await downloadHandle.DownloadDataAsync(url, webProxy, timeout, async (success, msg) =>\n        {\n            decimal.TryParse(msg, out var dec);\n            if (dec > 0)\n            {\n                ProfileExManager.Instance.SetTestSpeed(it.IndexId, dec);\n            }\n            await UpdateFunc(it.IndexId, \"\", msg);\n        });\n    }\n\n    private async Task<int> GetTcpingTime(string url, int port)\n    {\n        var responseTime = -1;\n\n        if (!IPAddress.TryParse(url, out var ipAddress))\n        {\n            var ipHostInfo = await Dns.GetHostEntryAsync(url);\n            ipAddress = ipHostInfo.AddressList.First();\n        }\n\n        IPEndPoint endPoint = new(ipAddress, port);\n        using Socket clientSocket = new(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);\n\n        var timer = Stopwatch.StartNew();\n        try\n        {\n            using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));\n            await clientSocket.ConnectAsync(endPoint, cts.Token).ConfigureAwait(false);\n            responseTime = (int)timer.ElapsedMilliseconds;\n        }\n        catch (OperationCanceledException)\n        {\n        }\n        finally\n        {\n            timer.Stop();\n        }\n        return responseTime;\n    }\n\n    private List<List<ServerTestItem>> GetTestBatchItem(List<ServerTestItem> lstSelected, int pageSize)\n    {\n        List<List<ServerTestItem>> lstTest = new();\n        var lst1 = lstSelected.Where(t => t.CoreType == ECoreType.Xray).ToList();\n        var lst2 = lstSelected.Where(t => t.CoreType == ECoreType.sing_box).ToList();\n\n        for (var num = 0; num < (int)Math.Ceiling(lst1.Count * 1.0 / pageSize); num++)\n        {\n            lstTest.Add(lst1.Skip(num * pageSize).Take(pageSize).ToList());\n        }\n        for (var num = 0; num < (int)Math.Ceiling(lst2.Count * 1.0 / pageSize); num++)\n        {\n            lstTest.Add(lst2.Skip(num * pageSize).Take(pageSize).ToList());\n        }\n\n        return lstTest;\n    }\n\n    private async Task UpdateFunc(string indexId, string delay, string speed = \"\")\n    {\n        await _updateFunc?.Invoke(new() { IndexId = indexId, Delay = delay, Speed = speed });\n        if (indexId.IsNotEmpty() && speed.IsNotEmpty())\n        {\n            ProfileExManager.Instance.SetTestMessage(indexId, speed);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/Statistics/StatisticsSingboxService.cs",
    "content": "using System.Net.WebSockets;\n\nnamespace ServiceLib.Services.Statistics;\n\npublic class StatisticsSingboxService\n{\n    private readonly Config _config;\n    private bool _exitFlag;\n    private ClientWebSocket? webSocket;\n    private readonly Func<ServerSpeedItem, Task>? _updateFunc;\n    private string Url => $\"ws://{Global.Loopback}:{AppManager.Instance.StatePort2}/traffic\";\n    private static readonly string _tag = \"StatisticsSingboxService\";\n\n    public StatisticsSingboxService(Config config, Func<ServerSpeedItem, Task> updateFunc)\n    {\n        _config = config;\n        _updateFunc = updateFunc;\n        _exitFlag = false;\n\n        _ = Task.Run(Run);\n    }\n\n    private async Task Init()\n    {\n        await Task.Delay(5000);\n\n        try\n        {\n            if (webSocket == null)\n            {\n                webSocket = new ClientWebSocket();\n                await webSocket.ConnectAsync(new Uri(Url), CancellationToken.None);\n            }\n        }\n        catch { }\n    }\n\n    public void Close()\n    {\n        try\n        {\n            _exitFlag = true;\n            if (webSocket != null)\n            {\n                webSocket.Abort();\n                webSocket = null;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private async Task Run()\n    {\n        await Init();\n\n        while (!_exitFlag)\n        {\n            await Task.Delay(1000);\n            try\n            {\n                if (!AppManager.Instance.IsRunningCore(ECoreType.sing_box))\n                {\n                    continue;\n                }\n                if (webSocket != null)\n                {\n                    if (webSocket.State is WebSocketState.Aborted or WebSocketState.Closed)\n                    {\n                        webSocket.Abort();\n                        webSocket = null;\n                        await Init();\n                        continue;\n                    }\n\n                    if (webSocket.State != WebSocketState.Open)\n                    {\n                        continue;\n                    }\n\n                    var buffer = new byte[1024];\n                    var res = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);\n                    while (!res.CloseStatus.HasValue)\n                    {\n                        var result = Encoding.UTF8.GetString(buffer, 0, res.Count);\n                        if (result.IsNotEmpty())\n                        {\n                            ParseOutput(result, out var up, out var down);\n\n                            await _updateFunc?.Invoke(new ServerSpeedItem()\n                            {\n                                ProxyUp = (long)(up / 1000),\n                                ProxyDown = (long)(down / 1000)\n                            });\n                        }\n                        res = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);\n                    }\n                }\n            }\n            catch\n            {\n            }\n        }\n    }\n\n    private void ParseOutput(string source, out ulong up, out ulong down)\n    {\n        up = 0;\n        down = 0;\n        try\n        {\n            var trafficItem = JsonUtils.Deserialize<TrafficItem>(source);\n            if (trafficItem != null)\n            {\n                up = trafficItem.Up;\n                down = trafficItem.Down;\n            }\n        }\n        catch\n        {\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/Statistics/StatisticsXrayService.cs",
    "content": "namespace ServiceLib.Services.Statistics;\n\npublic class StatisticsXrayService\n{\n    private const long linkBase = 1024;\n    private ServerSpeedItem _serverSpeedItem = new();\n    private readonly Config _config;\n    private bool _exitFlag;\n    private readonly Func<ServerSpeedItem, Task>? _updateFunc;\n    private string Url => $\"{Global.HttpProtocol}{Global.Loopback}:{AppManager.Instance.StatePort}/debug/vars\";\n\n    public StatisticsXrayService(Config config, Func<ServerSpeedItem, Task> updateFunc)\n    {\n        _config = config;\n        _updateFunc = updateFunc;\n        _exitFlag = false;\n\n        _ = Task.Run(Run);\n    }\n\n    public void Close()\n    {\n        _exitFlag = true;\n    }\n\n    private async Task Run()\n    {\n        while (!_exitFlag)\n        {\n            await Task.Delay(1000);\n            try\n            {\n                if (AppManager.Instance.RunningCoreType != ECoreType.Xray)\n                {\n                    continue;\n                }\n\n                var result = await HttpClientHelper.Instance.TryGetAsync(Url);\n                if (result != null)\n                {\n                    var server = ParseOutput(result) ?? new ServerSpeedItem();\n                    await _updateFunc?.Invoke(server);\n                }\n            }\n            catch\n            {\n                // ignored\n            }\n        }\n    }\n\n    private ServerSpeedItem? ParseOutput(string result)\n    {\n        try\n        {\n            var source = JsonUtils.Deserialize<V2rayMetricsVars>(result);\n            if (source?.stats?.outbound == null)\n            {\n                return null;\n            }\n\n            ServerSpeedItem server = new();\n            foreach (var key in source.stats.outbound.Keys.Cast<string>())\n            {\n                var value = source.stats.outbound[key];\n                if (value == null)\n                {\n                    continue;\n                }\n                var state = JsonUtils.Deserialize<V2rayMetricsVarsLink>(value.ToString());\n\n                if (key.StartsWith(Global.ProxyTag))\n                {\n                    server.ProxyUp += state.uplink / linkBase;\n                    server.ProxyDown += state.downlink / linkBase;\n                }\n                else if (key == Global.DirectTag)\n                {\n                    server.DirectUp = state.uplink / linkBase;\n                    server.DirectDown = state.downlink / linkBase;\n                }\n            }\n\n            if (server.DirectDown < _serverSpeedItem.DirectDown || server.ProxyDown < _serverSpeedItem.ProxyDown)\n            {\n                _serverSpeedItem = new();\n                return null;\n            }\n\n            ServerSpeedItem curItem = new()\n            {\n                ProxyUp = server.ProxyUp - _serverSpeedItem.ProxyUp,\n                ProxyDown = server.ProxyDown - _serverSpeedItem.ProxyDown,\n                DirectUp = server.DirectUp - _serverSpeedItem.DirectUp,\n                DirectDown = server.DirectDown - _serverSpeedItem.DirectDown,\n            };\n            _serverSpeedItem = server;\n            return curItem;\n        }\n        catch\n        {\n            // ignored\n        }\n\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/UpdateService.cs",
    "content": "namespace ServiceLib.Services;\n\npublic class UpdateService(Config config, Func<bool, string, Task> updateFunc)\n{\n    private readonly Config? _config = config;\n    private readonly Func<bool, string, Task>? _updateFunc = updateFunc;\n    private readonly int _timeout = 30;\n    private static readonly string _tag = \"UpdateService\";\n\n    public async Task CheckUpdateGuiN(bool preRelease)\n    {\n        var url = string.Empty;\n        var fileName = string.Empty;\n\n        DownloadService downloadHandle = new();\n        downloadHandle.UpdateCompleted += (sender2, args) =>\n        {\n            if (args.Success)\n            {\n                _ = UpdateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);\n                _ = UpdateFunc(true, Utils.UrlEncode(fileName));\n            }\n            else\n            {\n                _ = UpdateFunc(false, args.Msg);\n            }\n        };\n        downloadHandle.Error += (sender2, args) =>\n        {\n            _ = UpdateFunc(false, args.GetException().Message);\n        };\n\n        await UpdateFunc(false, string.Format(ResUI.MsgStartUpdating, ECoreType.v2rayN));\n        var result = await CheckUpdateAsync(downloadHandle, ECoreType.v2rayN, preRelease);\n        if (result.Success)\n        {\n            await UpdateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, ECoreType.v2rayN));\n            await UpdateFunc(false, result.Msg);\n\n            url = result.Url.ToString();\n            fileName = Utils.GetTempPath(Utils.GetGuid());\n            await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout);\n        }\n        else\n        {\n            await UpdateFunc(false, result.Msg);\n        }\n    }\n\n    public async Task CheckUpdateCore(ECoreType type, bool preRelease)\n    {\n        var url = string.Empty;\n        var fileName = string.Empty;\n\n        DownloadService downloadHandle = new();\n        downloadHandle.UpdateCompleted += (sender2, args) =>\n        {\n            if (args.Success)\n            {\n                _ = UpdateFunc(false, ResUI.MsgDownloadV2rayCoreSuccessfully);\n                _ = UpdateFunc(false, ResUI.MsgUnpacking);\n\n                try\n                {\n                    _ = UpdateFunc(true, fileName);\n                }\n                catch (Exception ex)\n                {\n                    _ = UpdateFunc(false, ex.Message);\n                }\n            }\n            else\n            {\n                _ = UpdateFunc(false, args.Msg);\n            }\n        };\n        downloadHandle.Error += (sender2, args) =>\n        {\n            _ = UpdateFunc(false, args.GetException().Message);\n        };\n\n        await UpdateFunc(false, string.Format(ResUI.MsgStartUpdating, type));\n        var result = await CheckUpdateAsync(downloadHandle, type, preRelease);\n        if (result.Success)\n        {\n            await UpdateFunc(false, string.Format(ResUI.MsgParsingSuccessfully, type));\n            await UpdateFunc(false, result.Msg);\n\n            url = result.Url.ToString();\n            var ext = url.Contains(\".tar.gz\") ? \".tar.gz\" : Path.GetExtension(url);\n            fileName = Utils.GetTempPath(Utils.GetGuid() + ext);\n            await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout);\n        }\n        else\n        {\n            if (!result.Msg.IsNullOrEmpty())\n            {\n                await UpdateFunc(false, result.Msg);\n            }\n        }\n    }\n\n    public async Task UpdateGeoFileAll()\n    {\n        await UpdateGeoFiles();\n        await UpdateOtherFiles();\n        await UpdateSrsFileAll();\n        await UpdateFunc(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, \"geo\"));\n    }\n\n    #region CheckUpdate private\n\n    private async Task<UpdateResult> CheckUpdateAsync(DownloadService downloadHandle, ECoreType type, bool preRelease)\n    {\n        try\n        {\n            var result = await GetRemoteVersion(downloadHandle, type, preRelease);\n            if (!result.Success || result.Version is null)\n            {\n                return result;\n            }\n            return await ParseDownloadUrl(type, result);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            await UpdateFunc(false, ex.Message);\n            return new UpdateResult(false, ex.Message);\n        }\n    }\n\n    private async Task<UpdateResult> GetRemoteVersion(DownloadService downloadHandle, ECoreType type, bool preRelease)\n    {\n        var coreInfo = CoreInfoManager.Instance.GetCoreInfo(type);\n        var tagName = string.Empty;\n        if (preRelease)\n        {\n            var url = coreInfo?.ReleaseApiUrl;\n            var result = await downloadHandle.TryDownloadString(url, true, Global.AppName);\n            if (result.IsNullOrEmpty())\n            {\n                return new UpdateResult(false, \"\");\n            }\n\n            var gitHubReleases = JsonUtils.Deserialize<List<GitHubRelease>>(result);\n            var gitHubRelease = preRelease ? gitHubReleases?.First() : gitHubReleases?.First(r => r.Prerelease == false);\n            tagName = gitHubRelease?.TagName;\n            //var body = gitHubRelease?.Body;\n        }\n        else\n        {\n            var url = Path.Combine(coreInfo.Url, \"latest\");\n            var lastUrl = await downloadHandle.UrlRedirectAsync(url, true);\n            if (lastUrl == null)\n            {\n                return new UpdateResult(false, \"\");\n            }\n\n            tagName = lastUrl?.Split(\"/tag/\").LastOrDefault();\n        }\n        return new UpdateResult(true, new SemanticVersion(tagName));\n    }\n\n    private async Task<SemanticVersion> GetCoreVersion(ECoreType type)\n    {\n        try\n        {\n            var coreInfo = CoreInfoManager.Instance.GetCoreInfo(type);\n            var filePath = string.Empty;\n            foreach (var name in coreInfo.CoreExes)\n            {\n                var vName = Utils.GetBinPath(Utils.GetExeName(name), coreInfo.CoreType.ToString());\n                if (File.Exists(vName))\n                {\n                    filePath = vName;\n                    break;\n                }\n            }\n\n            if (!File.Exists(filePath))\n            {\n                var msg = string.Format(ResUI.NotFoundCore, @\"\", \"\", \"\");\n                //ShowMsg(true, msg);\n                return new SemanticVersion(\"\");\n            }\n\n            var result = await Utils.GetCliWrapOutput(filePath, coreInfo.VersionArg);\n            var echo = result ?? \"\";\n            var version = string.Empty;\n            switch (type)\n            {\n                case ECoreType.v2fly:\n                case ECoreType.Xray:\n                case ECoreType.v2fly_v5:\n                    version = Regex.Match(echo, $\"{coreInfo.Match} ([0-9.]+) \\\\(\").Groups[1].Value;\n                    break;\n\n                case ECoreType.mihomo:\n                    version = Regex.Match(echo, $\"v[0-9.]+\").Groups[0].Value;\n                    break;\n\n                case ECoreType.sing_box:\n                    version = Regex.Match(echo, $\"([0-9.]+)\").Groups[1].Value;\n                    break;\n            }\n            return new SemanticVersion(version);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            await UpdateFunc(false, ex.Message);\n            return new SemanticVersion(\"\");\n        }\n    }\n\n    private async Task<UpdateResult> ParseDownloadUrl(ECoreType type, UpdateResult result)\n    {\n        try\n        {\n            var version = result.Version ?? new SemanticVersion(0, 0, 0);\n            var coreInfo = CoreInfoManager.Instance.GetCoreInfo(type);\n            var coreUrl = await GetUrlFromCore(coreInfo) ?? string.Empty;\n            SemanticVersion curVersion;\n            string message;\n            string? url;\n            switch (type)\n            {\n                case ECoreType.v2fly:\n                case ECoreType.Xray:\n                case ECoreType.v2fly_v5:\n                    {\n                        curVersion = await GetCoreVersion(type);\n                        message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString(\"v\"));\n                        url = string.Format(coreUrl, version.ToVersionString(\"v\"));\n                        break;\n                    }\n                case ECoreType.mihomo:\n                    {\n                        curVersion = await GetCoreVersion(type);\n                        message = string.Format(ResUI.IsLatestCore, type, curVersion);\n                        url = string.Format(coreUrl, version.ToVersionString(\"v\"));\n                        break;\n                    }\n                case ECoreType.sing_box:\n                    {\n                        curVersion = await GetCoreVersion(type);\n                        message = string.Format(ResUI.IsLatestCore, type, curVersion.ToVersionString(\"v\"));\n                        url = string.Format(coreUrl, version.ToVersionString(\"v\"), version);\n                        break;\n                    }\n                case ECoreType.v2rayN:\n                    {\n                        curVersion = new SemanticVersion(Utils.GetVersionInfo());\n                        message = string.Format(ResUI.IsLatestN, type, curVersion);\n                        url = string.Format(coreUrl, version);\n                        break;\n                    }\n                default:\n                    throw new ArgumentException(\"Type\");\n            }\n\n            if (curVersion >= version && version != new SemanticVersion(0, 0, 0))\n            {\n                return new UpdateResult(false, message);\n            }\n\n            result.Url = url;\n            return result;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            await UpdateFunc(false, ex.Message);\n            return new UpdateResult(false, ex.Message);\n        }\n    }\n\n    private async Task<string?> GetUrlFromCore(CoreInfo? coreInfo)\n    {\n        if (Utils.IsWindows())\n        {\n            var url = RuntimeInformation.ProcessArchitecture switch\n            {\n                Architecture.Arm64 => coreInfo?.DownloadUrlWinArm64,\n                Architecture.X64 => coreInfo?.DownloadUrlWin64,\n                _ => null,\n            };\n\n            if (coreInfo?.CoreType != ECoreType.v2rayN)\n            {\n                return url;\n            }\n\n            //Check for avalonia desktop windows version\n            if (File.Exists(Path.Combine(Utils.GetBaseDirectory(), \"libHarfBuzzSharp.dll\")))\n            {\n                return url?.Replace(\".zip\", \"-desktop.zip\");\n            }\n\n            return url;\n        }\n        else if (Utils.IsLinux())\n        {\n            return RuntimeInformation.ProcessArchitecture switch\n            {\n                Architecture.Arm64 => coreInfo?.DownloadUrlLinuxArm64,\n                Architecture.X64 => coreInfo?.DownloadUrlLinux64,\n                _ => null,\n            };\n        }\n        else if (Utils.IsMacOS())\n        {\n            return RuntimeInformation.ProcessArchitecture switch\n            {\n                Architecture.Arm64 => coreInfo?.DownloadUrlOSXArm64,\n                Architecture.X64 => coreInfo?.DownloadUrlOSX64,\n                _ => null,\n            };\n        }\n        return await Task.FromResult(\"\");\n    }\n\n    #endregion CheckUpdate private\n\n    #region Geo private\n\n    private async Task UpdateGeoFiles()\n    {\n        var geoUrl = string.IsNullOrEmpty(_config?.ConstItem.GeoSourceUrl)\n            ? Global.GeoUrl\n            : _config.ConstItem.GeoSourceUrl;\n\n        List<string> files = [\"geosite\", \"geoip\"];\n        foreach (var geoName in files)\n        {\n            var fileName = $\"{geoName}.dat\";\n            var targetPath = Utils.GetBinPath($\"{fileName}\");\n            var url = string.Format(geoUrl, geoName);\n\n            await DownloadGeoFile(url, fileName, targetPath);\n        }\n    }\n\n    private async Task UpdateOtherFiles()\n    {\n        //If it is not in China area, no update is required\n        if (_config.ConstItem.GeoSourceUrl.IsNotEmpty())\n        {\n            return;\n        }\n\n        foreach (var url in Global.OtherGeoUrls)\n        {\n            var fileName = Path.GetFileName(url);\n            var targetPath = Utils.GetBinPath($\"{fileName}\");\n\n            await DownloadGeoFile(url, fileName, targetPath);\n        }\n    }\n\n    private async Task UpdateSrsFileAll()\n    {\n        var geoipFiles = new List<string>();\n        var geoSiteFiles = new List<string>();\n\n        // Collect from routing rules\n        var routingItems = await AppManager.Instance.RoutingItems();\n        foreach (var routing in routingItems)\n        {\n            var rules = JsonUtils.Deserialize<List<RulesItem>>(routing.RuleSet);\n            foreach (var item in rules ?? [])\n            {\n                AddPrefixedItems(item.Ip, \"geoip:\", geoipFiles);\n                AddPrefixedItems(item.Domain, \"geosite:\", geoSiteFiles);\n            }\n        }\n\n        // Collect from DNS configuration\n        var dnsItem = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);\n        if (dnsItem != null)\n        {\n            ExtractDnsRuleSets(dnsItem.NormalDNS, geoipFiles, geoSiteFiles);\n            ExtractDnsRuleSets(dnsItem.TunDNS, geoipFiles, geoSiteFiles);\n        }\n\n        // Append default items\n        geoSiteFiles.AddRange([\"google\", \"cn\", \"geolocation-cn\", \"category-ads-all\"]);\n\n        // Download files\n        var path = Utils.GetBinPath(\"srss\");\n        if (!Directory.Exists(path))\n        {\n            Directory.CreateDirectory(path);\n        }\n\n        foreach (var item in geoipFiles.Distinct())\n        {\n            await UpdateSrsFile(\"geoip\", item);\n        }\n\n        foreach (var item in geoSiteFiles.Distinct())\n        {\n            await UpdateSrsFile(\"geosite\", item);\n        }\n    }\n\n    private void AddPrefixedItems(List<string>? items, string prefix, List<string> output)\n    {\n        if (items == null)\n        {\n            return;\n        }\n\n        foreach (var item in items)\n        {\n            if (item.StartsWith(prefix))\n            {\n                output.Add(item.Substring(prefix.Length));\n            }\n        }\n    }\n\n    private void ExtractDnsRuleSets(string? dnsJson, List<string> geoipFiles, List<string> geoSiteFiles)\n    {\n        if (string.IsNullOrEmpty(dnsJson))\n        {\n            return;\n        }\n\n        try\n        {\n            var dns = JsonUtils.Deserialize<Dns4Sbox>(dnsJson);\n            if (dns?.rules != null)\n            {\n                foreach (var rule in dns.rules)\n                {\n                    ExtractSrsRuleSets(rule, geoipFiles, geoSiteFiles);\n                }\n            }\n        }\n        catch { }\n    }\n\n    private void ExtractSrsRuleSets(Rule4Sbox? rule, List<string> geoipFiles, List<string> geoSiteFiles)\n    {\n        if (rule == null)\n        {\n            return;\n        }\n\n        AddPrefixedItems(rule.rule_set, \"geosite-\", geoSiteFiles);\n        AddPrefixedItems(rule.rule_set, \"geoip-\", geoipFiles);\n\n        // Handle nested rules recursively\n        if (rule.rules != null)\n        {\n            foreach (var nestedRule in rule.rules)\n            {\n                ExtractSrsRuleSets(nestedRule, geoipFiles, geoSiteFiles);\n            }\n        }\n    }\n\n    private async Task UpdateSrsFile(string type, string srsName)\n    {\n        var srsUrl = string.IsNullOrEmpty(_config.ConstItem.SrsSourceUrl)\n                        ? Global.SingboxRulesetUrl\n                        : _config.ConstItem.SrsSourceUrl;\n\n        var fileName = $\"{type}-{srsName}.srs\";\n        var targetPath = Path.Combine(Utils.GetBinPath(\"srss\"), fileName);\n        var url = string.Format(srsUrl, type, $\"{type}-{srsName}\", srsName);\n\n        await DownloadGeoFile(url, fileName, targetPath);\n    }\n\n    private async Task DownloadGeoFile(string url, string fileName, string targetPath)\n    {\n        var tmpFileName = Utils.GetTempPath(Utils.GetGuid());\n\n        DownloadService downloadHandle = new();\n        downloadHandle.UpdateCompleted += (sender2, args) =>\n        {\n            if (args.Success)\n            {\n                _ = UpdateFunc(false, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, fileName));\n\n                try\n                {\n                    if (File.Exists(tmpFileName))\n                    {\n                        File.Copy(tmpFileName, targetPath, true);\n\n                        File.Delete(tmpFileName);\n                        //await    UpdateFunc(true, \"\");\n                    }\n                }\n                catch (Exception ex)\n                {\n                    _ = UpdateFunc(false, ex.Message);\n                }\n            }\n            else\n            {\n                _ = UpdateFunc(false, args.Msg);\n            }\n        };\n        downloadHandle.Error += (sender2, args) =>\n        {\n            _ = UpdateFunc(false, args.GetException().Message);\n        };\n\n        await downloadHandle.DownloadFileAsync(url, tmpFileName, true, _timeout);\n    }\n\n    #endregion Geo private\n\n    private async Task UpdateFunc(bool notify, string msg)\n    {\n        await _updateFunc?.Invoke(notify, msg);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/Services/WindowsJobService.cs",
    "content": "namespace ServiceLib.Services;\n\n/// <summary>\n/// http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net\n/// </summary>\npublic sealed class WindowsJobService : IDisposable\n{\n    private nint handle = nint.Zero;\n\n    public WindowsJobService()\n    {\n        handle = CreateJobObject(nint.Zero, null);\n        var extendedInfoPtr = nint.Zero;\n        var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION\n        {\n            LimitFlags = 0x2000\n        };\n\n        var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION\n        {\n            BasicLimitInformation = info\n        };\n\n        try\n        {\n            var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));\n            extendedInfoPtr = Marshal.AllocHGlobal(length);\n            Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);\n\n            if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,\n                    (uint)length))\n            {\n                throw new Exception(string.Format(\"Unable to set information.  Error: {0}\",\n                    Marshal.GetLastWin32Error()));\n            }\n        }\n        finally\n        {\n            if (extendedInfoPtr != nint.Zero)\n            {\n                Marshal.FreeHGlobal(extendedInfoPtr);\n            }\n        }\n    }\n\n    public bool AddProcess(nint processHandle)\n    {\n        var succ = AssignProcessToJobObject(handle, processHandle);\n\n        if (!succ)\n        {\n            Logging.SaveLog(\"Failed to call AssignProcessToJobObject! GetLastError=\" + Marshal.GetLastWin32Error());\n        }\n\n        return succ;\n    }\n\n    public bool AddProcess(int processId)\n    {\n        return AddProcess(Process.GetProcessById(processId).Handle);\n    }\n\n    #region IDisposable\n\n    private bool disposed;\n\n    public void Dispose()\n    {\n        Dispose(true);\n        GC.SuppressFinalize(this);\n    }\n\n    private void Dispose(bool disposing)\n    {\n        if (disposed)\n        {\n            return;\n        }\n        disposed = true;\n\n        if (disposing)\n        {\n            // no managed objects to free\n        }\n\n        if (handle != nint.Zero)\n        {\n            CloseHandle(handle);\n            handle = nint.Zero;\n        }\n    }\n\n    ~WindowsJobService()\n    {\n        Dispose(false);\n    }\n\n    #endregion IDisposable\n\n    #region Interop\n\n    [DllImport(\"kernel32.dll\", CharSet = CharSet.Unicode)]\n    private static extern nint CreateJobObject(nint a, string? lpName);\n\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    private static extern bool SetInformationJobObject(nint hJob, JobObjectInfoType infoType, nint lpJobObjectInfo, uint cbJobObjectInfoLength);\n\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    private static extern bool AssignProcessToJobObject(nint job, nint process);\n\n    [DllImport(\"kernel32.dll\", SetLastError = true)]\n    [return: MarshalAs(UnmanagedType.Bool)]\n    private static extern bool CloseHandle(nint hObject);\n\n    #endregion Interop\n}\n\n[StructLayout(LayoutKind.Sequential)]\ninternal struct IO_COUNTERS\n{\n    public ulong ReadOperationCount;\n    public ulong WriteOperationCount;\n    public ulong OtherOperationCount;\n    public ulong ReadTransferCount;\n    public ulong WriteTransferCount;\n    public ulong OtherTransferCount;\n}\n\n[StructLayout(LayoutKind.Sequential)]\ninternal struct JOBOBJECT_BASIC_LIMIT_INFORMATION\n{\n    public long PerProcessUserTimeLimit;\n    public long PerJobUserTimeLimit;\n    public uint LimitFlags;\n    public nuint MinimumWorkingSetSize;\n    public nuint MaximumWorkingSetSize;\n    public uint ActiveProcessLimit;\n    public nuint Affinity;\n    public uint PriorityClass;\n    public uint SchedulingClass;\n}\n\n[StructLayout(LayoutKind.Sequential)]\npublic struct SECURITY_ATTRIBUTES\n{\n    public uint nLength;\n    public nint lpSecurityDescriptor;\n    public int bInheritHandle;\n}\n\n[StructLayout(LayoutKind.Sequential)]\ninternal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION\n{\n    public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;\n    public IO_COUNTERS IoInfo;\n    public nuint ProcessMemoryLimit;\n    public nuint JobMemoryLimit;\n    public nuint PeakProcessMemoryUsed;\n    public nuint PeakJobMemoryUsed;\n}\n\npublic enum JobObjectInfoType\n{\n    AssociateCompletionPortInformation = 7,\n    BasicLimitInformation = 2,\n    BasicUIRestrictions = 4,\n    EndOfJobTimeInformation = 6,\n    ExtendedLimitInformation = 9,\n    SecurityLimitInformation = 5,\n    GroupInformation = 11\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/AddGroupServerViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class AddGroupServerViewModel : MyReactiveObject\n{\n    [Reactive]\n    public ProfileItem SelectedSource { get; set; }\n\n    [Reactive]\n    public ProfileItem SelectedChild { get; set; }\n\n    [Reactive]\n    public IList<ProfileItem> SelectedChildren { get; set; }\n\n    [Reactive]\n    public string? CoreType { get; set; }\n\n    [Reactive]\n    public string? PolicyGroupType { get; set; }\n\n    [Reactive]\n    public SubItem? SelectedSubItem { get; set; }\n\n    [Reactive]\n    public string? Filter { get; set; }\n\n    public IObservableCollection<SubItem> SubItems { get; } = new ObservableCollectionExtended<SubItem>();\n\n    public IObservableCollection<ProfileItem> ChildItemsObs { get; } = new ObservableCollectionExtended<ProfileItem>();\n\n    public IObservableCollection<ProfileItem> AllProfilePreviewItemsObs { get; } = new ObservableCollectionExtended<ProfileItem>();\n\n    //public ReactiveCommand<Unit, Unit> AddCmd { get; }\n    public ReactiveCommand<Unit, Unit> RemoveCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> MoveTopCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveUpCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveDownCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveBottomCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    public AddGroupServerViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        var canEditRemove = this.WhenAnyValue(\n            x => x.SelectedChild,\n            SelectedChild => SelectedChild != null && !SelectedChild.Remarks.IsNullOrEmpty());\n\n        RemoveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ChildRemoveAsync();\n        }, canEditRemove);\n        MoveTopCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Top);\n        }, canEditRemove);\n        MoveUpCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Up);\n        }, canEditRemove);\n        MoveDownCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Down);\n        }, canEditRemove);\n        MoveBottomCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Bottom);\n        }, canEditRemove);\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveServerAsync();\n        });\n\n        SelectedSource = profileItem.IndexId.IsNullOrEmpty() ? profileItem : JsonUtils.DeepCopy(profileItem);\n        CoreType = (SelectedSource?.CoreType ?? ECoreType.Xray).ToString();\n\n        _ = Init();\n    }\n\n    public async Task Init()\n    {\n        var protocolExtra = SelectedSource.GetProtocolExtra();\n        PolicyGroupType = (protocolExtra?.MultipleLoad ?? EMultipleLoad.LeastPing) switch\n        {\n            EMultipleLoad.LeastPing => ResUI.TbLeastPing,\n            EMultipleLoad.Fallback => ResUI.TbFallback,\n            EMultipleLoad.Random => ResUI.TbRandom,\n            EMultipleLoad.RoundRobin => ResUI.TbRoundRobin,\n            EMultipleLoad.LeastLoad => ResUI.TbLeastLoad,\n            _ => ResUI.TbLeastPing,\n        };\n\n        var subs = await AppManager.Instance.SubItems();\n        subs.Add(new SubItem());\n        SubItems.AddRange(subs);\n        SelectedSubItem = SubItems.FirstOrDefault(s => s.Id == protocolExtra?.SubChildItems);\n        Filter = protocolExtra?.Filter;\n\n        var childIndexIds = Utils.String2List(protocolExtra?.ChildItems) ?? [];\n        var childItemList = await AppManager.Instance.GetProfileItemsOrderedByIndexIds(childIndexIds);\n        ChildItemsObs.AddRange(childItemList);\n    }\n\n    public async Task ChildRemoveAsync()\n    {\n        if (SelectedChild == null || SelectedChild.IndexId.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return;\n        }\n        foreach (var it in SelectedChildren ?? [SelectedChild])\n        {\n            if (it != null)\n            {\n                ChildItemsObs.Remove(it);\n            }\n        }\n        await Task.CompletedTask;\n    }\n\n    public async Task MoveServer(EMove eMove)\n    {\n        if (SelectedChild == null || SelectedChild.IndexId.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return;\n        }\n        var index = ChildItemsObs.IndexOf(SelectedChild);\n        if (index < 0)\n        {\n            return;\n        }\n        var selectedChild = JsonUtils.DeepCopy(SelectedChild);\n        switch (eMove)\n        {\n            case EMove.Top:\n                if (index == 0)\n                {\n                    return;\n                }\n                ChildItemsObs.RemoveAt(index);\n                ChildItemsObs.Insert(0, selectedChild);\n                break;\n\n            case EMove.Up:\n                if (index == 0)\n                {\n                    return;\n                }\n                ChildItemsObs.RemoveAt(index);\n                ChildItemsObs.Insert(index - 1, selectedChild);\n                break;\n\n            case EMove.Down:\n                if (index == ChildItemsObs.Count - 1)\n                {\n                    return;\n                }\n                ChildItemsObs.RemoveAt(index);\n                ChildItemsObs.Insert(index + 1, selectedChild);\n                break;\n\n            case EMove.Bottom:\n                if (index == ChildItemsObs.Count - 1)\n                {\n                    return;\n                }\n                ChildItemsObs.RemoveAt(index);\n                ChildItemsObs.Add(selectedChild);\n                break;\n\n            default:\n                break;\n        }\n        await Task.CompletedTask;\n    }\n\n    private ProtocolExtraItem GetUpdatedProtocolExtra()\n    {\n        return SelectedSource.GetProtocolExtra() with\n        {\n            ChildItems =\n            Utils.List2String(ChildItemsObs.Where(s => !s.IndexId.IsNullOrEmpty()).Select(s => s.IndexId).ToList()),\n            MultipleLoad = PolicyGroupType switch\n            {\n                var s when s == ResUI.TbLeastPing => EMultipleLoad.LeastPing,\n                var s when s == ResUI.TbFallback => EMultipleLoad.Fallback,\n                var s when s == ResUI.TbRandom => EMultipleLoad.Random,\n                var s when s == ResUI.TbRoundRobin => EMultipleLoad.RoundRobin,\n                var s when s == ResUI.TbLeastLoad => EMultipleLoad.LeastLoad,\n                _ => EMultipleLoad.LeastPing,\n            },\n            SubChildItems = SelectedSubItem?.Id,\n            Filter = Filter,\n        };\n    }\n\n    public async Task UpdatePreviewList()\n    {\n        AllProfilePreviewItemsObs.Clear();\n        AllProfilePreviewItemsObs.AddRange(await GroupProfileManager.GetChildProfileItemsByProtocolExtra(GetUpdatedProtocolExtra()));\n    }\n\n    private async Task SaveServerAsync()\n    {\n        var remarks = SelectedSource.Remarks;\n        if (remarks.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseFillRemarks);\n            return;\n        }\n        if (ChildItemsObs.Count == 0 && SelectedSubItem?.Id.IsNullOrEmpty() == true)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseAddAtLeastOneServer);\n            return;\n        }\n        SelectedSource.CoreType = CoreType.IsNullOrEmpty() ? ECoreType.Xray : (ECoreType)Enum.Parse(typeof(ECoreType), CoreType);\n        if (SelectedSource.CoreType is not (ECoreType.Xray or ECoreType.sing_box) ||\n            SelectedSource.ConfigType is not (EConfigType.ProxyChain or EConfigType.PolicyGroup))\n        {\n            return;\n        }\n\n        var protocolExtra = GetUpdatedProtocolExtra();\n\n        SelectedSource.SetProtocolExtra(protocolExtra);\n\n        if (await ConfigHandler.AddServerCommon(_config, SelectedSource) == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/AddServer2ViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class AddServer2ViewModel : MyReactiveObject\n{\n    [Reactive]\n    public ProfileItem SelectedSource { get; set; }\n\n    [Reactive]\n    public string? CoreType { get; set; }\n\n    public ReactiveCommand<Unit, Unit> BrowseServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> EditServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> SaveServerCmd { get; }\n    public bool IsModified { get; set; }\n\n    public AddServer2ViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        BrowseServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            _updateView?.Invoke(EViewAction.BrowseServer, null);\n            await Task.CompletedTask;\n        });\n        EditServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await EditServer();\n        });\n        SaveServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveServerAsync();\n        });\n\n        SelectedSource = profileItem.IndexId.IsNullOrEmpty() ? profileItem : JsonUtils.DeepCopy(profileItem);\n        CoreType = SelectedSource?.CoreType?.ToString();\n    }\n\n    private async Task SaveServerAsync()\n    {\n        var remarks = SelectedSource.Remarks;\n        if (remarks.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseFillRemarks);\n            return;\n        }\n\n        if (SelectedSource.Address.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.FillServerAddressCustom);\n            return;\n        }\n        SelectedSource.CoreType = CoreType.IsNullOrEmpty() ? null : (ECoreType)Enum.Parse(typeof(ECoreType), CoreType);\n\n        if (await ConfigHandler.EditCustomServer(_config, SelectedSource) == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n\n    public async Task BrowseServer(string fileName)\n    {\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        var item = await AppManager.Instance.GetProfileItem(SelectedSource.IndexId);\n        item ??= SelectedSource;\n        item.Address = fileName;\n        if (await ConfigHandler.AddCustomServer(_config, item, false) == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.SuccessfullyImportedCustomServer);\n            if (item.IndexId.IsNotEmpty())\n            {\n                SelectedSource = JsonUtils.DeepCopy(item);\n            }\n            IsModified = true;\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.FailedImportedCustomServer);\n        }\n    }\n\n    private async Task EditServer()\n    {\n        var address = SelectedSource.Address;\n        if (address.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.FillServerAddressCustom);\n            return;\n        }\n\n        address = Utils.GetConfigPath(address);\n        if (File.Exists(address))\n        {\n            ProcUtils.ProcessStart(address);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.FailedReadConfiguration);\n        }\n        await Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/AddServerViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class AddServerViewModel : MyReactiveObject\n{\n    [Reactive]\n    public ProfileItem SelectedSource { get; set; }\n\n    [Reactive]\n    public string? CoreType { get; set; }\n\n    [Reactive]\n    public string Cert { get; set; }\n\n    [Reactive]\n    public string CertTip { get; set; }\n\n    [Reactive]\n    public string CertSha { get; set; }\n\n    [Reactive]\n    public string SalamanderPass { get; set; }\n\n    [Reactive]\n    public int AlterId { get; set; }\n\n    [Reactive]\n    public string Ports { get; set; }\n\n    [Reactive]\n    public int? UpMbps { get; set; }\n\n    [Reactive]\n    public int? DownMbps { get; set; }\n\n    [Reactive]\n    public string HopInterval { get; set; }\n\n    [Reactive]\n    public string Flow { get; set; }\n\n    [Reactive]\n    public string VmessSecurity { get; set; }\n\n    [Reactive]\n    public string VlessEncryption { get; set; }\n\n    [Reactive]\n    public string SsMethod { get; set; }\n\n    [Reactive]\n    public string WgPublicKey { get; set; }\n\n    //[Reactive]\n    //public string WgPresharedKey { get; set; }\n    [Reactive]\n    public string WgInterfaceAddress { get; set; }\n\n    [Reactive]\n    public string WgReserved { get; set; }\n\n    [Reactive]\n    public int WgMtu { get; set; }\n\n    public ReactiveCommand<Unit, Unit> FetchCertCmd { get; }\n    public ReactiveCommand<Unit, Unit> FetchCertChainCmd { get; }\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    public AddServerViewModel(ProfileItem profileItem, Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        FetchCertCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await FetchCert();\n        });\n        FetchCertChainCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await FetchCertChain();\n        });\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveServerAsync();\n        });\n\n        this.WhenAnyValue(x => x.Cert)\n            .Subscribe(_ => UpdateCertTip());\n\n        this.WhenAnyValue(x => x.CertSha)\n            .Subscribe(_ => UpdateCertTip());\n\n        this.WhenAnyValue(x => x.Cert)\n            .Subscribe(_ => UpdateCertSha());\n\n        if (profileItem.IndexId.IsNullOrEmpty())\n        {\n            profileItem.Network = Global.DefaultNetwork;\n            profileItem.HeaderType = Global.None;\n            profileItem.RequestHost = \"\";\n            profileItem.StreamSecurity = \"\";\n            SelectedSource = profileItem;\n        }\n        else\n        {\n            SelectedSource = JsonUtils.DeepCopy(profileItem);\n        }\n        CoreType = SelectedSource?.CoreType?.ToString();\n        Cert = SelectedSource?.Cert?.ToString() ?? string.Empty;\n        CertSha = SelectedSource?.CertSha?.ToString() ?? string.Empty;\n\n        var protocolExtra = SelectedSource?.GetProtocolExtra();\n        Ports = protocolExtra?.Ports ?? string.Empty;\n        AlterId = int.TryParse(protocolExtra?.AlterId, out var result) ? result : 0;\n        Flow = protocolExtra?.Flow ?? string.Empty;\n        SalamanderPass = protocolExtra?.SalamanderPass ?? string.Empty;\n        UpMbps = protocolExtra?.UpMbps;\n        DownMbps = protocolExtra?.DownMbps;\n        HopInterval = protocolExtra?.HopInterval.IsNullOrEmpty() ?? true ? Global.Hysteria2DefaultHopInt.ToString() : protocolExtra.HopInterval;\n        VmessSecurity = protocolExtra?.VmessSecurity?.IsNullOrEmpty() == false ? protocolExtra.VmessSecurity : Global.DefaultSecurity;\n        VlessEncryption = protocolExtra?.VlessEncryption.IsNullOrEmpty() == false ? protocolExtra.VlessEncryption : Global.None;\n        SsMethod = protocolExtra?.SsMethod ?? string.Empty;\n        WgPublicKey = protocolExtra?.WgPublicKey ?? string.Empty;\n        WgInterfaceAddress = protocolExtra?.WgInterfaceAddress ?? string.Empty;\n        WgReserved = protocolExtra?.WgReserved ?? string.Empty;\n        WgMtu = protocolExtra?.WgMtu ?? 1280;\n    }\n\n    private async Task SaveServerAsync()\n    {\n        if (SelectedSource.Remarks.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseFillRemarks);\n            return;\n        }\n\n        if (SelectedSource.Address.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.FillServerAddress);\n            return;\n        }\n        var port = SelectedSource.Port.ToString();\n        if (port.IsNullOrEmpty() || !Utils.IsNumeric(port)\n            || SelectedSource.Port <= 0 || SelectedSource.Port >= Global.MaxPort)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.FillCorrectServerPort);\n            return;\n        }\n        if (SelectedSource.ConfigType == EConfigType.Shadowsocks)\n        {\n            if (SelectedSource.Password.IsNullOrEmpty())\n            {\n                NoticeManager.Instance.Enqueue(ResUI.FillPassword);\n                return;\n            }\n            if (SsMethod.IsNullOrEmpty())\n            {\n                NoticeManager.Instance.Enqueue(ResUI.PleaseSelectEncryption);\n                return;\n            }\n        }\n        if (SelectedSource.ConfigType is not EConfigType.SOCKS and not EConfigType.HTTP)\n        {\n            if (SelectedSource.Password.IsNullOrEmpty())\n            {\n                NoticeManager.Instance.Enqueue(ResUI.FillUUID);\n                return;\n            }\n        }\n        SelectedSource.CoreType = CoreType.IsNullOrEmpty() ? null : (ECoreType)Enum.Parse(typeof(ECoreType), CoreType);\n        SelectedSource.Cert = Cert.IsNullOrEmpty() ? string.Empty : Cert;\n        SelectedSource.CertSha = CertSha.IsNullOrEmpty() ? string.Empty : CertSha;\n        SelectedSource.SetProtocolExtra(SelectedSource.GetProtocolExtra() with\n        {\n            Ports = Ports.NullIfEmpty(),\n            AlterId = AlterId > 0 ? AlterId.ToString() : null,\n            Flow = Flow.NullIfEmpty(),\n            SalamanderPass = SalamanderPass.NullIfEmpty(),\n            UpMbps = UpMbps,\n            DownMbps = DownMbps,\n            HopInterval = HopInterval.NullIfEmpty(),\n            VmessSecurity = VmessSecurity.NullIfEmpty(),\n            VlessEncryption = VlessEncryption.NullIfEmpty(),\n            SsMethod = SsMethod.NullIfEmpty(),\n            WgPublicKey = WgPublicKey.NullIfEmpty(),\n            WgInterfaceAddress = WgInterfaceAddress.NullIfEmpty(),\n            WgReserved = WgReserved.NullIfEmpty(),\n            WgMtu = WgMtu >= 576 ? WgMtu : null,\n        });\n\n        if (await ConfigHandler.AddServer(_config, SelectedSource) == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n\n    private void UpdateCertTip(string? errorMessage = null)\n    {\n        CertTip = errorMessage.IsNullOrEmpty()\n            ? ((Cert.IsNullOrEmpty() && CertSha.IsNullOrEmpty()) ? ResUI.CertNotSet : ResUI.CertSet)\n            : errorMessage;\n    }\n\n    private void UpdateCertSha()\n    {\n        if (Cert.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        var certList = CertPemManager.ParsePemChain(Cert);\n        if (certList.Count == 0)\n        {\n            return;\n        }\n\n        List<string> shaList = [];\n        foreach (var cert in certList)\n        {\n            var sha = CertPemManager.GetCertSha256Thumbprint(cert);\n            if (sha.IsNullOrEmpty())\n            {\n                return;\n            }\n            shaList.Add(sha);\n        }\n        CertSha = string.Join(',', shaList);\n    }\n\n    private async Task FetchCert()\n    {\n        if (SelectedSource.StreamSecurity != Global.StreamSecurity)\n        {\n            return;\n        }\n        var domain = SelectedSource.Address;\n        var serverName = SelectedSource.Sni;\n        if (serverName.IsNullOrEmpty())\n        {\n            serverName = SelectedSource.RequestHost;\n        }\n        if (serverName.IsNullOrEmpty())\n        {\n            serverName = SelectedSource.Address;\n        }\n        if (SelectedSource.Port > 0)\n        {\n            domain += $\":{SelectedSource.Port}\";\n        }\n\n        (Cert, var certError) = await CertPemManager.Instance.GetCertPemAsync(domain, serverName);\n        UpdateCertTip(certError);\n    }\n\n    private async Task FetchCertChain()\n    {\n        if (SelectedSource.StreamSecurity != Global.StreamSecurity)\n        {\n            return;\n        }\n        var domain = SelectedSource.Address;\n        var serverName = SelectedSource.Sni;\n        if (serverName.IsNullOrEmpty())\n        {\n            serverName = SelectedSource.RequestHost;\n        }\n        if (serverName.IsNullOrEmpty())\n        {\n            serverName = SelectedSource.Address;\n        }\n        if (SelectedSource.Port > 0)\n        {\n            domain += $\":{SelectedSource.Port}\";\n        }\n\n        var (certs, certError) = await CertPemManager.Instance.GetCertChainPemAsync(domain, serverName);\n        Cert = CertPemManager.ConcatenatePemChain(certs);\n        UpdateCertTip(certError);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/BackupAndRestoreViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class BackupAndRestoreViewModel : MyReactiveObject\n{\n    private readonly string _guiConfigs = \"guiConfigs\";\n    private static string BackupFileName => $\"backup_{DateTime.Now:yyyyMMddHHmmss}.zip\";\n\n    public ReactiveCommand<Unit, Unit> RemoteBackupCmd { get; }\n    public ReactiveCommand<Unit, Unit> RemoteRestoreCmd { get; }\n    public ReactiveCommand<Unit, Unit> WebDavCheckCmd { get; }\n\n    [Reactive]\n    public WebDavItem SelectedSource { get; set; }\n\n    [Reactive]\n    public string OperationMsg { get; set; }\n\n    public BackupAndRestoreViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        WebDavCheckCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await WebDavCheck();\n        });\n        RemoteBackupCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RemoteBackup();\n        });\n        RemoteRestoreCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RemoteRestore();\n        });\n\n        SelectedSource = JsonUtils.DeepCopy(_config.WebDavItem);\n    }\n\n    private void DisplayOperationMsg(string msg = \"\")\n    {\n        OperationMsg = msg;\n    }\n\n    private async Task WebDavCheck()\n    {\n        DisplayOperationMsg();\n        _config.WebDavItem = SelectedSource;\n        _ = await ConfigHandler.SaveConfig(_config);\n\n        var result = await WebDavManager.Instance.CheckConnection();\n        if (result)\n        {\n            DisplayOperationMsg(ResUI.OperationSuccess);\n        }\n        else\n        {\n            DisplayOperationMsg(WebDavManager.Instance.GetLastError());\n        }\n    }\n\n    private async Task RemoteBackup()\n    {\n        DisplayOperationMsg();\n        var fileName = Utils.GetBackupPath(BackupFileName);\n        var result = await CreateZipFileFromDirectory(fileName);\n        if (result)\n        {\n            var result2 = await WebDavManager.Instance.PutFile(fileName);\n            if (result2)\n            {\n                DisplayOperationMsg(ResUI.OperationSuccess);\n                return;\n            }\n        }\n\n        DisplayOperationMsg(WebDavManager.Instance.GetLastError());\n    }\n\n    private async Task RemoteRestore()\n    {\n        DisplayOperationMsg();\n        var fileName = Utils.GetTempPath(Utils.GetGuid());\n        var result = await WebDavManager.Instance.GetRawFile(fileName);\n        if (result)\n        {\n            await LocalRestore(fileName);\n            return;\n        }\n\n        DisplayOperationMsg(WebDavManager.Instance.GetLastError());\n    }\n\n    public async Task<bool> LocalBackup(string fileName)\n    {\n        DisplayOperationMsg();\n        var result = await CreateZipFileFromDirectory(fileName);\n        if (result)\n        {\n            DisplayOperationMsg(ResUI.OperationSuccess);\n        }\n        else\n        {\n            DisplayOperationMsg(WebDavManager.Instance.GetLastError());\n        }\n\n        return result;\n    }\n\n    public async Task LocalRestore(string fileName)\n    {\n        DisplayOperationMsg();\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n        //exist\n        if (!File.Exists(fileName))\n        {\n            return;\n        }\n        //check\n        var lstFiles = FileUtils.GetFilesFromZip(fileName);\n        if (lstFiles is null || !lstFiles.Any(t => t.Contains(_guiConfigs)))\n        {\n            DisplayOperationMsg(ResUI.LocalRestoreInvalidZipTips);\n            return;\n        }\n\n        //backup first\n        var fileBackup = Utils.GetBackupPath(BackupFileName);\n        var result = await CreateZipFileFromDirectory(fileBackup);\n        if (result)\n        {\n            await AppManager.Instance.AppExitAsync(false);\n            await SQLiteHelper.Instance.DisposeDbConnectionAsync();\n\n            var toPath = Utils.GetConfigPath();\n            FileUtils.ZipExtractToFile(fileName, toPath, \"\");\n\n            if (Utils.IsWindows())\n            {\n                ProcUtils.RebootAsAdmin(false);\n            }\n            else\n            {\n                if (Utils.UpgradeAppExists(out var upgradeFileName))\n                {\n                    _ = ProcUtils.ProcessStart(upgradeFileName, Global.RebootAs, Utils.StartupPath());\n                }\n            }\n            AppManager.Instance.Shutdown(true);\n        }\n        else\n        {\n            DisplayOperationMsg(WebDavManager.Instance.GetLastError());\n        }\n    }\n\n    private async Task<bool> CreateZipFileFromDirectory(string fileName)\n    {\n        if (fileName.IsNullOrEmpty())\n        {\n            return false;\n        }\n\n        var configDir = Utils.GetConfigPath();\n        var configDirZipTemp = Utils.GetTempPath($\"v2rayN_{DateTime.Now:yyyyMMddHHmmss}\");\n        var configDirTemp = Path.Combine(configDirZipTemp, _guiConfigs);\n\n        FileUtils.CopyDirectory(configDir, configDirTemp, false, true, \"\");\n        var ret = FileUtils.CreateFromDirectory(configDirZipTemp, fileName);\n        Directory.Delete(configDirZipTemp, true);\n        return await Task.FromResult(ret);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/CheckUpdateViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class CheckUpdateViewModel : MyReactiveObject\n{\n    private const string _geo = \"GeoFiles\";\n    private readonly string _v2rayN = ECoreType.v2rayN.ToString();\n    private List<CheckUpdateModel> _lstUpdated = [];\n    private static readonly string _tag = \"CheckUpdateViewModel\";\n\n    public IObservableCollection<CheckUpdateModel> CheckUpdateModels { get; } = new ObservableCollectionExtended<CheckUpdateModel>();\n    public ReactiveCommand<Unit, Unit> CheckUpdateCmd { get; }\n    [Reactive] public bool EnableCheckPreReleaseUpdate { get; set; }\n\n    public CheckUpdateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        CheckUpdateCmd = ReactiveCommand.CreateFromTask(CheckUpdate);\n        CheckUpdateCmd.ThrownExceptions.Subscribe(ex =>\n        {\n            Logging.SaveLog(_tag, ex);\n            _ = UpdateView(_v2rayN, ex.Message);\n        });\n\n        EnableCheckPreReleaseUpdate = _config.CheckUpdateItem.CheckPreReleaseUpdate;\n\n        this.WhenAnyValue(\n        x => x.EnableCheckPreReleaseUpdate,\n        y => y == true)\n            .Subscribe(c => _config.CheckUpdateItem.CheckPreReleaseUpdate = EnableCheckPreReleaseUpdate);\n\n        RefreshCheckUpdateItems();\n    }\n\n    private void RefreshCheckUpdateItems()\n    {\n        CheckUpdateModels.Clear();\n\n        if (RuntimeInformation.ProcessArchitecture != Architecture.X86)\n        {\n            CheckUpdateModels.Add(GetCheckUpdateModel(_v2rayN));\n            //Not Windows and under Win10\n            if (!(Utils.IsWindows() && Environment.OSVersion.Version.Major < 10))\n            {\n                CheckUpdateModels.Add(GetCheckUpdateModel(ECoreType.Xray.ToString()));\n                CheckUpdateModels.Add(GetCheckUpdateModel(ECoreType.mihomo.ToString()));\n                CheckUpdateModels.Add(GetCheckUpdateModel(ECoreType.sing_box.ToString()));\n            }\n        }\n        CheckUpdateModels.Add(GetCheckUpdateModel(_geo));\n    }\n\n    private CheckUpdateModel GetCheckUpdateModel(string coreType)\n    {\n        if (coreType == _v2rayN && Utils.IsPackagedInstall())\n        {\n            return new()\n            {\n                IsSelected = false,\n                CoreType = coreType,\n                Remarks = ResUI.menuCheckUpdate + \" (Not Support)\",\n            };\n        }\n\n        return new()\n        {\n            IsSelected = _config.CheckUpdateItem.SelectedCoreTypes?.Contains(coreType) ?? true,\n            CoreType = coreType,\n            Remarks = ResUI.menuCheckUpdate,\n        };\n    }\n\n    private async Task SaveSelectedCoreTypes()\n    {\n        _config.CheckUpdateItem.SelectedCoreTypes = CheckUpdateModels.Where(t => t.IsSelected == true).Select(t => t.CoreType ?? \"\").ToList();\n        await ConfigHandler.SaveConfig(_config);\n    }\n\n    private async Task CheckUpdate()\n    {\n        await Task.Run(CheckUpdateTask);\n    }\n\n    private async Task CheckUpdateTask()\n    {\n        _lstUpdated.Clear();\n        _lstUpdated = CheckUpdateModels.Where(x => x.IsSelected == true)\n                .Select(x => new CheckUpdateModel() { CoreType = x.CoreType }).ToList();\n        await SaveSelectedCoreTypes();\n\n        for (var k = CheckUpdateModels.Count - 1; k >= 0; k--)\n        {\n            var item = CheckUpdateModels[k];\n            if (item.IsSelected != true)\n            {\n                continue;\n            }\n\n            await UpdateView(item.CoreType, \"...\");\n            if (item.CoreType == _geo)\n            {\n                await CheckUpdateGeo();\n            }\n            else if (item.CoreType == _v2rayN)\n            {\n                if (Utils.IsPackagedInstall())\n                {\n                    await UpdateView(_v2rayN, \"Not Support\");\n                    continue;\n                }\n                await CheckUpdateN(EnableCheckPreReleaseUpdate);\n            }\n            else if (item.CoreType == ECoreType.Xray.ToString())\n            {\n                await CheckUpdateCore(item, EnableCheckPreReleaseUpdate);\n            }\n            else\n            {\n                await CheckUpdateCore(item, false);\n            }\n        }\n\n        await UpdateFinished();\n    }\n\n    private void UpdatedPlusPlus(string coreType, string fileName)\n    {\n        var item = _lstUpdated.FirstOrDefault(x => x.CoreType == coreType);\n        if (item == null)\n        {\n            return;\n        }\n        item.IsFinished = true;\n        if (!fileName.IsNullOrEmpty())\n        {\n            item.FileName = fileName;\n        }\n    }\n\n    private async Task CheckUpdateGeo()\n    {\n        async Task _updateUI(bool success, string msg)\n        {\n            await UpdateView(_geo, msg);\n            if (success)\n            {\n                UpdatedPlusPlus(_geo, \"\");\n            }\n        }\n        await new UpdateService(_config, _updateUI).UpdateGeoFileAll()\n            .ContinueWith(t => UpdatedPlusPlus(_geo, \"\"));\n    }\n\n    private async Task CheckUpdateN(bool preRelease)\n    {\n        async Task _updateUI(bool success, string msg)\n        {\n            await UpdateView(_v2rayN, msg);\n            if (success)\n            {\n                await UpdateView(_v2rayN, ResUI.OperationSuccess);\n                UpdatedPlusPlus(_v2rayN, msg);\n            }\n        }\n        await new UpdateService(_config, _updateUI).CheckUpdateGuiN(preRelease)\n            .ContinueWith(t => UpdatedPlusPlus(_v2rayN, \"\"));\n    }\n\n    private async Task CheckUpdateCore(CheckUpdateModel model, bool preRelease)\n    {\n        async Task _updateUI(bool success, string msg)\n        {\n            await UpdateView(model.CoreType, msg);\n            if (success)\n            {\n                await UpdateView(model.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfullyMore);\n\n                UpdatedPlusPlus(model.CoreType, msg);\n            }\n        }\n        var type = (ECoreType)Enum.Parse(typeof(ECoreType), model.CoreType);\n        await new UpdateService(_config, _updateUI).CheckUpdateCore(type, preRelease)\n            .ContinueWith(t => UpdatedPlusPlus(model.CoreType, \"\"));\n    }\n\n    private async Task UpdateFinished()\n    {\n        if (_lstUpdated.Count > 0 && _lstUpdated.Count(x => x.IsFinished == true) == _lstUpdated.Count)\n        {\n            await UpdateFinishedSub(false);\n            await Task.Delay(2000);\n            await UpgradeCore();\n\n            if (_lstUpdated.Any(x => x.CoreType == _v2rayN && x.IsFinished == true))\n            {\n                await Task.Delay(1000);\n                await UpgradeN();\n            }\n            await Task.Delay(1000);\n            await UpdateFinishedSub(true);\n        }\n    }\n\n    private async Task UpdateFinishedSub(bool blReload)\n    {\n        RxSchedulers.MainThreadScheduler.Schedule(blReload, (scheduler, blReload) =>\n        {\n            _ = UpdateFinishedResult(blReload);\n            return Disposable.Empty;\n        });\n        await Task.CompletedTask;\n    }\n\n    public async Task UpdateFinishedResult(bool blReload)\n    {\n        if (blReload)\n        {\n            AppEvents.ReloadRequested.Publish();\n        }\n        else\n        {\n            await CoreManager.Instance.CoreStop();\n        }\n    }\n\n    private async Task UpgradeN()\n    {\n        try\n        {\n            var fileName = _lstUpdated.FirstOrDefault(x => x.CoreType == _v2rayN)?.FileName;\n            if (fileName.IsNullOrEmpty())\n            {\n                return;\n            }\n            if (!Utils.UpgradeAppExists(out var upgradeFileName))\n            {\n                await UpdateView(_v2rayN, ResUI.UpgradeAppNotExistTip);\n                NoticeManager.Instance.SendMessageAndEnqueue(ResUI.UpgradeAppNotExistTip);\n                Logging.SaveLog(\"UpgradeApp does not exist\");\n                return;\n            }\n\n            var id = ProcUtils.ProcessStart(upgradeFileName, fileName, Utils.StartupPath());\n            if (id > 0)\n            {\n                await AppManager.Instance.AppExitAsync(true);\n            }\n        }\n        catch (Exception ex)\n        {\n            await UpdateView(_v2rayN, ex.Message);\n        }\n    }\n\n    private async Task UpgradeCore()\n    {\n        foreach (var item in _lstUpdated)\n        {\n            if (item.FileName.IsNullOrEmpty())\n            {\n                continue;\n            }\n\n            var fileName = item.FileName;\n            if (!File.Exists(fileName))\n            {\n                continue;\n            }\n            var toPath = Utils.GetBinPath(\"\", item.CoreType);\n\n            if (fileName.Contains(\".tar.gz\"))\n            {\n                FileUtils.DecompressTarFile(fileName, toPath);\n                var dir = new DirectoryInfo(toPath);\n                if (dir.Exists)\n                {\n                    foreach (var subDir in dir.GetDirectories())\n                    {\n                        FileUtils.CopyDirectory(subDir.FullName, toPath, false, true);\n                        subDir.Delete(true);\n                    }\n                }\n            }\n            else if (fileName.Contains(\".gz\"))\n            {\n                FileUtils.DecompressFile(fileName, toPath, item.CoreType);\n            }\n            else\n            {\n                FileUtils.ZipExtractToFile(fileName, toPath, \"geo\");\n            }\n\n            if (Utils.IsNonWindows())\n            {\n                var filesList = new DirectoryInfo(toPath).GetFiles().Select(u => u.FullName).ToList();\n                foreach (var file in filesList)\n                {\n                    await Utils.SetLinuxChmod(Path.Combine(toPath, item.CoreType.ToLower()));\n                }\n            }\n\n            await UpdateView(item.CoreType, ResUI.MsgUpdateV2rayCoreSuccessfully);\n\n            if (File.Exists(fileName))\n            {\n                File.Delete(fileName);\n            }\n        }\n    }\n\n    private async Task UpdateView(string coreType, string msg)\n    {\n        var item = new CheckUpdateModel()\n        {\n            CoreType = coreType,\n            Remarks = msg,\n        };\n\n        RxSchedulers.MainThreadScheduler.Schedule(item, (scheduler, model) =>\n        {\n            _ = UpdateViewResult(model);\n            return Disposable.Empty;\n        });\n        await Task.CompletedTask;\n    }\n\n    public async Task UpdateViewResult(CheckUpdateModel model)\n    {\n        var found = CheckUpdateModels.FirstOrDefault(t => t.CoreType == model.CoreType);\n        if (found == null)\n        {\n            return;\n        }\n        found.Remarks = model.Remarks;\n        await Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/ClashConnectionsViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class ClashConnectionsViewModel : MyReactiveObject\n{\n    public IObservableCollection<ClashConnectionModel> ConnectionItems { get; } = new ObservableCollectionExtended<ClashConnectionModel>();\n\n    [Reactive]\n    public ClashConnectionModel SelectedSource { get; set; }\n\n    public ReactiveCommand<Unit, Unit> ConnectionCloseCmd { get; }\n    public ReactiveCommand<Unit, Unit> ConnectionCloseAllCmd { get; }\n\n    [Reactive]\n    public string HostFilter { get; set; }\n\n    [Reactive]\n    public bool AutoRefresh { get; set; }\n\n    public ClashConnectionsViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n        AutoRefresh = _config.ClashUIItem.ConnectionsAutoRefresh;\n\n        var canEditRemove = this.WhenAnyValue(\n         x => x.SelectedSource,\n         selectedSource => selectedSource != null && selectedSource.Id.IsNotEmpty());\n\n        this.WhenAnyValue(\n           x => x.AutoRefresh,\n           y => y == true)\n               .Subscribe(c => { _config.ClashUIItem.ConnectionsAutoRefresh = AutoRefresh; });\n        ConnectionCloseCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ClashConnectionClose(false);\n        }, canEditRemove);\n\n        ConnectionCloseAllCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ClashConnectionClose(true);\n        });\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        await DelayTestTask();\n    }\n\n    private async Task GetClashConnections()\n    {\n        var ret = await ClashApiManager.Instance.GetClashConnectionsAsync();\n        if (ret == null)\n        {\n            return;\n        }\n\n        RxSchedulers.MainThreadScheduler.Schedule(ret?.connections, (scheduler, model) =>\n        {\n            _ = RefreshConnections(model);\n            return Disposable.Empty;\n        });\n    }\n\n    public async Task RefreshConnections(List<ConnectionItem>? connections)\n    {\n        ConnectionItems.Clear();\n\n        var dtNow = DateTime.Now;\n        var lstModel = new List<ClashConnectionModel>();\n        foreach (var item in connections ?? new())\n        {\n            var host = $\"{(item.metadata.host.IsNullOrEmpty() ? item.metadata.destinationIP : item.metadata.host)}:{item.metadata.destinationPort}\";\n            if (HostFilter.IsNotEmpty() && !host.Contains(HostFilter))\n            {\n                continue;\n            }\n\n            var model = new ClashConnectionModel\n            {\n                Id = item.id,\n                Network = item.metadata.network,\n                Type = item.metadata.type,\n                Host = host,\n                Time = (dtNow - item.start).TotalSeconds < 0 ? 1 : (dtNow - item.start).TotalSeconds,\n                Elapsed = (dtNow - item.start).ToString(@\"hh\\:mm\\:ss\"),\n                Chain = $\"{item.rule} , {string.Join(\"->\", item.chains ?? new())}\"\n            };\n\n            lstModel.Add(model);\n        }\n        if (lstModel.Count <= 0)\n        {\n            return;\n        }\n\n        ConnectionItems.AddRange(lstModel);\n        await Task.CompletedTask;\n    }\n\n    public async Task ClashConnectionClose(bool all)\n    {\n        var id = string.Empty;\n        if (!all)\n        {\n            var item = SelectedSource;\n            if (item is null)\n            {\n                return;\n            }\n            id = item.Id;\n        }\n        else\n        {\n            ConnectionItems.Clear();\n        }\n        await ClashApiManager.Instance.ClashConnectionClose(id);\n        await GetClashConnections();\n    }\n\n    public async Task DelayTestTask()\n    {\n        _ = Task.Run(async () =>\n        {\n            var numOfExecuted = 1;\n            while (true)\n            {\n                await Task.Delay(1000 * 5);\n                numOfExecuted++;\n                if (!(AutoRefresh && AppManager.Instance.ShowInTaskbar && AppManager.Instance.IsRunningCore(ECoreType.sing_box)))\n                {\n                    continue;\n                }\n\n                if (_config.ClashUIItem.ConnectionsRefreshInterval <= 0)\n                {\n                    continue;\n                }\n\n                if (numOfExecuted % _config.ClashUIItem.ConnectionsRefreshInterval != 0)\n                {\n                    continue;\n                }\n                await GetClashConnections();\n            }\n        });\n\n        await Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/ClashProxiesViewModel.cs",
    "content": "using System.Reactive.Concurrency;\nusing static ServiceLib.Models.ClashProviders;\nusing static ServiceLib.Models.ClashProxies;\n\nnamespace ServiceLib.ViewModels;\n\npublic class ClashProxiesViewModel : MyReactiveObject\n{\n    private Dictionary<string, ProxiesItem>? _proxies;\n    private Dictionary<string, ProvidersItem>? _providers;\n    private readonly int _delayTimeout = 99999999;\n\n    public IObservableCollection<ClashProxyModel> ProxyGroups { get; } = new ObservableCollectionExtended<ClashProxyModel>();\n    public IObservableCollection<ClashProxyModel> ProxyDetails { get; } = new ObservableCollectionExtended<ClashProxyModel>();\n\n    [Reactive]\n    public ClashProxyModel SelectedGroup { get; set; }\n\n    [Reactive]\n    public ClashProxyModel SelectedDetail { get; set; }\n\n    public ReactiveCommand<Unit, Unit> ProxiesReloadCmd { get; }\n    public ReactiveCommand<Unit, Unit> ProxiesDelayTestCmd { get; }\n    public ReactiveCommand<Unit, Unit> ProxiesDelayTestPartCmd { get; }\n    public ReactiveCommand<Unit, Unit> ProxiesSelectActivityCmd { get; }\n\n    [Reactive]\n    public int RuleModeSelected { get; set; }\n\n    [Reactive]\n    public int SortingSelected { get; set; }\n\n    [Reactive]\n    public bool AutoRefresh { get; set; }\n\n    public ClashProxiesViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        ProxiesReloadCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ProxiesReload();\n        });\n        ProxiesDelayTestCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ProxiesDelayTest(true);\n        });\n\n        ProxiesDelayTestPartCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ProxiesDelayTest(false);\n        });\n        ProxiesSelectActivityCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SetActiveProxy();\n        });\n\n        SelectedGroup = new();\n        SelectedDetail = new();\n        AutoRefresh = _config.ClashUIItem.ProxiesAutoRefresh;\n        SortingSelected = _config.ClashUIItem.ProxiesSorting;\n        RuleModeSelected = (int)_config.ClashUIItem.RuleMode;\n\n        #region WhenAnyValue && ReactiveCommand\n\n        this.WhenAnyValue(\n           x => x.SelectedGroup,\n           y => y != null && y.Name.IsNotEmpty())\n               .Subscribe(c => RefreshProxyDetails(c));\n\n        this.WhenAnyValue(\n           x => x.RuleModeSelected,\n           y => y >= 0)\n               .Subscribe(async c => await DoRuleModeSelected(c));\n\n        this.WhenAnyValue(\n           x => x.SortingSelected,\n           y => y >= 0)\n              .Subscribe(c => DoSortingSelected(c));\n\n        this.WhenAnyValue(\n        x => x.AutoRefresh,\n        y => y == true)\n            .Subscribe(c => { _config.ClashUIItem.ProxiesAutoRefresh = AutoRefresh; });\n\n        #endregion WhenAnyValue && ReactiveCommand\n\n        #region AppEvents\n\n        AppEvents.ProxiesReloadRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await ProxiesReload());\n\n        #endregion AppEvents\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        await DelayTestTask();\n    }\n\n    private async Task DoRuleModeSelected(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        if (_config.ClashUIItem.RuleMode == (ERuleMode)RuleModeSelected)\n        {\n            return;\n        }\n        await SetRuleModeCheck((ERuleMode)RuleModeSelected);\n    }\n\n    public async Task SetRuleModeCheck(ERuleMode mode)\n    {\n        if (_config.ClashUIItem.RuleMode == mode)\n        {\n            return;\n        }\n        await SetRuleMode(mode);\n    }\n\n    private void DoSortingSelected(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        if (SortingSelected != _config.ClashUIItem.ProxiesSorting)\n        {\n            _config.ClashUIItem.ProxiesSorting = SortingSelected;\n        }\n\n        RefreshProxyDetails(c);\n    }\n\n    public async Task ProxiesReload()\n    {\n        await GetClashProxies(true);\n        await ProxiesDelayTest();\n    }\n\n    #region proxy function\n\n    private async Task SetRuleMode(ERuleMode mode)\n    {\n        _config.ClashUIItem.RuleMode = mode;\n\n        if (mode != ERuleMode.Unchanged)\n        {\n            Dictionary<string, string> headers = new()\n                {\n                    { \"mode\", mode.ToString().ToLower() }\n                };\n            await ClashApiManager.Instance.ClashConfigUpdate(headers);\n        }\n    }\n\n    private async Task GetClashProxies(bool refreshUI)\n    {\n        var ret = await ClashApiManager.Instance.GetClashProxiesAsync();\n        if (ret?.Item1 == null || ret.Item2 == null)\n        {\n            return;\n        }\n        _proxies = ret.Item1.proxies;\n        _providers = ret?.Item2.providers;\n\n        if (refreshUI)\n        {\n            RxSchedulers.MainThreadScheduler.Schedule(() => _ = RefreshProxyGroups());\n        }\n    }\n\n    public async Task RefreshProxyGroups()\n    {\n        if (_proxies == null)\n        {\n            return;\n        }\n\n        var selectedName = SelectedGroup?.Name;\n        ProxyGroups.Clear();\n\n        var proxyGroups = ClashApiManager.Instance.GetClashProxyGroups();\n        if (proxyGroups != null && proxyGroups.Count > 0)\n        {\n            foreach (var it in proxyGroups)\n            {\n                if (it.name.IsNullOrEmpty() || !_proxies.ContainsKey(it.name))\n                {\n                    continue;\n                }\n                var item = _proxies[it.name];\n                if (!Global.allowSelectType.Contains(item.type.ToLower()))\n                {\n                    continue;\n                }\n                ProxyGroups.Add(new ClashProxyModel()\n                {\n                    Now = item.now,\n                    Name = item.name,\n                    Type = item.type\n                });\n            }\n        }\n\n        //from api\n        foreach (var kv in _proxies)\n        {\n            if (!Global.allowSelectType.Contains(kv.Value.type.ToLower()))\n            {\n                continue;\n            }\n            var item = ProxyGroups.FirstOrDefault(t => t.Name == kv.Key);\n            if (item != null && item.Name.IsNotEmpty())\n            {\n                continue;\n            }\n            ProxyGroups.Add(new ClashProxyModel()\n            {\n                Now = kv.Value.now,\n                Name = kv.Key,\n                Type = kv.Value.type\n            });\n        }\n\n        if (ProxyGroups != null && ProxyGroups.Count > 0)\n        {\n            if (selectedName != null && ProxyGroups.Any(t => t.Name == selectedName))\n            {\n                SelectedGroup = ProxyGroups.FirstOrDefault(t => t.Name == selectedName);\n            }\n            else\n            {\n                SelectedGroup = ProxyGroups.First();\n            }\n        }\n        else\n        {\n            SelectedGroup = new();\n        }\n        await Task.CompletedTask;\n    }\n\n    private void RefreshProxyDetails(bool c)\n    {\n        ProxyDetails.Clear();\n        if (!c)\n        {\n            return;\n        }\n        var name = SelectedGroup?.Name;\n        if (name.IsNullOrEmpty())\n        {\n            return;\n        }\n        if (_proxies == null)\n        {\n            return;\n        }\n\n        _proxies.TryGetValue(name, out var proxy);\n        if (proxy?.all == null)\n        {\n            return;\n        }\n        var lstDetails = new List<ClashProxyModel>();\n        foreach (var item in proxy.all)\n        {\n            var proxy2 = TryGetProxy(item);\n            if (proxy2 == null)\n            {\n                continue;\n            }\n            var delay = proxy2.history?.Count > 0 ? proxy2.history.Last().delay : -1;\n\n            lstDetails.Add(new ClashProxyModel()\n            {\n                IsActive = item == proxy.now,\n                Name = item,\n                Type = proxy2.type,\n                Delay = delay <= 0 ? _delayTimeout : delay,\n                DelayName = delay <= 0 ? string.Empty : $\"{delay}ms\",\n            });\n        }\n        //sort\n        switch (SortingSelected)\n        {\n            case 0:\n                lstDetails = lstDetails.OrderBy(t => t.Delay).ToList();\n                break;\n\n            case 1:\n                lstDetails = lstDetails.OrderBy(t => t.Name).ToList();\n                break;\n\n            default:\n                break;\n        }\n        ProxyDetails.AddRange(lstDetails);\n    }\n\n    private ProxiesItem? TryGetProxy(string name)\n    {\n        if (_proxies == null)\n        {\n            return null;\n        }\n        _proxies.TryGetValue(name, out var proxy2);\n        if (proxy2 != null)\n        {\n            return proxy2;\n        }\n        //from providers\n        if (_providers != null)\n        {\n            foreach (var kv in _providers)\n            {\n                if (Global.proxyVehicleType.Contains(kv.Value.vehicleType.ToLower()))\n                {\n                    var proxy3 = kv.Value.proxies.FirstOrDefault(t => t.name == name);\n                    if (proxy3 != null)\n                    {\n                        return proxy3;\n                    }\n                }\n            }\n        }\n        return null;\n    }\n\n    public async Task SetActiveProxy()\n    {\n        if (SelectedGroup == null || SelectedGroup.Name.IsNullOrEmpty())\n        {\n            return;\n        }\n        if (SelectedDetail == null || SelectedDetail.Name.IsNullOrEmpty())\n        {\n            return;\n        }\n        var name = SelectedGroup.Name;\n        if (name.IsNullOrEmpty())\n        {\n            return;\n        }\n        var nameNode = SelectedDetail.Name;\n        if (nameNode.IsNullOrEmpty())\n        {\n            return;\n        }\n        var selectedProxy = TryGetProxy(name);\n        if (selectedProxy == null || selectedProxy.type != \"Selector\")\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n            return;\n        }\n\n        await ClashApiManager.Instance.ClashSetActiveProxy(name, nameNode);\n\n        selectedProxy.now = nameNode;\n        var group = ProxyGroups.FirstOrDefault(it => it.Name == SelectedGroup.Name);\n        if (group != null)\n        {\n            group.Now = nameNode;\n            var group2 = JsonUtils.DeepCopy(group);\n            ProxyGroups.Replace(group, group2);\n\n            SelectedGroup = group2;\n        }\n        NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n    }\n\n    private async Task ProxiesDelayTest(bool blAll = true)\n    {\n        ClashApiManager.Instance.ClashProxiesDelayTest(blAll, ProxyDetails.ToList(), async (item, result) =>\n        {\n            if (item == null || result.IsNullOrEmpty())\n            {\n                return;\n            }\n\n            var model = new SpeedTestResult() { IndexId = item.Name, Delay = result };\n            RxSchedulers.MainThreadScheduler.Schedule(model, (scheduler, model) =>\n            {\n                _ = ProxiesDelayTestResult(model);\n                return Disposable.Empty;\n            });\n            await Task.CompletedTask;\n        });\n        await Task.CompletedTask;\n    }\n\n    public async Task ProxiesDelayTestResult(SpeedTestResult result)\n    {\n        var detail = ProxyDetails.FirstOrDefault(it => it.Name == result.IndexId);\n        if (detail == null)\n        {\n            return;\n        }\n\n        var dicResult = JsonUtils.Deserialize<Dictionary<string, object>>(result.Delay);\n        if (dicResult != null && dicResult.TryGetValue(\"delay\", out var value))\n        {\n            detail.Delay = Convert.ToInt32(value.ToString());\n            detail.DelayName = $\"{detail.Delay}ms\";\n        }\n        else if (dicResult != null && dicResult.TryGetValue(\"message\", out var value1))\n        {\n            detail.Delay = _delayTimeout;\n            detail.DelayName = $\"{value1}\";\n        }\n        else\n        {\n            detail.Delay = _delayTimeout;\n            detail.DelayName = string.Empty;\n        }\n        await Task.CompletedTask;\n    }\n\n    #endregion proxy function\n\n    #region task\n\n    public async Task DelayTestTask()\n    {\n        _ = Task.Run(async () =>\n          {\n              var numOfExecuted = 1;\n              while (true)\n              {\n                  await Task.Delay(1000 * 60);\n                  numOfExecuted++;\n                  if (!(AutoRefresh && AppManager.Instance.ShowInTaskbar && AppManager.Instance.IsRunningCore(ECoreType.sing_box)))\n                  {\n                      continue;\n                  }\n                  if (_config.ClashUIItem.ProxiesAutoDelayTestInterval <= 0)\n                  {\n                      continue;\n                  }\n                  if (numOfExecuted % _config.ClashUIItem.ProxiesAutoDelayTestInterval != 0)\n                  {\n                      continue;\n                  }\n                  await ProxiesDelayTest();\n              }\n          });\n        await Task.CompletedTask;\n    }\n\n    #endregion task\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/DNSSettingViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class DNSSettingViewModel : MyReactiveObject\n{\n    [Reactive] public bool? UseSystemHosts { get; set; }\n    [Reactive] public bool? AddCommonHosts { get; set; }\n    [Reactive] public bool? FakeIP { get; set; }\n    [Reactive] public bool? BlockBindingQuery { get; set; }\n    [Reactive] public string? DirectDNS { get; set; }\n    [Reactive] public string? RemoteDNS { get; set; }\n    [Reactive] public string? BootstrapDNS { get; set; }\n    [Reactive] public string? Strategy4Freedom { get; set; }\n    [Reactive] public string? Strategy4Proxy { get; set; }\n    [Reactive] public string? Hosts { get; set; }\n    [Reactive] public string? DirectExpectedIPs { get; set; }\n    [Reactive] public bool? ParallelQuery { get; set; }\n    [Reactive] public bool? ServeStale { get; set; }\n\n    [Reactive] public bool UseSystemHostsCompatible { get; set; }\n    [Reactive] public string DomainStrategy4FreedomCompatible { get; set; }\n    [Reactive] public string DomainDNSAddressCompatible { get; set; }\n    [Reactive] public string NormalDNSCompatible { get; set; }\n\n    [Reactive] public string DomainStrategy4Freedom2Compatible { get; set; }\n    [Reactive] public string DomainDNSAddress2Compatible { get; set; }\n    [Reactive] public string NormalDNS2Compatible { get; set; }\n    [Reactive] public string TunDNS2Compatible { get; set; }\n    [Reactive] public bool RayCustomDNSEnableCompatible { get; set; }\n    [Reactive] public bool SBCustomDNSEnableCompatible { get; set; }\n\n    [ObservableAsProperty] public bool IsSimpleDNSEnabled { get; }\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n    public ReactiveCommand<Unit, Unit> ImportDefConfig4V2rayCompatibleCmd { get; }\n    public ReactiveCommand<Unit, Unit> ImportDefConfig4SingboxCompatibleCmd { get; }\n\n    public DNSSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n        SaveCmd = ReactiveCommand.CreateFromTask(SaveSettingAsync);\n\n        ImportDefConfig4V2rayCompatibleCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            NormalDNSCompatible = EmbedUtils.GetEmbedText(Global.DNSV2rayNormalFileName);\n            await Task.CompletedTask;\n        });\n\n        ImportDefConfig4SingboxCompatibleCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            NormalDNS2Compatible = EmbedUtils.GetEmbedText(Global.DNSSingboxNormalFileName);\n            TunDNS2Compatible = EmbedUtils.GetEmbedText(Global.TunSingboxDNSFileName);\n            await Task.CompletedTask;\n        });\n\n        this.WhenAnyValue(x => x.RayCustomDNSEnableCompatible, x => x.SBCustomDNSEnableCompatible)\n            .Select(x => !(x.Item1 && x.Item2))\n            .ToPropertyEx(this, x => x.IsSimpleDNSEnabled);\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        _config = AppManager.Instance.Config;\n        var item = _config.SimpleDNSItem;\n        UseSystemHosts = item.UseSystemHosts;\n        AddCommonHosts = item.AddCommonHosts;\n        FakeIP = item.FakeIP;\n        BlockBindingQuery = item.BlockBindingQuery;\n        DirectDNS = item.DirectDNS;\n        RemoteDNS = item.RemoteDNS;\n        BootstrapDNS = item.BootstrapDNS;\n        Strategy4Freedom = item.Strategy4Freedom;\n        Strategy4Proxy = item.Strategy4Proxy;\n        Hosts = item.Hosts;\n        DirectExpectedIPs = item.DirectExpectedIPs;\n        ParallelQuery = item.ParallelQuery;\n        ServeStale = item.ServeStale;\n\n        var item1 = await AppManager.Instance.GetDNSItem(ECoreType.Xray);\n        RayCustomDNSEnableCompatible = item1.Enabled;\n        UseSystemHostsCompatible = item1.UseSystemHosts;\n        DomainStrategy4FreedomCompatible = item1?.DomainStrategy4Freedom ?? string.Empty;\n        DomainDNSAddressCompatible = item1?.DomainDNSAddress ?? string.Empty;\n        NormalDNSCompatible = item1?.NormalDNS ?? string.Empty;\n\n        var item2 = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);\n        SBCustomDNSEnableCompatible = item2.Enabled;\n        DomainStrategy4Freedom2Compatible = item2?.DomainStrategy4Freedom ?? string.Empty;\n        DomainDNSAddress2Compatible = item2?.DomainDNSAddress ?? string.Empty;\n        NormalDNS2Compatible = item2?.NormalDNS ?? string.Empty;\n        TunDNS2Compatible = item2?.TunDNS ?? string.Empty;\n    }\n\n    private async Task SaveSettingAsync()\n    {\n        _config.SimpleDNSItem.UseSystemHosts = UseSystemHosts;\n        _config.SimpleDNSItem.AddCommonHosts = AddCommonHosts;\n        _config.SimpleDNSItem.FakeIP = FakeIP;\n        _config.SimpleDNSItem.BlockBindingQuery = BlockBindingQuery;\n        _config.SimpleDNSItem.DirectDNS = DirectDNS;\n        _config.SimpleDNSItem.RemoteDNS = RemoteDNS;\n        _config.SimpleDNSItem.BootstrapDNS = BootstrapDNS;\n        _config.SimpleDNSItem.Strategy4Freedom = Strategy4Freedom;\n        _config.SimpleDNSItem.Strategy4Proxy = Strategy4Proxy;\n        _config.SimpleDNSItem.Hosts = Hosts;\n        _config.SimpleDNSItem.DirectExpectedIPs = DirectExpectedIPs;\n        _config.SimpleDNSItem.ParallelQuery = ParallelQuery;\n        _config.SimpleDNSItem.ServeStale = ServeStale;\n\n        if (NormalDNSCompatible.IsNotEmpty())\n        {\n            var obj = JsonUtils.ParseJson(NormalDNSCompatible);\n            if (obj != null && obj[\"servers\"] != null)\n            {\n            }\n            else\n            {\n                if (NormalDNSCompatible.Contains('{') || NormalDNSCompatible.Contains('}'))\n                {\n                    NoticeManager.Instance.Enqueue(ResUI.FillCorrectDNSText);\n                    return;\n                }\n            }\n        }\n        if (NormalDNS2Compatible.IsNotEmpty())\n        {\n            var obj2 = JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2Compatible);\n            if (obj2 == null)\n            {\n                NoticeManager.Instance.Enqueue(ResUI.FillCorrectDNSText);\n                return;\n            }\n        }\n        if (TunDNS2Compatible.IsNotEmpty())\n        {\n            var obj2 = JsonUtils.Deserialize<Dns4Sbox>(TunDNS2Compatible);\n            if (obj2 == null)\n            {\n                NoticeManager.Instance.Enqueue(ResUI.FillCorrectDNSText);\n                return;\n            }\n        }\n\n        var item1 = await AppManager.Instance.GetDNSItem(ECoreType.Xray);\n        item1.Enabled = RayCustomDNSEnableCompatible;\n        item1.DomainStrategy4Freedom = DomainStrategy4FreedomCompatible;\n        item1.DomainDNSAddress = DomainDNSAddressCompatible;\n        item1.UseSystemHosts = UseSystemHostsCompatible;\n        item1.NormalDNS = NormalDNSCompatible;\n        await ConfigHandler.SaveDNSItems(_config, item1);\n\n        var item2 = await AppManager.Instance.GetDNSItem(ECoreType.sing_box);\n        item2.Enabled = SBCustomDNSEnableCompatible;\n        item2.DomainStrategy4Freedom = DomainStrategy4Freedom2Compatible;\n        item2.DomainDNSAddress = DomainDNSAddress2Compatible;\n        item2.NormalDNS = JsonUtils.Serialize(JsonUtils.ParseJson(NormalDNS2Compatible));\n        item2.TunDNS = JsonUtils.Serialize(JsonUtils.ParseJson(TunDNS2Compatible));\n        await ConfigHandler.SaveDNSItems(_config, item2);\n\n        await ConfigHandler.SaveConfig(_config);\n        if (_updateView != null)\n        {\n            await _updateView(EViewAction.CloseWindow, null);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/FullConfigTemplateViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class FullConfigTemplateViewModel : MyReactiveObject\n{\n    #region Reactive\n\n    [Reactive]\n    public bool EnableFullConfigTemplate4Ray { get; set; }\n\n    [Reactive]\n    public bool EnableFullConfigTemplate4Singbox { get; set; }\n\n    [Reactive]\n    public string FullConfigTemplate4Ray { get; set; }\n\n    [Reactive]\n    public string FullConfigTemplate4Singbox { get; set; }\n\n    [Reactive]\n    public string FullTunConfigTemplate4Singbox { get; set; }\n\n    [Reactive]\n    public bool AddProxyOnly4Ray { get; set; }\n\n    [Reactive]\n    public bool AddProxyOnly4Singbox { get; set; }\n\n    [Reactive]\n    public string ProxyDetour4Ray { get; set; }\n\n    [Reactive]\n    public string ProxyDetour4Singbox { get; set; }\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    #endregion Reactive\n\n    public FullConfigTemplateViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveSettingAsync();\n        });\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        var item = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.Xray);\n        EnableFullConfigTemplate4Ray = item?.Enabled ?? false;\n        FullConfigTemplate4Ray = item?.Config ?? string.Empty;\n        AddProxyOnly4Ray = item?.AddProxyOnly ?? false;\n        ProxyDetour4Ray = item?.ProxyDetour ?? string.Empty;\n\n        var item2 = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);\n        EnableFullConfigTemplate4Singbox = item2?.Enabled ?? false;\n        FullConfigTemplate4Singbox = item2?.Config ?? string.Empty;\n        FullTunConfigTemplate4Singbox = item2?.TunConfig ?? string.Empty;\n        AddProxyOnly4Singbox = item2?.AddProxyOnly ?? false;\n        ProxyDetour4Singbox = item2?.ProxyDetour ?? string.Empty;\n    }\n\n    private async Task SaveSettingAsync()\n    {\n        if (!await SaveXrayConfigAsync())\n        {\n            return;\n        }\n\n        if (!await SaveSingboxConfigAsync())\n        {\n            return;\n        }\n\n        NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n        _ = _updateView?.Invoke(EViewAction.CloseWindow, null);\n    }\n\n    private async Task<bool> SaveXrayConfigAsync()\n    {\n        var item = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.Xray);\n        item.Enabled = EnableFullConfigTemplate4Ray;\n        item.Config = null;\n\n        item.Config = FullConfigTemplate4Ray;\n\n        item.AddProxyOnly = AddProxyOnly4Ray;\n        item.ProxyDetour = ProxyDetour4Ray;\n\n        await ConfigHandler.SaveFullConfigTemplate(_config, item);\n        return true;\n    }\n\n    private async Task<bool> SaveSingboxConfigAsync()\n    {\n        var item = await AppManager.Instance.GetFullConfigTemplateItem(ECoreType.sing_box);\n        item.Enabled = EnableFullConfigTemplate4Singbox;\n        item.Config = null;\n        item.TunConfig = null;\n\n        item.Config = FullConfigTemplate4Singbox;\n        item.TunConfig = FullTunConfigTemplate4Singbox;\n\n        item.AddProxyOnly = AddProxyOnly4Singbox;\n        item.ProxyDetour = ProxyDetour4Singbox;\n\n        await ConfigHandler.SaveFullConfigTemplate(_config, item);\n        return true;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/GlobalHotkeySettingViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class GlobalHotkeySettingViewModel : MyReactiveObject\n{\n    private readonly List<KeyEventItem> _globalHotkeys;\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    public GlobalHotkeySettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        _globalHotkeys = JsonUtils.DeepCopy(_config.GlobalHotkeys);\n\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveSettingAsync();\n        });\n    }\n\n    public KeyEventItem GetKeyEventItem(EGlobalHotkey eg)\n    {\n        var item = _globalHotkeys.FirstOrDefault((it) => it.EGlobalHotkey == eg);\n        if (item != null)\n        {\n            return item;\n        }\n\n        item = new()\n        {\n            EGlobalHotkey = eg,\n            Control = false,\n            Alt = false,\n            Shift = false,\n            KeyCode = null\n        };\n        _globalHotkeys.Add(item);\n\n        return item;\n    }\n\n    public void ResetKeyEventItem()\n    {\n        _globalHotkeys.Clear();\n    }\n\n    private async Task SaveSettingAsync()\n    {\n        _config.GlobalHotkeys = _globalHotkeys;\n\n        if (await ConfigHandler.SaveConfig(_config) == 0)\n        {\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/MainWindowViewModel.cs",
    "content": "using System.Reactive.Concurrency;\n\nnamespace ServiceLib.ViewModels;\n\npublic class MainWindowViewModel : MyReactiveObject\n{\n    #region Menu\n\n    //servers\n    public ReactiveCommand<Unit, Unit> AddVmessServerCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> AddVlessServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddShadowsocksServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddSocksServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddHttpServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddTrojanServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddHysteria2ServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddTuicServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddWireguardServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddAnytlsServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddCustomServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddPolicyGroupServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddProxyChainServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddServerViaImageCmd { get; }\n\n    //Subscription\n    public ReactiveCommand<Unit, Unit> SubSettingCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubGroupUpdateCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubGroupUpdateViaProxyCmd { get; }\n\n    //Setting\n    public ReactiveCommand<Unit, Unit> OptionSettingCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> RoutingSettingCmd { get; }\n    public ReactiveCommand<Unit, Unit> DNSSettingCmd { get; }\n    public ReactiveCommand<Unit, Unit> FullConfigTemplateCmd { get; }\n    public ReactiveCommand<Unit, Unit> GlobalHotkeySettingCmd { get; }\n    public ReactiveCommand<Unit, Unit> RebootAsAdminCmd { get; }\n    public ReactiveCommand<Unit, Unit> ClearServerStatisticsCmd { get; }\n    public ReactiveCommand<Unit, Unit> OpenTheFileLocationCmd { get; }\n\n    //Presets\n    public ReactiveCommand<Unit, Unit> RegionalPresetDefaultCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> RegionalPresetRussiaCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> RegionalPresetIranCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> ReloadCmd { get; }\n\n    [Reactive]\n    public bool BlReloadEnabled { get; set; }\n\n    [Reactive]\n    public bool ShowClashUI { get; set; }\n\n    [Reactive]\n    public int TabMainSelectedIndex { get; set; }\n\n    [Reactive] public bool BlIsWindows { get; set; }\n\n    #endregion Menu\n\n    #region Init\n\n    public MainWindowViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n        BlIsWindows = Utils.IsWindows();\n\n        #region WhenAnyValue && ReactiveCommand\n\n        //servers\n        AddVmessServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.VMess);\n        });\n        AddVlessServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.VLESS);\n        });\n        AddShadowsocksServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.Shadowsocks);\n        });\n        AddSocksServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.SOCKS);\n        });\n        AddHttpServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.HTTP);\n        });\n        AddTrojanServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.Trojan);\n        });\n        AddHysteria2ServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.Hysteria2);\n        });\n        AddTuicServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.TUIC);\n        });\n        AddWireguardServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.WireGuard);\n        });\n        AddAnytlsServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.Anytls);\n        });\n        AddCustomServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.Custom);\n        });\n        AddPolicyGroupServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.PolicyGroup);\n        });\n        AddProxyChainServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerAsync(EConfigType.ProxyChain);\n        });\n        AddServerViaClipboardCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerViaClipboardAsync(null);\n        });\n        AddServerViaScanCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerViaScanAsync();\n        });\n        AddServerViaImageCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerViaImageAsync();\n        });\n\n        //Subscription\n        SubSettingCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SubSettingAsync();\n        });\n\n        SubUpdateCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await UpdateSubscriptionProcess(\"\", false);\n        });\n        SubUpdateViaProxyCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await UpdateSubscriptionProcess(\"\", true);\n        });\n        SubGroupUpdateCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await UpdateSubscriptionProcess(_config.SubIndexId, false);\n        });\n        SubGroupUpdateViaProxyCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await UpdateSubscriptionProcess(_config.SubIndexId, true);\n        });\n\n        //Setting\n        OptionSettingCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await OptionSettingAsync();\n        });\n        RoutingSettingCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RoutingSettingAsync();\n        });\n        DNSSettingCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await DNSSettingAsync();\n        });\n        FullConfigTemplateCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await FullConfigTemplateAsync();\n        });\n        GlobalHotkeySettingCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            if (await _updateView?.Invoke(EViewAction.GlobalHotkeySettingWindow, null) == true)\n            {\n                NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n            }\n        });\n        RebootAsAdminCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AppManager.Instance.RebootAsAdmin();\n        });\n        ClearServerStatisticsCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ClearServerStatistics();\n        });\n        OpenTheFileLocationCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await OpenTheFileLocation();\n        });\n\n        ReloadCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await Reload();\n        });\n\n        RegionalPresetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ApplyRegionalPreset(EPresetType.Default);\n        });\n\n        RegionalPresetRussiaCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ApplyRegionalPreset(EPresetType.Russia);\n        });\n\n        RegionalPresetIranCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ApplyRegionalPreset(EPresetType.Iran);\n        });\n\n        #endregion WhenAnyValue && ReactiveCommand\n\n        #region AppEvents\n\n        AppEvents.ReloadRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await Reload());\n\n        AppEvents.AddServerViaScanRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await AddServerViaScanAsync());\n\n        AppEvents.AddServerViaClipboardRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await AddServerViaClipboardAsync(null));\n\n        AppEvents.SubscriptionsUpdateRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async blProxy => await UpdateSubscriptionProcess(\"\", blProxy));\n\n        #endregion AppEvents\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        AppManager.Instance.ShowInTaskbar = true;\n\n        //await ConfigHandler.InitBuiltinRouting(_config);\n        await ConfigHandler.InitBuiltinDNS(_config);\n        await ConfigHandler.InitBuiltinFullConfigTemplate(_config);\n        await ProfileExManager.Instance.Init();\n        await CoreManager.Instance.Init(_config, UpdateHandler);\n        TaskManager.Instance.RegUpdateTask(_config, UpdateTaskHandler);\n\n        if (_config.GuiItem.EnableStatistics || _config.GuiItem.DisplayRealTimeSpeed)\n        {\n            await StatisticsManager.Instance.Init(_config, UpdateStatisticsHandler);\n        }\n        await RefreshServers();\n\n        await Reload();\n    }\n\n    #endregion Init\n\n    #region Actions\n\n    private async Task UpdateHandler(bool notify, string msg)\n    {\n        NoticeManager.Instance.SendMessage(msg);\n        if (notify)\n        {\n            NoticeManager.Instance.Enqueue(msg);\n        }\n        await Task.CompletedTask;\n    }\n\n    private async Task UpdateTaskHandler(bool success, string msg)\n    {\n        NoticeManager.Instance.SendMessageEx(msg);\n        if (success)\n        {\n            var indexIdOld = _config.IndexId;\n            await RefreshServers();\n            if (indexIdOld != _config.IndexId)\n            {\n                await Reload();\n            }\n            if (_config.UiItem.EnableAutoAdjustMainLvColWidth)\n            {\n                AppEvents.AdjustMainLvColWidthRequested.Publish();\n            }\n        }\n    }\n\n    private async Task UpdateStatisticsHandler(ServerSpeedItem update)\n    {\n        if (!AppManager.Instance.ShowInTaskbar)\n        {\n            return;\n        }\n        AppEvents.DispatcherStatisticsRequested.Publish(update);\n        await Task.CompletedTask;\n    }\n\n    #endregion Actions\n\n    #region Servers && Groups\n\n    private async Task RefreshServers()\n    {\n        AppEvents.ProfilesRefreshRequested.Publish();\n\n        await Task.Delay(200);\n    }\n\n    private void RefreshSubscriptions()\n    {\n        AppEvents.SubscriptionsRefreshRequested.Publish();\n    }\n\n    #endregion Servers && Groups\n\n    #region Add Servers\n\n    public async Task AddServerAsync(EConfigType eConfigType)\n    {\n        ProfileItem item = new()\n        {\n            Subid = _config.SubIndexId,\n            ConfigType = eConfigType,\n            IsSub = false,\n        };\n\n        bool? ret = false;\n        if (eConfigType == EConfigType.Custom)\n        {\n            ret = await _updateView?.Invoke(EViewAction.AddServer2Window, item);\n        }\n        else if (eConfigType.IsGroupType())\n        {\n            ret = await _updateView?.Invoke(EViewAction.AddGroupServerWindow, item);\n        }\n        else\n        {\n            ret = await _updateView?.Invoke(EViewAction.AddServerWindow, item);\n        }\n        if (ret == true)\n        {\n            await RefreshServers();\n            if (item.IndexId == _config.IndexId)\n            {\n                await Reload();\n            }\n        }\n    }\n\n    public async Task AddServerViaClipboardAsync(string? clipboardData)\n    {\n        if (clipboardData == null)\n        {\n            await _updateView?.Invoke(EViewAction.AddServerViaClipboard, null);\n            return;\n        }\n        var ret = await ConfigHandler.AddBatchServers(_config, clipboardData, _config.SubIndexId, false);\n        if (ret > 0)\n        {\n            RefreshSubscriptions();\n            await RefreshServers();\n            NoticeManager.Instance.Enqueue(string.Format(ResUI.SuccessfullyImportedServerViaClipboard, ret));\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n\n    public async Task AddServerViaScanAsync()\n    {\n        _updateView?.Invoke(EViewAction.ScanScreenTask, null);\n        await Task.CompletedTask;\n    }\n\n    public async Task ScanScreenResult(byte[]? bytes)\n    {\n        var result = QRCodeUtils.ParseBarcode(bytes);\n        await AddScanResultAsync(result);\n    }\n\n    public async Task AddServerViaImageAsync()\n    {\n        _updateView?.Invoke(EViewAction.ScanImageTask, null);\n        await Task.CompletedTask;\n    }\n\n    public async Task ScanImageResult(string fileName)\n    {\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        var result = QRCodeUtils.ParseBarcode(fileName);\n        await AddScanResultAsync(result);\n    }\n\n    private async Task AddScanResultAsync(string? result)\n    {\n        if (result.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.NoValidQRcodeFound);\n        }\n        else\n        {\n            var ret = await ConfigHandler.AddBatchServers(_config, result, _config.SubIndexId, false);\n            if (ret > 0)\n            {\n                RefreshSubscriptions();\n                await RefreshServers();\n                NoticeManager.Instance.Enqueue(ResUI.SuccessfullyImportedServerViaScan);\n            }\n            else\n            {\n                NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n            }\n        }\n    }\n\n    #endregion Add Servers\n\n    #region Subscription\n\n    private async Task SubSettingAsync()\n    {\n        if (await _updateView?.Invoke(EViewAction.SubSettingWindow, null) == true)\n        {\n            RefreshSubscriptions();\n        }\n    }\n\n    public async Task UpdateSubscriptionProcess(string subId, bool blProxy)\n    {\n        await Task.Run(async () => await SubscriptionHandler.UpdateProcess(_config, subId, blProxy, UpdateTaskHandler));\n    }\n\n    #endregion Subscription\n\n    #region Setting\n\n    private async Task OptionSettingAsync()\n    {\n        var ret = await _updateView?.Invoke(EViewAction.OptionSettingWindow, null);\n        if (ret == true)\n        {\n            AppEvents.InboundDisplayRequested.Publish();\n            await Reload();\n        }\n    }\n\n    private async Task RoutingSettingAsync()\n    {\n        var ret = await _updateView?.Invoke(EViewAction.RoutingSettingWindow, null);\n        if (ret == true)\n        {\n            await ConfigHandler.InitBuiltinRouting(_config);\n            AppEvents.RoutingsMenuRefreshRequested.Publish();\n            await Reload();\n        }\n    }\n\n    private async Task DNSSettingAsync()\n    {\n        var ret = await _updateView?.Invoke(EViewAction.DNSSettingWindow, null);\n        if (ret == true)\n        {\n            await Reload();\n        }\n    }\n\n    private async Task FullConfigTemplateAsync()\n    {\n        var ret = await _updateView?.Invoke(EViewAction.FullConfigTemplateWindow, null);\n        if (ret == true)\n        {\n            await Reload();\n        }\n    }\n\n    private async Task ClearServerStatistics()\n    {\n        await StatisticsManager.Instance.ClearAllServerStatistics();\n        await RefreshServers();\n    }\n\n    private async Task OpenTheFileLocation()\n    {\n        var path = Utils.StartupPath();\n        if (Utils.IsWindows())\n        {\n            ProcUtils.ProcessStart(path);\n        }\n        else if (Utils.IsLinux())\n        {\n            ProcUtils.ProcessStart(\"xdg-open\", path);\n        }\n        else if (Utils.IsMacOS())\n        {\n            ProcUtils.ProcessStart(\"open\", path);\n        }\n        await Task.CompletedTask;\n    }\n\n    #endregion Setting\n\n    #region core job\n\n    private bool _hasNextReloadJob = false;\n    private readonly SemaphoreSlim _reloadSemaphore = new(1, 1);\n\n    public async Task Reload()\n    {\n        //If there are unfinished reload job, marked with next job.\n        if (!await _reloadSemaphore.WaitAsync(0))\n        {\n            _hasNextReloadJob = true;\n            return;\n        }\n\n        try\n        {\n            SetReloadEnabled(false);\n\n            var profileItem = await ConfigHandler.GetDefaultServer(_config);\n            if (profileItem == null)\n            {\n                NoticeManager.Instance.Enqueue(ResUI.CheckServerSettings);\n                return;\n            }\n            var allResult = await CoreConfigContextBuilder.BuildAll(_config, profileItem);\n            if (NoticeManager.Instance.NotifyValidatorResult(allResult.CombinedValidatorResult) && !allResult.Success)\n            {\n                return;\n            }\n\n            await Task.Run(async () =>\n            {\n                await LoadCore(allResult.ResolvedMainContext, allResult.PreSocksResult?.Context);\n                await SysProxyHandler.UpdateSysProxy(_config, false);\n                await Task.Delay(1000);\n            });\n            AppEvents.TestServerRequested.Publish();\n\n            var showClashUI = AppManager.Instance.IsRunningCore(ECoreType.sing_box);\n            if (showClashUI)\n            {\n                AppEvents.ProxiesReloadRequested.Publish();\n            }\n\n            ReloadResult(showClashUI);\n        }\n        finally\n        {\n            SetReloadEnabled(true);\n            _reloadSemaphore.Release();\n            //If there is a next reload job, execute it.\n            if (_hasNextReloadJob)\n            {\n                _hasNextReloadJob = false;\n                await Reload();\n            }\n        }\n    }\n\n    private void ReloadResult(bool showClashUI)\n    {\n        RxSchedulers.MainThreadScheduler.Schedule(() =>\n        {\n            ShowClashUI = showClashUI;\n            TabMainSelectedIndex = showClashUI ? TabMainSelectedIndex : 0;\n        });\n    }\n\n    private void SetReloadEnabled(bool enabled)\n    {\n        RxSchedulers.MainThreadScheduler.Schedule(() => BlReloadEnabled = enabled);\n    }\n\n    private async Task LoadCore(CoreConfigContext? mainContext, CoreConfigContext? preContext)\n    {\n        await CoreManager.Instance.LoadCore(mainContext, preContext);\n    }\n\n    #endregion core job\n\n    #region Presets\n\n    public async Task ApplyRegionalPreset(EPresetType type)\n    {\n        await ConfigHandler.ApplyRegionalPreset(_config, type);\n        await ConfigHandler.InitRouting(_config);\n        AppEvents.RoutingsMenuRefreshRequested.Publish();\n\n        await ConfigHandler.SaveConfig(_config);\n        await new UpdateService(_config, UpdateTaskHandler).UpdateGeoFileAll();\n        await Reload();\n    }\n\n    #endregion Presets\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/MsgViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class MsgViewModel : MyReactiveObject\n{\n    private readonly ConcurrentQueue<string> _queueMsg = new();\n    private volatile bool _lastMsgFilterNotAvailable;\n    private int _showLock = 0; // 0 = unlocked, 1 = locked\n    public int NumMaxMsg { get; } = 500;\n\n    [Reactive]\n    public string MsgFilter { get; set; }\n\n    [Reactive]\n    public bool AutoRefresh { get; set; }\n\n    public MsgViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n        MsgFilter = _config.MsgUIItem.MainMsgFilter ?? string.Empty;\n        AutoRefresh = _config.MsgUIItem.AutoRefresh ?? true;\n\n        this.WhenAnyValue(\n           x => x.MsgFilter)\n               .Subscribe(c => DoMsgFilter());\n\n        this.WhenAnyValue(\n          x => x.AutoRefresh,\n          y => y == true)\n              .Subscribe(c => _config.MsgUIItem.AutoRefresh = AutoRefresh);\n\n        AppEvents.SendMsgViewRequested\n         .AsObservable()\n         //.ObserveOn(RxSchedulers.MainThreadScheduler)\n         .Subscribe(content => _ = AppendQueueMsg(content));\n    }\n\n    private async Task AppendQueueMsg(string msg)\n    {\n        if (AutoRefresh == false)\n        {\n            return;\n        }\n\n        EnqueueQueueMsg(msg);\n\n        if (!AppManager.Instance.ShowInTaskbar)\n        {\n            return;\n        }\n\n        if (Interlocked.CompareExchange(ref _showLock, 1, 0) != 0)\n        {\n            return;\n        }\n\n        try\n        {\n            await Task.Delay(500).ConfigureAwait(false);\n\n            var sb = new StringBuilder();\n            while (_queueMsg.TryDequeue(out var line))\n            {\n                sb.Append(line);\n            }\n\n            await _updateView?.Invoke(EViewAction.DispatcherShowMsg, sb.ToString());\n        }\n        finally\n        {\n            Interlocked.Exchange(ref _showLock, 0);\n        }\n    }\n\n    private void EnqueueQueueMsg(string msg)\n    {\n        //filter msg\n        if (MsgFilter.IsNotEmpty() && !_lastMsgFilterNotAvailable)\n        {\n            try\n            {\n                if (!Regex.IsMatch(msg, MsgFilter))\n                {\n                    return;\n                }\n            }\n            catch (Exception ex)\n            {\n                EnqueueWithLimit(ex.Message);\n                _lastMsgFilterNotAvailable = true;\n            }\n        }\n\n        EnqueueWithLimit(msg);\n        if (!msg.EndsWith(Environment.NewLine))\n        {\n            EnqueueWithLimit(Environment.NewLine);\n        }\n    }\n\n    private void EnqueueWithLimit(string item)\n    {\n        _queueMsg.Enqueue(item);\n\n        while (_queueMsg.Count > NumMaxMsg)\n        {\n            _queueMsg.TryDequeue(out _);\n        }\n    }\n\n    //public void ClearMsg()\n    //{\n    //    _queueMsg.Clear();\n    //}\n\n    private void DoMsgFilter()\n    {\n        _config.MsgUIItem.MainMsgFilter = MsgFilter;\n        _lastMsgFilterNotAvailable = false;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/OptionSettingViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class OptionSettingViewModel : MyReactiveObject\n{\n    #region Core\n\n    [Reactive] public int localPort { get; set; }\n    [Reactive] public bool SecondLocalPortEnabled { get; set; }\n    [Reactive] public bool udpEnabled { get; set; }\n    [Reactive] public bool sniffingEnabled { get; set; }\n    public IList<string> destOverride { get; set; }\n    [Reactive] public bool routeOnly { get; set; }\n    [Reactive] public bool allowLANConn { get; set; }\n    [Reactive] public bool newPort4LAN { get; set; }\n    [Reactive] public string user { get; set; }\n    [Reactive] public string pass { get; set; }\n    [Reactive] public bool muxEnabled { get; set; }\n    [Reactive] public bool logEnabled { get; set; }\n    [Reactive] public string loglevel { get; set; }\n    [Reactive] public bool defAllowInsecure { get; set; }\n    [Reactive] public string defFingerprint { get; set; }\n    [Reactive] public string defUserAgent { get; set; }\n    [Reactive] public string mux4SboxProtocol { get; set; }\n    [Reactive] public bool enableCacheFile4Sbox { get; set; }\n    [Reactive] public int? hyUpMbps { get; set; }\n    [Reactive] public int? hyDownMbps { get; set; }\n    [Reactive] public bool enableFragment { get; set; }\n\n    #endregion Core\n\n    #region Core KCP\n\n    //[Reactive] public int Kcpmtu { get; set; }\n    //[Reactive] public int Kcptti { get; set; }\n    //[Reactive] public int KcpuplinkCapacity { get; set; }\n    //[Reactive] public int KcpdownlinkCapacity { get; set; }\n    //[Reactive] public int KcpreadBufferSize { get; set; }\n    //[Reactive] public int KcpwriteBufferSize { get; set; }\n    //[Reactive] public bool Kcpcongestion { get; set; }\n\n    #endregion Core KCP\n\n    #region UI\n\n    [Reactive] public bool AutoRun { get; set; }\n    [Reactive] public bool EnableStatistics { get; set; }\n    [Reactive] public bool KeepOlderDedupl { get; set; }\n    [Reactive] public bool DisplayRealTimeSpeed { get; set; }\n    [Reactive] public bool EnableAutoAdjustMainLvColWidth { get; set; }\n    [Reactive] public bool AutoHideStartup { get; set; }\n    [Reactive] public bool Hide2TrayWhenClose { get; set; }\n    [Reactive] public bool MacOSShowInDock { get; set; }\n    [Reactive] public bool EnableDragDropSort { get; set; }\n    [Reactive] public bool DoubleClick2Activate { get; set; }\n    [Reactive] public int AutoUpdateInterval { get; set; }\n    [Reactive] public int TrayMenuServersLimit { get; set; }\n    [Reactive] public string CurrentFontFamily { get; set; }\n    [Reactive] public int SpeedTestTimeout { get; set; }\n    [Reactive] public string SpeedTestUrl { get; set; }\n    [Reactive] public string SpeedPingTestUrl { get; set; }\n    [Reactive] public int MixedConcurrencyCount { get; set; }\n    [Reactive] public bool EnableHWA { get; set; }\n    [Reactive] public string SubConvertUrl { get; set; }\n    [Reactive] public int MainGirdOrientation { get; set; }\n    [Reactive] public string GeoFileSourceUrl { get; set; }\n    [Reactive] public string SrsFileSourceUrl { get; set; }\n    [Reactive] public string RoutingRulesSourceUrl { get; set; }\n    [Reactive] public string IPAPIUrl { get; set; }\n\n    #endregion UI\n\n    #region UI visibility\n\n    [Reactive] public bool BlIsWindows { get; set; }\n    [Reactive] public bool BlIsLinux { get; set; }\n    [Reactive] public bool BlIsIsMacOS { get; set; }\n    [Reactive] public bool BlIsNonWindows { get; set; }\n\n    #endregion UI visibility\n\n    #region System proxy\n\n    [Reactive] public bool notProxyLocalAddress { get; set; }\n    [Reactive] public string systemProxyAdvancedProtocol { get; set; }\n    [Reactive] public string systemProxyExceptions { get; set; }\n    [Reactive] public string CustomSystemProxyPacPath { get; set; }\n    [Reactive] public string CustomSystemProxyScriptPath { get; set; }\n\n    #endregion System proxy\n\n    #region Tun mode\n\n    [Reactive] public bool TunAutoRoute { get; set; }\n    [Reactive] public bool TunStrictRoute { get; set; }\n    [Reactive] public string TunStack { get; set; }\n    [Reactive] public int TunMtu { get; set; }\n    [Reactive] public bool TunEnableIPv6Address { get; set; }\n\n    #endregion Tun mode\n\n    #region CoreType\n\n    [Reactive] public string CoreType1 { get; set; }\n    [Reactive] public string CoreType2 { get; set; }\n    [Reactive] public string CoreType3 { get; set; }\n    [Reactive] public string CoreType4 { get; set; }\n    [Reactive] public string CoreType5 { get; set; }\n    [Reactive] public string CoreType6 { get; set; }\n    [Reactive] public string CoreType7 { get; set; }\n    [Reactive] public string CoreType9 { get; set; }\n\n    #endregion CoreType\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    public OptionSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n        BlIsWindows = Utils.IsWindows();\n        BlIsLinux = Utils.IsLinux();\n        BlIsIsMacOS = Utils.IsMacOS();\n        BlIsNonWindows = Utils.IsNonWindows();\n\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveSettingAsync();\n        });\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        await _updateView?.Invoke(EViewAction.InitSettingFont, null);\n\n        #region Core\n\n        var inbound = _config.Inbound.First();\n        localPort = inbound.LocalPort;\n        SecondLocalPortEnabled = inbound.SecondLocalPortEnabled;\n        udpEnabled = inbound.UdpEnabled;\n        sniffingEnabled = inbound.SniffingEnabled;\n        routeOnly = inbound.RouteOnly;\n        allowLANConn = inbound.AllowLANConn;\n        newPort4LAN = inbound.NewPort4LAN;\n        user = inbound.User;\n        pass = inbound.Pass;\n        muxEnabled = _config.CoreBasicItem.MuxEnabled;\n        logEnabled = _config.CoreBasicItem.LogEnabled;\n        loglevel = _config.CoreBasicItem.Loglevel;\n        defAllowInsecure = _config.CoreBasicItem.DefAllowInsecure;\n        defFingerprint = _config.CoreBasicItem.DefFingerprint;\n        defUserAgent = _config.CoreBasicItem.DefUserAgent;\n        mux4SboxProtocol = _config.Mux4SboxItem.Protocol;\n        enableCacheFile4Sbox = _config.CoreBasicItem.EnableCacheFile4Sbox;\n        hyUpMbps = _config.HysteriaItem.UpMbps;\n        hyDownMbps = _config.HysteriaItem.DownMbps;\n        enableFragment = _config.CoreBasicItem.EnableFragment;\n\n        #endregion Core\n\n        #region Core KCP\n\n        //Kcpmtu = _config.kcpItem.mtu;\n        //Kcptti = _config.kcpItem.tti;\n        //KcpuplinkCapacity = _config.kcpItem.uplinkCapacity;\n        //KcpdownlinkCapacity = _config.kcpItem.downlinkCapacity;\n        //KcpreadBufferSize = _config.kcpItem.readBufferSize;\n        //KcpwriteBufferSize = _config.kcpItem.writeBufferSize;\n        //Kcpcongestion = _config.kcpItem.congestion;\n\n        #endregion Core KCP\n\n        #region UI\n\n        AutoRun = _config.GuiItem.AutoRun;\n        EnableStatistics = _config.GuiItem.EnableStatistics;\n        DisplayRealTimeSpeed = _config.GuiItem.DisplayRealTimeSpeed;\n        KeepOlderDedupl = _config.GuiItem.KeepOlderDedupl;\n        EnableAutoAdjustMainLvColWidth = _config.UiItem.EnableAutoAdjustMainLvColWidth;\n        AutoHideStartup = _config.UiItem.AutoHideStartup;\n        Hide2TrayWhenClose = _config.UiItem.Hide2TrayWhenClose;\n        MacOSShowInDock = _config.UiItem.MacOSShowInDock;\n        EnableDragDropSort = _config.UiItem.EnableDragDropSort;\n        DoubleClick2Activate = _config.UiItem.DoubleClick2Activate;\n        AutoUpdateInterval = _config.GuiItem.AutoUpdateInterval;\n        TrayMenuServersLimit = _config.GuiItem.TrayMenuServersLimit;\n        CurrentFontFamily = _config.UiItem.CurrentFontFamily;\n        SpeedTestTimeout = _config.SpeedTestItem.SpeedTestTimeout;\n        SpeedTestUrl = _config.SpeedTestItem.SpeedTestUrl;\n        MixedConcurrencyCount = _config.SpeedTestItem.MixedConcurrencyCount;\n        SpeedPingTestUrl = _config.SpeedTestItem.SpeedPingTestUrl;\n        EnableHWA = _config.GuiItem.EnableHWA;\n        SubConvertUrl = _config.ConstItem.SubConvertUrl;\n        MainGirdOrientation = (int)_config.UiItem.MainGirdOrientation;\n        GeoFileSourceUrl = _config.ConstItem.GeoSourceUrl;\n        SrsFileSourceUrl = _config.ConstItem.SrsSourceUrl;\n        RoutingRulesSourceUrl = _config.ConstItem.RouteRulesTemplateSourceUrl;\n        IPAPIUrl = _config.SpeedTestItem.IPAPIUrl;\n\n        #endregion UI\n\n        #region System proxy\n\n        notProxyLocalAddress = _config.SystemProxyItem.NotProxyLocalAddress;\n        systemProxyAdvancedProtocol = _config.SystemProxyItem.SystemProxyAdvancedProtocol;\n        systemProxyExceptions = _config.SystemProxyItem.SystemProxyExceptions;\n        CustomSystemProxyPacPath = _config.SystemProxyItem.CustomSystemProxyPacPath;\n        CustomSystemProxyScriptPath = _config.SystemProxyItem.CustomSystemProxyScriptPath;\n\n        #endregion System proxy\n\n        #region Tun mode\n\n        TunAutoRoute = _config.TunModeItem.AutoRoute;\n        TunStrictRoute = _config.TunModeItem.StrictRoute;\n        TunStack = _config.TunModeItem.Stack;\n        TunMtu = _config.TunModeItem.Mtu;\n        TunEnableIPv6Address = _config.TunModeItem.EnableIPv6Address;\n\n        #endregion Tun mode\n\n        await InitCoreType();\n    }\n\n    private async Task InitCoreType()\n    {\n        if (_config.CoreTypeItem == null)\n        {\n            _config.CoreTypeItem = new List<CoreTypeItem>();\n        }\n\n        foreach (EConfigType it in Enum.GetValues(typeof(EConfigType)))\n        {\n            if (_config.CoreTypeItem.FindIndex(t => t.ConfigType == it) >= 0)\n            {\n                continue;\n            }\n\n            _config.CoreTypeItem.Add(new CoreTypeItem()\n            {\n                ConfigType = it,\n                CoreType = ECoreType.Xray\n            });\n        }\n        _config.CoreTypeItem.ForEach(it =>\n        {\n            var type = it.CoreType.ToString();\n            switch ((int)it.ConfigType)\n            {\n                case 1:\n                    CoreType1 = type;\n                    break;\n\n                case 2:\n                    CoreType2 = type;\n                    break;\n\n                case 3:\n                    CoreType3 = type;\n                    break;\n\n                case 4:\n                    CoreType4 = type;\n                    break;\n\n                case 5:\n                    CoreType5 = type;\n                    break;\n\n                case 6:\n                    CoreType6 = type;\n                    break;\n\n                case 7:\n                    CoreType7 = type;\n                    break;\n\n                case 9:\n                    CoreType9 = type;\n                    break;\n            }\n        });\n        await Task.CompletedTask;\n    }\n\n    private async Task SaveSettingAsync()\n    {\n        if (localPort.ToString().IsNullOrEmpty() || !Utils.IsNumeric(localPort.ToString())\n           || localPort <= 0 || localPort >= Global.MaxPort)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.FillLocalListeningPort);\n            return;\n        }\n        var needReboot = EnableStatistics != _config.GuiItem.EnableStatistics\n                          || DisplayRealTimeSpeed != _config.GuiItem.DisplayRealTimeSpeed\n                        || EnableDragDropSort != _config.UiItem.EnableDragDropSort\n                        || EnableHWA != _config.GuiItem.EnableHWA\n                        || CurrentFontFamily != _config.UiItem.CurrentFontFamily\n                        || MainGirdOrientation != (int)_config.UiItem.MainGirdOrientation;\n\n        //if (Utile.IsNullOrEmpty(Kcpmtu.ToString()) || !Utile.IsNumeric(Kcpmtu.ToString())\n        //       || Utile.IsNullOrEmpty(Kcptti.ToString()) || !Utile.IsNumeric(Kcptti.ToString())\n        //       || Utile.IsNullOrEmpty(KcpuplinkCapacity.ToString()) || !Utile.IsNumeric(KcpuplinkCapacity.ToString())\n        //       || Utile.IsNullOrEmpty(KcpdownlinkCapacity.ToString()) || !Utile.IsNumeric(KcpdownlinkCapacity.ToString())\n        //       || Utile.IsNullOrEmpty(KcpreadBufferSize.ToString()) || !Utile.IsNumeric(KcpreadBufferSize.ToString())\n        //       || Utile.IsNullOrEmpty(KcpwriteBufferSize.ToString()) || !Utile.IsNumeric(KcpwriteBufferSize.ToString()))\n        //{\n        //    NoticeHandler.Instance.Enqueue(ResUI.FillKcpParameters);\n        //    return;\n        //}\n\n        //Core\n        _config.Inbound.First().LocalPort = localPort;\n        _config.Inbound.First().SecondLocalPortEnabled = SecondLocalPortEnabled;\n        _config.Inbound.First().UdpEnabled = udpEnabled;\n        _config.Inbound.First().SniffingEnabled = sniffingEnabled;\n        _config.Inbound.First().DestOverride = destOverride?.ToList();\n        _config.Inbound.First().RouteOnly = routeOnly;\n        _config.Inbound.First().AllowLANConn = allowLANConn;\n        _config.Inbound.First().NewPort4LAN = newPort4LAN;\n        _config.Inbound.First().User = user;\n        _config.Inbound.First().Pass = pass;\n        if (_config.Inbound.Count > 1)\n        {\n            _config.Inbound.RemoveAt(1);\n        }\n        _config.CoreBasicItem.LogEnabled = logEnabled;\n        _config.CoreBasicItem.Loglevel = loglevel;\n        _config.CoreBasicItem.MuxEnabled = muxEnabled;\n        _config.CoreBasicItem.DefAllowInsecure = defAllowInsecure;\n        _config.CoreBasicItem.DefFingerprint = defFingerprint;\n        _config.CoreBasicItem.DefUserAgent = defUserAgent;\n        _config.Mux4SboxItem.Protocol = mux4SboxProtocol;\n        _config.CoreBasicItem.EnableCacheFile4Sbox = enableCacheFile4Sbox;\n        _config.HysteriaItem.UpMbps = hyUpMbps ?? 0;\n        _config.HysteriaItem.DownMbps = hyDownMbps ?? 0;\n        _config.CoreBasicItem.EnableFragment = enableFragment;\n\n        _config.GuiItem.AutoRun = AutoRun;\n        _config.GuiItem.EnableStatistics = EnableStatistics;\n        _config.GuiItem.DisplayRealTimeSpeed = DisplayRealTimeSpeed;\n        _config.GuiItem.KeepOlderDedupl = KeepOlderDedupl;\n        _config.UiItem.EnableAutoAdjustMainLvColWidth = EnableAutoAdjustMainLvColWidth;\n        _config.UiItem.AutoHideStartup = AutoHideStartup;\n        _config.UiItem.Hide2TrayWhenClose = Hide2TrayWhenClose;\n        _config.UiItem.MacOSShowInDock = MacOSShowInDock;\n        _config.GuiItem.AutoUpdateInterval = AutoUpdateInterval;\n        _config.UiItem.EnableDragDropSort = EnableDragDropSort;\n        _config.UiItem.DoubleClick2Activate = DoubleClick2Activate;\n        _config.GuiItem.TrayMenuServersLimit = TrayMenuServersLimit;\n        _config.UiItem.CurrentFontFamily = CurrentFontFamily;\n        _config.SpeedTestItem.SpeedTestTimeout = SpeedTestTimeout;\n        _config.SpeedTestItem.MixedConcurrencyCount = MixedConcurrencyCount;\n        _config.SpeedTestItem.SpeedTestUrl = SpeedTestUrl;\n        _config.SpeedTestItem.SpeedPingTestUrl = SpeedPingTestUrl;\n        _config.GuiItem.EnableHWA = EnableHWA;\n        _config.ConstItem.SubConvertUrl = SubConvertUrl;\n        _config.UiItem.MainGirdOrientation = (EGirdOrientation)MainGirdOrientation;\n        _config.ConstItem.GeoSourceUrl = GeoFileSourceUrl;\n        _config.ConstItem.SrsSourceUrl = SrsFileSourceUrl;\n        _config.ConstItem.RouteRulesTemplateSourceUrl = RoutingRulesSourceUrl;\n        _config.SpeedTestItem.IPAPIUrl = IPAPIUrl;\n\n        //systemProxy\n        _config.SystemProxyItem.SystemProxyExceptions = systemProxyExceptions;\n        _config.SystemProxyItem.NotProxyLocalAddress = notProxyLocalAddress;\n        _config.SystemProxyItem.SystemProxyAdvancedProtocol = systemProxyAdvancedProtocol;\n        _config.SystemProxyItem.CustomSystemProxyPacPath = CustomSystemProxyPacPath;\n        _config.SystemProxyItem.CustomSystemProxyScriptPath = CustomSystemProxyScriptPath;\n\n        //tun mode\n        _config.TunModeItem.AutoRoute = TunAutoRoute;\n        _config.TunModeItem.StrictRoute = TunStrictRoute;\n        _config.TunModeItem.Stack = TunStack;\n        _config.TunModeItem.Mtu = TunMtu;\n        _config.TunModeItem.EnableIPv6Address = TunEnableIPv6Address;\n\n        //coreType\n        await SaveCoreType();\n\n        if (await ConfigHandler.SaveConfig(_config) == 0)\n        {\n            await AutoStartupHandler.UpdateTask(_config);\n            AppManager.Instance.Reset();\n\n            NoticeManager.Instance.Enqueue(needReboot ? ResUI.NeedRebootTips : ResUI.OperationSuccess);\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n\n    private async Task SaveCoreType()\n    {\n        for (var k = 1; k <= _config.CoreTypeItem.Count; k++)\n        {\n            var item = _config.CoreTypeItem[k - 1];\n            var type = string.Empty;\n            switch ((int)item.ConfigType)\n            {\n                case 1:\n                    type = CoreType1;\n                    break;\n\n                case 2:\n                    type = CoreType2;\n                    break;\n\n                case 3:\n                    type = CoreType3;\n                    break;\n\n                case 4:\n                    type = CoreType4;\n                    break;\n\n                case 5:\n                    type = CoreType5;\n                    break;\n\n                case 6:\n                    type = CoreType6;\n                    break;\n\n                case 7:\n                    type = CoreType7;\n                    break;\n\n                case 9:\n                    type = CoreType9;\n                    break;\n\n                default:\n                    continue;\n            }\n            item.CoreType = (ECoreType)Enum.Parse(typeof(ECoreType), type);\n        }\n        await Task.CompletedTask;\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/ProfilesSelectViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class ProfilesSelectViewModel : MyReactiveObject\n{\n    #region private prop\n\n    private string _serverFilter = string.Empty;\n    private Dictionary<string, bool> _dicHeaderSort = new();\n    private string _subIndexId = string.Empty;\n\n    // ConfigType filter state: default include-mode with all types selected\n    private List<EConfigType> _filterConfigTypes = new();\n\n    private bool _filterExclude = false;\n\n    #endregion private prop\n\n    #region ObservableCollection\n\n    public IObservableCollection<ProfileItemModel> ProfileItems { get; } = new ObservableCollectionExtended<ProfileItemModel>();\n\n    public IObservableCollection<SubItem> SubItems { get; } = new ObservableCollectionExtended<SubItem>();\n\n    [Reactive]\n    public ProfileItemModel SelectedProfile { get; set; }\n\n    public IList<ProfileItemModel> SelectedProfiles { get; set; }\n\n    [Reactive]\n    public SubItem SelectedSub { get; set; }\n\n    [Reactive]\n    public string ServerFilter { get; set; }\n\n    // Include/Exclude filter for ConfigType\n    public List<EConfigType> FilterConfigTypes\n    {\n        get => _filterConfigTypes;\n        set => this.RaiseAndSetIfChanged(ref _filterConfigTypes, value);\n    }\n\n    [Reactive]\n    public bool FilterExclude\n    {\n        get => _filterExclude;\n        set => this.RaiseAndSetIfChanged(ref _filterExclude, value);\n    }\n\n    #endregion ObservableCollection\n\n    #region Init\n\n    public ProfilesSelectViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n        _subIndexId = _config.SubIndexId ?? string.Empty;\n\n        #region WhenAnyValue && ReactiveCommand\n\n        this.WhenAnyValue(\n            x => x.SelectedSub,\n            y => y != null && !y.Remarks.IsNullOrEmpty() && _subIndexId != y.Id)\n                .Subscribe(async c => await SubSelectedChangedAsync(c));\n\n        this.WhenAnyValue(\n          x => x.ServerFilter,\n          y => y != null && _serverFilter != y)\n              .Subscribe(async c => await ServerFilterChanged(c));\n\n        // React to ConfigType filter changes\n        this.WhenAnyValue(x => x.FilterExclude)\n            .Skip(1)\n            .Subscribe(async _ => await RefreshServersBiz());\n\n        this.WhenAnyValue(x => x.FilterConfigTypes)\n            .Skip(1)\n            .Subscribe(async _ => await RefreshServersBiz());\n\n        #endregion WhenAnyValue && ReactiveCommand\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        SelectedProfile = new();\n        SelectedSub = new();\n\n        // Default: include mode with all ConfigTypes selected\n        try\n        {\n            FilterExclude = false;\n            FilterConfigTypes = Enum.GetValues(typeof(EConfigType)).Cast<EConfigType>().ToList();\n        }\n        catch\n        {\n            FilterConfigTypes = new();\n        }\n\n        await RefreshSubscriptions();\n        await RefreshServers();\n    }\n\n    #endregion Init\n\n    #region Actions\n\n    public bool CanOk()\n    {\n        return SelectedProfile != null && !SelectedProfile.IndexId.IsNullOrEmpty();\n    }\n\n    public bool SelectFinish()\n    {\n        if (!CanOk())\n        {\n            return false;\n        }\n        _updateView?.Invoke(EViewAction.CloseWindow, null);\n        return true;\n    }\n\n    #endregion Actions\n\n    #region Servers && Groups\n\n    private async Task SubSelectedChangedAsync(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        _subIndexId = SelectedSub?.Id;\n\n        await RefreshServers();\n\n        await _updateView?.Invoke(EViewAction.ProfilesFocus, null);\n    }\n\n    private async Task ServerFilterChanged(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        _serverFilter = ServerFilter;\n        if (_serverFilter.IsNullOrEmpty())\n        {\n            await RefreshServers();\n        }\n    }\n\n    public async Task RefreshServers()\n    {\n        await RefreshServersBiz();\n    }\n\n    private async Task RefreshServersBiz()\n    {\n        var lstModel = await GetProfileItemsEx(_subIndexId, _serverFilter);\n\n        ProfileItems.Clear();\n        ProfileItems.AddRange(lstModel);\n        if (lstModel.Count > 0)\n        {\n            var selected = lstModel.FirstOrDefault(t => t.IndexId == _config.IndexId);\n            if (selected != null)\n            {\n                SelectedProfile = selected;\n            }\n            else\n            {\n                SelectedProfile = lstModel.First();\n            }\n        }\n\n        await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null);\n    }\n\n    public async Task RefreshSubscriptions()\n    {\n        SubItems.Clear();\n\n        SubItems.Add(new SubItem { Remarks = ResUI.AllGroupServers });\n\n        foreach (var item in await AppManager.Instance.SubItems())\n        {\n            SubItems.Add(item);\n        }\n        SelectedSub = (_config.SubIndexId.IsNotEmpty()\n                        ? SubItems.FirstOrDefault(t => t.Id == _config.SubIndexId)\n                        : null) ?? SubItems.LastOrDefault();\n    }\n\n    private async Task<List<ProfileItemModel>?> GetProfileItemsEx(string subid, string filter)\n    {\n        var lstModel = await AppManager.Instance.ProfileModels(_subIndexId, filter);\n        lstModel = (from t in lstModel\n                    select new ProfileItemModel\n                    {\n                        IndexId = t.IndexId,\n                        ConfigType = t.ConfigType,\n                        Remarks = t.Remarks,\n                        Address = t.Address,\n                        Port = t.Port,\n                        //Security = t.Security,\n                        Network = t.Network,\n                        StreamSecurity = t.StreamSecurity,\n                        Subid = t.Subid,\n                        SubRemarks = t.SubRemarks,\n                        IsActive = t.IndexId == _config.IndexId,\n                    }).OrderBy(t => t.Sort).ToList();\n\n        // Apply ConfigType filter (include or exclude)\n        if (FilterConfigTypes != null && FilterConfigTypes.Count > 0)\n        {\n            if (FilterExclude)\n            {\n                lstModel = lstModel.Where(t => !FilterConfigTypes.Contains(t.ConfigType)).ToList();\n            }\n            else\n            {\n                lstModel = lstModel.Where(t => FilterConfigTypes.Contains(t.ConfigType)).ToList();\n            }\n        }\n\n        return lstModel;\n    }\n\n    public async Task<ProfileItem?> GetProfileItem()\n    {\n        if (string.IsNullOrEmpty(SelectedProfile?.IndexId))\n        {\n            return null;\n        }\n        var indexId = SelectedProfile.IndexId;\n        var item = await AppManager.Instance.GetProfileItem(indexId);\n        if (item is null)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return null;\n        }\n        return item;\n    }\n\n    public async Task<List<ProfileItem>?> GetProfileItems()\n    {\n        if (SelectedProfiles == null || SelectedProfiles.Count == 0)\n        {\n            return null;\n        }\n        var lst = await AppManager.Instance.GetProfileItemsOrderedByIndexIds(SelectedProfiles.Select(sp => sp?.IndexId));\n        if (lst.Count == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return null;\n        }\n        return lst;\n    }\n\n    public void SortServer(string colName)\n    {\n        if (colName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        var prop = typeof(ProfileItemModel).GetProperty(colName);\n        if (prop == null)\n        {\n            return;\n        }\n\n        _dicHeaderSort.TryAdd(colName, true);\n        var asc = _dicHeaderSort[colName];\n\n        var comparer = Comparer<object?>.Create((a, b) =>\n        {\n            if (ReferenceEquals(a, b))\n            {\n                return 0;\n            }\n            if (a is null)\n            {\n                return -1;\n            }\n            if (b is null)\n            {\n                return 1;\n            }\n            if (a.GetType() == b.GetType() && a is IComparable ca)\n            {\n                return ca.CompareTo(b);\n            }\n            return string.Compare(a.ToString(), b.ToString(), StringComparison.OrdinalIgnoreCase);\n        });\n\n        object? KeySelector(ProfileItemModel x)\n        {\n            return prop.GetValue(x);\n        }\n\n        IEnumerable<ProfileItemModel> sorted = asc\n            ? ProfileItems.OrderBy(KeySelector, comparer)\n            : ProfileItems.OrderByDescending(KeySelector, comparer);\n\n        var list = sorted.ToList();\n        ProfileItems.Clear();\n        ProfileItems.AddRange(list);\n\n        _dicHeaderSort[colName] = !asc;\n\n        return;\n    }\n\n    #endregion Servers && Groups\n\n    #region Public API\n\n    // External setter for ConfigType filter\n    public void SetConfigTypeFilter(IEnumerable<EConfigType> types, bool exclude = false)\n    {\n        FilterConfigTypes = types?.Distinct().ToList() ?? new List<EConfigType>();\n        FilterExclude = exclude;\n    }\n\n    #endregion Public API\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class ProfilesViewModel : MyReactiveObject\n{\n    #region private prop\n\n    private List<ProfileItem> _lstProfile;\n    private string _serverFilter = string.Empty;\n    private Dictionary<string, bool> _dicHeaderSort = new();\n    private SpeedtestService? _speedtestService;\n    private string? _pendingSelectIndexId;\n\n    #endregion private prop\n\n    #region ObservableCollection\n\n    public IObservableCollection<ProfileItemModel> ProfileItems { get; } = new ObservableCollectionExtended<ProfileItemModel>();\n\n    public IObservableCollection<SubItem> SubItems { get; } = new ObservableCollectionExtended<SubItem>();\n\n    [Reactive]\n    public ProfileItemModel SelectedProfile { get; set; }\n\n    public IList<ProfileItemModel> SelectedProfiles { get; set; }\n\n    [Reactive]\n    public SubItem SelectedSub { get; set; }\n\n    [Reactive]\n    public SubItem SelectedMoveToGroup { get; set; }\n\n    [Reactive]\n    public string ServerFilter { get; set; }\n\n    #endregion ObservableCollection\n\n    #region Menu\n\n    //servers delete\n    public ReactiveCommand<Unit, Unit> EditServerCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> RemoveServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> RemoveDuplicateServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> CopyServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> SetDefaultServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> ShareServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> GenGroupAllServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> GenGroupRegionServerCmd { get; }\n\n    //servers move\n    public ReactiveCommand<Unit, Unit> MoveTopCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> MoveUpCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveDownCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveBottomCmd { get; }\n    public ReactiveCommand<SubItem, Unit> MoveToGroupCmd { get; }\n\n    //servers ping\n    public ReactiveCommand<Unit, Unit> MixedTestServerCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> TcpingServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> RealPingServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> SpeedServerCmd { get; }\n    public ReactiveCommand<Unit, Unit> SortServerResultCmd { get; }\n    public ReactiveCommand<Unit, Unit> RemoveInvalidServerResultCmd { get; }\n    public ReactiveCommand<Unit, Unit> FastRealPingCmd { get; }\n\n    //servers export\n    public ReactiveCommand<Unit, Unit> Export2ClientConfigCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> Export2ClientConfigClipboardCmd { get; }\n    public ReactiveCommand<Unit, Unit> Export2ShareUrlCmd { get; }\n    public ReactiveCommand<Unit, Unit> Export2ShareUrlBase64Cmd { get; }\n\n    public ReactiveCommand<Unit, Unit> AddSubCmd { get; }\n    public ReactiveCommand<Unit, Unit> EditSubCmd { get; }\n    public ReactiveCommand<Unit, Unit> DeleteSubCmd { get; }\n\n    #endregion Menu\n\n    #region Init\n\n    public ProfilesViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        #region WhenAnyValue && ReactiveCommand\n\n        var canEditRemove = this.WhenAnyValue(\n           x => x.SelectedProfile,\n           selectedSource => selectedSource != null && !selectedSource.IndexId.IsNullOrEmpty());\n\n        this.WhenAnyValue(\n            x => x.SelectedSub,\n            y => y != null && !y.Remarks.IsNullOrEmpty() && _config.SubIndexId != y.Id)\n                .Subscribe(async c => await SubSelectedChangedAsync(c));\n        this.WhenAnyValue(\n             x => x.SelectedMoveToGroup,\n             y => y != null && !y.Remarks.IsNullOrEmpty())\n                 .Subscribe(async c => await MoveToGroup(c));\n\n        this.WhenAnyValue(\n          x => x.ServerFilter,\n          y => y != null && _serverFilter != y)\n              .Subscribe(async c => await ServerFilterChanged(c));\n\n        //servers delete\n        EditServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await EditServerAsync();\n        }, canEditRemove);\n        RemoveServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RemoveServerAsync();\n        }, canEditRemove);\n        RemoveDuplicateServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RemoveDuplicateServer();\n        });\n        CopyServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await CopyServer();\n        }, canEditRemove);\n        SetDefaultServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SetDefaultServer();\n        }, canEditRemove);\n        ShareServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ShareServerAsync();\n        }, canEditRemove);\n        GenGroupAllServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await GenGroupAllServer();\n        }, canEditRemove);\n        GenGroupRegionServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await GenGroupRegionServer();\n        }, canEditRemove);\n\n        //servers move\n        MoveTopCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Top);\n        }, canEditRemove);\n        MoveUpCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Up);\n        }, canEditRemove);\n        MoveDownCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Down);\n        }, canEditRemove);\n        MoveBottomCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveServer(EMove.Bottom);\n        }, canEditRemove);\n        MoveToGroupCmd = ReactiveCommand.CreateFromTask<SubItem>(async sub =>\n        {\n            SelectedMoveToGroup = sub;\n        });\n\n        //servers ping\n        FastRealPingCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ServerSpeedtest(ESpeedActionType.FastRealping);\n        });\n        MixedTestServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ServerSpeedtest(ESpeedActionType.Mixedtest);\n        });\n        TcpingServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ServerSpeedtest(ESpeedActionType.Tcping);\n        }, canEditRemove);\n        RealPingServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ServerSpeedtest(ESpeedActionType.Realping);\n        }, canEditRemove);\n        SpeedServerCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ServerSpeedtest(ESpeedActionType.Speedtest);\n        }, canEditRemove);\n        SortServerResultCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SortServer(EServerColName.DelayVal.ToString());\n        });\n        RemoveInvalidServerResultCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RemoveInvalidServerResult();\n        });\n        //servers export\n        Export2ClientConfigCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await Export2ClientConfigAsync(false);\n        }, canEditRemove);\n        Export2ClientConfigClipboardCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await Export2ClientConfigAsync(true);\n        }, canEditRemove);\n        Export2ShareUrlCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await Export2ShareUrlAsync(false);\n        }, canEditRemove);\n        Export2ShareUrlBase64Cmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await Export2ShareUrlAsync(true);\n        }, canEditRemove);\n\n        //Subscription\n        AddSubCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await EditSubAsync(true);\n        });\n        EditSubCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await EditSubAsync(false);\n        });\n        DeleteSubCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await DeleteSubAsync();\n        });\n\n        #endregion WhenAnyValue && ReactiveCommand\n\n        #region AppEvents\n\n        AppEvents.ProfilesRefreshRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await RefreshServersBiz());\n\n        AppEvents.SubscriptionsRefreshRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await RefreshSubscriptions());\n\n        AppEvents.DispatcherStatisticsRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async result => await UpdateStatistics(result));\n\n        AppEvents.SetDefaultServerRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async indexId => await SetDefaultServer(indexId));\n\n        #endregion AppEvents\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        SelectedProfile = new();\n        SelectedSub = new();\n        SelectedMoveToGroup = new();\n\n        await RefreshSubscriptions();\n        //await RefreshServers();\n    }\n\n    #endregion Init\n\n    #region Actions\n\n    private void Reload()\n    {\n        AppEvents.ReloadRequested.Publish();\n    }\n\n    public async Task SetSpeedTestResult(SpeedTestResult result)\n    {\n        if (result.IndexId.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.SendMessageEx(result.Delay);\n            NoticeManager.Instance.Enqueue(result.Delay);\n            return;\n        }\n        var item = ProfileItems.FirstOrDefault(it => it.IndexId == result.IndexId);\n        if (item == null)\n        {\n            return;\n        }\n\n        if (result.Delay.IsNotEmpty())\n        {\n            item.Delay = result.Delay.ToInt();\n            item.DelayVal = result.Delay ?? string.Empty;\n        }\n        if (result.Speed.IsNotEmpty())\n        {\n            item.SpeedVal = result.Speed ?? string.Empty;\n        }\n        await Task.CompletedTask;\n    }\n\n    public async Task UpdateStatistics(ServerSpeedItem update)\n    {\n        if (!_config.GuiItem.EnableStatistics\n            || (update.ProxyUp + update.ProxyDown) <= 0\n            || DateTime.Now.Second % 3 != 0)\n        {\n            return;\n        }\n\n        try\n        {\n            var item = ProfileItems.FirstOrDefault(it => it.IndexId == update.IndexId);\n            if (item != null)\n            {\n                item.TodayDown = Utils.HumanFy(update.TodayDown);\n                item.TodayUp = Utils.HumanFy(update.TodayUp);\n                item.TotalDown = Utils.HumanFy(update.TotalDown);\n                item.TotalUp = Utils.HumanFy(update.TotalUp);\n            }\n        }\n        catch\n        {\n        }\n        await Task.CompletedTask;\n    }\n\n    #endregion Actions\n\n    #region Servers && Groups\n\n    private async Task SubSelectedChangedAsync(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        _config.SubIndexId = SelectedSub?.Id;\n\n        await RefreshServers();\n\n        await _updateView?.Invoke(EViewAction.ProfilesFocus, null);\n    }\n\n    private async Task ServerFilterChanged(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        _serverFilter = ServerFilter;\n        if (_serverFilter.IsNullOrEmpty())\n        {\n            await RefreshServers();\n        }\n    }\n\n    public async Task RefreshServers()\n    {\n        AppEvents.ProfilesRefreshRequested.Publish();\n\n        await Task.Delay(200);\n    }\n\n    private async Task RefreshServersBiz()\n    {\n        var lstModel = await GetProfileItemsEx(_config.SubIndexId, _serverFilter);\n        _lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];\n\n        ProfileItems.Clear();\n        ProfileItems.AddRange(lstModel);\n        if (lstModel.Count > 0)\n        {\n            ProfileItemModel? selected = null;\n            if (!_pendingSelectIndexId.IsNullOrEmpty())\n            {\n                selected = lstModel.FirstOrDefault(t => t.IndexId == _pendingSelectIndexId);\n                _pendingSelectIndexId = null;\n            }\n            selected ??= lstModel.FirstOrDefault(t => t.IndexId == _config.IndexId);\n            SelectedProfile = selected ?? lstModel.First();\n        }\n\n        await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null);\n    }\n\n    private async Task RefreshSubscriptions()\n    {\n        SubItems.Clear();\n\n        SubItems.Add(new SubItem { Remarks = ResUI.AllGroupServers });\n\n        foreach (var item in await AppManager.Instance.SubItems())\n        {\n            SubItems.Add(item);\n        }\n        SelectedSub = (_config.SubIndexId.IsNotEmpty()\n                        ? SubItems.FirstOrDefault(t => t.Id == _config.SubIndexId)\n                        : null) ?? SubItems.LastOrDefault();\n    }\n\n    private async Task<List<ProfileItemModel>?> GetProfileItemsEx(string subid, string filter)\n    {\n        var lstModel = await AppManager.Instance.ProfileModels(_config.SubIndexId, filter);\n\n        await ConfigHandler.SetDefaultServer(_config, lstModel);\n\n        var lstServerStat = (_config.GuiItem.EnableStatistics ? StatisticsManager.Instance.ServerStat : null) ?? [];\n        var lstProfileExs = await ProfileExManager.Instance.GetProfileExs();\n        lstModel = (from t in lstModel\n                    join t2 in lstServerStat on t.IndexId equals t2.IndexId into t2b\n                    from t22 in t2b.DefaultIfEmpty()\n                    join t3 in lstProfileExs on t.IndexId equals t3.IndexId into t3b\n                    from t33 in t3b.DefaultIfEmpty()\n                    select new ProfileItemModel\n                    {\n                        IndexId = t.IndexId,\n                        ConfigType = t.ConfigType,\n                        Remarks = t.Remarks,\n                        Address = t.Address,\n                        Port = t.Port,\n                        //Security = t.Security,\n                        Network = t.Network,\n                        StreamSecurity = t.StreamSecurity,\n                        Subid = t.Subid,\n                        SubRemarks = t.SubRemarks,\n                        IsActive = t.IndexId == _config.IndexId,\n                        Sort = t33?.Sort ?? 0,\n                        Delay = t33?.Delay ?? 0,\n                        Speed = t33?.Speed ?? 0,\n                        DelayVal = t33?.Delay != 0 ? $\"{t33?.Delay}\" : string.Empty,\n                        SpeedVal = t33?.Speed > 0 ? $\"{t33?.Speed}\" : t33?.Message ?? string.Empty,\n                        TodayDown = t22 == null ? \"\" : Utils.HumanFy(t22.TodayDown),\n                        TodayUp = t22 == null ? \"\" : Utils.HumanFy(t22.TodayUp),\n                        TotalDown = t22 == null ? \"\" : Utils.HumanFy(t22.TotalDown),\n                        TotalUp = t22 == null ? \"\" : Utils.HumanFy(t22.TotalUp)\n                    }).OrderBy(t => t.Sort).ToList();\n\n        return lstModel;\n    }\n\n    #endregion Servers && Groups\n\n    #region Add Servers\n\n    private async Task<List<ProfileItem>?> GetProfileItems(bool latest)\n    {\n        var lstSelected = new List<ProfileItem>();\n        if (SelectedProfiles == null || SelectedProfiles.Count <= 0)\n        {\n            return null;\n        }\n\n        var orderProfiles = SelectedProfiles?.OrderBy(t => t.Sort);\n        if (latest)\n        {\n            lstSelected.AddRange(await AppManager.Instance.GetProfileItemsOrderedByIndexIds(orderProfiles.Select(sp => sp?.IndexId)));\n        }\n        else\n        {\n            lstSelected = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(orderProfiles));\n        }\n\n        return lstSelected;\n    }\n\n    public async Task EditServerAsync()\n    {\n        if (string.IsNullOrEmpty(SelectedProfile?.IndexId))\n        {\n            return;\n        }\n        var item = await AppManager.Instance.GetProfileItem(SelectedProfile.IndexId);\n        if (item is null)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return;\n        }\n        var eConfigType = item.ConfigType;\n\n        bool? ret = false;\n        if (eConfigType == EConfigType.Custom)\n        {\n            ret = await _updateView?.Invoke(EViewAction.AddServer2Window, item);\n        }\n        else if (eConfigType.IsGroupType())\n        {\n            ret = await _updateView?.Invoke(EViewAction.AddGroupServerWindow, item);\n        }\n        else\n        {\n            ret = await _updateView?.Invoke(EViewAction.AddServerWindow, item);\n        }\n        if (ret == true)\n        {\n            await RefreshServers();\n            if (item.IndexId == _config.IndexId)\n            {\n                Reload();\n            }\n        }\n    }\n\n    public async Task RemoveServerAsync()\n    {\n        var lstSelected = await GetProfileItems(true);\n        if (lstSelected == null)\n        {\n            return;\n        }\n        if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)\n        {\n            return;\n        }\n        var exists = lstSelected.Exists(t => t.IndexId == _config.IndexId);\n\n        await ConfigHandler.RemoveServers(_config, lstSelected);\n        NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n        if (lstSelected.Count == ProfileItems.Count)\n        {\n            ProfileItems.Clear();\n        }\n        await RefreshServers();\n        if (exists)\n        {\n            Reload();\n        }\n    }\n\n    private async Task RemoveDuplicateServer()\n    {\n        if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)\n        {\n            return;\n        }\n\n        var tuple = await ConfigHandler.DedupServerList(_config, _config.SubIndexId);\n        if (tuple.Item1 > 0 || tuple.Item2 > 0)\n        {\n            await RefreshServers();\n            Reload();\n        }\n        NoticeManager.Instance.Enqueue(string.Format(ResUI.RemoveDuplicateServerResult, tuple.Item1, tuple.Item2));\n    }\n\n    private async Task CopyServer()\n    {\n        var lstSelected = await GetProfileItems(false);\n        if (lstSelected == null)\n        {\n            return;\n        }\n        if (await ConfigHandler.CopyServer(_config, lstSelected) == 0)\n        {\n            await RefreshServers();\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n        }\n    }\n\n    public async Task SetDefaultServer()\n    {\n        if (string.IsNullOrEmpty(SelectedProfile?.IndexId))\n        {\n            return;\n        }\n        await SetDefaultServer(SelectedProfile.IndexId);\n    }\n\n    private async Task SetDefaultServer(string? indexId)\n    {\n        if (indexId.IsNullOrEmpty())\n        {\n            return;\n        }\n        if (indexId == _config.IndexId)\n        {\n            return;\n        }\n        var item = await AppManager.Instance.GetProfileItem(indexId);\n        if (item is null)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return;\n        }\n\n        if (await ConfigHandler.SetDefaultServerIndex(_config, indexId) == 0)\n        {\n            await RefreshServers();\n            Reload();\n        }\n    }\n\n    public async Task ShareServerAsync()\n    {\n        var item = await AppManager.Instance.GetProfileItem(SelectedProfile.IndexId);\n        if (item is null)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return;\n        }\n        var url = FmtHandler.GetShareUri(item);\n        if (url.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        await _updateView?.Invoke(EViewAction.ShareServer, url);\n    }\n\n    private async Task GenGroupAllServer()\n    {\n        var ret = await ConfigHandler.AddGroupAllServer(_config, SelectedSub);\n        if (ret.Success != true)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n            return;\n        }\n        _pendingSelectIndexId = ret.Data?.ToString();\n        await RefreshServers();\n    }\n\n    private async Task GenGroupRegionServer()\n    {\n        var ret = await ConfigHandler.AddGroupRegionServer(_config, SelectedSub);\n        if (ret.Success != true)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n            return;\n        }\n        var indexIdList = ret.Data as List<string>;\n        _pendingSelectIndexId = indexIdList?.FirstOrDefault();\n        await RefreshServers();\n    }\n\n    public async Task SortServer(string colName)\n    {\n        if (colName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        _dicHeaderSort.TryAdd(colName, true);\n        _dicHeaderSort.TryGetValue(colName, out var asc);\n        if (await ConfigHandler.SortServers(_config, _config.SubIndexId, colName, asc) != 0)\n        {\n            return;\n        }\n        _dicHeaderSort[colName] = !asc;\n        await RefreshServers();\n    }\n\n    public async Task RemoveInvalidServerResult()\n    {\n        var count = await ConfigHandler.RemoveInvalidServerResult(_config, _config.SubIndexId);\n        await RefreshServers();\n        NoticeManager.Instance.Enqueue(string.Format(ResUI.RemoveInvalidServerResultTip, count));\n    }\n\n    //move server\n    private async Task MoveToGroup(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n\n        var lstSelected = await GetProfileItems(true);\n        if (lstSelected == null)\n        {\n            return;\n        }\n\n        await ConfigHandler.MoveToGroup(_config, lstSelected, SelectedMoveToGroup.Id);\n        NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n\n        await RefreshServers();\n        SelectedMoveToGroup = null;\n        SelectedMoveToGroup = new();\n    }\n\n    public async Task MoveServer(EMove eMove)\n    {\n        var item = _lstProfile.FirstOrDefault(t => t.IndexId == SelectedProfile.IndexId);\n        if (item is null)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return;\n        }\n\n        var index = _lstProfile.IndexOf(item);\n        if (index < 0)\n        {\n            return;\n        }\n        if (await ConfigHandler.MoveServer(_config, _lstProfile, index, eMove) == 0)\n        {\n            await RefreshServers();\n        }\n    }\n\n    public async Task MoveServerTo(int startIndex, ProfileItemModel targetItem)\n    {\n        var targetIndex = ProfileItems.IndexOf(targetItem);\n        if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex)\n        {\n            if (await ConfigHandler.MoveServer(_config, _lstProfile, startIndex, EMove.Position, targetIndex) == 0)\n            {\n                await RefreshServers();\n            }\n        }\n    }\n\n    public async Task ServerSpeedtest(ESpeedActionType actionType)\n    {\n        if (actionType == ESpeedActionType.Mixedtest)\n        {\n            SelectedProfiles = ProfileItems;\n        }\n        else if (actionType == ESpeedActionType.FastRealping)\n        {\n            SelectedProfiles = ProfileItems;\n            actionType = ESpeedActionType.Realping;\n        }\n\n        var lstSelected = await GetProfileItems(false);\n        if (lstSelected == null)\n        {\n            return;\n        }\n\n        _speedtestService ??= new SpeedtestService(_config, async (SpeedTestResult result) =>\n        {\n            RxSchedulers.MainThreadScheduler.Schedule(result, (scheduler, result) =>\n            {\n                _ = SetSpeedTestResult(result);\n                return Disposable.Empty;\n            });\n            await Task.CompletedTask;\n        });\n        _speedtestService?.RunLoop(actionType, lstSelected);\n    }\n\n    public void ServerSpeedtestStop()\n    {\n        _speedtestService?.ExitLoop();\n    }\n\n    private async Task Export2ClientConfigAsync(bool blClipboard)\n    {\n        var item = await AppManager.Instance.GetProfileItem(SelectedProfile.IndexId);\n        if (item is null)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectServer);\n            return;\n        }\n\n        var (context, validatorResult) = await CoreConfigContextBuilder.Build(_config, item);\n        if (NoticeManager.Instance.NotifyValidatorResult(validatorResult) && !validatorResult.Success)\n        {\n            return;\n        }\n\n        if (blClipboard)\n        {\n            var result = await CoreConfigHandler.GenerateClientConfig(context, null);\n            if (result.Success != true)\n            {\n                NoticeManager.Instance.Enqueue(result.Msg);\n            }\n            else\n            {\n                await _updateView?.Invoke(EViewAction.SetClipboardData, result.Data);\n                NoticeManager.Instance.SendMessage(ResUI.OperationSuccess);\n            }\n        }\n        else\n        {\n            await _updateView?.Invoke(EViewAction.SaveFileDialog, item);\n        }\n    }\n\n    public async Task Export2ClientConfigResult(string fileName, ProfileItem item)\n    {\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n        var (context, validatorResult) = await CoreConfigContextBuilder.Build(_config, item);\n        if (NoticeManager.Instance.NotifyValidatorResult(validatorResult) && !validatorResult.Success)\n        {\n            return;\n        }\n        var result = await CoreConfigHandler.GenerateClientConfig(context, fileName);\n        if (result.Success != true)\n        {\n            NoticeManager.Instance.Enqueue(result.Msg);\n        }\n        else\n        {\n            NoticeManager.Instance.SendMessageAndEnqueue(string.Format(ResUI.SaveClientConfigurationIn, fileName));\n        }\n    }\n\n    public async Task Export2ShareUrlAsync(bool blEncode)\n    {\n        var lstSelected = await GetProfileItems(true);\n        if (lstSelected == null)\n        {\n            return;\n        }\n\n        StringBuilder sb = new();\n        foreach (var it in lstSelected)\n        {\n            var url = FmtHandler.GetShareUri(it);\n            if (url.IsNullOrEmpty())\n            {\n                continue;\n            }\n            sb.Append(url);\n            sb.AppendLine();\n        }\n        if (sb.Length > 0)\n        {\n            if (blEncode)\n            {\n                await _updateView?.Invoke(EViewAction.SetClipboardData, Utils.Base64Encode(sb.ToString()));\n            }\n            else\n            {\n                await _updateView?.Invoke(EViewAction.SetClipboardData, sb.ToString());\n            }\n            NoticeManager.Instance.SendMessage(ResUI.BatchExportURLSuccessfully);\n        }\n    }\n\n    #endregion Add Servers\n\n    #region Subscription\n\n    private async Task EditSubAsync(bool blNew)\n    {\n        SubItem item;\n        if (blNew)\n        {\n            item = new();\n        }\n        else\n        {\n            item = await AppManager.Instance.GetSubItem(_config.SubIndexId);\n            if (item is null)\n            {\n                return;\n            }\n        }\n        if (await _updateView?.Invoke(EViewAction.SubEditWindow, item) == true)\n        {\n            await RefreshSubscriptions();\n            await SubSelectedChangedAsync(true);\n        }\n    }\n\n    private async Task DeleteSubAsync()\n    {\n        var item = await AppManager.Instance.GetSubItem(_config.SubIndexId);\n        if (item is null)\n        {\n            return;\n        }\n\n        if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)\n        {\n            return;\n        }\n        await ConfigHandler.DeleteSubItem(_config, item.Id);\n\n        await RefreshSubscriptions();\n        await SubSelectedChangedAsync(true);\n    }\n\n    #endregion Subscription\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/RoutingRuleDetailsViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class RoutingRuleDetailsViewModel : MyReactiveObject\n{\n    public IList<string> ProtocolItems { get; set; }\n    public IList<string> InboundTagItems { get; set; }\n\n    [Reactive]\n    public RulesItem SelectedSource { get; set; }\n\n    [Reactive]\n    public string Domain { get; set; }\n\n    [Reactive]\n    public string IP { get; set; }\n\n    [Reactive]\n    public string Process { get; set; }\n\n    [Reactive]\n    public string? RuleType { get; set; }\n\n    [Reactive]\n    public bool AutoSort { get; set; }\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    public RoutingRuleDetailsViewModel(RulesItem rulesItem, Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveRulesAsync();\n        });\n\n        if (rulesItem.Id.IsNullOrEmpty())\n        {\n            rulesItem.Id = Utils.GetGuid(false);\n            rulesItem.OutboundTag = Global.ProxyTag;\n            rulesItem.Enabled = true;\n            SelectedSource = rulesItem;\n        }\n        else\n        {\n            SelectedSource = rulesItem;\n        }\n\n        Domain = Utils.List2String(SelectedSource.Domain, true);\n        IP = Utils.List2String(SelectedSource.Ip, true);\n        Process = Utils.List2String(SelectedSource.Process, true);\n        RuleType = SelectedSource.RuleType?.ToString();\n    }\n\n    private async Task SaveRulesAsync()\n    {\n        Domain = Utils.Convert2Comma(Domain);\n        IP = Utils.Convert2Comma(IP);\n        Process = Utils.Convert2Comma(Process);\n\n        if (AutoSort)\n        {\n            SelectedSource.Domain = Utils.String2ListSorted(Domain);\n            SelectedSource.Ip = Utils.String2ListSorted(IP);\n            SelectedSource.Process = Utils.String2ListSorted(Process);\n        }\n        else\n        {\n            SelectedSource.Domain = Utils.String2List(Domain);\n            SelectedSource.Ip = Utils.String2List(IP);\n            SelectedSource.Process = Utils.String2List(Process);\n        }\n        SelectedSource.Protocol = ProtocolItems?.ToList();\n        SelectedSource.InboundTag = InboundTagItems?.ToList();\n        SelectedSource.RuleType = RuleType.IsNullOrEmpty() ? null : (ERuleType)Enum.Parse(typeof(ERuleType), RuleType);\n\n        var hasRule = SelectedSource.Domain?.Count > 0\n          || SelectedSource.Ip?.Count > 0\n          || SelectedSource.Protocol?.Count > 0\n          || SelectedSource.Process?.Count > 0\n          || SelectedSource.Port.IsNotEmpty()\n          || SelectedSource.Network.IsNotEmpty();\n\n        if (!hasRule)\n        {\n            NoticeManager.Instance.Enqueue(string.Format(ResUI.RoutingRuleDetailRequiredTips, \"Network/Port/Protocol/Domain/IP/Process\"));\n            return;\n        }\n        //NoticeHandler.Instance.Enqueue(ResUI.OperationSuccess);\n        await _updateView?.Invoke(EViewAction.CloseWindow, null);\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/RoutingRuleSettingViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class RoutingRuleSettingViewModel : MyReactiveObject\n{\n    private List<RulesItem> _rules;\n\n    [Reactive]\n    public RoutingItem SelectedRouting { get; set; }\n\n    public IObservableCollection<RulesItemModel> RulesItems { get; } = new ObservableCollectionExtended<RulesItemModel>();\n\n    [Reactive]\n    public RulesItemModel SelectedSource { get; set; }\n\n    public IList<RulesItemModel> SelectedSources { get; set; }\n\n    public ReactiveCommand<Unit, Unit> RuleAddCmd { get; }\n    public ReactiveCommand<Unit, Unit> ImportRulesFromFileCmd { get; }\n    public ReactiveCommand<Unit, Unit> ImportRulesFromClipboardCmd { get; }\n    public ReactiveCommand<Unit, Unit> ImportRulesFromUrlCmd { get; }\n    public ReactiveCommand<Unit, Unit> RuleRemoveCmd { get; }\n    public ReactiveCommand<Unit, Unit> RuleExportSelectedCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveTopCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveUpCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveDownCmd { get; }\n    public ReactiveCommand<Unit, Unit> MoveBottomCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    public RoutingRuleSettingViewModel(RoutingItem routingItem, Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        var canEditRemove = this.WhenAnyValue(\n            x => x.SelectedSource,\n            selectedSource => selectedSource != null && !selectedSource.OutboundTag.IsNullOrEmpty());\n\n        RuleAddCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RuleEditAsync(true);\n        });\n        ImportRulesFromFileCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await _updateView?.Invoke(EViewAction.ImportRulesFromFile, null);\n        });\n        ImportRulesFromClipboardCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ImportRulesFromClipboardAsync(null);\n        });\n        ImportRulesFromUrlCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await ImportRulesFromUrl();\n        });\n\n        RuleRemoveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RuleRemoveAsync();\n        }, canEditRemove);\n        RuleExportSelectedCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RuleExportSelectedAsync();\n        }, canEditRemove);\n\n        MoveTopCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveRule(EMove.Top);\n        }, canEditRemove);\n        MoveUpCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveRule(EMove.Up);\n        }, canEditRemove);\n        MoveDownCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveRule(EMove.Down);\n        }, canEditRemove);\n        MoveBottomCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await MoveRule(EMove.Bottom);\n        }, canEditRemove);\n\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveRoutingAsync();\n        });\n\n        SelectedSource = new();\n        SelectedRouting = routingItem;\n        _rules = routingItem.Id.IsNullOrEmpty() ? new() : JsonUtils.Deserialize<List<RulesItem>>(SelectedRouting.RuleSet);\n\n        RefreshRulesItems();\n    }\n\n    public void RefreshRulesItems()\n    {\n        RulesItems.Clear();\n\n        foreach (var item in _rules)\n        {\n            var it = new RulesItemModel()\n            {\n                Id = item.Id,\n                RuleTypeName = item.RuleType?.ToString(),\n                OutboundTag = item.OutboundTag,\n                Port = item.Port,\n                Network = item.Network,\n                Protocols = Utils.List2String(item.Protocol),\n                InboundTags = Utils.List2String(item.InboundTag),\n                Domains = Utils.List2String((item.Domain ?? []).Concat(item.Ip ?? []).ToList().Concat(item.Process ?? []).ToList()),\n                Enabled = item.Enabled,\n                Remarks = item.Remarks,\n            };\n            RulesItems.Add(it);\n        }\n    }\n\n    public async Task RuleEditAsync(bool blNew)\n    {\n        RulesItem? item;\n        if (blNew)\n        {\n            item = new();\n        }\n        else\n        {\n            item = _rules.FirstOrDefault(t => t.Id == SelectedSource?.Id);\n            if (item is null)\n            {\n                return;\n            }\n        }\n        if (await _updateView?.Invoke(EViewAction.RoutingRuleDetailsWindow, item) == true)\n        {\n            if (blNew)\n            {\n                _rules.Insert(0, item);\n            }\n            RefreshRulesItems();\n        }\n    }\n\n    public async Task RuleRemoveAsync()\n    {\n        if (SelectedSource is null || SelectedSource.OutboundTag.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules);\n            return;\n        }\n        if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)\n        {\n            return;\n        }\n        foreach (var it in SelectedSources ?? [SelectedSource])\n        {\n            var item = _rules.FirstOrDefault(t => t.Id == it?.Id);\n            if (item != null)\n            {\n                _rules.Remove(item);\n            }\n        }\n\n        RefreshRulesItems();\n    }\n\n    public async Task RuleExportSelectedAsync()\n    {\n        if (SelectedSource is null || SelectedSource.OutboundTag.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules);\n            return;\n        }\n\n        var lst = new List<RulesItem>();\n        var sources = SelectedSources ?? [SelectedSource];\n        foreach (var it in _rules)\n        {\n            if (sources.Any(t => t.Id == it?.Id))\n            {\n                var item2 = JsonUtils.DeepCopy(it);\n                item2.Id = null;\n                lst.Add(item2 ?? new());\n            }\n        }\n        if (lst.Count > 0)\n        {\n            var options = new JsonSerializerOptions\n            {\n                WriteIndented = true,\n                DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,\n                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,\n            };\n            await _updateView?.Invoke(EViewAction.SetClipboardData, JsonUtils.Serialize(lst, options));\n        }\n    }\n\n    public async Task MoveRule(EMove eMove)\n    {\n        if (SelectedSource is null || SelectedSource.OutboundTag.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules);\n            return;\n        }\n\n        var item = _rules.FirstOrDefault(t => t.Id == SelectedSource?.Id);\n        if (item == null)\n        {\n            return;\n        }\n        var index = _rules.IndexOf(item);\n        if (await ConfigHandler.MoveRoutingRule(_rules, index, eMove) == 0)\n        {\n            RefreshRulesItems();\n        }\n    }\n\n    private async Task SaveRoutingAsync()\n    {\n        var remarks = SelectedRouting.Remarks;\n        if (remarks.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseFillRemarks);\n            return;\n        }\n        var item = SelectedRouting;\n        foreach (var it in _rules)\n        {\n            it.Id = Utils.GetGuid(false);\n        }\n        item.RuleNum = _rules.Count;\n        item.RuleSet = JsonUtils.Serialize(_rules, false);\n\n        if (await ConfigHandler.SaveRoutingItem(_config, item) == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n\n    #region Import rules\n\n    public async Task ImportRulesFromFileAsync(string fileName)\n    {\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        var result = EmbedUtils.LoadResource(fileName);\n        if (result.IsNullOrEmpty())\n        {\n            return;\n        }\n        var ret = await AddBatchRoutingRulesAsync(SelectedRouting, result);\n        if (ret == 0)\n        {\n            RefreshRulesItems();\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n        }\n    }\n\n    public async Task ImportRulesFromClipboardAsync(string? clipboardData)\n    {\n        if (clipboardData == null)\n        {\n            await _updateView?.Invoke(EViewAction.ImportRulesFromClipboard, null);\n            return;\n        }\n        var ret = await AddBatchRoutingRulesAsync(SelectedRouting, clipboardData);\n        if (ret == 0)\n        {\n            RefreshRulesItems();\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n        }\n    }\n\n    private async Task ImportRulesFromUrl()\n    {\n        var url = SelectedRouting.Url;\n        if (url.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.MsgNeedUrl);\n            return;\n        }\n\n        var downloadHandle = new DownloadService();\n        var result = await downloadHandle.TryDownloadString(url, true, \"\");\n        var ret = await AddBatchRoutingRulesAsync(SelectedRouting, result);\n        if (ret == 0)\n        {\n            RefreshRulesItems();\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n        }\n    }\n\n    private async Task<int> AddBatchRoutingRulesAsync(RoutingItem routingItem, string? clipboardData)\n    {\n        var blReplace = false;\n        if (await _updateView?.Invoke(EViewAction.AddBatchRoutingRulesYesNo, null) == false)\n        {\n            blReplace = true;\n        }\n        if (clipboardData.IsNullOrEmpty())\n        {\n            return -1;\n        }\n        var lstRules = JsonUtils.Deserialize<List<RulesItem>>(clipboardData);\n        if (lstRules == null)\n        {\n            return -1;\n        }\n        foreach (var rule in lstRules)\n        {\n            rule.Id = Utils.GetGuid(false);\n        }\n\n        if (blReplace)\n        {\n            _rules = lstRules;\n        }\n        else\n        {\n            _rules.AddRange(lstRules);\n        }\n        return 0;\n    }\n\n    #endregion Import rules\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/RoutingSettingViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class RoutingSettingViewModel : MyReactiveObject\n{\n    #region Reactive\n\n    public IObservableCollection<RoutingItemModel> RoutingItems { get; } = new ObservableCollectionExtended<RoutingItemModel>();\n\n    [Reactive]\n    public RoutingItemModel SelectedSource { get; set; }\n\n    public IList<RoutingItemModel> SelectedSources { get; set; }\n\n    [Reactive]\n    public string DomainStrategy { get; set; }\n\n    [Reactive]\n    public string DomainStrategy4Singbox { get; set; }\n\n    public ReactiveCommand<Unit, Unit> RoutingAdvancedAddCmd { get; }\n    public ReactiveCommand<Unit, Unit> RoutingAdvancedRemoveCmd { get; }\n    public ReactiveCommand<Unit, Unit> RoutingAdvancedSetDefaultCmd { get; }\n    public ReactiveCommand<Unit, Unit> RoutingAdvancedImportRulesCmd { get; }\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n    public bool IsModified { get; set; }\n\n    #endregion Reactive\n\n    public RoutingSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        var canEditRemove = this.WhenAnyValue(\n            x => x.SelectedSource,\n            selectedSource => selectedSource != null && !selectedSource.Remarks.IsNullOrEmpty());\n\n        RoutingAdvancedAddCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RoutingAdvancedEditAsync(true);\n        });\n        RoutingAdvancedRemoveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RoutingAdvancedRemoveAsync();\n        }, canEditRemove);\n        RoutingAdvancedSetDefaultCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RoutingAdvancedSetDefault();\n        }, canEditRemove);\n        RoutingAdvancedImportRulesCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await RoutingAdvancedImportRules();\n        });\n\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveRoutingAsync();\n        });\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        SelectedSource = new();\n\n        DomainStrategy = _config.RoutingBasicItem.DomainStrategy;\n        DomainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox;\n\n        await ConfigHandler.InitBuiltinRouting(_config);\n        await RefreshRoutingItems();\n    }\n\n    #region Refresh Save\n\n    public async Task RefreshRoutingItems()\n    {\n        RoutingItems.Clear();\n\n        var routings = await AppManager.Instance.RoutingItems();\n        foreach (var item in routings)\n        {\n            var it = new RoutingItemModel()\n            {\n                IsActive = item.IsActive,\n                RuleNum = item.RuleNum,\n                Id = item.Id,\n                Remarks = item.Remarks,\n                Url = item.Url,\n                CustomIcon = item.CustomIcon,\n                CustomRulesetPath4Singbox = item.CustomRulesetPath4Singbox,\n                Sort = item.Sort,\n            };\n            RoutingItems.Add(it);\n        }\n    }\n\n    private async Task SaveRoutingAsync()\n    {\n        _config.RoutingBasicItem.DomainStrategy = DomainStrategy;\n        _config.RoutingBasicItem.DomainStrategy4Singbox = DomainStrategy4Singbox;\n\n        if (await ConfigHandler.SaveConfig(_config) == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n\n    #endregion Refresh Save\n\n    public async Task RoutingAdvancedEditAsync(bool blNew)\n    {\n        RoutingItem item;\n        if (blNew)\n        {\n            item = new();\n        }\n        else\n        {\n            item = await AppManager.Instance.GetRoutingItem(SelectedSource?.Id);\n            if (item is null)\n            {\n                return;\n            }\n        }\n        if (await _updateView?.Invoke(EViewAction.RoutingRuleSettingWindow, item) == true)\n        {\n            await RefreshRoutingItems();\n            IsModified = true;\n        }\n    }\n\n    public async Task RoutingAdvancedRemoveAsync()\n    {\n        if (SelectedSource is null || SelectedSource.Remarks.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules);\n            return;\n        }\n        if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)\n        {\n            return;\n        }\n        foreach (var it in SelectedSources ?? [SelectedSource])\n        {\n            var item = await AppManager.Instance.GetRoutingItem(it?.Id);\n            if (item != null)\n            {\n                await ConfigHandler.RemoveRoutingItem(item);\n            }\n        }\n\n        await RefreshRoutingItems();\n        IsModified = true;\n    }\n\n    public async Task RoutingAdvancedSetDefault()\n    {\n        var item = await AppManager.Instance.GetRoutingItem(SelectedSource?.Id);\n        if (item is null)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules);\n            return;\n        }\n\n        if (await ConfigHandler.SetDefaultRouting(_config, item) == 0)\n        {\n            await RefreshRoutingItems();\n            IsModified = true;\n        }\n    }\n\n    private async Task RoutingAdvancedImportRules()\n    {\n        if (await ConfigHandler.InitRouting(_config, true) == 0)\n        {\n            await RefreshRoutingItems();\n            IsModified = true;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/StatusBarViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class StatusBarViewModel : MyReactiveObject\n{\n    private static readonly Lazy<StatusBarViewModel> _instance = new(() => new(null));\n    public static StatusBarViewModel Instance => _instance.Value;\n\n    #region ObservableCollection\n\n    public IObservableCollection<RoutingItem> RoutingItems { get; } = new ObservableCollectionExtended<RoutingItem>();\n\n    public IObservableCollection<ComboItem> Servers { get; } = new ObservableCollectionExtended<ComboItem>();\n\n    [Reactive]\n    public RoutingItem SelectedRouting { get; set; }\n\n    [Reactive]\n    public ComboItem SelectedServer { get; set; }\n\n    [Reactive]\n    public bool BlServers { get; set; }\n\n    #endregion ObservableCollection\n\n    public ReactiveCommand<Unit, Unit> AddServerViaClipboardCmd { get; }\n    public ReactiveCommand<Unit, Unit> AddServerViaScanCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; }\n    public ReactiveCommand<Unit, Unit> CopyProxyCmdToClipboardCmd { get; }\n    public ReactiveCommand<Unit, Unit> NotifyLeftClickCmd { get; }\n    public ReactiveCommand<Unit, Unit> ShowWindowCmd { get; }\n    public ReactiveCommand<Unit, Unit> HideWindowCmd { get; }\n\n    #region System Proxy\n\n    [Reactive]\n    public bool BlSystemProxyClear { get; set; }\n\n    [Reactive]\n    public bool BlSystemProxySet { get; set; }\n\n    [Reactive]\n    public bool BlSystemProxyNothing { get; set; }\n\n    [Reactive]\n    public bool BlSystemProxyPac { get; set; }\n\n    public ReactiveCommand<Unit, Unit> SystemProxyClearCmd { get; }\n    public ReactiveCommand<Unit, Unit> SystemProxySetCmd { get; }\n    public ReactiveCommand<Unit, Unit> SystemProxyNothingCmd { get; }\n    public ReactiveCommand<Unit, Unit> SystemProxyPacCmd { get; }\n\n    [Reactive]\n    public bool BlRouting { get; set; }\n\n    [Reactive]\n    public int SystemProxySelected { get; set; }\n\n    [Reactive]\n    public bool BlSystemProxyPacVisible { get; set; }\n\n    #endregion System Proxy\n\n    #region UI\n\n    [Reactive]\n    public string InboundDisplay { get; set; }\n\n    [Reactive]\n    public string InboundLanDisplay { get; set; }\n\n    [Reactive]\n    public string RunningServerDisplay { get; set; }\n\n    [Reactive]\n    public string RunningServerToolTipText { get; set; }\n\n    [Reactive]\n    public string RunningInfoDisplay { get; set; }\n\n    [Reactive]\n    public string SpeedProxyDisplay { get; set; }\n\n    [Reactive]\n    public string SpeedDirectDisplay { get; set; }\n\n    [Reactive]\n    public bool EnableTun { get; set; }\n\n    [Reactive]\n    public bool BlIsNonWindows { get; set; }\n\n    #endregion UI\n\n    public StatusBarViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        SelectedRouting = new();\n        SelectedServer = new();\n        RunningServerToolTipText = \"-\";\n        BlSystemProxyPacVisible = Utils.IsWindows();\n        BlIsNonWindows = Utils.IsNonWindows();\n\n        if (_config.TunModeItem.EnableTun && AllowEnableTun())\n        {\n            EnableTun = true;\n        }\n        else\n        {\n            _config.TunModeItem.EnableTun = EnableTun = false;\n        }\n\n        #region WhenAnyValue && ReactiveCommand\n\n        this.WhenAnyValue(\n                x => x.SelectedRouting,\n                y => y != null && !y.Remarks.IsNullOrEmpty())\n            .Subscribe(async c => await RoutingSelectedChangedAsync(c));\n\n        this.WhenAnyValue(\n                x => x.SelectedServer,\n                y => y != null && !y.Text.IsNullOrEmpty())\n            .Subscribe(ServerSelectedChanged);\n\n        SystemProxySelected = (int)_config.SystemProxyItem.SysProxyType;\n        this.WhenAnyValue(\n                x => x.SystemProxySelected,\n                y => y >= 0)\n            .Subscribe(async c => await DoSystemProxySelected(c));\n\n        this.WhenAnyValue(\n                x => x.EnableTun,\n                y => y == true)\n            .Subscribe(async c => await DoEnableTun(c));\n\n        CopyProxyCmdToClipboardCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await CopyProxyCmdToClipboard();\n        });\n\n        NotifyLeftClickCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            AppEvents.ShowHideWindowRequested.Publish(null);\n            await Task.CompletedTask;\n        });\n        ShowWindowCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            AppEvents.ShowHideWindowRequested.Publish(true);\n            await Task.CompletedTask;\n        });\n        HideWindowCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            AppEvents.ShowHideWindowRequested.Publish(false);\n            await Task.CompletedTask;\n        });\n\n        AddServerViaClipboardCmd = ReactiveCommand.CreateFromTask(async () =>\n            {\n                await AddServerViaClipboard();\n            });\n        AddServerViaScanCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await AddServerViaScan();\n        });\n        SubUpdateCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await UpdateSubscriptionProcess(false);\n        });\n        SubUpdateViaProxyCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await UpdateSubscriptionProcess(true);\n        });\n\n        //System proxy\n        SystemProxyClearCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SetListenerType(ESysProxyType.ForcedClear);\n        });\n        SystemProxySetCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SetListenerType(ESysProxyType.ForcedChange);\n        });\n        SystemProxyNothingCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SetListenerType(ESysProxyType.Unchanged);\n        });\n        SystemProxyPacCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SetListenerType(ESysProxyType.Pac);\n        });\n\n        #endregion WhenAnyValue && ReactiveCommand\n\n        #region AppEvents\n\n        if (updateView != null)\n        {\n            InitUpdateView(updateView);\n        }\n\n        AppEvents.DispatcherStatisticsRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async result => await UpdateStatistics(result));\n\n        AppEvents.RoutingsMenuRefreshRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await RefreshRoutingsMenu());\n\n        AppEvents.TestServerRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await TestServerAvailability());\n\n        AppEvents.InboundDisplayRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async _ => await InboundDisplayStatus());\n\n        AppEvents.SysProxyChangeRequested\n            .AsObservable()\n            .ObserveOn(RxSchedulers.MainThreadScheduler)\n            .Subscribe(async result => await SetListenerType(result));\n\n        #endregion AppEvents\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        await ConfigHandler.InitBuiltinRouting(_config);\n        await RefreshRoutingsMenu();\n        await InboundDisplayStatus();\n        await ChangeSystemProxyAsync(_config.SystemProxyItem.SysProxyType, true);\n    }\n\n    public void InitUpdateView(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _updateView = updateView;\n        if (_updateView != null)\n        {\n            AppEvents.ProfilesRefreshRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(async _ => await RefreshServersBiz()); //.DisposeWith(_disposables);\n        }\n    }\n\n    private async Task CopyProxyCmdToClipboard()\n    {\n        var cmd = Utils.IsWindows() ? \"set\" : \"export\";\n        var address = $\"{Global.Loopback}:{AppManager.Instance.GetLocalPort(EInboundProtocol.socks)}\";\n\n        var sb = new StringBuilder();\n        sb.AppendLine($\"{cmd} http_proxy={Global.HttpProtocol}{address}\");\n        sb.AppendLine($\"{cmd} https_proxy={Global.HttpProtocol}{address}\");\n        sb.AppendLine($\"{cmd} all_proxy={Global.Socks5Protocol}{address}\");\n        sb.AppendLine(\"\");\n        sb.AppendLine($\"{cmd} HTTP_PROXY={Global.HttpProtocol}{address}\");\n        sb.AppendLine($\"{cmd} HTTPS_PROXY={Global.HttpProtocol}{address}\");\n        sb.AppendLine($\"{cmd} ALL_PROXY={Global.Socks5Protocol}{address}\");\n\n        await _updateView?.Invoke(EViewAction.SetClipboardData, sb.ToString());\n    }\n\n    private async Task AddServerViaClipboard()\n    {\n        AppEvents.AddServerViaClipboardRequested.Publish();\n        await Task.Delay(1000);\n    }\n\n    private async Task AddServerViaScan()\n    {\n        AppEvents.AddServerViaScanRequested.Publish();\n        await Task.Delay(1000);\n    }\n\n    private async Task UpdateSubscriptionProcess(bool blProxy)\n    {\n        AppEvents.SubscriptionsUpdateRequested.Publish(blProxy);\n        await Task.Delay(1000);\n    }\n\n    private async Task RefreshServersBiz()\n    {\n        await RefreshServersMenu();\n\n        //display running server\n        var running = await ConfigHandler.GetDefaultServer(_config);\n        if (running != null)\n        {\n            RunningServerDisplay =\n                RunningServerToolTipText = running.GetSummary();\n        }\n        else\n        {\n            RunningServerDisplay =\n                RunningServerToolTipText = ResUI.CheckServerSettings;\n        }\n    }\n\n    private async Task RefreshServersMenu()\n    {\n        var lstModel = await AppManager.Instance.ProfileModels(_config.SubIndexId, \"\");\n\n        Servers.Clear();\n        if (lstModel.Count > _config.GuiItem.TrayMenuServersLimit)\n        {\n            BlServers = false;\n            return;\n        }\n\n        BlServers = true;\n        for (var k = 0; k < lstModel.Count; k++)\n        {\n            var it = lstModel[k];\n            var name = it.GetSummary();\n\n            var item = new ComboItem() { ID = it.IndexId, Text = name };\n            Servers.Add(item);\n            if (_config.IndexId == it.IndexId)\n            {\n                SelectedServer = item;\n            }\n        }\n    }\n\n    private void ServerSelectedChanged(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        if (SelectedServer == null)\n        {\n            return;\n        }\n        if (SelectedServer.ID.IsNullOrEmpty())\n        {\n            return;\n        }\n        AppEvents.SetDefaultServerRequested.Publish(SelectedServer.ID);\n    }\n\n    public async Task TestServerAvailability()\n    {\n        var item = await ConfigHandler.GetDefaultServer(_config);\n        if (item == null)\n        {\n            return;\n        }\n\n        await TestServerAvailabilitySub(ResUI.Speedtesting);\n\n        var msg = await Task.Run(ConnectionHandler.RunAvailabilityCheck);\n\n        NoticeManager.Instance.SendMessageEx(msg);\n        await TestServerAvailabilitySub(msg);\n    }\n\n    private async Task TestServerAvailabilitySub(string msg)\n    {\n        RxSchedulers.MainThreadScheduler.Schedule(msg, (scheduler, msg) =>\n        {\n            _ = TestServerAvailabilityResult(msg);\n            return Disposable.Empty;\n        });\n        await Task.CompletedTask;\n    }\n\n    public async Task TestServerAvailabilityResult(string msg)\n    {\n        RunningInfoDisplay = msg;\n        await Task.CompletedTask;\n    }\n\n    #region System proxy and Routings\n\n    private async Task SetListenerType(ESysProxyType type)\n    {\n        if (_config.SystemProxyItem.SysProxyType == type)\n        {\n            return;\n        }\n        _config.SystemProxyItem.SysProxyType = type;\n        await ChangeSystemProxyAsync(type, true);\n        NoticeManager.Instance.SendMessageEx($\"{ResUI.TipChangeSystemProxy} - {_config.SystemProxyItem.SysProxyType}\");\n\n        SystemProxySelected = (int)_config.SystemProxyItem.SysProxyType;\n        await ConfigHandler.SaveConfig(_config);\n    }\n\n    public async Task ChangeSystemProxyAsync(ESysProxyType type, bool blChange)\n    {\n        await SysProxyHandler.UpdateSysProxy(_config, false);\n\n        BlSystemProxyClear = type == ESysProxyType.ForcedClear;\n        BlSystemProxySet = type == ESysProxyType.ForcedChange;\n        BlSystemProxyNothing = type == ESysProxyType.Unchanged;\n        BlSystemProxyPac = type == ESysProxyType.Pac;\n\n        if (blChange)\n        {\n            _updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null);\n        }\n    }\n\n    private async Task RefreshRoutingsMenu()\n    {\n        RoutingItems.Clear();\n\n        BlRouting = true;\n        var routings = await AppManager.Instance.RoutingItems();\n        foreach (var item in routings)\n        {\n            RoutingItems.Add(item);\n            if (item.IsActive)\n            {\n                SelectedRouting = item;\n            }\n        }\n    }\n\n    private async Task RoutingSelectedChangedAsync(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n\n        if (SelectedRouting == null)\n        {\n            return;\n        }\n\n        var item = await AppManager.Instance.GetRoutingItem(SelectedRouting?.Id);\n        if (item is null)\n        {\n            return;\n        }\n\n        if (await ConfigHandler.SetDefaultRouting(_config, item) == 0)\n        {\n            NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting);\n            AppEvents.ReloadRequested.Publish();\n            _updateView?.Invoke(EViewAction.DispatcherRefreshIcon, null);\n        }\n    }\n\n    private async Task DoSystemProxySelected(bool c)\n    {\n        if (!c)\n        {\n            return;\n        }\n        if (_config.SystemProxyItem.SysProxyType == (ESysProxyType)SystemProxySelected)\n        {\n            return;\n        }\n        await SetListenerType((ESysProxyType)SystemProxySelected);\n    }\n\n    private async Task DoEnableTun(bool c)\n    {\n        if (_config.TunModeItem.EnableTun == EnableTun)\n        {\n            return;\n        }\n\n        _config.TunModeItem.EnableTun = EnableTun;\n\n        if (EnableTun && AllowEnableTun() == false)\n        {\n            // When running as a non-administrator, reboot to administrator mode\n            if (Utils.IsWindows())\n            {\n                _config.TunModeItem.EnableTun = false;\n                await AppManager.Instance.RebootAsAdmin();\n                return;\n            }\n            else\n            {\n                bool? passwordResult = await _updateView?.Invoke(EViewAction.PasswordInput, null);\n                if (passwordResult == false)\n                {\n                    _config.TunModeItem.EnableTun = false;\n                    return;\n                }\n            }\n        }\n        await ConfigHandler.SaveConfig(_config);\n        AppEvents.ReloadRequested.Publish();\n    }\n\n    private bool AllowEnableTun()\n    {\n        if (Utils.IsWindows())\n        {\n            return Utils.IsAdministrator();\n        }\n        else if (Utils.IsLinux())\n        {\n            return AppManager.Instance.LinuxSudoPwd.IsNotEmpty();\n        }\n        else if (Utils.IsMacOS())\n        {\n            return AppManager.Instance.LinuxSudoPwd.IsNotEmpty();\n        }\n        return false;\n    }\n\n    #endregion System proxy and Routings\n\n    #region UI\n\n    private async Task InboundDisplayStatus()\n    {\n        StringBuilder sb = new();\n        sb.Append($\"[{EInboundProtocol.mixed}:{AppManager.Instance.GetLocalPort(EInboundProtocol.socks)}\");\n        if (_config.Inbound.First().SecondLocalPortEnabled)\n        {\n            sb.Append($\",{AppManager.Instance.GetLocalPort(EInboundProtocol.socks2)}\");\n        }\n        sb.Append(']');\n        InboundDisplay = $\"{ResUI.LabLocal}:{sb}\";\n\n        if (_config.Inbound.First().AllowLANConn)\n        {\n            var lan = _config.Inbound.First().NewPort4LAN\n                ? $\"[{EInboundProtocol.mixed}:{AppManager.Instance.GetLocalPort(EInboundProtocol.socks3)}]\"\n                : $\"[{EInboundProtocol.mixed}:{AppManager.Instance.GetLocalPort(EInboundProtocol.socks)}]\";\n            InboundLanDisplay = $\"{ResUI.LabLAN}:{lan}\";\n        }\n        else\n        {\n            InboundLanDisplay = $\"{ResUI.LabLAN}:{Global.None}\";\n        }\n        await Task.CompletedTask;\n    }\n\n    public async Task UpdateStatistics(ServerSpeedItem update)\n    {\n        if (!_config.GuiItem.DisplayRealTimeSpeed)\n        {\n            return;\n        }\n\n        try\n        {\n            if (AppManager.Instance.IsRunningCore(ECoreType.sing_box))\n            {\n                SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, EInboundProtocol.mixed, Utils.HumanFy(update.ProxyUp), Utils.HumanFy(update.ProxyDown));\n                SpeedDirectDisplay = string.Empty;\n            }\n            else\n            {\n                SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.ProxyTag, Utils.HumanFy(update.ProxyUp), Utils.HumanFy(update.ProxyDown));\n                SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.DirectTag, Utils.HumanFy(update.DirectUp), Utils.HumanFy(update.DirectDown));\n            }\n        }\n        catch\n        {\n        }\n        await Task.CompletedTask;\n    }\n\n    #endregion UI\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/SubEditViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class SubEditViewModel : MyReactiveObject\n{\n    [Reactive]\n    public SubItem SelectedSource { get; set; }\n\n    public ReactiveCommand<Unit, Unit> SaveCmd { get; }\n\n    public SubEditViewModel(SubItem subItem, Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        SaveCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await SaveSubAsync();\n        });\n\n        SelectedSource = subItem.Id.IsNullOrEmpty() ? subItem : JsonUtils.DeepCopy(subItem);\n    }\n\n    private async Task SaveSubAsync()\n    {\n        var remarks = SelectedSource.Remarks;\n        if (remarks.IsNullOrEmpty())\n        {\n            NoticeManager.Instance.Enqueue(ResUI.PleaseFillRemarks);\n            return;\n        }\n\n        var url = SelectedSource.Url;\n        if (url.IsNotEmpty())\n        {\n            var uri = Utils.TryUri(url);\n            if (uri == null)\n            {\n                NoticeManager.Instance.Enqueue(ResUI.InvalidUrlTip);\n                return;\n            }\n            //Do not allow http protocol\n            if (url.StartsWith(Global.HttpProtocol) && !Utils.IsPrivateNetwork(uri.IdnHost))\n            {\n                NoticeManager.Instance.Enqueue(ResUI.InsecureUrlProtocol);\n                //return;\n            }\n        }\n\n        if (await ConfigHandler.AddSubItem(_config, SelectedSource) == 0)\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n            _updateView?.Invoke(EViewAction.CloseWindow, null);\n        }\n        else\n        {\n            NoticeManager.Instance.Enqueue(ResUI.OperationFailed);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/ServiceLib/ViewModels/SubSettingViewModel.cs",
    "content": "namespace ServiceLib.ViewModels;\n\npublic class SubSettingViewModel : MyReactiveObject\n{\n    public IObservableCollection<SubItem> SubItems { get; } = new ObservableCollectionExtended<SubItem>();\n\n    [Reactive]\n    public SubItem SelectedSource { get; set; }\n\n    public IList<SubItem> SelectedSources { get; set; }\n\n    public ReactiveCommand<Unit, Unit> SubAddCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubDeleteCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubEditCmd { get; }\n    public ReactiveCommand<Unit, Unit> SubShareCmd { get; }\n    public bool IsModified { get; set; }\n\n    public SubSettingViewModel(Func<EViewAction, object?, Task<bool>>? updateView)\n    {\n        _config = AppManager.Instance.Config;\n        _updateView = updateView;\n\n        var canEditRemove = this.WhenAnyValue(\n           x => x.SelectedSource,\n           selectedSource => selectedSource != null && !selectedSource.Id.IsNullOrEmpty());\n\n        SubAddCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await EditSubAsync(true);\n        });\n        SubDeleteCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await DeleteSubAsync();\n        }, canEditRemove);\n        SubEditCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await EditSubAsync(false);\n        }, canEditRemove);\n        SubShareCmd = ReactiveCommand.CreateFromTask(async () =>\n        {\n            await _updateView?.Invoke(EViewAction.ShareSub, SelectedSource?.Url);\n        }, canEditRemove);\n\n        _ = Init();\n    }\n\n    private async Task Init()\n    {\n        SelectedSource = new();\n\n        await RefreshSubItems();\n    }\n\n    public async Task RefreshSubItems()\n    {\n        SubItems.Clear();\n        SubItems.AddRange(await AppManager.Instance.SubItems());\n    }\n\n    public async Task EditSubAsync(bool blNew)\n    {\n        SubItem item;\n        if (blNew)\n        {\n            item = new();\n        }\n        else\n        {\n            item = await AppManager.Instance.GetSubItem(SelectedSource?.Id);\n            if (item is null)\n            {\n                return;\n            }\n        }\n        if (await _updateView?.Invoke(EViewAction.SubEditWindow, item) == true)\n        {\n            await RefreshSubItems();\n            IsModified = true;\n        }\n    }\n\n    private async Task DeleteSubAsync()\n    {\n        if (await _updateView?.Invoke(EViewAction.ShowYesNo, null) == false)\n        {\n            return;\n        }\n\n        foreach (var it in SelectedSources ?? [SelectedSource])\n        {\n            await ConfigHandler.DeleteSubItem(_config, it.Id);\n        }\n        await RefreshSubItems();\n        NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);\n        IsModified = true;\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/App.xaml",
    "content": "<Application\n    x:Class=\"v2rayN.App\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:conv=\"clr-namespace:v2rayN.Converters\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    ShutdownMode=\"OnExplicitShutdown\"\n    StartupUri=\"Views/MainWindow.xaml\">\n    <Application.Resources>\n        <ResourceDictionary xmlns:system=\"clr-namespace:System;assembly=mscorlib\">\n            <ResourceDictionary.MergedDictionaries>\n                <materialDesign:BundledTheme\n                    BaseTheme=\"Light\"\n                    PrimaryColor=\"Blue\"\n                    SecondaryColor=\"Lime\" />\n                <ResourceDictionary Source=\"pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesign2.Defaults.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n            <system:Double x:Key=\"MenuItemHeight\">32</system:Double>\n            <system:Double x:Key=\"StdFontSize\">12</system:Double>\n            <system:Double x:Key=\"StdFontSize1\">13</system:Double>\n            <system:Double x:Key=\"StdFontSize-1\">11</system:Double>\n\n            <conv:InverseBooleanConverter x:Key=\"InverseBooleanConverter\" />\n            <Thickness\n                x:Key=\"Margin4\"\n                Bottom=\"4\"\n                Left=\"4\"\n                Right=\"4\"\n                Top=\"4\" />\n            <Thickness\n                x:Key=\"Margin8\"\n                Bottom=\"8\"\n                Left=\"8\"\n                Right=\"8\"\n                Top=\"8\" />\n            <Thickness\n                x:Key=\"OutlinedTextBoxDefaultPadding\"\n                Bottom=\"8\"\n                Left=\"8\"\n                Right=\"8\"\n                Top=\"8\" />\n            <Thickness\n                x:Key=\"MarginLeftRight4\"\n                Bottom=\"0\"\n                Left=\"4\"\n                Right=\"4\"\n                Top=\"0\" />\n            <Thickness\n                x:Key=\"MarginLeftRight8\"\n                Bottom=\"0\"\n                Left=\"8\"\n                Right=\"8\"\n                Top=\"0\" />\n            <Thickness\n                x:Key=\"MarginLeft8\"\n                Bottom=\"0\"\n                Left=\"8\"\n                Right=\"0\"\n                Top=\"0\" />\n            <Thickness\n                x:Key=\"MarginRight8\"\n                Bottom=\"0\"\n                Left=\"0\"\n                Right=\"8\"\n                Top=\"0\" />\n            <Style\n                x:Key=\"ModuleTitle\"\n                BasedOn=\"{StaticResource MaterialDesignTextBlock}\"\n                TargetType=\"{x:Type TextBlock}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize1}\" />\n            </Style>\n            <Style\n                x:Key=\"ToolbarTextBlock\"\n                BasedOn=\"{StaticResource MaterialDesignTextBlock}\"\n                TargetType=\"{x:Type TextBlock}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"StatusbarItem\"\n                BasedOn=\"{StaticResource MaterialDesignTextBlock}\"\n                TargetType=\"{x:Type TextBlock}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n                <Setter Property=\"Padding\" Value=\"0\" />\n            </Style>\n            <Style TargetType=\"{x:Type TextElement}\">\n                <Setter Property=\"FontWeight\" Value=\"Regular\" />\n            </Style>\n            <Style TargetType=\"{x:Type TextBlock}\">\n                <Setter Property=\"FontWeight\" Value=\"Regular\" />\n            </Style>\n            <Style x:Key=\"lvItemSelected\" TargetType=\"{x:Type ListViewItem}\">\n                <Setter Property=\"Margin\" Value=\"2\" />\n                <Setter Property=\"Template\">\n                    <Setter.Value>\n                        <ControlTemplate TargetType=\"ListViewItem\">\n                            <materialDesign:Card Name=\"_Card\" SnapsToDevicePixels=\"true\">\n                                <ContentPresenter />\n                            </materialDesign:Card>\n                            <ControlTemplate.Triggers>\n                                <Trigger Property=\"IsSelected\" Value=\"true\">\n                                    <Setter TargetName=\"_Card\" Property=\"Background\" Value=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\" />\n                                </Trigger>\n                            </ControlTemplate.Triggers>\n                        </ControlTemplate>\n                    </Setter.Value>\n                </Setter>\n            </Style>\n\n            <Style x:Key=\"GridViewColumnHeaderStyle\" TargetType=\"{x:Type GridViewColumnHeader}\">\n                <Setter Property=\"Height\" Value=\"30\" />\n            </Style>\n            <Style\n                x:Key=\"ListItemCheckBox\"\n                BasedOn=\"{StaticResource MaterialDesignUserForegroundCheckBox}\"\n                TargetType=\"{x:Type CheckBox}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"DefButton\"\n                BasedOn=\"{StaticResource MaterialDesignRaisedButton}\"\n                TargetType=\"{x:Type ButtonBase}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"DefContextMenu\"\n                BasedOn=\"{StaticResource MaterialDesignContextMenu}\"\n                TargetType=\"{x:Type ContextMenu}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n                <Setter Property=\"FontFamily\" Value=\"{x:Static conv:MaterialDesignFonts.MyFont}\" />\n            </Style>\n\n            <Style\n                x:Key=\"ToolbarMenu\"\n                BasedOn=\"{StaticResource MaterialDesignMenu}\"\n                TargetType=\"{x:Type Menu}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n                <Setter Property=\"FontFamily\" Value=\"{x:Static conv:MaterialDesignFonts.MyFont}\" />\n            </Style>\n\n            <Style\n                x:Key=\"DefComboBox\"\n                BasedOn=\"{StaticResource MaterialDesignComboBox}\"\n                TargetType=\"{x:Type ComboBox}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n                <Setter Property=\"HorizontalAlignment\" Value=\"Left\" />\n            </Style>\n            <Style\n                x:Key=\"DefDataGrid\"\n                BasedOn=\"{StaticResource MaterialDesignDataGrid}\"\n                TargetType=\"{x:Type DataGrid}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"DefTextBox\"\n                BasedOn=\"{StaticResource MaterialDesignTextBox}\"\n                TargetType=\"{x:Type TextBox}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"MyOutlinedTextBox\"\n                BasedOn=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                TargetType=\"{x:Type TextBox}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n                <Setter Property=\"Padding\" Value=\"{StaticResource OutlinedTextBoxDefaultPadding}\" />\n            </Style>\n            <Style\n                x:Key=\"MyGroupBox\"\n                BasedOn=\"{StaticResource MaterialDesignGroupBox}\"\n                TargetType=\"{x:Type GroupBox}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"MyChipListBoxItem\"\n                BasedOn=\"{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBoxItem}\"\n                TargetType=\"{x:Type ListBoxItem}\">\n                <Setter Property=\"Margin\" Value=\"-2,0\" />\n            </Style>\n            <Style\n                x:Key=\"MyOutlinedTextComboBox\"\n                BasedOn=\"{StaticResource MaterialDesignOutlinedComboBox}\"\n                TargetType=\"{x:Type ComboBox}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n                <Setter Property=\"Padding\" Value=\"{StaticResource OutlinedTextBoxDefaultPadding}\" />\n            </Style>\n            <Style x:Key=\"ListItemChip\" TargetType=\"{x:Type materialDesign:Chip}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"ListItemTitle\"\n                BasedOn=\"{StaticResource MaterialDesignTextBlock}\"\n                TargetType=\"{x:Type TextBlock}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"ListItemSubTitle\"\n                BasedOn=\"{StaticResource MaterialDesignTextBlock}\"\n                TargetType=\"{x:Type TextBlock}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize}\" />\n            </Style>\n            <Style\n                x:Key=\"ListItemSubTitle2\"\n                BasedOn=\"{StaticResource MaterialDesignTextBlock}\"\n                TargetType=\"{x:Type TextBlock}\">\n                <Setter Property=\"FontSize\" Value=\"{DynamicResource StdFontSize-1}\" />\n            </Style>\n\n            <Style\n                x:Key=\"WindowGlobal\"\n                BasedOn=\"{StaticResource {x:Type Window}}\"\n                TargetType=\"{x:Type Window}\">\n                <Setter Property=\"TextOptions.TextFormattingMode\" Value=\"Display\" />\n                <Setter Property=\"TextOptions.TextRenderingMode\" Value=\"ClearType\" />\n                <Setter Property=\"TextOptions.TextHintingMode\" Value=\"Fixed\" />\n                <Setter Property=\"TextElement.Foreground\" Value=\"{DynamicResource MaterialDesignBody}\" />\n                <Setter Property=\"Background\" Value=\"{DynamicResource MaterialDesignPaper}\" />\n                <Setter Property=\"TextElement.FontFamily\" Value=\"{x:Static conv:MaterialDesignFonts.MyFont}\" />\n                <Setter Property=\"FontFamily\" Value=\"{x:Static conv:MaterialDesignFonts.MyFont}\" />\n                <Setter Property=\"ResizeMode\" Value=\"CanResize\" />\n            </Style>\n            <Style\n                x:Key=\"ViewGlobal\"\n                BasedOn=\"{StaticResource {x:Type UserControl}}\"\n                TargetType=\"{x:Type UserControl}\">\n                <Setter Property=\"TextOptions.TextFormattingMode\" Value=\"Display\" />\n                <Setter Property=\"TextOptions.TextRenderingMode\" Value=\"ClearType\" />\n                <Setter Property=\"TextOptions.TextHintingMode\" Value=\"Fixed\" />\n                <Setter Property=\"TextElement.Foreground\" Value=\"{DynamicResource MaterialDesignBody}\" />\n                <Setter Property=\"Background\" Value=\"{DynamicResource MaterialDesignPaper}\" />\n                <Setter Property=\"TextElement.FontFamily\" Value=\"{x:Static conv:MaterialDesignFonts.MyFont}\" />\n                <Setter Property=\"FontFamily\" Value=\"{x:Static conv:MaterialDesignFonts.MyFont}\" />\n            </Style>\n        </ResourceDictionary>\n    </Application.Resources>\n</Application>\n"
  },
  {
    "path": "v2rayN/v2rayN/App.xaml.cs",
    "content": "namespace v2rayN;\n\n/// <summary>\n/// Interaction logic for App.xaml\n/// </summary>\npublic partial class App : Application\n{\n    public static EventWaitHandle ProgramStarted;\n\n    public App()\n    {\n        DispatcherUnhandledException += App_DispatcherUnhandledException;\n        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;\n        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;\n    }\n\n    /// <summary>\n    /// Open only one process\n    /// </summary>\n    /// <param name=\"e\"></param>\n    protected override void OnStartup(StartupEventArgs e)\n    {\n        var exePathKey = Utils.GetMd5(Utils.GetExePath());\n\n        var rebootas = (e.Args ?? Array.Empty<string>()).Any(t => t == Global.RebootAs);\n        ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out var bCreatedNew);\n        if (!rebootas && !bCreatedNew)\n        {\n            ProgramStarted.Set();\n            Environment.Exit(0);\n            return;\n        }\n\n        if (!AppManager.Instance.InitApp())\n        {\n            UI.Show($\"Loading GUI configuration file is abnormal,please restart the application{Environment.NewLine}加载GUI配置文件异常,请重启应用\");\n            Environment.Exit(0);\n            return;\n        }\n\n        AppManager.Instance.InitComponents();\n\n        RxAppBuilder.CreateReactiveUIBuilder()\n            .WithWpf()\n            .BuildApp();\n\n        base.OnStartup(e);\n    }\n\n    private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)\n    {\n        Logging.SaveLog(\"App_DispatcherUnhandledException\", e.Exception);\n        e.Handled = true;\n    }\n\n    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)\n    {\n        if (e.ExceptionObject != null)\n        {\n            Logging.SaveLog(\"CurrentDomain_UnhandledException\", (Exception)e.ExceptionObject);\n        }\n    }\n\n    private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)\n    {\n        Logging.SaveLog(\"TaskScheduler_UnobservedTaskException\", e.Exception);\n    }\n\n    protected override void OnExit(ExitEventArgs e)\n    {\n        Logging.SaveLog(\"OnExit\");\n        base.OnExit(e);\n        Process.GetCurrentProcess().Kill();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/AssemblyInfo.cs",
    "content": "[assembly: ThemeInfo(\n    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located\n                                     //(used if a resource is not found in the page,\n                                     // or application resource dictionaries)\n    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located\n                                              //(used if a resource is not found in the page,\n                                              // app, or any theme specific resource dictionaries)\n)]\n"
  },
  {
    "path": "v2rayN/v2rayN/Base/MyDGTextColumn.cs",
    "content": "using System.Windows.Controls;\n\nnamespace v2rayN.Base;\n\ninternal class MyDGTextColumn : DataGridTextColumn\n{\n    public string ExName { get; set; }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Base/WindowBase.cs",
    "content": "namespace v2rayN.Base;\n\npublic class WindowBase<TViewModel> : ReactiveWindow<TViewModel> where TViewModel : class\n{\n    public WindowBase()\n    {\n        Loaded += OnLoaded;\n    }\n\n    protected virtual void OnLoaded(object? sender, RoutedEventArgs e)\n    {\n        try\n        {\n            var sizeItem = ConfigHandler.GetWindowSizeItem(AppManager.Instance.Config, GetType().Name);\n            if (sizeItem == null)\n            {\n                return;\n            }\n\n            Width = Math.Min(sizeItem.Width, SystemParameters.WorkArea.Width);\n            Height = Math.Min(sizeItem.Height, SystemParameters.WorkArea.Height);\n\n            Left = SystemParameters.WorkArea.Left + ((SystemParameters.WorkArea.Width - Width) / 2);\n            Top = SystemParameters.WorkArea.Top + ((SystemParameters.WorkArea.Height - Height) / 2);\n        }\n        catch { }\n    }\n\n    protected override void OnClosed(EventArgs e)\n    {\n        base.OnClosed(e);\n\n        try\n        {\n            ConfigHandler.SaveWindowSizeItem(AppManager.Instance.Config, GetType().Name, Width, Height);\n        }\n        catch { }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Common/QRCodeWindowsUtils.cs",
    "content": "using System.Drawing;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\n\nnamespace v2rayN.Common;\n\npublic class QRCodeWindowsUtils\n{\n    public static ImageSource? GetQRCode(string? strContent)\n    {\n        if (strContent is null)\n        {\n            return null;\n        }\n        try\n        {\n            var qrCodeImage = QRCodeUtils.GenQRCode(strContent);\n            return qrCodeImage is null ? null : ByteToImage(qrCodeImage);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"GetQRCode\", ex);\n            return null;\n        }\n    }\n\n    public static byte[]? CaptureScreen(Window window)\n    {\n        try\n        {\n            GetDpi(window, out var dpiX, out var dpiY);\n\n            var left = (int)SystemParameters.WorkArea.Left;\n            var top = (int)SystemParameters.WorkArea.Top;\n            var width = (int)(SystemParameters.WorkArea.Width / dpiX);\n            var height = (int)(SystemParameters.WorkArea.Height / dpiY);\n\n            using var fullImage = new Bitmap(width, height);\n            using var g = Graphics.FromImage(fullImage);\n\n            g.CopyFromScreen(left, top, 0, 0, fullImage.Size, CopyPixelOperation.SourceCopy);\n            //fullImage.Save(\"test1.png\", ImageFormat.Png);\n            return ImageToByte(fullImage);\n        }\n        catch\n        {\n            return null;\n        }\n    }\n\n    private static void GetDpi(Window window, out float x, out float y)\n    {\n        var hWnd = new WindowInteropHelper(window).EnsureHandle();\n        var g = Graphics.FromHwnd(hWnd);\n\n        x = 96 / g.DpiX;\n        y = 96 / g.DpiY;\n    }\n\n    private static ImageSource? ByteToImage(IEnumerable imageData)\n    {\n        return new ImageSourceConverter().ConvertFrom(imageData) as BitmapSource;\n    }\n\n    private static byte[]? ImageToByte(Image img)\n    {\n        return new ImageConverter().ConvertTo(img, typeof(byte[])) as byte[];\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Common/UI.cs",
    "content": "using Microsoft.Win32;\n\nnamespace v2rayN.Common;\n\ninternal class UI\n{\n    private static readonly string caption = Global.AppName;\n\n    public static void Show(string msg)\n    {\n        MessageBox.Show(msg, caption, MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);\n    }\n\n    public static MessageBoxResult ShowYesNo(string msg)\n    {\n        return MessageBox.Show(msg, caption, MessageBoxButton.YesNo, MessageBoxImage.Question);\n    }\n\n    public static bool? OpenFileDialog(out string fileName, string filter)\n    {\n        fileName = string.Empty;\n\n        var fileDialog = new OpenFileDialog\n        {\n            Multiselect = false,\n            Filter = filter\n        };\n\n        if (fileDialog.ShowDialog() != true)\n        {\n            return false;\n        }\n        fileName = fileDialog.FileName;\n\n        return true;\n    }\n\n    public static bool? SaveFileDialog(out string fileName, string filter)\n    {\n        fileName = string.Empty;\n\n        SaveFileDialog fileDialog = new()\n        {\n            Filter = filter,\n            FilterIndex = 2,\n            RestoreDirectory = true\n        };\n        if (fileDialog.ShowDialog() != true)\n        {\n            return false;\n        }\n\n        fileName = fileDialog.FileName;\n\n        return true;\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Common/WindowsUtils.cs",
    "content": "using System.Drawing;\nusing System.Windows.Media;\nusing System.Windows.Media.Imaging;\nusing Microsoft.Win32;\n\nnamespace v2rayN.Common;\n\ninternal static class WindowsUtils\n{\n    private static readonly string _tag = \"WindowsUtils\";\n\n    public static string? GetClipboardData()\n    {\n        var strData = string.Empty;\n        try\n        {\n            var data = Clipboard.GetDataObject();\n            if (data?.GetDataPresent(DataFormats.UnicodeText) == true)\n            {\n                strData = data.GetData(DataFormats.UnicodeText)?.ToString();\n            }\n            return strData;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n        return strData;\n    }\n\n    public static void SetClipboardData(string strData)\n    {\n        try\n        {\n            Clipboard.SetText(strData);\n        }\n        catch\n        {\n        }\n    }\n\n    [DllImport(\"dwmapi.dll\")]\n    public static extern int DwmSetWindowAttribute(nint hwnd, DWMWINDOWATTRIBUTE attribute, ref int attributeValue, uint attributeSize);\n\n    public static ImageSource IconToImageSource(Icon icon)\n    {\n        return Imaging.CreateBitmapSourceFromHIcon(\n            icon.Handle,\n            new Int32Rect(0, 0, icon.Width, icon.Height),\n            BitmapSizeOptions.FromEmptyOptions());\n    }\n\n    public static void SetDarkBorder(Window window, string? theme)\n    {\n        var isDark = theme switch\n        {\n            nameof(ETheme.Dark) => true,\n            nameof(ETheme.Light) => false,\n            _ => IsDarkTheme(),\n        };\n\n        SetDarkBorder(window, isDark);\n    }\n\n    private static void SetDarkBorder(Window window, bool dark)\n    {\n        // Make sure the handle is created before the window is shown\n        var hWnd = new WindowInteropHelper(window).EnsureHandle();\n        var attribute = dark ? 1 : 0;\n        var attributeSize = (uint)Marshal.SizeOf(attribute);\n        DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1, ref attribute, attributeSize);\n        DwmSetWindowAttribute(hWnd, DWMWINDOWATTRIBUTE.DWMWA_USE_IMMERSIVE_DARK_MODE, ref attribute, attributeSize);\n    }\n\n    private static bool IsDarkTheme()\n    {\n        using var key = Registry.CurrentUser.OpenSubKey(@\"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize\");\n        var obj = key?.GetValue(\"AppsUseLightTheme\");\n        var value = obj?.ToString().ToInt();\n        return value == 0;\n    }\n\n    #region Windows API\n\n    [Flags]\n    public enum DWMWINDOWATTRIBUTE : uint\n    {\n        DWMWA_USE_IMMERSIVE_DARK_MODE_BEFORE_20H1 = 19,\n        DWMWA_USE_IMMERSIVE_DARK_MODE = 20,\n    }\n\n    #endregion Windows API\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Converters/DelayColorConverter.cs",
    "content": "using System.Windows.Media;\n\nnamespace v2rayN.Converters;\n\npublic class DelayColorConverter : IValueConverter\n{\n    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)\n    {\n        var delay = value.ToString().ToInt();\n\n        return delay switch\n        {\n            <= 0 => new SolidColorBrush(Colors.Red),\n            <= 500 => new SolidColorBrush(Colors.Green),\n            _ => new SolidColorBrush(Colors.IndianRed)\n        };\n    }\n\n    public object? ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)\n    {\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Converters/InverseBooleanConverter.cs",
    "content": "namespace v2rayN.Converters;\n\n[ValueConversion(typeof(bool), typeof(bool))]\npublic class InverseBooleanConverter : IValueConverter\n{\n    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)\n    {\n        if (targetType != typeof(bool))\n        {\n            throw new InvalidOperationException(\"The target must be a boolean\");\n        }\n\n        return !(bool)value;\n    }\n\n    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)\n    {\n        throw new NotImplementedException();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Converters/MaterialDesignFonts.cs",
    "content": "using System.Windows.Media;\n\nnamespace v2rayN.Converters;\n\npublic class MaterialDesignFonts\n{\n    public static FontFamily MyFont { get; }\n\n    static MaterialDesignFonts()\n    {\n        try\n        {\n            var fontFamily = AppManager.Instance.Config.UiItem.CurrentFontFamily;\n            if (fontFamily.IsNotEmpty())\n            {\n                var fontPath = Utils.GetFontsPath();\n                MyFont = new FontFamily(new Uri(@$\"file:///{fontPath}\\\"), $\"./#{fontFamily}\");\n            }\n        }\n        catch\n        {\n        }\n        MyFont ??= new FontFamily(\"Microsoft YaHei\");\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/FodyWeavers.xml",
    "content": "﻿<Weavers xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n  <ReactiveUI />\n</Weavers>"
  },
  {
    "path": "v2rayN/v2rayN/GlobalUsings.cs",
    "content": "global using System;\nglobal using System.Collections;\nglobal using System.Collections.Generic;\nglobal using System.ComponentModel;\nglobal using System.Diagnostics;\nglobal using System.Globalization;\nglobal using System.IO;\nglobal using System.Linq;\nglobal using System.Reactive.Disposables.Fluent;\nglobal using System.Reactive.Linq;\nglobal using System.Runtime.InteropServices;\nglobal using System.Text;\nglobal using System.Threading;\nglobal using System.Threading.Tasks;\nglobal using System.Windows;\nglobal using System.Windows.Data;\nglobal using System.Windows.Input;\nglobal using System.Windows.Interop;\nglobal using System.Windows.Threading;\nglobal using DynamicData;\nglobal using DynamicData.Binding;\nglobal using ReactiveUI;\nglobal using ReactiveUI.Builder;\nglobal using ReactiveUI.Fody.Helpers;\nglobal using ServiceLib;\nglobal using ServiceLib.Base;\nglobal using ServiceLib.Common;\nglobal using ServiceLib.Enums;\nglobal using ServiceLib.Events;\nglobal using ServiceLib.Handler;\nglobal using ServiceLib.Manager;\nglobal using ServiceLib.Models;\nglobal using ServiceLib.Resx;\nglobal using ServiceLib.ViewModels;\nglobal using v2rayN.Common;\n"
  },
  {
    "path": "v2rayN/v2rayN/Manager/HotkeyManager.cs",
    "content": "namespace v2rayN.Manager;\n\npublic sealed class HotkeyManager\n{\n    private static readonly Lazy<HotkeyManager> _instance = new(() => new());\n    public static HotkeyManager Instance = _instance.Value;\n    private const int WmHotkey = 0x0312;\n    private readonly Dictionary<int, List<EGlobalHotkey>> _hotkeyTriggerDic = new();\n\n    public bool IsPause { get; set; } = false;\n\n    public event Action<bool, string>? UpdateViewEvent;\n\n    public event Action<EGlobalHotkey>? HotkeyTriggerEvent;\n\n    public HotkeyManager()\n    {\n        ComponentDispatcher.ThreadPreprocessMessage += OnThreadPreProcessMessage;\n        Init();\n    }\n\n    private void Init()\n    {\n        _hotkeyTriggerDic.Clear();\n        foreach (var item in AppManager.Instance.Config.GlobalHotkeys)\n        {\n            if (item.KeyCode != null && (Key)item.KeyCode != Key.None)\n            {\n                var key = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode);\n                var modifiers = KeyModifiers.None;\n                if (item.Control)\n                {\n                    modifiers |= KeyModifiers.Ctrl;\n                }\n\n                if (item.Shift)\n                {\n                    modifiers |= KeyModifiers.Shift;\n                }\n\n                if (item.Alt)\n                {\n                    modifiers |= KeyModifiers.Alt;\n                }\n\n                key = (key << 16) | (int)modifiers;\n                if (!_hotkeyTriggerDic.ContainsKey(key))\n                {\n                    _hotkeyTriggerDic.Add(key, new() { item.EGlobalHotkey });\n                }\n                else\n                {\n                    if (!_hotkeyTriggerDic[key].Contains(item.EGlobalHotkey))\n                    {\n                        _hotkeyTriggerDic[key].Add(item.EGlobalHotkey);\n                    }\n                }\n            }\n        }\n    }\n\n    public void Load()\n    {\n        foreach (var _hotkeyCode in _hotkeyTriggerDic.Keys)\n        {\n            var hotkeyInfo = GetHotkeyInfo(_hotkeyCode);\n            var isSuccess = false;\n            var msg = string.Empty;\n\n            Application.Current?.Dispatcher.Invoke(() =>\n            {\n                isSuccess = RegisterHotKey(nint.Zero, _hotkeyCode, hotkeyInfo.fsModifiers, hotkeyInfo.vKey);\n            });\n            foreach (var name in hotkeyInfo.Names)\n            {\n                if (isSuccess)\n                {\n                    msg = string.Format(ResUI.RegisterGlobalHotkeySuccessfully, $\"{name}({hotkeyInfo.hotkeyStr})\");\n                }\n                else\n                {\n                    var errInfo = new Win32Exception(Marshal.GetLastWin32Error()).Message;\n                    msg = string.Format(ResUI.RegisterGlobalHotkeyFailed, $\"{name}({hotkeyInfo.hotkeyStr})\", errInfo);\n                }\n                UpdateViewEvent?.Invoke(false, msg);\n            }\n        }\n    }\n\n    public void ReLoad()\n    {\n        foreach (var hotkey in _hotkeyTriggerDic.Keys)\n        {\n            Application.Current?.Dispatcher.Invoke(() =>\n            {\n                UnregisterHotKey(nint.Zero, hotkey);\n            });\n        }\n        Init();\n        Load();\n    }\n\n    private (int fsModifiers, int vKey, string hotkeyStr, List<string> Names) GetHotkeyInfo(int hotkeyCode)\n    {\n        var fsModifiers = hotkeyCode & 0xffff;\n        var vKey = (hotkeyCode >> 16) & 0xffff;\n        var hotkeyStr = new StringBuilder();\n        var names = new List<string>();\n\n        var modify = (KeyModifiers)fsModifiers;\n        var key = KeyInterop.KeyFromVirtualKey(vKey);\n        if ((modify & KeyModifiers.Ctrl) == KeyModifiers.Ctrl)\n        {\n            hotkeyStr.Append($\"{KeyModifiers.Ctrl}+\");\n        }\n\n        if ((modify & KeyModifiers.Alt) == KeyModifiers.Alt)\n        {\n            hotkeyStr.Append($\"{KeyModifiers.Alt}+\");\n        }\n\n        if ((modify & KeyModifiers.Shift) == KeyModifiers.Shift)\n        {\n            hotkeyStr.Append($\"{KeyModifiers.Shift}+\");\n        }\n\n        hotkeyStr.Append(key.ToString());\n\n        foreach (var name in _hotkeyTriggerDic[hotkeyCode])\n        {\n            names.Add(name.ToString());\n        }\n\n        return (fsModifiers, vKey, hotkeyStr.ToString(), names);\n    }\n\n    private void OnThreadPreProcessMessage(ref MSG msg, ref bool handled)\n    {\n        if (msg.message != WmHotkey || !_hotkeyTriggerDic.ContainsKey((int)msg.lParam))\n        {\n            return;\n        }\n        handled = true;\n        var hotKeyCode = (int)msg.lParam;\n        if (IsPause)\n        {\n            Application.Current?.Dispatcher.Invoke(() =>\n            {\n                if (Keyboard.FocusedElement is UIElement element)\n                {\n                    var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, PresentationSource.FromVisual(element), 0, KeyInterop.KeyFromVirtualKey(GetHotkeyInfo(hotKeyCode).vKey))\n                    {\n                        RoutedEvent = UIElement.KeyDownEvent\n                    };\n                    element.RaiseEvent(keyEventArgs);\n                }\n            });\n        }\n        else\n        {\n            foreach (var keyEvent in _hotkeyTriggerDic[(int)msg.lParam])\n            {\n                HotkeyTriggerEvent?.Invoke(keyEvent);\n            }\n        }\n    }\n\n    [DllImport(\"user32.dll\", SetLastError = true)]\n    private static extern bool RegisterHotKey(nint hWnd, int id, int fsModifiers, int vlc);\n\n    [DllImport(\"user32.dll\", SetLastError = true)]\n    private static extern bool UnregisterHotKey(nint hWnd, int id);\n\n    [Flags]\n    private enum KeyModifiers\n    {\n        None = 0x0000,\n        Alt = 0x0001,\n        Ctrl = 0x0002,\n        Shift = 0x0004,\n        Win = 0x0008,\n        NoRepeat = 0x4000\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Manager/WindowsManager.cs",
    "content": "using System.Drawing;\nusing System.Windows.Media.Imaging;\n\nnamespace v2rayN.Manager;\n\npublic sealed class WindowsManager\n{\n    private static readonly Lazy<WindowsManager> instance = new(() => new());\n    public static WindowsManager Instance => instance.Value;\n    private static readonly string _tag = \"WindowsHandler\";\n\n    public async Task<Icon> GetNotifyIcon(Config config)\n    {\n        try\n        {\n            var index = (int)config.SystemProxyItem.SysProxyType;\n\n            //Load from routing setting\n            var createdIcon = await GetNotifyIcon4Routing(config);\n            if (createdIcon != null)\n            {\n                return createdIcon;\n            }\n\n            //Load from local file\n            var fileName = Utils.GetPath($\"NotifyIcon{index + 1}.ico\");\n            if (File.Exists(fileName))\n            {\n                return new Icon(fileName);\n            }\n            return index switch\n            {\n                0 => Properties.Resources.NotifyIcon1,\n                1 => Properties.Resources.NotifyIcon2,\n                2 => Properties.Resources.NotifyIcon3,\n                3 => Properties.Resources.NotifyIcon4,\n                _ => Properties.Resources.NotifyIcon1, // default\n            };\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return Properties.Resources.NotifyIcon1;\n        }\n    }\n\n    public System.Windows.Media.ImageSource GetAppIcon(Config config)\n    {\n        var index = (int)config.SystemProxyItem.SysProxyType + 1;\n        return BitmapFrame.Create(new Uri($\"pack://application:,,,/Resources/NotifyIcon{index}.ico\", UriKind.RelativeOrAbsolute));\n    }\n\n    private async Task<Icon?> GetNotifyIcon4Routing(Config config)\n    {\n        try\n        {\n            var item = await ConfigHandler.GetDefaultRouting(config);\n            if (item == null || item.CustomIcon.IsNullOrEmpty() || !File.Exists(item.CustomIcon))\n            {\n                return null;\n            }\n\n            var color = ColorTranslator.FromHtml(\"#3399CC\");\n            var index = (int)config.SystemProxyItem.SysProxyType;\n            if (index > 0)\n            {\n                color = (new[] { Color.Red, Color.Purple, Color.DarkGreen, Color.Orange, Color.DarkSlateBlue, Color.RoyalBlue })[index - 1];\n            }\n\n            var width = 128;\n            var height = 128;\n\n            Bitmap bitmap = new(width, height);\n            var graphics = Graphics.FromImage(bitmap);\n            SolidBrush drawBrush = new(color);\n\n            graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;\n            //graphics.FillRectangle(drawBrush, new Rectangle(0, 0, width, height));\n            graphics.DrawImage(new Bitmap(item.CustomIcon), 0, 0, width, height);\n            graphics.FillEllipse(drawBrush, width / 2, width / 2, width / 2, width / 2);\n\n            var createdIcon = Icon.FromHandle(bitmap.GetHicon());\n\n            drawBrush.Dispose();\n            graphics.Dispose();\n            bitmap.Dispose();\n\n            return createdIcon;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n            return null;\n        }\n    }\n\n    public void RegisterGlobalHotkey(Config config, Action<EGlobalHotkey> handler, Action<bool, string>? update)\n    {\n        HotkeyManager.Instance.UpdateViewEvent += update;\n        HotkeyManager.Instance.HotkeyTriggerEvent += handler;\n        HotkeyManager.Instance.Load();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Properties/Resources.Designer.cs",
    "content": "﻿//------------------------------------------------------------------------------\n// <auto-generated>\n//     此代码由工具生成。\n//     运行时版本:4.0.30319.42000\n//\n//     对此文件的更改可能会导致不正确的行为，并且如果\n//     重新生成代码，这些更改将会丢失。\n// </auto-generated>\n//------------------------------------------------------------------------------\n\nnamespace v2rayN.Properties {\n    using System;\n    \n    \n    /// <summary>\n    ///   一个强类型的资源类，用于查找本地化的字符串等。\n    /// </summary>\n    // 此类是由 StronglyTypedResourceBuilder\n    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。\n    // 若要添加或移除成员，请编辑 .ResX 文件，然后重新运行 ResGen\n    // (以 /str 作为命令选项)，或重新生成 VS 项目。\n    [global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"System.Resources.Tools.StronglyTypedResourceBuilder\", \"17.0.0.0\")]\n    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]\n    internal class Resources {\n        \n        private static global::System.Resources.ResourceManager resourceMan;\n        \n        private static global::System.Globalization.CultureInfo resourceCulture;\n        \n        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(\"Microsoft.Performance\", \"CA1811:AvoidUncalledPrivateCode\")]\n        internal Resources() {\n        }\n        \n        /// <summary>\n        ///   返回此类使用的缓存的 ResourceManager 实例。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Resources.ResourceManager ResourceManager {\n            get {\n                if (object.ReferenceEquals(resourceMan, null)) {\n                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager(\"v2rayN.Properties.Resources\", typeof(Resources).Assembly);\n                    resourceMan = temp;\n                }\n                return resourceMan;\n            }\n        }\n        \n        /// <summary>\n        ///   重写当前线程的 CurrentUICulture 属性，对\n        ///   使用此强类型资源类的所有资源查找执行重写。\n        /// </summary>\n        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]\n        internal static global::System.Globalization.CultureInfo Culture {\n            get {\n                return resourceCulture;\n            }\n            set {\n                resourceCulture = value;\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap about {\n            get {\n                object obj = ResourceManager.GetObject(\"about\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap active {\n            get {\n                object obj = ResourceManager.GetObject(\"active\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap checkupdate {\n            get {\n                object obj = ResourceManager.GetObject(\"checkupdate\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap help {\n            get {\n                object obj = ResourceManager.GetObject(\"help\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap minimize {\n            get {\n                object obj = ResourceManager.GetObject(\"minimize\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap notify {\n            get {\n                object obj = ResourceManager.GetObject(\"notify\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Icon NotifyIcon1 {\n            get {\n                object obj = ResourceManager.GetObject(\"NotifyIcon1\", resourceCulture);\n                return ((System.Drawing.Icon)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Icon NotifyIcon2 {\n            get {\n                object obj = ResourceManager.GetObject(\"NotifyIcon2\", resourceCulture);\n                return ((System.Drawing.Icon)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Icon NotifyIcon3 {\n            get {\n                object obj = ResourceManager.GetObject(\"NotifyIcon3\", resourceCulture);\n                return ((System.Drawing.Icon)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找类似于 (图标) 的 System.Drawing.Icon 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Icon NotifyIcon4 {\n            get {\n                object obj = ResourceManager.GetObject(\"NotifyIcon4\", resourceCulture);\n                return ((System.Drawing.Icon)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap option {\n            get {\n                object obj = ResourceManager.GetObject(\"option\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap promotion {\n            get {\n                object obj = ResourceManager.GetObject(\"promotion\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap restart {\n            get {\n                object obj = ResourceManager.GetObject(\"restart\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap server {\n            get {\n                object obj = ResourceManager.GetObject(\"server\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap share {\n            get {\n                object obj = ResourceManager.GetObject(\"share\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap speedtest {\n            get {\n                object obj = ResourceManager.GetObject(\"speedtest\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n        \n        /// <summary>\n        ///   查找 System.Drawing.Bitmap 类型的本地化资源。\n        /// </summary>\n        internal static System.Drawing.Bitmap sub {\n            get {\n                object obj = ResourceManager.GetObject(\"sub\", resourceCulture);\n                return ((System.Drawing.Bitmap)(obj));\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Properties/Resources.resx",
    "content": "﻿<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<root>\n  <!-- \n    Microsoft ResX Schema \n    \n    Version 2.0\n    \n    The primary goals of this format is to allow a simple XML format \n    that is mostly human readable. The generation and parsing of the \n    various data types are done through the TypeConverter classes \n    associated with the data types.\n    \n    Example:\n    \n    ... ado.net/XML headers & schema ...\n    <resheader name=\"resmimetype\">text/microsoft-resx</resheader>\n    <resheader name=\"version\">2.0</resheader>\n    <resheader name=\"reader\">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>\n    <resheader name=\"writer\">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>\n    <data name=\"Name1\"><value>this is my long string</value><comment>this is a comment</comment></data>\n    <data name=\"Color1\" type=\"System.Drawing.Color, System.Drawing\">Blue</data>\n    <data name=\"Bitmap1\" mimetype=\"application/x-microsoft.net.object.binary.base64\">\n        <value>[base64 mime encoded serialized .NET Framework object]</value>\n    </data>\n    <data name=\"Icon1\" type=\"System.Drawing.Icon, System.Drawing\" mimetype=\"application/x-microsoft.net.object.bytearray.base64\">\n        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>\n        <comment>This is a comment</comment>\n    </data>\n                \n    There are any number of \"resheader\" rows that contain simple \n    name/value pairs.\n    \n    Each data row contains a name, and value. The row also contains a \n    type or mimetype. Type corresponds to a .NET class that support \n    text/value conversion through the TypeConverter architecture. \n    Classes that don't support this are serialized and stored with the \n    mimetype set.\n    \n    The mimetype is used for serialized objects, and tells the \n    ResXResourceReader how to depersist the object. This is currently not \n    extensible. For a given mimetype the value must be set accordingly:\n    \n    Note - application/x-microsoft.net.object.binary.base64 is the format \n    that the ResXResourceWriter will generate, however the reader can \n    read any of the formats listed below.\n    \n    mimetype: application/x-microsoft.net.object.binary.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter\n            : and then encoded with base64 encoding.\n    \n    mimetype: application/x-microsoft.net.object.soap.base64\n    value   : The object must be serialized with \n            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter\n            : and then encoded with base64 encoding.\n\n    mimetype: application/x-microsoft.net.object.bytearray.base64\n    value   : The object must be serialized into a byte array \n            : using a System.ComponentModel.TypeConverter\n            : and then encoded with base64 encoding.\n    -->\n  <xsd:schema id=\"root\" xmlns=\"\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:msdata=\"urn:schemas-microsoft-com:xml-msdata\">\n    <xsd:import namespace=\"http://www.w3.org/XML/1998/namespace\" />\n    <xsd:element name=\"root\" msdata:IsDataSet=\"true\">\n      <xsd:complexType>\n        <xsd:choice maxOccurs=\"unbounded\">\n          <xsd:element name=\"metadata\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" use=\"required\" type=\"xsd:string\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"assembly\">\n            <xsd:complexType>\n              <xsd:attribute name=\"alias\" type=\"xsd:string\" />\n              <xsd:attribute name=\"name\" type=\"xsd:string\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"data\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n                <xsd:element name=\"comment\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"2\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" msdata:Ordinal=\"1\" />\n              <xsd:attribute name=\"type\" type=\"xsd:string\" msdata:Ordinal=\"3\" />\n              <xsd:attribute name=\"mimetype\" type=\"xsd:string\" msdata:Ordinal=\"4\" />\n              <xsd:attribute ref=\"xml:space\" />\n            </xsd:complexType>\n          </xsd:element>\n          <xsd:element name=\"resheader\">\n            <xsd:complexType>\n              <xsd:sequence>\n                <xsd:element name=\"value\" type=\"xsd:string\" minOccurs=\"0\" msdata:Ordinal=\"1\" />\n              </xsd:sequence>\n              <xsd:attribute name=\"name\" type=\"xsd:string\" use=\"required\" />\n            </xsd:complexType>\n          </xsd:element>\n        </xsd:choice>\n      </xsd:complexType>\n    </xsd:element>\n  </xsd:schema>\n  <resheader name=\"resmimetype\">\n    <value>text/microsoft-resx</value>\n  </resheader>\n  <resheader name=\"version\">\n    <value>2.0</value>\n  </resheader>\n  <resheader name=\"reader\">\n    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <resheader name=\"writer\">\n    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>\n  </resheader>\n  <assembly alias=\"System.Windows.Forms\" name=\"System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089\" />\n  <data name=\"NotifyIcon1\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\Resources\\NotifyIcon1.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>\n  </data>\n  <data name=\"NotifyIcon2\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\Resources\\NotifyIcon2.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>\n  </data>\n  <data name=\"NotifyIcon3\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\Resources\\NotifyIcon3.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>\n  </data>\n  <data name=\"NotifyIcon4\" type=\"System.Resources.ResXFileRef, System.Windows.Forms\">\n    <value>..\\Resources\\NotifyIcon4.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>\n  </data>\n</root>"
  },
  {
    "path": "v2rayN/v2rayN/ViewModels/ThemeSettingViewModel.cs",
    "content": "using MaterialDesignColors;\nusing MaterialDesignColors.ColorManipulation;\nusing MaterialDesignThemes.Wpf;\nusing Microsoft.Win32;\n\nnamespace v2rayN.ViewModels;\n\npublic class ThemeSettingViewModel : MyReactiveObject\n{\n    private readonly PaletteHelper _paletteHelper = new();\n\n    private IObservableCollection<Swatch> _swatches = new ObservableCollectionExtended<Swatch>();\n    public IObservableCollection<Swatch> Swatches => _swatches;\n\n    [Reactive]\n    public Swatch SelectedSwatch { get; set; }\n\n    [Reactive] public string CurrentTheme { get; set; }\n\n    [Reactive] public int CurrentFontSize { get; set; }\n\n    [Reactive] public string CurrentLanguage { get; set; }\n\n    public ThemeSettingViewModel()\n    {\n        _config = AppManager.Instance.Config;\n\n        RegisterSystemColorSet(_config, ModifyTheme);\n\n        BindingUI();\n        RestoreUI();\n    }\n\n    private void RestoreUI()\n    {\n        ModifyTheme();\n        ModifyFontSize();\n        if (!_config.UiItem.ColorPrimaryName.IsNullOrEmpty())\n        {\n            var swatch = new SwatchesProvider().Swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName);\n            if (swatch != null\n               && swatch.ExemplarHue != null\n               && swatch.ExemplarHue?.Color != null)\n            {\n                ChangePrimaryColor(swatch.ExemplarHue.Color);\n            }\n        }\n    }\n\n    private void BindingUI()\n    {\n        _swatches.AddRange(new SwatchesProvider().Swatches);\n        if (!_config.UiItem.ColorPrimaryName.IsNullOrEmpty())\n        {\n            SelectedSwatch = _swatches.FirstOrDefault(t => t.Name == _config.UiItem.ColorPrimaryName);\n        }\n        CurrentTheme = _config.UiItem.CurrentTheme;\n        CurrentFontSize = _config.UiItem.CurrentFontSize;\n        CurrentLanguage = _config.UiItem.CurrentLanguage;\n\n        this.WhenAnyValue(\n                x => x.CurrentTheme,\n                y => y != null && !y.IsNullOrEmpty())\n            .Subscribe(c =>\n             {\n                 if (_config.UiItem.CurrentTheme != CurrentTheme)\n                 {\n                     _config.UiItem.CurrentTheme = CurrentTheme;\n                     ModifyTheme();\n                     ConfigHandler.SaveConfig(_config);\n                 }\n             });\n\n        this.WhenAnyValue(\n          x => x.SelectedSwatch,\n          y => y != null && !y.Name.IsNullOrEmpty())\n             .Subscribe(c =>\n             {\n                 if (SelectedSwatch == null\n                 || SelectedSwatch.Name.IsNullOrEmpty()\n                 || SelectedSwatch.ExemplarHue == null\n                 || SelectedSwatch.ExemplarHue?.Color == null)\n                 {\n                     return;\n                 }\n                 if (_config.UiItem.ColorPrimaryName != SelectedSwatch?.Name)\n                 {\n                     _config.UiItem.ColorPrimaryName = SelectedSwatch?.Name;\n                     ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color);\n                     ConfigHandler.SaveConfig(_config);\n                 }\n             });\n\n        this.WhenAnyValue(\n           x => x.CurrentFontSize,\n           y => y > 0)\n              .Subscribe(c =>\n              {\n                  if (_config.UiItem.CurrentFontSize != CurrentFontSize)\n                  {\n                      _config.UiItem.CurrentFontSize = CurrentFontSize;\n                      ModifyFontSize();\n                      ConfigHandler.SaveConfig(_config);\n                  }\n              });\n\n        this.WhenAnyValue(\n         x => x.CurrentLanguage,\n         y => y != null && !y.IsNullOrEmpty())\n            .Subscribe(c =>\n            {\n                if (CurrentLanguage.IsNotEmpty() && _config.UiItem.CurrentLanguage != CurrentLanguage)\n                {\n                    _config.UiItem.CurrentLanguage = CurrentLanguage;\n                    Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);\n                    ConfigHandler.SaveConfig(_config);\n                    NoticeManager.Instance.Enqueue(ResUI.NeedRebootTips);\n                }\n            });\n    }\n\n    public void ModifyTheme()\n    {\n        var baseTheme = CurrentTheme switch\n        {\n            nameof(ETheme.Dark) => BaseTheme.Dark,\n            nameof(ETheme.Light) => BaseTheme.Light,\n            _ => BaseTheme.Inherit,\n        };\n\n        var theme = _paletteHelper.GetTheme();\n        theme.SetBaseTheme(baseTheme);\n        _paletteHelper.SetTheme(theme);\n\n        WindowsUtils.SetDarkBorder(Application.Current.MainWindow, CurrentTheme);\n    }\n\n    private void ModifyFontSize()\n    {\n        double size = (long)CurrentFontSize;\n        if (size < Global.MinFontSize)\n        {\n            return;\n        }\n\n        Application.Current.Resources[\"StdFontSize\"] = size;\n        Application.Current.Resources[\"StdFontSize1\"] = size + 1;\n        Application.Current.Resources[\"StdFontSize-1\"] = size - 1;\n    }\n\n    public void ChangePrimaryColor(System.Windows.Media.Color color)\n    {\n        var theme = _paletteHelper.GetTheme();\n\n        theme.PrimaryLight = new ColorPair(color.Lighten());\n        theme.PrimaryMid = new ColorPair(color);\n        theme.PrimaryDark = new ColorPair(color.Darken());\n\n        _paletteHelper.SetTheme(theme);\n    }\n\n    public static void RegisterSystemColorSet(Config config, Action updateFunc)\n    {\n        SystemEvents.UserPreferenceChanged += (s, e) =>\n        {\n            if ((e.Category == UserPreferenceCategory.Color || e.Category == UserPreferenceCategory.General)\n                && config.UiItem.CurrentTheme == nameof(ETheme.FollowSystem))\n            {\n                updateFunc?.Invoke();\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/AddGroupServerWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.AddGroupServerWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuServers}\"\n    Width=\"900\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:AddGroupServerViewModel\"\n    ResizeMode=\"CanResize\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <Grid DockPanel.Dock=\"Top\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"*\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n\n            <Grid Grid.Row=\"0\">\n                <Grid.RowDefinitions>\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                </Grid.RowDefinitions>\n                <Grid.ColumnDefinitions>\n                    <ColumnDefinition Width=\"300\" />\n                    <ColumnDefinition Width=\"Auto\" />\n                    <ColumnDefinition Width=\"Auto\" />\n                </Grid.ColumnDefinitions>\n\n                <TextBlock\n                    Grid.Row=\"0\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Style=\"{StaticResource ModuleTitle}\"\n                    Text=\"{x:Static resx:ResUI.menuServers}\" />\n\n                <TextBlock\n                    Grid.Row=\"1\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.TbRemarks}\" />\n                <TextBox\n                    x:Name=\"txtRemarks\"\n                    Grid.Row=\"1\"\n                    Grid.Column=\"1\"\n                    Width=\"400\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Style=\"{StaticResource DefTextBox}\" />\n\n                <TextBlock\n                    Grid.Row=\"2\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.TbCoreType}\" />\n                <ComboBox\n                    x:Name=\"cmbCoreType\"\n                    Grid.Row=\"2\"\n                    Grid.Column=\"1\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.TbCoreType}\"\n                    Style=\"{StaticResource DefComboBox}\" />\n\n                <Grid\n                    x:Name=\"gridPolicyGroup\"\n                    Grid.Row=\"3\"\n                    Grid.Column=\"0\"\n                    Grid.ColumnSpan=\"3\">\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPolicyGroupType}\" />\n                    <ComboBox\n                        x:Name=\"cmbPolicyGroupType\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.TbPolicyGroupType}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n                </Grid>\n            </Grid>\n        </Grid>\n\n        <TabControl\n            x:Name=\"tabControl\"\n            Margin=\"{StaticResource Margin8}\"\n            HorizontalContentAlignment=\"Left\"\n            DockPanel.Dock=\"Top\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuServerList}\">\n                <Grid Margin=\"{StaticResource Margin8}\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.menuSubscription}\" />\n                    <ComboBox\n                        x:Name=\"cmbSubChildItems\"\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        Width=\"600\"\n                        Margin=\"{StaticResource Margin4}\"\n                        DisplayMemberPath=\"Remarks\"\n                        Style=\"{StaticResource DefComboBox}\" />\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPolicyGroupSubChildTip}\"\n                        TextWrapping=\"Wrap\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.LvFilter}\" />\n                    <ComboBox\n                        x:Name=\"cmbFilter\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"600\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        IsEditable=\"True\"\n                        Style=\"{StaticResource DefComboBox}\" />\n                </Grid>\n            </TabItem>\n\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuServerList2}\">\n                <DataGrid\n                    x:Name=\"lstChild\"\n                    AutoGenerateColumns=\"False\"\n                    BorderThickness=\"1\"\n                    CanUserAddRows=\"False\"\n                    CanUserResizeRows=\"False\"\n                    CanUserSortColumns=\"False\"\n                    EnableRowVirtualization=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    Style=\"{StaticResource DefDataGrid}\">\n                    <DataGrid.ContextMenu>\n                        <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                            <MenuItem\n                                x:Name=\"menuAddChildServer\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Click=\"MenuAddChild_Click\"\n                                Header=\"{x:Static resx:ResUI.menuAddChildServer}\" />\n                            <MenuItem\n                                x:Name=\"menuRemoveChildServer\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRemoveChildServer}\" />\n                            <MenuItem\n                                x:Name=\"menuSelectAllChild\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                                InputGestureText=\"Ctrl+A\" />\n                            <Separator />\n                            <MenuItem\n                                x:Name=\"menuMoveTop\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveTop}\"\n                                InputGestureText=\"T\" />\n                            <MenuItem\n                                x:Name=\"menuMoveUp\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveUp}\"\n                                InputGestureText=\"U\" />\n                            <MenuItem\n                                x:Name=\"menuMoveDown\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveDown}\"\n                                InputGestureText=\"D\" />\n                            <MenuItem\n                                x:Name=\"menuMoveBottom\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveBottom}\"\n                                InputGestureText=\"B\" />\n                        </ContextMenu>\n                    </DataGrid.ContextMenu>\n                    <DataGrid.Columns>\n                        <DataGridTextColumn\n                            Width=\"150\"\n                            Binding=\"{Binding ConfigType}\"\n                            Header=\"{x:Static resx:ResUI.LvServiceType}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Address}\"\n                            Header=\"{x:Static resx:ResUI.LvAddress}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            Header=\"{x:Static resx:ResUI.LvPort}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            Header=\"{x:Static resx:ResUI.LvTransportProtocol}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding StreamSecurity}\"\n                            Header=\"{x:Static resx:ResUI.LvTLS}\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuServerListPreview}\">\n                <DataGrid\n                    x:Name=\"lstPreviewChild\"\n                    AutoGenerateColumns=\"False\"\n                    BorderThickness=\"1\"\n                    CanUserAddRows=\"False\"\n                    CanUserResizeRows=\"False\"\n                    CanUserSortColumns=\"False\"\n                    EnableRowVirtualization=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    Style=\"{StaticResource DefDataGrid}\">\n                    <DataGrid.Columns>\n                        <DataGridTextColumn\n                            Width=\"150\"\n                            Binding=\"{Binding ConfigType}\"\n                            Header=\"{x:Static resx:ResUI.LvServiceType}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Address}\"\n                            Header=\"{x:Static resx:ResUI.LvAddress}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            Header=\"{x:Static resx:ResUI.LvPort}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            Header=\"{x:Static resx:ResUI.LvTransportProtocol}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding StreamSecurity}\"\n                            Header=\"{x:Static resx:ResUI.LvTLS}\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/AddGroupServerWindow.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class AddGroupServerWindow\n{\n    public AddGroupServerWindow(ProfileItem profileItem)\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        Loaded += Window_Loaded;\n        PreviewKeyDown += AddGroupServerWindow_PreviewKeyDown;\n        lstChild.SelectionChanged += LstChild_SelectionChanged;\n        menuSelectAllChild.Click += MenuSelectAllChild_Click;\n        tabControl.SelectionChanged += TabControl_SelectionChanged;\n\n        ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler);\n\n        cmbCoreType.ItemsSource = Global.CoreTypes;\n        cmbPolicyGroupType.ItemsSource = new List<string>\n        {\n            ResUI.TbLeastPing,\n            ResUI.TbFallback,\n            ResUI.TbRandom,\n            ResUI.TbRoundRobin,\n            ResUI.TbLeastLoad,\n        };\n        cmbFilter.ItemsSource = Global.PolicyGroupDefaultFilterList;\n\n        switch (profileItem.ConfigType)\n        {\n            case EConfigType.PolicyGroup:\n                Title = ResUI.TbConfigTypePolicyGroup;\n                break;\n\n            case EConfigType.ProxyChain:\n                Title = ResUI.TbConfigTypeProxyChain;\n                gridPolicyGroup.Visibility = Visibility.Collapsed;\n                if (tabControl.Items.Count > 0)\n                {\n                    tabControl.Items.RemoveAt(0);\n                }\n                break;\n        }\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbSubChildItems.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSubItem, v => v.cmbSubChildItems.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Filter, v => v.cmbFilter.Text).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.ChildItemsObs, v => v.lstChild.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedChild, v => v.lstChild.SelectedItem).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.AllProfilePreviewItemsObs, v => v.lstPreviewChild.ItemsSource).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RemoveCmd, v => v.menuRemoveChildServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void AddGroupServerWindow_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (!lstChild.IsKeyboardFocusWithin)\n        {\n            return;\n        }\n\n        if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))\n        {\n            if (e.Key == Key.A)\n            {\n                lstChild.SelectAll();\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.T:\n                    ViewModel?.MoveServer(EMove.Top);\n                    break;\n\n                case Key.U:\n                    ViewModel?.MoveServer(EMove.Up);\n                    break;\n\n                case Key.D:\n                    ViewModel?.MoveServer(EMove.Down);\n                    break;\n\n                case Key.B:\n                    ViewModel?.MoveServer(EMove.Bottom);\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.ChildRemoveAsync();\n                    break;\n            }\n        }\n    }\n\n    private async void MenuAddChild_Click(object sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter([EConfigType.Custom], exclude: true);\n        selectWindow.AllowMultiSelect(true);\n        if (selectWindow.ShowDialog() == true)\n        {\n            var profiles = await selectWindow.ProfileItems;\n            ViewModel?.ChildItemsObs.AddRange(profiles);\n        }\n    }\n\n    private void LstChild_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedChildren = lstChild.SelectedItems.Cast<ProfileItem>().ToList();\n        }\n    }\n\n    private void MenuSelectAllChild_Click(object sender, RoutedEventArgs e)\n    {\n        lstChild.SelectAll();\n    }\n\n    private async void TabControl_SelectionChanged(object? sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        try\n        {\n            if (e.Source is not System.Windows.Controls.TabControl tc)\n            {\n                return;\n            }\n            if (!(tc.SelectedIndex == tc.Items.Count - 1 && tc.Items.Count > 0))\n            {\n                return;\n            }\n            if (ViewModel == null)\n            {\n                return;\n            }\n\n            await ViewModel.UpdatePreviewList();\n        }\n        catch\n        {\n            // ignored\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/AddServer2Window.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.AddServer2Window\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuAddCustomServer}\"\n    Width=\"700\"\n    Height=\"500\"\n    x:TypeArguments=\"vms:AddServer2ViewModel\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n        <ScrollViewer\n            materialDesign:ScrollViewerAssist.IsAutoHideEnabled=\"True\"\n            HorizontalScrollBarVisibility=\"Auto\"\n            VerticalScrollBarVisibility=\"Auto\">\n            <Grid>\n                <Grid.RowDefinitions>\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                </Grid.RowDefinitions>\n                <Grid Grid.Row=\"0\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource ModuleTitle}\"\n                        Text=\"{x:Static resx:ResUI.menuServers}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbRemarks}\" />\n\n                    <TextBox\n                        x:Name=\"txtRemarks\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        AcceptsReturn=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbAddress}\" />\n                    <TextBox\n                        x:Name=\"txtAddress\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        AcceptsReturn=\"True\"\n                        IsReadOnly=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n                    <StackPanel\n                        Grid.Row=\"2\"\n                        Grid.Column=\"2\"\n                        VerticalAlignment=\"Center\"\n                        Orientation=\"Horizontal\">\n                        <Button\n                            x:Name=\"btnBrowse\"\n                            Margin=\"{StaticResource MarginLeftRight4}\"\n                            Content=\"{x:Static resx:ResUI.TbBrowse}\"\n                            Style=\"{StaticResource DefButton}\" />\n                        <Button\n                            x:Name=\"btnEdit\"\n                            Margin=\"{StaticResource MarginLeftRight4}\"\n                            Content=\"{x:Static resx:ResUI.TbEdit}\"\n                            Style=\"{StaticResource DefButton}\" />\n                    </StackPanel>\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbCoreType}\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        MaxDropDownHeight=\"1000\"\n                        Style=\"{StaticResource MyOutlinedTextComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbDisplayLog}\" />\n                    <StackPanel\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Orientation=\"Horizontal\">\n                        <ToggleButton x:Name=\"togDisplayLog\" HorizontalAlignment=\"Left\" />\n                        <TextBlock\n                            Margin=\"{StaticResource MarginLeftRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TipDisplayLog}\" />\n                    </StackPanel>\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPreSocksPort}\" />\n                    <TextBox\n                        x:Name=\"txtPreSocksPort\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        AcceptsReturn=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n                    <StackPanel\n                        Grid.Row=\"6\"\n                        Grid.Column=\"1\"\n                        Grid.ColumnSpan=\"2\">\n                        <TextBlock\n                            Width=\"500\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TipPreSocksPort}\"\n                            TextWrapping=\"Wrap\" />\n                        <TextBlock\n                            Width=\"500\"\n                            Margin=\"{StaticResource MarginLeftRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.CustomServerTips}\"\n                            TextWrapping=\"Wrap\" />\n                    </StackPanel>\n                </Grid>\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/AddServer2Window.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class AddServer2Window\n{\n    public AddServer2Window(ProfileItem profileItem)\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        Loaded += Window_Loaded;\n        ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);\n\n        cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Address, v => v.txtAddress.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.DisplayLog, v => v.togDisplayLog.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.BrowseServerCmd, v => v.btnBrowse).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.btnEdit).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SaveServerCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n\n            case EViewAction.BrowseServer:\n                if (UI.OpenFileDialog(out var fileName, \"Config|*.json|YAML|*.yaml;*.yml|All|*.*\") != true)\n                {\n                    return false;\n                }\n                ViewModel?.BrowseServer(fileName);\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/AddServerWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.AddServerWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuServers}\"\n    Width=\"900\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:AddServerViewModel\"\n    ResizeMode=\"CanResize\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <Window.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceDictionary Source=\"pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Popupbox.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n        </ResourceDictionary>\n    </Window.Resources>\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n        <ScrollViewer\n            materialDesign:ScrollViewerAssist.IsAutoHideEnabled=\"True\"\n            HorizontalScrollBarVisibility=\"Auto\"\n            VerticalScrollBarVisibility=\"Auto\">\n            <Grid>\n                <Grid.RowDefinitions>\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                </Grid.RowDefinitions>\n\n                <Grid Grid.Row=\"0\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource ModuleTitle}\"\n                        Text=\"{x:Static resx:ResUI.menuServers}\" />\n                    <StackPanel\n                        Grid.Row=\"0\"\n                        Grid.Column=\"2\"\n                        Orientation=\"Horizontal\">\n                        <ComboBox\n                            x:Name=\"cmbCoreType\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\"\n                            materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.TbCoreType}\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                    </StackPanel>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbRemarks}\" />\n                    <TextBox\n                        x:Name=\"txtRemarks\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbAddress}\" />\n                    <TextBox\n                        x:Name=\"txtAddress\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPort}\" />\n                    <TextBox\n                        x:Name=\"txtPort\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                </Grid>\n\n                <Separator\n                    Grid.Row=\"1\"\n                    Margin=\"0,2\"\n                    Style=\"{DynamicResource MaterialDesignSeparator}\" />\n\n                <Grid\n                    x:Name=\"gridVMess\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId}\" />\n                    <TextBox\n                        x:Name=\"txtId\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                    <Button\n                        x:Name=\"btnGUID\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource MarginLeftRight4}\"\n                        Content=\"{x:Static resx:ResUI.TbGUID}\"\n                        Style=\"{StaticResource DefButton}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbAlterId}\" />\n                    <TextBox\n                        x:Name=\"txtAlterId\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity}\" />\n                    <ComboBox\n                        x:Name=\"cmbSecurity\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleButton\n                        x:Name=\"togmuxEnabled\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridSs\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId3\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity3}\" />\n                    <ComboBox\n                        x:Name=\"cmbSecurity3\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"300\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleButton\n                        x:Name=\"togmuxEnabled3\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridSocks\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity4}\" />\n                    <TextBox\n                        x:Name=\"txtSecurity4\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId4}\" />\n                    <TextBox\n                        x:Name=\"txtId4\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridVLESS\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId5}\" />\n                    <TextBox\n                        x:Name=\"txtId5\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                    <Button\n                        x:Name=\"btnGUID5\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource MarginLeftRight4}\"\n                        Content=\"{x:Static resx:ResUI.TbGUID}\"\n                        Style=\"{StaticResource DefButton}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbFlow5}\" />\n                    <ComboBox\n                        x:Name=\"cmbFlow5\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity5}\" />\n                    <TextBox\n                        x:Name=\"txtSecurity5\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleButton\n                        x:Name=\"togmuxEnabled5\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridTrojan\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId6\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbFlow5}\" />\n                    <ComboBox\n                        x:Name=\"cmbFlow6\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleButton\n                        x:Name=\"togmuxEnabled6\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridHysteria2\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId7\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPath7}\" />\n                    <TextBox\n                        x:Name=\"txtPath7\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPorts7}\" />\n                    <TextBox\n                        x:Name=\"txtPorts7\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        materialDesign:HintAssist.Hint=\"1000-2000,3000,4000\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPorts7Tips}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbHopInt7}\" />\n                    <TextBox\n                        x:Name=\"txtHopInt7\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsHysteriaBandwidth}\" />\n                    <StackPanel\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Orientation=\"Horizontal\">\n                        <TextBox\n                            x:Name=\"txtUpMbps7\"\n                            Width=\"90\"\n                            Margin=\"{StaticResource Margin4}\"\n                            materialDesign:HintAssist.Hint=\"Up\"\n                            Style=\"{StaticResource DefTextBox}\" />\n                        <TextBox\n                            x:Name=\"txtDownMbps7\"\n                            Width=\"90\"\n                            Margin=\"{StaticResource Margin4}\"\n                            materialDesign:HintAssist.Hint=\"Down\"\n                            Style=\"{StaticResource DefTextBox}\" />\n                    </StackPanel>\n                </Grid>\n                <Grid\n                    x:Name=\"gridTuic\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId}\" />\n                    <TextBox\n                        x:Name=\"txtId8\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtSecurity8\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbHeaderType8}\" />\n                    <ComboBox\n                        x:Name=\"cmbHeaderType8\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridWireguard\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPrivateKey}\" />\n                    <TextBox\n                        x:Name=\"txtId9\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPublicKey}\" />\n                    <TextBox\n                        x:Name=\"txtPublicKey9\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbReserved}\" />\n                    <TextBox\n                        x:Name=\"txtPath9\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        materialDesign:HintAssist.Hint=\"2,3,4\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbLocalAddress}\" />\n                    <TextBox\n                        x:Name=\"txtRequestHost9\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        materialDesign:HintAssist.Hint=\"Ipv4,Ipv6\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunMtu}\" />\n                    <TextBox\n                        x:Name=\"txtShortId9\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        materialDesign:HintAssist.Hint=\"1500\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridAnytls\"\n                    Grid.Row=\"2\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId10\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                </Grid>\n\n                <Separator\n                    x:Name=\"sepa2\"\n                    Grid.Row=\"3\"\n                    Margin=\"0,2\"\n                    Style=\"{DynamicResource MaterialDesignSeparator}\" />\n\n                <Grid x:Name=\"gridTransport\" Grid.Row=\"4\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.ColumnSpan=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource ModuleTitle}\"\n                        Text=\"{x:Static resx:ResUI.GbTransport}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbNetwork}\" />\n                    <ComboBox\n                        x:Name=\"cmbNetwork\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TipNetwork}\" />\n\n                    <TextBlock\n                        x:Name=\"labHeaderType\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbHeaderType}\" />\n                    <StackPanel\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Orientation=\"Horizontal\">\n                        <ComboBox\n                            x:Name=\"cmbHeaderType\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <materialDesign:PopupBox\n                            x:Name=\"popExtra\"\n                            HorizontalAlignment=\"Right\"\n                            StaysOpen=\"True\"\n                            Style=\"{StaticResource MaterialDesignToolForegroundPopupBox}\">\n                            <StackPanel>\n                                <TextBlock\n                                    Margin=\"{StaticResource Margin4}\"\n                                    VerticalAlignment=\"Center\"\n                                    Style=\"{StaticResource ToolbarTextBlock}\"\n                                    Text=\"{x:Static resx:ResUI.TransportExtraTip}\" />\n                                <TextBox\n                                    x:Name=\"txtExtra\"\n                                    Width=\"400\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    VerticalAlignment=\"Center\"\n                                    AcceptsReturn=\"True\"\n                                    MinLines=\"6\"\n                                    Style=\"{StaticResource MyOutlinedTextBox}\"\n                                    TextWrapping=\"Wrap\" />\n                            </StackPanel>\n                        </materialDesign:PopupBox>\n                    </StackPanel>\n                    <TextBlock\n                        x:Name=\"tipHeaderType\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbHeaderType}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbRequestHost}\" />\n                    <TextBox\n                        x:Name=\"txtRequestHost\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                    <TextBlock\n                        x:Name=\"tipRequestHost\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbRequestHost}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPath}\" />\n                    <TextBox\n                        x:Name=\"txtPath\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                    <TextBlock\n                        x:Name=\"tipPath\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPath}\" />\n                </Grid>\n\n                <Grid x:Name=\"gridFinalmask\" Grid.Row=\"5\">\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbFinalmask}\" />\n                    <materialDesign:PopupBox\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        HorizontalAlignment=\"Left\"\n                        VerticalAlignment=\"Center\"\n                        StaysOpen=\"True\"\n                        Style=\"{StaticResource MaterialDesignToolForegroundPopupBox}\">\n                        <StackPanel>\n                            <TextBox\n                                x:Name=\"txtFinalmask\"\n                                Width=\"400\"\n                                Margin=\"{StaticResource Margin4}\"\n                                AcceptsReturn=\"True\"\n                                HorizontalScrollBarVisibility=\"Auto\"\n                                MaxLines=\"8\"\n                                MinLines=\"4\"\n                                Style=\"{StaticResource MyOutlinedTextBox}\"\n                                TextWrapping=\"NoWrap\"\n                                VerticalScrollBarVisibility=\"Auto\" />\n                        </StackPanel>\n                    </materialDesign:PopupBox>\n                </Grid>\n\n                <Separator\n                    Grid.Row=\"6\"\n                    Margin=\"0,2\"\n                    Style=\"{DynamicResource MaterialDesignSeparator}\" />\n\n                <Grid x:Name=\"gridTls\" Grid.Row=\"7\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbStreamSecurity}\" />\n                    <ComboBox\n                        x:Name=\"cmbStreamSecurity\"\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridTlsMore\"\n                    Grid.Row=\"8\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSNI}\" />\n                    <TextBox\n                        x:Name=\"txtSNI\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbFingerprint}\" />\n                    <ComboBox\n                        x:Name=\"cmbFingerprint\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        IsEditable=\"True\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbAlpn}\" />\n                    <ComboBox\n                        x:Name=\"cmbAlpn\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbAllowInsecure}\" />\n                    <ComboBox\n                        x:Name=\"cmbAllowInsecure\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbEchConfigList}\" />\n                    <TextBox\n                        x:Name=\"txtEchConfigList\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"6\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbEchForceQuery}\" />\n                    <ComboBox\n                        x:Name=\"cmbEchForceQuery\"\n                        Grid.Row=\"6\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"7\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbCertPinning}\" />\n                    <StackPanel\n                        Grid.Row=\"7\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Orientation=\"Horizontal\">\n                        <TextBlock\n                            x:Name=\"labCertPinning\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\" />\n                        <materialDesign:PopupBox\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\"\n                            StaysOpen=\"True\"\n                            Style=\"{StaticResource MaterialDesignToolForegroundPopupBox}\">\n                            <StackPanel>\n                                <TextBlock\n                                    Width=\"400\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    VerticalAlignment=\"Center\"\n                                    Style=\"{StaticResource ToolbarTextBlock}\"\n                                    Text=\"{x:Static resx:ResUI.TbCertPinningTips}\"\n                                    TextWrapping=\"Wrap\" />\n                                <StackPanel HorizontalAlignment=\"Left\" Orientation=\"Horizontal\">\n                                    <Button\n                                        x:Name=\"btnFetchCert\"\n                                        Margin=\"{StaticResource MarginLeftRight4}\"\n                                        Content=\"{x:Static resx:ResUI.TbFetchCert}\"\n                                        Style=\"{StaticResource DefButton}\" />\n                                    <Button\n                                        x:Name=\"btnFetchCertChain\"\n                                        Margin=\"{StaticResource MarginLeftRight4}\"\n                                        Content=\"{x:Static resx:ResUI.TbFetchCertChain}\"\n                                        Style=\"{StaticResource DefButton}\" />\n                                </StackPanel>\n                                <TextBlock\n                                    Width=\"400\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    VerticalAlignment=\"Center\"\n                                    Style=\"{StaticResource ToolbarTextBlock}\"\n                                    Text=\"{x:Static resx:ResUI.TbCertSha256Tips}\"\n                                    TextWrapping=\"Wrap\" />\n                                <TextBox\n                                    x:Name=\"txtCertSha256Pinning\"\n                                    Width=\"400\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    HorizontalAlignment=\"Left\"\n                                    Style=\"{StaticResource DefTextBox}\" />\n                                <TextBlock\n                                    Width=\"400\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    VerticalAlignment=\"Center\"\n                                    Style=\"{StaticResource ToolbarTextBlock}\"\n                                    Text=\"{x:Static resx:ResUI.TbFullCertTips}\"\n                                    TextWrapping=\"Wrap\" />\n                                <TextBox\n                                    x:Name=\"txtCert\"\n                                    Width=\"400\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    AcceptsReturn=\"True\"\n                                    HorizontalScrollBarVisibility=\"Auto\"\n                                    MaxLines=\"18\"\n                                    MinLines=\"6\"\n                                    Style=\"{StaticResource MyOutlinedTextBox}\"\n                                    TextWrapping=\"NoWrap\"\n                                    VerticalScrollBarVisibility=\"Auto\" />\n                            </StackPanel>\n                        </materialDesign:PopupBox>\n                    </StackPanel>\n                </Grid>\n                <Grid\n                    x:Name=\"gridRealityMore\"\n                    Grid.Row=\"8\"\n                    Visibility=\"Hidden\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSNI}\" />\n                    <TextBox\n                        x:Name=\"txtSNI2\"\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbFingerprint}\" />\n                    <ComboBox\n                        x:Name=\"cmbFingerprint2\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        IsEditable=\"True\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbPublicKey}\" />\n                    <TextBox\n                        x:Name=\"txtPublicKey\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbShortId}\" />\n                    <TextBox\n                        x:Name=\"txtShortId\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSpiderX}\" />\n                    <TextBox\n                        x:Name=\"txtSpiderX\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbMldsa65Verify}\" />\n                    <TextBox\n                        x:Name=\"txtMldsa65Verify\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                </Grid>\n                <Separator\n                    Grid.Row=\"9\"\n                    Margin=\"0,2\"\n                    Style=\"{DynamicResource MaterialDesignSeparator}\" />\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/AddServerWindow.xaml.cs",
    "content": "using System.Windows.Controls;\n\nnamespace v2rayN.Views;\n\npublic partial class AddServerWindow\n{\n    public AddServerWindow(ProfileItem profileItem)\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        Loaded += Window_Loaded;\n        cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;\n        cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;\n        btnGUID.Click += btnGUID_Click;\n        btnGUID5.Click += btnGUID_Click;\n\n        ViewModel = new AddServerViewModel(profileItem, UpdateViewHandler);\n\n        cmbCoreType.ItemsSource = Global.CoreTypes.AppendEmpty();\n        cmbNetwork.ItemsSource = Global.Networks;\n        cmbFingerprint.ItemsSource = Global.Fingerprints;\n        cmbFingerprint2.ItemsSource = Global.Fingerprints;\n        cmbAllowInsecure.ItemsSource = Global.AllowInsecure;\n        cmbAlpn.ItemsSource = Global.Alpns;\n        cmbEchForceQuery.ItemsSource = Global.EchForceQuerys;\n\n        var lstStreamSecurity = new List<string>();\n        lstStreamSecurity.Add(string.Empty);\n        lstStreamSecurity.Add(Global.StreamSecurity);\n\n        switch (profileItem.ConfigType)\n        {\n            case EConfigType.VMess:\n                gridVMess.Visibility = Visibility.Visible;\n                cmbSecurity.ItemsSource = Global.VmessSecurities;\n                break;\n\n            case EConfigType.Shadowsocks:\n                gridSs.Visibility = Visibility.Visible;\n                cmbSecurity3.ItemsSource = AppManager.Instance.GetShadowsocksSecurities(profileItem);\n                break;\n\n            case EConfigType.SOCKS:\n            case EConfigType.HTTP:\n                gridSocks.Visibility = Visibility.Visible;\n                break;\n\n            case EConfigType.VLESS:\n                gridVLESS.Visibility = Visibility.Visible;\n                lstStreamSecurity.Add(Global.StreamSecurityReality);\n                cmbFlow5.ItemsSource = Global.Flows;\n                break;\n\n            case EConfigType.Trojan:\n                gridTrojan.Visibility = Visibility.Visible;\n                lstStreamSecurity.Add(Global.StreamSecurityReality);\n                cmbFlow6.ItemsSource = Global.Flows;\n                break;\n\n            case EConfigType.Hysteria2:\n                gridHysteria2.Visibility = Visibility.Visible;\n                sepa2.Visibility = Visibility.Collapsed;\n                gridTransport.Visibility = Visibility.Collapsed;\n                cmbFingerprint.IsEnabled = false;\n                cmbFingerprint.Text = string.Empty;\n                break;\n\n            case EConfigType.TUIC:\n                gridTuic.Visibility = Visibility.Visible;\n                sepa2.Visibility = Visibility.Collapsed;\n                gridTransport.Visibility = Visibility.Collapsed;\n                cmbCoreType.IsEnabled = false;\n                cmbFingerprint.IsEnabled = false;\n                cmbFingerprint.Text = string.Empty;\n                gridFinalmask.Visibility = Visibility.Collapsed;\n\n                cmbHeaderType8.ItemsSource = Global.TuicCongestionControls;\n                break;\n\n            case EConfigType.WireGuard:\n                gridWireguard.Visibility = Visibility.Visible;\n\n                sepa2.Visibility = Visibility.Collapsed;\n                gridTransport.Visibility = Visibility.Collapsed;\n                gridTls.Visibility = Visibility.Collapsed;\n\n                break;\n\n            case EConfigType.Anytls:\n                gridAnytls.Visibility = Visibility.Visible;\n                cmbCoreType.IsEnabled = false;\n                lstStreamSecurity.Add(Global.StreamSecurityReality);\n                gridFinalmask.Visibility = Visibility.Collapsed;\n                break;\n        }\n        cmbStreamSecurity.ItemsSource = lstStreamSecurity;\n\n        gridTlsMore.Visibility = Visibility.Hidden;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Address, v => v.txtAddress.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Port, v => v.txtPort.Text).DisposeWith(disposables);\n\n            switch (profileItem.ConfigType)\n            {\n                case EConfigType.VMess:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.AlterId, v => v.txtAlterId.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.VmessSecurity, v => v.cmbSecurity.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Shadowsocks:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId3.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SsMethod, v => v.cmbSecurity3.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled3.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.SOCKS:\n                case EConfigType.HTTP:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId4.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtSecurity4.Text).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.VLESS:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId5.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.Flow, v => v.cmbFlow5.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.VlessEncryption, v => v.txtSecurity5.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled5.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Trojan:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId6.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.Flow, v => v.cmbFlow6.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled6.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Hysteria2:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SalamanderPass, v => v.txtPath7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.Ports, v => v.txtPorts7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.HopInterval, v => v.txtHopInt7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.UpMbps, v => v.txtUpMbps7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.DownMbps, v => v.txtDownMbps7.Text).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.TUIC:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtId8.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity8.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType8.Text).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.WireGuard:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgPublicKey, v => v.txtPublicKey9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgReserved, v => v.txtPath9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgInterfaceAddress, v => v.txtRequestHost9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgMtu, v => v.txtShortId9.Text).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Anytls:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId10.Text).DisposeWith(disposables);\n                    break;\n            }\n            this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CertSha, v => v.txtCertSha256Pinning.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CertTip, v => v.labCertPinning.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Cert, v => v.txtCert.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Cert, v => v.txtCert.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.EchConfigList, v => v.txtEchConfigList.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.EchForceQuery, v => v.cmbEchForceQuery.Text).DisposeWith(disposables);\n\n            //reality\n            this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint2.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PublicKey, v => v.txtPublicKey.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedSource.Finalmask, v => v.txtFinalmask.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n\n        Title = $\"{profileItem.ConfigType}\";\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void CmbNetwork_SelectionChanged(object sender, SelectionChangedEventArgs e)\n    {\n        SetHeaderType();\n        SetTips();\n    }\n\n    private void CmbStreamSecurity_SelectionChanged(object sender, SelectionChangedEventArgs e)\n    {\n        var security = cmbStreamSecurity.SelectedItem.ToString();\n        if (security == Global.StreamSecurityReality)\n        {\n            gridRealityMore.Visibility = Visibility.Visible;\n            gridTlsMore.Visibility = Visibility.Hidden;\n        }\n        else if (security == Global.StreamSecurity)\n        {\n            gridRealityMore.Visibility = Visibility.Hidden;\n            gridTlsMore.Visibility = Visibility.Visible;\n        }\n        else\n        {\n            gridRealityMore.Visibility = Visibility.Hidden;\n            gridTlsMore.Visibility = Visibility.Hidden;\n        }\n    }\n\n    private void btnGUID_Click(object sender, RoutedEventArgs e)\n    {\n        txtId.Text =\n        txtId5.Text = Utils.GetGuid();\n    }\n\n    private void SetHeaderType()\n    {\n        var lstHeaderType = new List<string>();\n\n        var network = cmbNetwork.SelectedItem.ToString();\n        if (network.IsNullOrEmpty())\n        {\n            lstHeaderType.Add(Global.None);\n            cmbHeaderType.ItemsSource = lstHeaderType;\n            cmbHeaderType.SelectedIndex = 0;\n            return;\n        }\n\n        if (network == nameof(ETransport.tcp))\n        {\n            lstHeaderType.Add(Global.None);\n            lstHeaderType.Add(Global.TcpHeaderHttp);\n        }\n        else if (network is nameof(ETransport.kcp) or nameof(ETransport.quic))\n        {\n            lstHeaderType.Add(Global.None);\n            lstHeaderType.AddRange(Global.KcpHeaderTypes);\n        }\n        else if (network is nameof(ETransport.xhttp))\n        {\n            lstHeaderType.AddRange(Global.XhttpMode);\n        }\n        else if (network == nameof(ETransport.grpc))\n        {\n            lstHeaderType.Add(Global.GrpcGunMode);\n            lstHeaderType.Add(Global.GrpcMultiMode);\n        }\n        else\n        {\n            lstHeaderType.Add(Global.None);\n        }\n        cmbHeaderType.ItemsSource = lstHeaderType;\n        cmbHeaderType.SelectedIndex = 0;\n    }\n\n    private void SetTips()\n    {\n        var network = cmbNetwork.SelectedItem.ToString();\n        if (network.IsNullOrEmpty())\n        {\n            network = Global.DefaultNetwork;\n        }\n        labHeaderType.Visibility = Visibility.Visible;\n        popExtra.Visibility = Visibility.Hidden;\n        tipRequestHost.Text =\n        tipPath.Text =\n        tipHeaderType.Text = string.Empty;\n\n        switch (network)\n        {\n            case nameof(ETransport.tcp):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip1;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip1;\n                break;\n\n            case nameof(ETransport.kcp):\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip2;\n                tipPath.Text = ResUI.TransportPathTip5;\n                break;\n\n            case nameof(ETransport.ws):\n            case nameof(ETransport.httpupgrade):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip2;\n                tipPath.Text = ResUI.TransportPathTip1;\n                break;\n\n            case nameof(ETransport.xhttp):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip2;\n                tipPath.Text = ResUI.TransportPathTip1;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip5;\n                labHeaderType.Visibility = Visibility.Hidden;\n                popExtra.Visibility = Visibility.Visible;\n                break;\n\n            case nameof(ETransport.h2):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip3;\n                tipPath.Text = ResUI.TransportPathTip2;\n                break;\n\n            case nameof(ETransport.quic):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip4;\n                tipPath.Text = ResUI.TransportPathTip3;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip3;\n                break;\n\n            case nameof(ETransport.grpc):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip5;\n                tipPath.Text = ResUI.TransportPathTip4;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip4;\n                labHeaderType.Visibility = Visibility.Hidden;\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/BackupAndRestoreView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.BackupAndRestoreView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:converters=\"clr-namespace:v2rayN.Converters\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"600\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:BackupAndRestoreViewModel\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n    <UserControl.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceDictionary Source=\"pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Popupbox.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n        </ResourceDictionary>\n    </UserControl.Resources>\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <DockPanel Margin=\"{StaticResource Margin8}\" DockPanel.Dock=\"Bottom\">\n            <TextBlock\n                x:Name=\"txtMsg\"\n                Margin=\"{StaticResource Margin8}\"\n                HorizontalAlignment=\"Left\"\n                Style=\"{StaticResource ToolbarTextBlock}\" />\n        </DockPanel>\n\n        <StackPanel>\n            <materialDesign:Card Width=\"Auto\" Margin=\"{StaticResource Margin8}\">\n                <Grid Margin=\"{StaticResource Margin8}\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"200\" />\n                    </Grid.ColumnDefinitions>\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource ModuleTitle}\"\n                        Text=\"{x:Static resx:ResUI.menuLocalBackupAndRestore}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.menuLocalBackup}\" />\n                    <Button\n                        x:Name=\"menuLocalBackup\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Content=\"{x:Static resx:ResUI.menuLocalBackup}\"\n                        Style=\"{StaticResource DefButton}\" />\n\n                    <Separator\n                        Grid.Row=\"2\"\n                        Grid.ColumnSpan=\"2\"\n                        Style=\"{StaticResource MaterialDesignLightSeparator}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.menuLocalRestore}\" />\n                    <Button\n                        x:Name=\"menuLocalRestore\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Content=\"{x:Static resx:ResUI.menuLocalRestore}\"\n                        Style=\"{StaticResource DefButton}\" />\n                </Grid>\n            </materialDesign:Card>\n            <materialDesign:Card Width=\"Auto\" Margin=\"{StaticResource Margin8}\">\n                <Grid Margin=\"{StaticResource Margin8}\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"300\" />\n                        <ColumnDefinition Width=\"200\" />\n                    </Grid.ColumnDefinitions>\n                    <StackPanel Orientation=\"Horizontal\">\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource ModuleTitle}\"\n                            Text=\"{x:Static resx:ResUI.menuRemoteBackupAndRestore}\" />\n\n                        <materialDesign:PopupBox\n                            HorizontalAlignment=\"Right\"\n                            StaysOpen=\"True\"\n                            Style=\"{StaticResource MaterialDesignToolForegroundPopupBox}\">\n                            <StackPanel Margin=\"{StaticResource Margin8}\">\n                                <Grid>\n                                    <Grid.RowDefinitions>\n                                        <RowDefinition Height=\"Auto\" />\n                                        <RowDefinition Height=\"Auto\" />\n                                        <RowDefinition Height=\"Auto\" />\n                                        <RowDefinition Height=\"Auto\" />\n                                        <RowDefinition Height=\"Auto\" />\n                                    </Grid.RowDefinitions>\n                                    <Grid.ColumnDefinitions>\n                                        <ColumnDefinition Width=\"Auto\" />\n                                        <ColumnDefinition Width=\"300\" />\n                                    </Grid.ColumnDefinitions>\n                                    <TextBlock\n                                        Grid.Row=\"0\"\n                                        Grid.Column=\"0\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource ToolbarTextBlock}\"\n                                        Text=\"{x:Static resx:ResUI.LvWebDavUrl}\" />\n\n                                    <TextBox\n                                        x:Name=\"txtWebDavUrl\"\n                                        Grid.Row=\"0\"\n                                        Grid.Column=\"1\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource DefTextBox}\"\n                                        TextWrapping=\"Wrap\" />\n\n                                    <TextBlock\n                                        Grid.Row=\"1\"\n                                        Grid.Column=\"0\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource ToolbarTextBlock}\"\n                                        Text=\"{x:Static resx:ResUI.LvWebDavUserName}\" />\n\n                                    <TextBox\n                                        x:Name=\"txtWebDavUserName\"\n                                        Grid.Row=\"1\"\n                                        Grid.Column=\"1\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource DefTextBox}\" />\n\n                                    <TextBlock\n                                        Grid.Row=\"2\"\n                                        Grid.Column=\"0\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource ToolbarTextBlock}\"\n                                        Text=\"{x:Static resx:ResUI.LvWebDavPassword}\" />\n\n                                    <TextBox\n                                        x:Name=\"txtWebDavPassword\"\n                                        Grid.Row=\"2\"\n                                        Grid.Column=\"1\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource DefTextBox}\" />\n\n                                    <TextBlock\n                                        Grid.Row=\"3\"\n                                        Grid.Column=\"0\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource ToolbarTextBlock}\"\n                                        Text=\"{x:Static resx:ResUI.LvWebDavDirName}\" />\n\n                                    <TextBox\n                                        x:Name=\"txtWebDavDirName\"\n                                        Grid.Row=\"3\"\n                                        Grid.Column=\"1\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Style=\"{StaticResource DefTextBox}\" />\n\n                                    <Button\n                                        x:Name=\"menuWebDavCheck\"\n                                        Grid.Row=\"4\"\n                                        Grid.Column=\"1\"\n                                        Margin=\"{StaticResource Margin8}\"\n                                        VerticalAlignment=\"Center\"\n                                        Content=\"{x:Static resx:ResUI.LvWebDavCheck}\"\n                                        Style=\"{StaticResource DefButton}\" />\n                                </Grid>\n                            </StackPanel>\n                        </materialDesign:PopupBox>\n                    </StackPanel>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.menuRemoteBackup}\" />\n                    <Button\n                        x:Name=\"menuRemoteBackup\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Content=\"{x:Static resx:ResUI.menuRemoteBackup}\"\n                        Style=\"{StaticResource DefButton}\" />\n\n                    <Separator\n                        Grid.Row=\"2\"\n                        Grid.ColumnSpan=\"3\"\n                        Style=\"{StaticResource MaterialDesignLightSeparator}\" />\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.menuRemoteRestore}\" />\n                    <Button\n                        x:Name=\"menuRemoteRestore\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Content=\"{x:Static resx:ResUI.menuRemoteRestore}\"\n                        Style=\"{StaticResource DefButton}\" />\n                </Grid>\n            </materialDesign:Card>\n        </StackPanel>\n    </DockPanel>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/BackupAndRestoreView.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class BackupAndRestoreView\n{\n    public BackupAndRestoreView()\n    {\n        InitializeComponent();\n        menuLocalBackup.Click += MenuLocalBackup_Click;\n        menuLocalRestore.Click += MenuLocalRestore_Click;\n\n        ViewModel = new BackupAndRestoreViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.OperationMsg, v => v.txtMsg.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedSource.Url, v => v.txtWebDavUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.UserName, v => v.txtWebDavUserName.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtWebDavPassword.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.DirName, v => v.txtWebDavDirName.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.WebDavCheckCmd, v => v.menuWebDavCheck).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RemoteBackupCmd, v => v.menuRemoteBackup).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoteRestoreCmd, v => v.menuRemoteRestore).DisposeWith(disposables);\n        });\n    }\n\n    private void MenuLocalBackup_Click(object sender, RoutedEventArgs e)\n    {\n        if (UI.SaveFileDialog(out var fileName, \"Zip|*.zip\") != true)\n        {\n            return;\n        }\n        ViewModel?.LocalBackup(fileName);\n    }\n\n    private void MenuLocalRestore_Click(object sender, RoutedEventArgs e)\n    {\n        if (UI.OpenFileDialog(out var fileName, \"Zip|*.zip|All|*.*\") != true)\n        {\n            return;\n        }\n        ViewModel?.LocalRestore(fileName);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/CheckUpdateView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.CheckUpdateView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:converters=\"clr-namespace:v2rayN.Converters\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:CheckUpdateViewModel\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin8}\"\n            HorizontalAlignment=\"Right\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n\n            <TextBlock\n                Margin=\"{StaticResource Margin8}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbSettingsEnableCheckPreReleaseUpdate}\" />\n            <ToggleButton\n                x:Name=\"togEnableCheckPreReleaseUpdate\"\n                Margin=\"{StaticResource Margin8}\"\n                HorizontalAlignment=\"Left\" />\n\n            <Button\n                x:Name=\"btnCheckUpdate\"\n                Width=\"100\"\n                Margin=\"{StaticResource Margin8}\"\n                Content=\"{x:Static resx:ResUI.menuCheckUpdate}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <StackPanel>\n            <ListView\n                x:Name=\"lstCheckUpdates\"\n                BorderThickness=\"1\"\n                ItemContainerStyle=\"{StaticResource lvItemSelected}\">\n                <ListView.ItemsPanel>\n                    <ItemsPanelTemplate>\n                        <StackPanel Orientation=\"Vertical\" />\n                    </ItemsPanelTemplate>\n                </ListView.ItemsPanel>\n                <ListView.ItemTemplate>\n                    <DataTemplate>\n                        <Border\n                            Width=\"500\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Padding=\"0\"\n                            VerticalAlignment=\"Center\">\n                            <Grid>\n                                <Grid.RowDefinitions>\n                                    <RowDefinition Height=\"Auto\" />\n                                </Grid.RowDefinitions>\n                                <Grid.ColumnDefinitions>\n                                    <ColumnDefinition Width=\"1*\" />\n                                    <ColumnDefinition Width=\"1*\" />\n                                    <ColumnDefinition Width=\"3*\" />\n                                </Grid.ColumnDefinitions>\n                                <ToggleButton\n                                    x:Name=\"togAutoRefresh\"\n                                    Grid.Column=\"0\"\n                                    Margin=\"{StaticResource Margin8}\"\n                                    HorizontalAlignment=\"Left\"\n                                    VerticalAlignment=\"Center\"\n                                    IsChecked=\"{Binding IsSelected}\" />\n                                <TextBlock\n                                    Grid.Column=\"1\"\n                                    Style=\"{StaticResource ListItemTitle}\"\n                                    Text=\"{Binding CoreType}\" />\n                                <TextBlock\n                                    Grid.Column=\"2\"\n                                    Style=\"{StaticResource ListItemSubTitle}\"\n                                    Text=\"{Binding Remarks}\"\n                                    TextWrapping=\"WrapWithOverflow\" />\n                            </Grid>\n                        </Border>\n                    </DataTemplate>\n                </ListView.ItemTemplate>\n            </ListView>\n        </StackPanel>\n    </DockPanel>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/CheckUpdateView.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class CheckUpdateView\n{\n    public CheckUpdateView()\n    {\n        InitializeComponent();\n\n        ViewModel = new CheckUpdateViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ClashConnectionsView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.ClashConnectionsView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:ClashConnectionsViewModel\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"{StaticResource Margin4}\">\n        <WrapPanel\n            Margin=\"{StaticResource Margin8}\"\n            VerticalAlignment=\"Center\"\n            DockPanel.Dock=\"Top\"\n            Orientation=\"Horizontal\">\n\n            <TextBox\n                x:Name=\"txtHostFilter\"\n                Width=\"200\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                VerticalContentAlignment=\"Center\"\n                materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.ConnectionsHostFilterTitle}\"\n                materialDesign:TextFieldAssist.HasClearButton=\"True\"\n                Style=\"{StaticResource DefTextBox}\" />\n\n            <Button\n                x:Name=\"btnConnectionCloseAll\"\n                Width=\"24\"\n                Height=\"24\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                ToolTip=\"{x:Static resx:ResUI.menuConnectionCloseAll}\">\n                <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"Close\" />\n            </Button>\n\n            <Button\n                x:Name=\"btnAutofitColumnWidth\"\n                Width=\"24\"\n                Height=\"24\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                ToolTip=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\">\n                <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"ArrowSplitVertical\" />\n            </Button>\n\n            <TextBlock\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbAutoRefresh}\" />\n            <ToggleButton\n                x:Name=\"togAutoRefresh\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                HorizontalAlignment=\"Left\" />\n        </WrapPanel>\n\n        <DataGrid\n            x:Name=\"lstConnections\"\n            AutoGenerateColumns=\"False\"\n            BorderThickness=\"1\"\n            CanUserAddRows=\"False\"\n            CanUserResizeRows=\"False\"\n            EnableRowVirtualization=\"True\"\n            GridLinesVisibility=\"All\"\n            HeadersVisibility=\"Column\"\n            IsReadOnly=\"True\"\n            Style=\"{StaticResource DefDataGrid}\">\n            <DataGrid.ContextMenu>\n                <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                    <MenuItem x:Name=\"menuConnectionClose\" Header=\"{x:Static resx:ResUI.menuConnectionClose}\" />\n                    <MenuItem x:Name=\"menuConnectionCloseAll\" Header=\"{x:Static resx:ResUI.menuConnectionCloseAll}\" />\n                </ContextMenu>\n            </DataGrid.ContextMenu>\n            <DataGrid.Columns>\n                <base:MyDGTextColumn\n                    Width=\"300\"\n                    Binding=\"{Binding Host}\"\n                    ExName=\"Host\"\n                    Header=\"{x:Static resx:ResUI.TbSortingHost}\" />\n                <base:MyDGTextColumn\n                    Width=\"500\"\n                    Binding=\"{Binding Chain}\"\n                    ExName=\"Chain\"\n                    Header=\"{x:Static resx:ResUI.TbSortingChain}\" />\n                <base:MyDGTextColumn\n                    Width=\"80\"\n                    Binding=\"{Binding Network}\"\n                    ExName=\"Network\"\n                    Header=\"{x:Static resx:ResUI.TbSortingNetwork}\" />\n                <base:MyDGTextColumn\n                    Width=\"160\"\n                    Binding=\"{Binding Type}\"\n                    ExName=\"Type\"\n                    Header=\"{x:Static resx:ResUI.TbSortingType}\" />\n                <base:MyDGTextColumn\n                    Width=\"100\"\n                    Binding=\"{Binding Elapsed}\"\n                    ExName=\"Elapsed\"\n                    Header=\"{x:Static resx:ResUI.TbSortingTime}\" />\n            </DataGrid.Columns>\n        </DataGrid>\n    </DockPanel>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ClashConnectionsView.xaml.cs",
    "content": "using System.Windows.Controls;\nusing v2rayN.Base;\n\nnamespace v2rayN.Views;\n\n/// <summary>\n/// Interaction logic for ConnectionsView.xaml\n/// </summary>\npublic partial class ClashConnectionsView\n{\n    private static Config _config;\n    private static readonly string _tag = \"ClashConnectionsView\";\n\n    public ClashConnectionsView()\n    {\n        InitializeComponent();\n        _config = AppManager.Instance.Config;\n\n        ViewModel = new ClashConnectionsViewModel(UpdateViewHandler);\n        btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ConnectionItems, v => v.lstConnections.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstConnections.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ConnectionCloseCmd, v => v.menuConnectionClose).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);\n\n            AppEvents.AppExitRequested\n                .AsObservable()\n                .ObserveOn(RxSchedulers.MainThreadScheduler)\n                .Subscribe(_ => StorageUI())\n                .DisposeWith(disposables);\n        });\n\n        RestoreUI();\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n\n    private void BtnAutofitColumnWidth_Click(object sender, RoutedEventArgs e)\n    {\n        AutofitColumnWidth();\n    }\n\n    private void AutofitColumnWidth()\n    {\n        try\n        {\n            foreach (var it in lstConnections.Columns)\n            {\n                it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void btnClose_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        ViewModel?.ClashConnectionClose(false);\n    }\n\n    #region UI\n\n    private void RestoreUI()\n    {\n        try\n        {\n            var lvColumnItem = _config.ClashUIItem?.ConnectionsColumnItem?.OrderBy(t => t.Index).ToList();\n            if (lvColumnItem == null)\n            {\n                return;\n            }\n\n            var displayIndex = 0;\n            foreach (var item in lvColumnItem)\n            {\n                foreach (var col in lstConnections.Columns.Cast<MyDGTextColumn>())\n                {\n                    if (col.ExName == item.Name)\n                    {\n                        if (item.Width > 0)\n                        {\n                            col.Width = item.Width;\n                        }\n\n                        col.DisplayIndex = displayIndex++;\n                        break;\n                    }\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void StorageUI()\n    {\n        try\n        {\n            List<ColumnItem> lvColumnItem = new();\n            foreach (var col in lstConnections.Columns.Cast<MyDGTextColumn>())\n            {\n                var name = col.ExName;\n                if (string.IsNullOrWhiteSpace(name))\n                {\n                    continue;\n                }\n\n                lvColumnItem.Add(new()\n                {\n                    Name = name,\n                    Width = (int)col.ActualWidth,\n                    Index = col.DisplayIndex\n                });\n            }\n\n            _config.ClashUIItem.ConnectionsColumnItem = lvColumnItem;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    #endregion UI\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ClashProxiesView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.ClashProxiesView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:converters=\"clr-namespace:v2rayN.Converters\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:ClashProxiesViewModel\"\n    KeyDown=\"ProxiesView_KeyDown\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n    <UserControl.Resources>\n        <BooleanToVisibilityConverter x:Key=\"BoolToVisConverter\" />\n        <converters:DelayColorConverter x:Key=\"DelayColorConverter\" />\n    </UserControl.Resources>\n\n    <DockPanel Margin=\"{StaticResource Margin4}\">\n        <WrapPanel\n            Margin=\"{StaticResource Margin8}\"\n            VerticalAlignment=\"Center\"\n            DockPanel.Dock=\"Top\"\n            Orientation=\"Horizontal\">\n\n            <TextBlock\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.menuRulemode}\" />\n            <ComboBox\n                x:Name=\"cmbRulemode\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Style=\"{StaticResource DefComboBox}\">\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.menuModeRule}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.menuModeGlobal}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.menuModeDirect}\" />\n            </ComboBox>\n\n            <TextBlock\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbSorting}\" />\n            <ComboBox\n                x:Name=\"cmbSorting\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Style=\"{StaticResource DefComboBox}\">\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.TbSortingDelay}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.TbSortingName}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.TbSortingDefault}\" />\n            </ComboBox>\n\n            <Button\n                x:Name=\"menuProxiesReload\"\n                Width=\"24\"\n                Height=\"24\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                ToolTip=\"{x:Static resx:ResUI.menuProxiesReload}\">\n                <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"Reload\" />\n            </Button>\n\n            <Button\n                x:Name=\"menuProxiesDelaytest\"\n                Width=\"24\"\n                Height=\"24\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                ToolTip=\"{x:Static resx:ResUI.menuProxiesDelaytest}\">\n                <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"LightningBolt\" />\n            </Button>\n\n            <TextBlock\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbAutoRefresh}\" />\n            <ToggleButton\n                x:Name=\"togAutoRefresh\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                HorizontalAlignment=\"Left\" />\n        </WrapPanel>\n        <DockPanel>\n            <ListView\n                x:Name=\"lstProxyGroups\"\n                Margin=\"{StaticResource MarginRight8}\"\n                BorderThickness=\"0\"\n                DockPanel.Dock=\"Left\"\n                ItemContainerStyle=\"{StaticResource lvItemSelected}\"\n                ScrollViewer.HorizontalScrollBarVisibility=\"Disabled\"\n                ScrollViewer.VerticalScrollBarVisibility=\"Visible\"\n                Style=\"{StaticResource MaterialDesignListView}\">\n                <ListView.ItemsPanel>\n                    <ItemsPanelTemplate>\n                        <StackPanel Orientation=\"Vertical\" />\n                    </ItemsPanelTemplate>\n                </ListView.ItemsPanel>\n                <ListView.ItemTemplate>\n                    <DataTemplate>\n                        <Border\n                            Width=\"160\"\n                            Margin=\"{StaticResource MarginLeftRight4}\"\n                            Padding=\"0\">\n                            <DockPanel>\n                                <Grid Grid.Column=\"0\" Margin=\"{StaticResource Margin4}\">\n                                    <Grid.RowDefinitions>\n                                        <RowDefinition />\n                                        <RowDefinition />\n                                    </Grid.RowDefinitions>\n                                    <DockPanel Grid.Row=\"0\">\n                                        <TextBlock\n                                            DockPanel.Dock=\"Right\"\n                                            Style=\"{StaticResource ListItemSubTitle}\"\n                                            Text=\"{Binding Type}\" />\n                                        <TextBlock Style=\"{StaticResource ListItemTitle}\" Text=\"{Binding Name}\" />\n                                    </DockPanel>\n                                    <TextBlock\n                                        Grid.Row=\"1\"\n                                        Style=\"{StaticResource ListItemSubTitle}\"\n                                        Text=\"{Binding Now}\" />\n                                </Grid>\n                            </DockPanel>\n                        </Border>\n                    </DataTemplate>\n                </ListView.ItemTemplate>\n            </ListView>\n\n            <ListView\n                x:Name=\"lstProxyDetails\"\n                BorderThickness=\"0\"\n                ItemContainerStyle=\"{StaticResource lvItemSelected}\"\n                ScrollViewer.HorizontalScrollBarVisibility=\"Disabled\"\n                ScrollViewer.VerticalScrollBarVisibility=\"Visible\"\n                Style=\"{StaticResource MaterialDesignListView}\">\n                <ListView.ContextMenu>\n                    <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                        <MenuItem x:Name=\"menuProxiesDelaytestPart\" Header=\"{x:Static resx:ResUI.menuProxiesDelaytestPart}\" />\n                        <MenuItem\n                            x:Name=\"menuProxiesSelectActivity\"\n                            Header=\"{x:Static resx:ResUI.menuProxiesSelectActivity}\"\n                            InputGestureText=\"Enter\" />\n                    </ContextMenu>\n                </ListView.ContextMenu>\n                <ListView.ItemsPanel>\n                    <ItemsPanelTemplate>\n                        <WrapPanel Orientation=\"Horizontal\" />\n                    </ItemsPanelTemplate>\n                </ListView.ItemsPanel>\n                <ListView.ItemTemplate>\n                    <DataTemplate>\n                        <Border Width=\"160\" Padding=\"0\">\n                            <DockPanel>\n                                <Border\n                                    Width=\"5\"\n                                    Height=\"auto\"\n                                    Margin=\"0,1\"\n                                    Background=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\"\n                                    CornerRadius=\"4\"\n                                    DockPanel.Dock=\"Left\"\n                                    Visibility=\"{Binding Path=IsActive, Converter={StaticResource BoolToVisConverter}}\" />\n                                <Grid Margin=\"{StaticResource Margin4}\">\n                                    <Grid.RowDefinitions>\n                                        <RowDefinition Height=\"2*\" />\n                                        <RowDefinition Height=\"1*\" />\n                                    </Grid.RowDefinitions>\n                                    <TextBlock\n                                        Grid.Row=\"0\"\n                                        Style=\"{StaticResource ListItemSubTitle}\"\n                                        Text=\"{Binding Name}\"\n                                        TextWrapping=\"WrapWithOverflow\" />\n                                    <DockPanel Grid.Row=\"1\">\n                                        <TextBlock\n                                            DockPanel.Dock=\"Right\"\n                                            Foreground=\"{Binding Path=Delay, Converter={StaticResource DelayColorConverter}}\"\n                                            Style=\"{StaticResource ListItemSubTitle2}\"\n                                            Text=\"{Binding DelayName}\" />\n                                        <TextBlock Style=\"{StaticResource ListItemSubTitle2}\" Text=\"{Binding Type}\" />\n                                    </DockPanel>\n                                </Grid>\n                            </DockPanel>\n                        </Border>\n                    </DataTemplate>\n                </ListView.ItemTemplate>\n            </ListView>\n        </DockPanel>\n    </DockPanel>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ClashProxiesView.xaml.cs",
    "content": "namespace v2rayN.Views;\n\n/// <summary>\n/// Interaction logic for ProxiesView.xaml\n/// </summary>\npublic partial class ClashProxiesView\n{\n    public ClashProxiesView()\n    {\n        InitializeComponent();\n        ViewModel = new ClashProxiesViewModel(UpdateViewHandler);\n        lstProxyDetails.PreviewMouseDoubleClick += lstProxyDetails_PreviewMouseDoubleClick;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ProxyGroups, v => v.lstProxyGroups.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedGroup, v => v.lstProxyGroups.SelectedItem).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.ProxyDetails, v => v.lstProxyDetails.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedDetail, v => v.lstProxyDetails.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ProxiesReloadCmd, v => v.menuProxiesReload).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ProxiesDelayTestCmd, v => v.menuProxiesDelaytest).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ProxiesDelayTestPartCmd, v => v.menuProxiesDelaytestPart).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ProxiesSelectActivityCmd, v => v.menuProxiesSelectActivity).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.RuleModeSelected, v => v.cmbRulemode.SelectedIndex).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SortingSelected, v => v.cmbSorting.SelectedIndex).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n\n    private void ProxiesView_KeyDown(object sender, KeyEventArgs e)\n    {\n        switch (e.Key)\n        {\n            case Key.F5:\n                ViewModel?.ProxiesReload();\n                break;\n\n            case Key.Enter:\n                ViewModel?.SetActiveProxy();\n                break;\n        }\n    }\n\n    private void lstProxyDetails_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)\n    {\n        ViewModel?.SetActiveProxy();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/DNSSettingWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.DNSSettingWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuDNSSetting}\"\n    Width=\"1000\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:DNSSettingViewModel\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <TabControl HorizontalContentAlignment=\"Left\">\n            <TabItem Header=\"{x:Static resx:ResUI.ThBasicDNSSettings}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid x:Name=\"gridBasicDNSSettings\" Margin=\"{StaticResource Margin8}\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"*\" />\n                        </Grid.ColumnDefinitions>\n\n                        <TextBlock\n                            x:Name=\"txtBasicDNSSettingsInvalid\"\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Grid.ColumnSpan=\"3\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbDomesticDNS}\" />\n                        <ComboBox\n                            x:Name=\"cmbDirectDNS\"\n                            Grid.Row=\"1\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbDomesticDNSTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteDNS}\" />\n                        <ComboBox\n                            x:Name=\"cmbRemoteDNS\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteDNSTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbBootstrapDNS}\" />\n                        <ComboBox\n                            x:Name=\"cmbBootstrapDNS\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbBootstrapDNSTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbDirectResolveStrategy}\" />\n                        <ComboBox\n                            x:Name=\"cmbDirectDNSStrategy\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            materialDesign:HintAssist.Hint=\"Default\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbDirectResolveStrategyTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteResolveStrategy}\" />\n                        <ComboBox\n                            x:Name=\"cmbRemoteDNSStrategy\"\n                            Grid.Row=\"6\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            materialDesign:HintAssist.Hint=\"Default\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteResolveStrategyTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"7\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbParallelQuery}\" />\n                        <ToggleButton\n                            x:Name=\"togParallelQuery\"\n                            Grid.Row=\"7\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"8\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbServeStale}\" />\n                        <ToggleButton\n                            x:Name=\"togServeStale\"\n                            Grid.Row=\"8\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n            <TabItem Header=\"{x:Static resx:ResUI.ThAdvancedDNSSettings}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid x:Name=\"gridAdvancedDNSSettings\" Margin=\"{StaticResource Margin8}\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"*\" />\n                        </Grid.RowDefinitions>\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"*\" />\n                        </Grid.ColumnDefinitions>\n\n                        <TextBlock\n                            x:Name=\"txtAdvancedDNSSettingsInvalid\"\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Grid.ColumnSpan=\"3\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsUseSystemHosts}\" />\n                        <ToggleButton\n                            x:Name=\"togUseSystemHosts\"\n                            Grid.Row=\"1\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbAddCommonDNSHosts}\" />\n                        <ToggleButton\n                            x:Name=\"togAddCommonHosts\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbFakeIP}\" />\n                        <ToggleButton\n                            x:Name=\"togFakeIP\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbFakeIPTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}\" />\n                        <ToggleButton\n                            x:Name=\"togBlockBindingQuery\"\n                            Grid.Row=\"4\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbBlockSVCBHTTPSQueriesTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbValidateDirectExpectedIPs}\" />\n                        <ComboBox\n                            x:Name=\"cmbDirectExpectedIPs\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbValidateDirectExpectedIPsDesc}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"0\"\n                            Grid.ColumnSpan=\"3\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbDNSHostsConfig}\" />\n                        <TextBox\n                            x:Name=\"txtHosts\"\n                            Grid.Row=\"7\"\n                            Grid.Column=\"0\"\n                            Grid.ColumnSpan=\"3\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Stretch\"\n                            materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.TbDNSHostsConfig}\"\n                            AcceptsReturn=\"True\"\n                            BorderThickness=\"1\"\n                            Style=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                            TextWrapping=\"Wrap\"\n                            VerticalScrollBarVisibility=\"Auto\" />\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbCustomDnsRay}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <Grid DockPanel.Dock=\"Top\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n\n                        <StackPanel Grid.Row=\"0\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbCustomDNSEnable}\" />\n                            <ToggleButton\n                                x:Name=\"togRayCustomDNSEnableCompatible\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsRemoteDNS}\" />\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\">\n                                <Hyperlink Click=\"linkDnsObjectDoc_Click\">\n                                    <TextBlock Text=\"{x:Static resx:ResUI.TbDnsObjectDoc}\" />\n                                    <materialDesign:PackIcon Kind=\"Link\" />\n                                </Hyperlink>\n                            </TextBlock>\n                            <Button\n                                x:Name=\"btnImportDefConfig4V2rayCompatible\"\n                                Margin=\"{StaticResource Margin8}\"\n                                Content=\"{x:Static resx:ResUI.TbSettingDnsImportDefConfig}\"\n                                Style=\"{StaticResource DefButton}\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsUseSystemHosts}\" />\n                            <ToggleButton\n                                x:Name=\"togUseSystemHostsCompatible\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainStrategy4FreedomCompatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin8}\"\n                                Style=\"{StaticResource DefComboBox}\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainDNSAddress}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainDNSAddressCompatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin8}\"\n                                IsEditable=\"True\"\n                                Style=\"{StaticResource DefComboBox}\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <TextBox\n                        x:Name=\"txtnormalDNSCompatible\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Stretch\"\n                        materialDesign:HintAssist.Hint=\"HTTP/SOCKS\"\n                        AcceptsReturn=\"True\"\n                        BorderThickness=\"1\"\n                        Style=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                        TextWrapping=\"Wrap\"\n                        VerticalScrollBarVisibility=\"Auto\" />\n                </DockPanel>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbCustomDnsSingbox}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <Grid DockPanel.Dock=\"Top\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n\n                        <StackPanel Grid.Row=\"0\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbCustomDNSEnable}\" />\n                            <ToggleButton\n                                x:Name=\"togSBCustomDNSEnableCompatible\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\">\n                                <Hyperlink Click=\"linkDnsSingboxObjectDoc_Click\">\n                                    <TextBlock Text=\"{x:Static resx:ResUI.TbDnsSingboxObjectDoc}\" />\n                                    <materialDesign:PackIcon Kind=\"Link\" />\n                                </Hyperlink>\n                            </TextBlock>\n                            <Button\n                                x:Name=\"btnImportDefConfig4SingboxCompatible\"\n                                Margin=\"{StaticResource Margin8}\"\n                                Content=\"{x:Static resx:ResUI.TbSettingDnsImportDefConfig}\"\n                                Style=\"{StaticResource DefButton}\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainStrategy4OutCompatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin8}\"\n                                Style=\"{StaticResource DefComboBox}\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainDNSAddress}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainDNSAddress2Compatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin8}\"\n                                IsEditable=\"True\"\n                                Style=\"{StaticResource DefComboBox}\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <Grid Margin=\"{StaticResource Margin8}\">\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"1*\" />\n                            <ColumnDefinition Width=\"10\" />\n                            <ColumnDefinition Width=\"1*\" />\n                        </Grid.ColumnDefinitions>\n\n                        <TextBox\n                            x:Name=\"txtnormalDNS2Compatible\"\n                            Grid.Column=\"0\"\n                            VerticalAlignment=\"Stretch\"\n                            materialDesign:HintAssist.Hint=\"HTTP/SOCKS\"\n                            AcceptsReturn=\"True\"\n                            BorderThickness=\"1\"\n                            Style=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                            TextWrapping=\"Wrap\"\n                            VerticalScrollBarVisibility=\"Auto\" />\n\n                        <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n\n                        <TextBox\n                            x:Name=\"txttunDNS2Compatible\"\n                            Grid.Column=\"2\"\n                            VerticalAlignment=\"Stretch\"\n                            materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.TbSettingsTunMode}\"\n                            AcceptsReturn=\"True\"\n                            BorderThickness=\"1\"\n                            Style=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                            TextWrapping=\"Wrap\"\n                            VerticalScrollBarVisibility=\"Auto\" />\n                    </Grid>\n                </DockPanel>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/DNSSettingWindow.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class DNSSettingWindow\n{\n    private static Config _config;\n\n    public DNSSettingWindow()\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        _config = AppManager.Instance.Config;\n\n        ViewModel = new DNSSettingViewModel(UpdateViewHandler);\n\n        cmbDirectDNSStrategy.ItemsSource = Global.DomainStrategy;\n        cmbRemoteDNSStrategy.ItemsSource = Global.DomainStrategy;\n        cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;\n        cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;\n        cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress;\n        cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;\n\n        cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy;\n        cmbdomainStrategy4OutCompatible.ItemsSource = Global.DomainStrategies4Sbox;\n        cmbdomainDNSAddressCompatible.ItemsSource = Global.DomainPureIPDNSAddress;\n        cmbdomainDNSAddress2Compatible.ItemsSource = Global.DomainPureIPDNSAddress;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.BootstrapDNS, v => v.cmbBootstrapDNS.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Strategy4Freedom, v => v.cmbDirectDNSStrategy.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Strategy4Proxy, v => v.cmbRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ParallelQuery, v => v.togParallelQuery.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ServeStale, v => v.togServeStale.IsChecked).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.RayCustomDNSEnableCompatible, v => v.togRayCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SBCustomDNSEnableCompatible, v => v.togSBCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.UseSystemHostsCompatible, v => v.togUseSystemHostsCompatible.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.NormalDNS2Compatible, v => v.txtnormalDNS2Compatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunDNS2Compatible, v => v.txttunDNS2Compatible.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables);\n\n            this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)\n                .Select(b => b ? Visibility.Collapsed : Visibility.Visible)\n                .BindTo(this, x => x.txtBasicDNSSettingsInvalid.Visibility)\n                .DisposeWith(disposables);\n            this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)\n                .Select(b => b ? Visibility.Collapsed : Visibility.Visible)\n                .BindTo(this, x => x.txtAdvancedDNSSettingsInvalid.Visibility)\n                .DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridBasicDNSSettings.IsEnabled).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridAdvancedDNSSettings.IsEnabled).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void linkDnsObjectDoc_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://xtls.github.io/config/dns.html#dnsobject\");\n    }\n\n    private void linkDnsSingboxObjectDoc_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://sing-box.sagernet.org/zh/configuration/dns/\");\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.FullConfigTemplateWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuFullConfigTemplate}\"\n    Width=\"1000\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:FullConfigTemplateViewModel\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <TabControl HorizontalContentAlignment=\"Left\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.TbRayFullConfigTemplate}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <Grid DockPanel.Dock=\"Top\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbFullConfigTemplateDesc}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\">\n                            <Hyperlink Click=\"linkFullConfigTemplateDoc_Click\">\n                                <TextBlock Text=\"{x:Static resx:ResUI.TbRayFullConfigTemplateDesc}\" />\n                                <materialDesign:PackIcon Kind=\"Link\" />\n                            </Hyperlink>\n                        </TextBlock>\n\n                        <StackPanel Grid.Row=\"2\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbFullConfigTemplateEnable}\" />\n                            <ToggleButton\n                                x:Name=\"rayFullConfigTemplateEnable\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}\" />\n                            <ToggleButton\n                                x:Name=\"togAddProxyProtocolOutboundOnly4Ray\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSetUpstreamProxyDetour}\" />\n                            <TextBox\n                                x:Name=\"txtProxyDetour4Ray\"\n                                Width=\"200\"\n                                Margin=\"{StaticResource Margin8}\"\n                                Style=\"{StaticResource DefTextBox}\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <TextBox\n                        x:Name=\"rayFullConfigTemplate\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Stretch\"\n                        materialDesign:HintAssist.Hint=\"xray config template json\"\n                        AcceptsReturn=\"True\"\n                        BorderThickness=\"1\"\n                        Style=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                        TextWrapping=\"Wrap\"\n                        VerticalScrollBarVisibility=\"Auto\" />\n                </DockPanel>\n            </TabItem>\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.TbSBFullConfigTemplate}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <Grid DockPanel.Dock=\"Top\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbFullConfigTemplateDesc}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\">\n                            <Hyperlink Click=\"linkFullConfigTemplateDoc_Click\">\n                                <TextBlock Text=\"{x:Static resx:ResUI.TbSBFullConfigTemplateDesc}\" />\n                                <materialDesign:PackIcon Kind=\"Link\" />\n                            </Hyperlink>\n                        </TextBlock>\n\n                        <StackPanel Grid.Row=\"2\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbFullConfigTemplateEnable}\" />\n                            <ToggleButton\n                                x:Name=\"sbFullConfigTemplateEnable\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}\" />\n                            <ToggleButton\n                                x:Name=\"togAddProxyProtocolOutboundOnly4Singbox\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSetUpstreamProxyDetour}\" />\n                            <TextBox\n                                x:Name=\"txtProxyDetour4Singbox\"\n                                Width=\"200\"\n                                Margin=\"{StaticResource Margin8}\"\n                                Style=\"{StaticResource DefTextBox}\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <Grid Margin=\"{StaticResource Margin8}\">\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"1*\" />\n                            <ColumnDefinition Width=\"10\" />\n                            <ColumnDefinition Width=\"1*\" />\n                        </Grid.ColumnDefinitions>\n\n                        <TextBox\n                            x:Name=\"sbFullConfigTemplate\"\n                            Grid.Column=\"0\"\n                            VerticalAlignment=\"Stretch\"\n                            materialDesign:HintAssist.Hint=\"sing-box config template json\"\n                            AcceptsReturn=\"True\"\n                            BorderThickness=\"1\"\n                            Style=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                            TextWrapping=\"Wrap\"\n                            VerticalScrollBarVisibility=\"Auto\" />\n\n                        <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n\n                        <TextBox\n                            x:Name=\"sbFullTunConfigTemplate\"\n                            Grid.Column=\"2\"\n                            VerticalAlignment=\"Stretch\"\n                            materialDesign:HintAssist.Hint=\"sing-box tun config template json\"\n                            AcceptsReturn=\"True\"\n                            BorderThickness=\"1\"\n                            Style=\"{StaticResource MaterialDesignOutlinedTextBox}\"\n                            TextWrapping=\"Wrap\"\n                            VerticalScrollBarVisibility=\"Auto\" />\n                    </Grid>\n                </DockPanel>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/FullConfigTemplateWindow.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class FullConfigTemplateWindow\n{\n    private static Config _config;\n\n    public FullConfigTemplateWindow()\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        _config = AppManager.Instance.Config;\n\n        ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FullConfigTemplate4Singbox, v => v.sbFullConfigTemplate.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Singbox, v => v.sbFullTunConfigTemplate.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AddProxyOnly4Singbox, v => v.togAddProxyProtocolOutboundOnly4Singbox.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ProxyDetour4Singbox, v => v.txtProxyDetour4Singbox.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void linkFullConfigTemplateDoc_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://github.com/2dust/v2rayN/wiki/Description-of-some-ui#%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE%E6%A8%A1%E6%9D%BF%E8%AE%BE%E7%BD%AE\");\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.GlobalHotkeySettingWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuGlobalHotkeySetting}\"\n    Width=\"700\"\n    Height=\"500\"\n    x:TypeArguments=\"vms:GlobalHotkeySettingViewModel\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnReset\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbReset}\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n        <ScrollViewer\n            materialDesign:ScrollViewerAssist.IsAutoHideEnabled=\"True\"\n            HorizontalScrollBarVisibility=\"Auto\"\n            VerticalScrollBarVisibility=\"Auto\">\n            <Grid>\n                <Grid.RowDefinitions>\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                </Grid.RowDefinitions>\n                <Grid x:Name=\"gridText\" Grid.Row=\"0\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"400\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Style=\"{StaticResource ModuleTitle}\"\n                        Text=\"{x:Static resx:ResUI.TbGlobalHotkeySetting}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbDisplayGUI}\" />\n\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey0\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        AcceptsReturn=\"True\"\n                        IsReadOnly=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbClearSystemProxy}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey1\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        AcceptsReturn=\"True\"\n                        IsReadOnly=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSetSystemProxy}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey2\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        AcceptsReturn=\"True\"\n                        IsReadOnly=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbNotChangeSystemProxy}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey3\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        AcceptsReturn=\"True\"\n                        IsReadOnly=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSystemProxyPac}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey4\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        AcceptsReturn=\"True\"\n                        IsReadOnly=\"True\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n                </Grid>\n\n                <TextBlock\n                    Grid.Row=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.TbGlobalHotkeySettingTip}\" />\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/GlobalHotkeySettingWindow.xaml.cs",
    "content": "using System.Windows.Controls;\nusing v2rayN.Manager;\n\nnamespace v2rayN.Views;\n\npublic partial class GlobalHotkeySettingWindow\n{\n    private readonly List<object> _textBoxKeyEventItem = new();\n\n    public GlobalHotkeySettingWindow()\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n\n        ViewModel = new GlobalHotkeySettingViewModel(UpdateViewHandler);\n\n        btnReset.Click += btnReset_Click;\n\n        HotkeyManager.Instance.IsPause = true;\n        Closing += (s, e) => HotkeyManager.Instance.IsPause = false;\n\n        this.WhenActivated(disposables =>\n        {\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n\n        Init();\n        BindingData();\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Init()\n    {\n        _textBoxKeyEventItem.Add(txtGlobalHotkey0);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey1);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey2);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey3);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey4);\n\n        for (var index = 0; index < _textBoxKeyEventItem.Count; index++)\n        {\n            var sender = _textBoxKeyEventItem[index];\n            if (sender is not TextBox txtBox)\n            {\n                continue;\n            }\n            txtBox.Tag = (EGlobalHotkey)index;\n            txtBox.PreviewKeyDown += TxtGlobalHotkey_PreviewKeyDown;\n        }\n    }\n\n    private void TxtGlobalHotkey_PreviewKeyDown(object? sender, KeyEventArgs e)\n    {\n        e.Handled = true;\n        if (sender is not TextBox txtBox)\n        {\n            return;\n        }\n\n        var item = ViewModel?.GetKeyEventItem((EGlobalHotkey)txtBox.Tag);\n        var modifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin };\n\n        item.KeyCode = (int)(e.Key == Key.System ? (modifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (modifierKeys.Contains(e.Key) ? Key.None : e.Key));\n        item.Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;\n        item.Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;\n        item.Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;\n\n        txtBox.Text = KeyEventItemToString(item);\n    }\n\n    private void BindingData()\n    {\n        foreach (var sender in _textBoxKeyEventItem)\n        {\n            if (sender is not TextBox txtBox)\n            {\n                continue;\n            }\n\n            var item = ViewModel?.GetKeyEventItem((EGlobalHotkey)txtBox.Tag);\n            txtBox.Text = KeyEventItemToString(item);\n        }\n    }\n\n    private void btnReset_Click(object sender, RoutedEventArgs e)\n    {\n        ViewModel?.ResetKeyEventItem();\n        BindingData();\n    }\n\n    private string KeyEventItemToString(KeyEventItem? item)\n    {\n        if (item == null)\n        {\n            return string.Empty;\n        }\n        var res = new StringBuilder();\n\n        if (item.Control)\n        {\n            res.Append($\"{ModifierKeys.Control} +\");\n        }\n\n        if (item.Shift)\n        {\n            res.Append($\"{ModifierKeys.Shift} +\");\n        }\n\n        if (item.Alt)\n        {\n            res.Append($\"{ModifierKeys.Alt} +\");\n        }\n\n        if (item.KeyCode != null && (Key)item.KeyCode != Key.None)\n        {\n            res.Append($\"{(Key)item.KeyCode}\");\n        }\n\n        return res.ToString();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/MainWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.MainWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:view=\"clr-namespace:v2rayN.Views\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"v2rayN\"\n    Width=\"1200\"\n    Height=\"800\"\n    MinWidth=\"800\"\n    x:TypeArguments=\"vms:MainWindowViewModel\"\n    Icon=\"/Resources/v2rayN.ico\"\n    ResizeMode=\"CanResizeWithGrip\"\n    ShowInTaskbar=\"True\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <Window.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceDictionary Source=\"pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Popupbox.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n            <BooleanToVisibilityConverter x:Key=\"BoolToVisConverter\" />\n        </ResourceDictionary>\n    </Window.Resources>\n\n    <materialDesign:DialogHost\n        materialDesign:TransitionAssist.DisableTransitions=\"True\"\n        CloseOnClickAway=\"True\"\n        Identifier=\"RootDialog\"\n        SnackbarMessageQueue=\"{Binding ElementName=MainSnackbar, Path=MessageQueue}\"\n        Style=\"{StaticResource MaterialDesignEmbeddedDialogHost}\">\n        <Grid>\n            <DockPanel>\n                <ToolBarTray DockPanel.Dock=\"Top\">\n                    <ToolBar\n                        HorizontalAlignment=\"Center\"\n                        VerticalAlignment=\"Center\"\n                        ClipToBounds=\"True\"\n                        KeyboardNavigation.TabNavigation=\"Continue\"\n                        Style=\"{StaticResource MaterialDesignToolBar}\">\n                        <Menu Margin=\"0,1\" Style=\"{StaticResource ToolbarMenu}\">\n                            <MenuItem Padding=\"{StaticResource MarginLeftRight8}\" AutomationProperties.Name=\"{x:Static resx:ResUI.menuServers}\">\n                                <MenuItem.Header>\n                                    <StackPanel Orientation=\"Horizontal\">\n                                        <materialDesign:PackIcon\n                                            Margin=\"{StaticResource MarginRight8}\"\n                                            VerticalAlignment=\"Center\"\n                                            Kind=\"Server\" />\n                                        <TextBlock Text=\"{x:Static resx:ResUI.menuServers}\" />\n                                    </StackPanel>\n                                </MenuItem.Header>\n                                <MenuItem\n                                    x:Name=\"menuAddServerViaClipboard\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddServerViaClipboard}\"\n                                    InputGestureText=\"Ctrl+V\" />\n                                <MenuItem\n                                    x:Name=\"menuAddServerViaScan\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddServerViaScan}\"\n                                    InputGestureText=\"Ctrl+S\" />\n                                <MenuItem\n                                    x:Name=\"menuAddServerViaImage\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddServerViaImage}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddCustomServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddCustomServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddPolicyGroupServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddPolicyGroupServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddProxyChainServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddProxyChainServer}\" />\n                                <Separator Margin=\"-40,5\" />\n                                <MenuItem\n                                    x:Name=\"menuAddVmessServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddVmessServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddVlessServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddVlessServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddShadowsocksServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddShadowsocksServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddTrojanServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddTrojanServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddHysteria2Server\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddHysteria2Server}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddWireguardServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddWireguardServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddSocksServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddSocksServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddHttpServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddHttpServer}\" />\n                                <Separator Margin=\"-40,5\" />\n                                <MenuItem\n                                    x:Name=\"menuAddTuicServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddTuicServer}\" />\n                                <MenuItem\n                                    x:Name=\"menuAddAnytlsServer\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuAddAnytlsServer}\" />\n                            </MenuItem>\n                        </Menu>\n                        <Separator />\n                        <Menu Margin=\"0,1\" Style=\"{StaticResource ToolbarMenu}\">\n                            <MenuItem Padding=\"{StaticResource MarginLeftRight8}\" AutomationProperties.Name=\"{x:Static resx:ResUI.menuSubscription}\">\n                                <MenuItem.Header>\n                                    <StackPanel Orientation=\"Horizontal\">\n                                        <materialDesign:PackIcon\n                                            Margin=\"{StaticResource MarginRight8}\"\n                                            VerticalAlignment=\"Center\"\n                                            Kind=\"BookClockOutline\" />\n                                        <TextBlock Text=\"{x:Static resx:ResUI.menuSubscription}\" />\n                                    </StackPanel>\n                                </MenuItem.Header>\n                                <MenuItem\n                                    x:Name=\"menuSubSetting\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuSubSetting}\" />\n                                <Separator Margin=\"-40,5\" />\n                                <MenuItem\n                                    x:Name=\"menuSubUpdate\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuSubUpdate}\" />\n                                <MenuItem\n                                    x:Name=\"menuSubUpdateViaProxy\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuSubUpdateViaProxy}\" />\n                                <MenuItem\n                                    x:Name=\"menuSubGroupUpdate\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuSubGroupUpdate}\" />\n                                <MenuItem\n                                    x:Name=\"menuSubGroupUpdateViaProxy\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuSubGroupUpdateViaProxy}\" />\n                            </MenuItem>\n                        </Menu>\n                        <Separator />\n                        <Menu Margin=\"0,1\" Style=\"{StaticResource ToolbarMenu}\">\n                            <MenuItem Padding=\"{StaticResource MarginLeftRight8}\" AutomationProperties.Name=\"{x:Static resx:ResUI.menuSetting}\">\n                                <MenuItem.Header>\n                                    <StackPanel Orientation=\"Horizontal\">\n                                        <materialDesign:PackIcon\n                                            Margin=\"{StaticResource MarginRight8}\"\n                                            VerticalAlignment=\"Center\"\n                                            Kind=\"SettingsOutline\" />\n                                        <TextBlock Text=\"{x:Static resx:ResUI.menuSetting}\" />\n                                    </StackPanel>\n                                </MenuItem.Header>\n                                <MenuItem\n                                    x:Name=\"menuOptionSetting\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuOptionSetting}\" />\n                                <MenuItem\n                                    x:Name=\"menuRoutingSetting\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuRoutingSetting}\" />\n                                <MenuItem\n                                    x:Name=\"menuDNSSetting\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuDNSSetting}\" />\n                                <MenuItem\n                                    x:Name=\"menuFullConfigTemplate\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuFullConfigTemplate}\" />\n                                <MenuItem\n                                    x:Name=\"menuGlobalHotkeySetting\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuGlobalHotkeySetting}\" />\n                                <Separator Margin=\"-40,5\" />\n                                <MenuItem\n                                    x:Name=\"menuRebootAsAdmin\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuRebootAsAdmin}\" />\n                                <MenuItem\n                                    x:Name=\"menuSettingsSetUWP\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.TbSettingsSetUWP}\" />\n                                <MenuItem\n                                    x:Name=\"menuClearServerStatistics\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuClearServerStatistics}\" />\n                                <Separator Margin=\"-40,5\" />\n                                <MenuItem Height=\"{StaticResource MenuItemHeight}\" Header=\"{x:Static resx:ResUI.menuRegionalPresets}\">\n                                    <MenuItem\n                                        x:Name=\"menuRegionalPresetsDefault\"\n                                        Height=\"{StaticResource MenuItemHeight}\"\n                                        Header=\"{x:Static resx:ResUI.menuRegionalPresetsDefault}\" />\n                                    <MenuItem\n                                        x:Name=\"menuRegionalPresetsRussia\"\n                                        Height=\"{StaticResource MenuItemHeight}\"\n                                        Header=\"{x:Static resx:ResUI.menuRegionalPresetsRussia}\" />\n                                    <MenuItem\n                                        x:Name=\"menuRegionalPresetsIran\"\n                                        Height=\"{StaticResource MenuItemHeight}\"\n                                        Header=\"{x:Static resx:ResUI.menuRegionalPresetsIran}\" />\n                                </MenuItem>\n                                <MenuItem\n                                    x:Name=\"menuBackupAndRestore\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuBackupAndRestore}\" />\n                                <MenuItem\n                                    x:Name=\"menuOpenTheFileLocation\"\n                                    Height=\"{StaticResource MenuItemHeight}\"\n                                    Header=\"{x:Static resx:ResUI.menuOpenTheFileLocation}\" />\n                            </MenuItem>\n                        </Menu>\n                        <Separator />\n                        <Menu Margin=\"0,1\" Style=\"{StaticResource ToolbarMenu}\">\n                            <MenuItem\n                                x:Name=\"menuHelp\"\n                                Padding=\"{StaticResource MarginLeftRight8}\"\n                                AutomationProperties.Name=\"{x:Static resx:ResUI.menuHelp}\">\n                                <MenuItem.Header>\n                                    <StackPanel Orientation=\"Horizontal\">\n                                        <materialDesign:PackIcon\n                                            Margin=\"{StaticResource MarginRight8}\"\n                                            VerticalAlignment=\"Center\"\n                                            Kind=\"HelpCircleOutline\" />\n                                        <TextBlock Text=\"{x:Static resx:ResUI.menuHelp}\" />\n                                    </StackPanel>\n                                </MenuItem.Header>\n                                <MenuItem x:Name=\"menuCheckUpdate\" Header=\"{x:Static resx:ResUI.menuCheckUpdate}\" />\n                                <Separator Margin=\"-40,5\" />\n                            </MenuItem>\n                        </Menu>\n                        <Separator />\n                        <Menu Margin=\"0,1\" Style=\"{StaticResource ToolbarMenu}\">\n                            <MenuItem\n                                x:Name=\"menuReload\"\n                                Padding=\"{StaticResource MarginLeftRight8}\"\n                                AutomationProperties.Name=\"{x:Static resx:ResUI.menuReload}\">\n                                <MenuItem.Header>\n                                    <StackPanel Orientation=\"Horizontal\">\n                                        <materialDesign:PackIcon\n                                            Margin=\"{StaticResource MarginRight8}\"\n                                            VerticalAlignment=\"Center\"\n                                            Kind=\"Reload\" />\n                                        <TextBlock Text=\"{x:Static resx:ResUI.menuReload}\" />\n                                    </StackPanel>\n                                </MenuItem.Header>\n                            </MenuItem>\n                        </Menu>\n                        <Separator />\n                        <Menu Margin=\"0,1\" Style=\"{StaticResource ToolbarMenu}\">\n                            <MenuItem\n                                x:Name=\"menuPromotion\"\n                                Padding=\"{StaticResource MarginLeftRight8}\"\n                                AutomationProperties.Name=\"{x:Static resx:ResUI.menuPromotion}\">\n                                <MenuItem.Header>\n                                    <StackPanel Orientation=\"Horizontal\">\n                                        <materialDesign:PackIcon\n                                            Margin=\"{StaticResource MarginRight8}\"\n                                            VerticalAlignment=\"Center\"\n                                            Kind=\"VolumeHigh\" />\n                                        <TextBlock Text=\"{x:Static resx:ResUI.menuPromotion}\" />\n                                    </StackPanel>\n                                </MenuItem.Header>\n                            </MenuItem>\n                        </Menu>\n                        <Separator />\n                        <Menu Margin=\"0,1\" Style=\"{StaticResource ToolbarMenu}\">\n                            <MenuItem\n                                x:Name=\"menuClose\"\n                                Padding=\"{StaticResource MarginLeftRight8}\"\n                                AutomationProperties.Name=\"{x:Static resx:ResUI.menuClose}\">\n                                <MenuItem.Header>\n                                    <StackPanel Orientation=\"Horizontal\">\n                                        <materialDesign:PackIcon\n                                            Margin=\"{StaticResource MarginRight8}\"\n                                            VerticalAlignment=\"Center\"\n                                            Kind=\"Minimize\" />\n                                        <TextBlock Text=\"{x:Static resx:ResUI.menuClose}\" />\n                                    </StackPanel>\n                                </MenuItem.Header>\n                            </MenuItem>\n                        </Menu>\n\n                        <materialDesign:PopupBox\n                            Padding=\"-2\"\n                            HorizontalAlignment=\"Right\"\n                            StaysOpen=\"True\"\n                            Style=\"{StaticResource MaterialDesignToolForegroundPopupBox}\">\n                            <ContentControl x:Name=\"pbTheme\" />\n                        </materialDesign:PopupBox>\n                    </ToolBar>\n                </ToolBarTray>\n\n                <view:StatusBarView DockPanel.Dock=\"Bottom\" />\n\n                <Grid>\n                    <Grid x:Name=\"gridMain\" Visibility=\"Collapsed\">\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"1*\" />\n                            <ColumnDefinition Width=\"10\" />\n                            <ColumnDefinition Width=\"1*\" />\n                        </Grid.ColumnDefinitions>\n                        <ContentControl x:Name=\"tabProfiles\" Grid.Column=\"0\" />\n                        <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n                        <TabControl\n                            x:Name=\"tabMain\"\n                            Grid.Column=\"2\"\n                            HorizontalContentAlignment=\"Left\">\n                            <TabItem x:Name=\"tabMsgView\" Header=\"{x:Static resx:ResUI.MsgInformationTitle}\" />\n                            <TabItem x:Name=\"tabClashProxies\" Header=\"{x:Static resx:ResUI.TbProxies}\" />\n                            <TabItem x:Name=\"tabClashConnections\" Header=\"{x:Static resx:ResUI.TbConnections}\" />\n                        </TabControl>\n                    </Grid>\n                    <Grid x:Name=\"gridMain1\" Visibility=\"Collapsed\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"1*\" />\n                            <RowDefinition Height=\"10\" />\n                            <RowDefinition Height=\"1*\" />\n                        </Grid.RowDefinitions>\n                        <ContentControl x:Name=\"tabProfiles1\" Grid.Row=\"0\" />\n                        <GridSplitter Grid.Row=\"1\" HorizontalAlignment=\"Stretch\" />\n                        <TabControl\n                            x:Name=\"tabMain1\"\n                            Grid.Row=\"2\"\n                            materialDesign:NavigationRailAssist.ShowSelectionBackground=\"True\"\n                            Style=\"{StaticResource MaterialDesignNavigationRailTabControl}\"\n                            TabStripPlacement=\"Left\">\n                            <TabItem x:Name=\"tabMsgView1\">\n                                <TabItem.Header>\n                                    <StackPanel>\n                                        <materialDesign:PackIcon HorizontalAlignment=\"Center\" Kind=\"MessageTextOutline\" />\n                                        <TextBlock\n                                            HorizontalAlignment=\"Center\"\n                                            Style=\"{StaticResource ToolbarTextBlock}\"\n                                            Text=\"{x:Static resx:ResUI.MsgInformationTitle}\" />\n                                    </StackPanel>\n                                </TabItem.Header>\n                            </TabItem>\n                            <TabItem x:Name=\"tabClashProxies1\">\n                                <TabItem.Header>\n                                    <StackPanel>\n                                        <materialDesign:PackIcon HorizontalAlignment=\"Center\" Kind=\"ArrowDecisionOutline\" />\n                                        <TextBlock\n                                            HorizontalAlignment=\"Center\"\n                                            Style=\"{StaticResource ToolbarTextBlock}\"\n                                            Text=\"{x:Static resx:ResUI.TbProxies}\" />\n                                    </StackPanel>\n                                </TabItem.Header>\n                            </TabItem>\n                            <TabItem x:Name=\"tabClashConnections1\">\n                                <TabItem.Header>\n                                    <StackPanel>\n                                        <materialDesign:PackIcon HorizontalAlignment=\"Center\" Kind=\"LanConnect\" />\n                                        <TextBlock\n                                            HorizontalAlignment=\"Center\"\n                                            Style=\"{StaticResource ToolbarTextBlock}\"\n                                            Text=\"{x:Static resx:ResUI.TbConnections}\" />\n                                    </StackPanel>\n                                </TabItem.Header>\n                            </TabItem>\n                        </TabControl>\n                    </Grid>\n                    <Grid x:Name=\"gridMain2\" Visibility=\"Collapsed\">\n                        <TabControl\n                            x:Name=\"tabMain2\"\n                            materialDesign:NavigationRailAssist.ShowSelectionBackground=\"True\"\n                            Style=\"{StaticResource MaterialDesignNavigationRailTabControl}\"\n                            TabStripPlacement=\"Left\">\n                            <TabItem x:Name=\"tabProfiles2\">\n                                <TabItem.Header>\n                                    <StackPanel>\n                                        <materialDesign:PackIcon HorizontalAlignment=\"Center\" Kind=\"Server\" />\n                                        <TextBlock\n                                            HorizontalAlignment=\"Center\"\n                                            Style=\"{StaticResource ToolbarTextBlock}\"\n                                            Text=\"{x:Static resx:ResUI.menuServers}\" />\n                                    </StackPanel>\n                                </TabItem.Header>\n                            </TabItem>\n                            <TabItem x:Name=\"tabMsgView2\">\n                                <TabItem.Header>\n                                    <StackPanel>\n                                        <materialDesign:PackIcon HorizontalAlignment=\"Center\" Kind=\"MessageTextOutline\" />\n                                        <TextBlock\n                                            HorizontalAlignment=\"Center\"\n                                            Style=\"{StaticResource ToolbarTextBlock}\"\n                                            Text=\"{x:Static resx:ResUI.MsgInformationTitle}\" />\n                                    </StackPanel>\n                                </TabItem.Header>\n                            </TabItem>\n                            <TabItem x:Name=\"tabClashProxies2\">\n                                <TabItem.Header>\n                                    <StackPanel>\n                                        <materialDesign:PackIcon HorizontalAlignment=\"Center\" Kind=\"ArrowDecisionOutline\" />\n                                        <TextBlock\n                                            HorizontalAlignment=\"Center\"\n                                            Style=\"{StaticResource ToolbarTextBlock}\"\n                                            Text=\"{x:Static resx:ResUI.TbProxies}\" />\n                                    </StackPanel>\n                                </TabItem.Header>\n                            </TabItem>\n                            <TabItem x:Name=\"tabClashConnections2\">\n                                <TabItem.Header>\n                                    <StackPanel>\n                                        <materialDesign:PackIcon HorizontalAlignment=\"Center\" Kind=\"LanConnect\" />\n                                        <TextBlock\n                                            HorizontalAlignment=\"Center\"\n                                            Style=\"{StaticResource ToolbarTextBlock}\"\n                                            Text=\"{x:Static resx:ResUI.TbConnections}\" />\n                                    </StackPanel>\n                                </TabItem.Header>\n                            </TabItem>\n                        </TabControl>\n                    </Grid>\n                    <materialDesign:Snackbar x:Name=\"MainSnackbar\" MessageQueue=\"{materialDesign:MessageQueue}\" />\n                </Grid>\n            </DockPanel>\n        </Grid>\n    </materialDesign:DialogHost>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/MainWindow.xaml.cs",
    "content": "using System.Windows.Controls;\nusing System.Windows.Media;\nusing MaterialDesignThemes.Wpf;\nusing v2rayN.Manager;\n\nnamespace v2rayN.Views;\n\npublic partial class MainWindow\n{\n    private static Config _config;\n    private CheckUpdateView? _checkUpdateView;\n    private BackupAndRestoreView? _backupAndRestoreView;\n\n    public MainWindow()\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n        ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);\n\n        App.Current.SessionEnding += Current_SessionEnding;\n        Closing += MainWindow_Closing;\n        PreviewKeyDown += MainWindow_PreviewKeyDown;\n        menuSettingsSetUWP.Click += MenuSettingsSetUWP_Click;\n        menuPromotion.Click += MenuPromotion_Click;\n        menuClose.Click += MenuClose_Click;\n        menuCheckUpdate.Click += MenuCheckUpdate_Click;\n        menuBackupAndRestore.Click += MenuBackupAndRestore_Click;\n\n        ViewModel = new MainWindowViewModel(UpdateViewHandler);\n\n        switch (_config.UiItem.MainGirdOrientation)\n        {\n            case EGirdOrientation.Horizontal:\n                tabProfiles.Content ??= new ProfilesView();\n                tabMsgView.Content ??= new MsgView();\n                tabClashProxies.Content ??= new ClashProxiesView();\n                tabClashConnections.Content ??= new ClashConnectionsView();\n                gridMain.Visibility = Visibility.Visible;\n                break;\n\n            case EGirdOrientation.Vertical:\n                tabProfiles1.Content ??= new ProfilesView();\n                tabMsgView1.Content ??= new MsgView();\n                tabClashProxies1.Content ??= new ClashProxiesView();\n                tabClashConnections1.Content ??= new ClashConnectionsView();\n                gridMain1.Visibility = Visibility.Visible;\n                break;\n\n            case EGirdOrientation.Tab:\n            default:\n                tabProfiles2.Content ??= new ProfilesView();\n                tabMsgView2.Content ??= new MsgView();\n                tabClashProxies2.Content ??= new ClashProxiesView();\n                tabClashConnections2.Content ??= new ClashConnectionsView();\n                gridMain2.Visibility = Visibility.Visible;\n                break;\n        }\n        pbTheme.Content ??= new ThemeSettingView();\n\n        this.WhenActivated(disposables =>\n        {\n            //servers\n            this.BindCommand(ViewModel, vm => vm.AddVmessServerCmd, v => v.menuAddVmessServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddVlessServerCmd, v => v.menuAddVlessServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddShadowsocksServerCmd, v => v.menuAddShadowsocksServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddSocksServerCmd, v => v.menuAddSocksServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddHttpServerCmd, v => v.menuAddHttpServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddTrojanServerCmd, v => v.menuAddTrojanServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddPolicyGroupServerCmd, v => v.menuAddPolicyGroupServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddProxyChainServerCmd, v => v.menuAddProxyChainServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddServerViaImageCmd, v => v.menuAddServerViaImage).DisposeWith(disposables);\n\n            //sub\n            this.BindCommand(ViewModel, vm => vm.SubSettingCmd, v => v.menuSubSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubUpdateCmd, v => v.menuSubUpdate).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubGroupUpdateCmd, v => v.menuSubGroupUpdate).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubGroupUpdateViaProxyCmd, v => v.menuSubGroupUpdateViaProxy).DisposeWith(disposables);\n\n            //setting\n            this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.FullConfigTemplateCmd, v => v.menuFullConfigTemplate).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RegionalPresetIranCmd, v => v.menuRegionalPresetsIran).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);\n\n            switch (_config.UiItem.MainGirdOrientation)\n            {\n                case EGirdOrientation.Horizontal:\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView.Visibility).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.Visibility).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.Visibility).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);\n                    break;\n\n                case EGirdOrientation.Vertical:\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView1.Visibility).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies1.Visibility).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections1.Visibility).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain1.SelectedIndex).DisposeWith(disposables);\n                    break;\n\n                case EGirdOrientation.Tab:\n                default:\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies2.Visibility).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections2.Visibility).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain2.SelectedIndex).DisposeWith(disposables);\n                    break;\n            }\n\n            AppEvents.SendSnackMsgRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(async content => await DelegateSnackMsg(content))\n              .DisposeWith(disposables);\n\n            AppEvents.AppExitRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(_ => StorageUI())\n              .DisposeWith(disposables);\n\n            AppEvents.ShutdownRequested\n             .AsObservable()\n             .ObserveOn(RxSchedulers.MainThreadScheduler)\n             .Subscribe(content => Shutdown(content))\n             .DisposeWith(disposables);\n\n            AppEvents.ShowHideWindowRequested\n             .AsObservable()\n             .ObserveOn(RxSchedulers.MainThreadScheduler)\n             .Subscribe(blShow => ShowHideWindow(blShow))\n             .DisposeWith(disposables);\n        });\n\n        Title = $\"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}\";\n        if (_config.UiItem.AutoHideStartup)\n        {\n            WindowState = WindowState.Minimized;\n        }\n\n        if (!_config.GuiItem.EnableHWA)\n        {\n            RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;\n        }\n\n        AddHelpMenuItem();\n        WindowsManager.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);\n    }\n\n    #region Event\n\n    private void OnProgramStarted(object state, bool timeout)\n    {\n        Application.Current?.Dispatcher.Invoke((Action)(() =>\n        {\n            ShowHideWindow(true);\n        }));\n    }\n\n    private async Task DelegateSnackMsg(string content)\n    {\n        MainSnackbar.MessageQueue?.Enqueue(content);\n        await Task.CompletedTask;\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.AddServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new AddServerWindow((ProfileItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.AddServer2Window:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new AddServer2Window((ProfileItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.AddGroupServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new AddGroupServerWindow((ProfileItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.DNSSettingWindow:\n                return new DNSSettingWindow().ShowDialog() ?? false;\n\n            case EViewAction.RoutingSettingWindow:\n                return new RoutingSettingWindow().ShowDialog() ?? false;\n\n            case EViewAction.OptionSettingWindow:\n                return new OptionSettingWindow().ShowDialog() ?? false;\n\n            case EViewAction.FullConfigTemplateWindow:\n                return new FullConfigTemplateWindow().ShowDialog() ?? false;\n\n            case EViewAction.GlobalHotkeySettingWindow:\n                return new GlobalHotkeySettingWindow().ShowDialog() ?? false;\n\n            case EViewAction.SubSettingWindow:\n                return new SubSettingWindow().ShowDialog() ?? false;\n\n            case EViewAction.ScanScreenTask:\n                await ScanScreenTaskAsync();\n                break;\n\n            case EViewAction.ScanImageTask:\n                await ScanImageTaskAsync();\n                break;\n\n            case EViewAction.AddServerViaClipboard:\n                await AddServerViaClipboardAsync();\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    private void OnHotkeyHandler(EGlobalHotkey e)\n    {\n        switch (e)\n        {\n            case EGlobalHotkey.ShowForm:\n                ShowHideWindow(null);\n                break;\n\n            case EGlobalHotkey.SystemProxyClear:\n            case EGlobalHotkey.SystemProxySet:\n            case EGlobalHotkey.SystemProxyUnchanged:\n            case EGlobalHotkey.SystemProxyPac:\n                AppEvents.SysProxyChangeRequested.Publish((ESysProxyType)((int)e - 1));\n                break;\n        }\n    }\n\n    private void MainWindow_Closing(object? sender, CancelEventArgs e)\n    {\n        e.Cancel = true;\n        ShowHideWindow(false);\n    }\n\n    private async void Current_SessionEnding(object sender, SessionEndingCancelEventArgs e)\n    {\n        Logging.SaveLog(\"Current_SessionEnding\");\n        StorageUI();\n        await AppManager.Instance.AppExitAsync(false);\n    }\n\n    private void Shutdown(bool obj)\n    {\n        Application.Current.Shutdown();\n    }\n\n    private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))\n        {\n            switch (e.Key)\n            {\n                case Key.V:\n                    if (Keyboard.FocusedElement is TextBox)\n                    {\n                        return;\n                    }\n                    AddServerViaClipboardAsync().ContinueWith(_ => { });\n\n                    break;\n\n                case Key.S:\n                    ScanScreenTaskAsync().ContinueWith(_ => { });\n                    break;\n            }\n        }\n        else\n        {\n            if (e.Key == Key.F5)\n            {\n                ViewModel?.Reload();\n            }\n        }\n    }\n\n    private void MenuClose_Click(object sender, RoutedEventArgs e)\n    {\n        StorageUI();\n        ShowHideWindow(false);\n    }\n\n    private void MenuPromotion_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart($\"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}\");\n    }\n\n    private void MenuSettingsSetUWP_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(Utils.GetBinPath(\"EnableLoopback.exe\"));\n    }\n\n    public async Task AddServerViaClipboardAsync()\n    {\n        var clipboardData = WindowsUtils.GetClipboardData();\n        if (clipboardData.IsNotEmpty() && ViewModel != null)\n        {\n            await ViewModel.AddServerViaClipboardAsync(clipboardData);\n        }\n    }\n\n    private async Task ScanScreenTaskAsync()\n    {\n        ShowHideWindow(false);\n\n        if (Application.Current?.MainWindow is Window window)\n        {\n            var bytes = QRCodeWindowsUtils.CaptureScreen(window);\n            await ViewModel?.ScanScreenResult(bytes);\n        }\n\n        ShowHideWindow(true);\n    }\n\n    private async Task ScanImageTaskAsync()\n    {\n        if (UI.OpenFileDialog(out var fileName, \"PNG|*.png|All|*.*\") != true)\n        {\n            return;\n        }\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n        await ViewModel?.ScanImageResult(fileName);\n    }\n\n    private void MenuCheckUpdate_Click(object sender, RoutedEventArgs e)\n    {\n        _checkUpdateView ??= new CheckUpdateView();\n        DialogHost.Show(_checkUpdateView, \"RootDialog\");\n    }\n\n    private void MenuBackupAndRestore_Click(object sender, RoutedEventArgs e)\n    {\n        _backupAndRestoreView ??= new BackupAndRestoreView();\n        DialogHost.Show(_backupAndRestoreView, \"RootDialog\");\n    }\n\n    #endregion Event\n\n    #region UI\n\n    public void ShowHideWindow(bool? blShow)\n    {\n        var bl = blShow ?? !AppManager.Instance.ShowInTaskbar;\n        if (bl)\n        {\n            this?.Show();\n            if (this?.WindowState == WindowState.Minimized)\n            {\n                WindowState = WindowState.Normal;\n            }\n            this?.Activate();\n            this?.Focus();\n        }\n        else\n        {\n            this?.Hide();\n        }\n        AppManager.Instance.ShowInTaskbar = bl;\n    }\n\n    protected override void OnLoaded(object? sender, RoutedEventArgs e)\n    {\n        base.OnLoaded(sender, e);\n        if (_config.UiItem.AutoHideStartup)\n        {\n            ShowHideWindow(false);\n        }\n        RestoreUI();\n    }\n\n    private void RestoreUI()\n    {\n        if (_config.UiItem.MainGirdHeight1 > 0 && _config.UiItem.MainGirdHeight2 > 0)\n        {\n            if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)\n            {\n                gridMain.ColumnDefinitions[0].Width = new GridLength(_config.UiItem.MainGirdHeight1, GridUnitType.Star);\n                gridMain.ColumnDefinitions[2].Width = new GridLength(_config.UiItem.MainGirdHeight2, GridUnitType.Star);\n            }\n            else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)\n            {\n                gridMain1.RowDefinitions[0].Height = new GridLength(_config.UiItem.MainGirdHeight1, GridUnitType.Star);\n                gridMain1.RowDefinitions[2].Height = new GridLength(_config.UiItem.MainGirdHeight2, GridUnitType.Star);\n            }\n        }\n    }\n\n    private void StorageUI()\n    {\n        ConfigHandler.SaveWindowSizeItem(_config, GetType().Name, Width, Height);\n\n        if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)\n        {\n            ConfigHandler.SaveMainGirdHeight(_config, gridMain.ColumnDefinitions[0].ActualWidth, gridMain.ColumnDefinitions[2].ActualWidth);\n        }\n        else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)\n        {\n            ConfigHandler.SaveMainGirdHeight(_config, gridMain1.RowDefinitions[0].ActualHeight, gridMain1.RowDefinitions[2].ActualHeight);\n        }\n    }\n\n    private void AddHelpMenuItem()\n    {\n        var coreInfo = CoreInfoManager.Instance.GetCoreInfo();\n        foreach (var it in coreInfo\n            .Where(t => t.CoreType is not ECoreType.v2fly\n                        and not ECoreType.hysteria))\n        {\n            var item = new MenuItem()\n            {\n                Tag = it.Url.Replace(@\"/releases\", \"\"),\n                Header = string.Format(ResUI.menuWebsiteItem, it.CoreType.ToString().Replace(\"_\", \" \")).UpperFirstChar()\n            };\n            item.Click += MenuItem_Click;\n            menuHelp.Items.Add(item);\n        }\n    }\n\n    private void MenuItem_Click(object sender, RoutedEventArgs e)\n    {\n        if (sender is MenuItem item)\n        {\n            ProcUtils.ProcessStart(item.Tag.ToString());\n        }\n    }\n\n    #endregion UI\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/MsgView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.MsgView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:MsgViewModel\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin4}\">\n        <WrapPanel\n            Margin=\"{StaticResource Margin8}\"\n            VerticalAlignment=\"Center\"\n            DockPanel.Dock=\"Top\"\n            Orientation=\"Horizontal\">\n\n            <ComboBox\n                x:Name=\"cmbMsgFilter\"\n                Width=\"200\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.MsgFilterTitle}\"\n                materialDesign:TextFieldAssist.HasClearButton=\"True\"\n                AutomationProperties.Name=\"{x:Static resx:ResUI.MsgFilterTitle}\"\n                IsEditable=\"True\"\n                Style=\"{StaticResource DefComboBox}\" />\n            <Button\n                x:Name=\"btnCopy\"\n                Width=\"24\"\n                Height=\"24\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                AutomationProperties.Name=\"{x:Static resx:ResUI.menuMsgViewCopyAll}\"\n                Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                ToolTip=\"{x:Static resx:ResUI.menuMsgViewCopyAll}\">\n                <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"ContentCopy\" />\n            </Button>\n            <Button\n                x:Name=\"btnClear\"\n                Width=\"24\"\n                Height=\"24\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                AutomationProperties.Name=\"{x:Static resx:ResUI.menuMsgViewClear}\"\n                Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                ToolTip=\"{x:Static resx:ResUI.menuMsgViewClear}\">\n                <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"Delete\" />\n            </Button>\n            <TextBlock\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbAutoRefresh}\" />\n            <ToggleButton\n                x:Name=\"togAutoRefresh\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                HorizontalAlignment=\"Left\"\n                AutomationProperties.Name=\"{x:Static resx:ResUI.TbAutoRefresh}\"\n                IsChecked=\"True\" />\n            <TextBlock\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbAutoScrollToEnd}\" />\n            <ToggleButton\n                x:Name=\"togScrollToEnd\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                HorizontalAlignment=\"Left\"\n                AutomationProperties.Name=\"{x:Static resx:ResUI.TbAutoScrollToEnd}\"\n                IsChecked=\"True\" />\n        </WrapPanel>\n        <TextBox\n            Name=\"txtMsg\"\n            VerticalAlignment=\"Stretch\"\n            AcceptsReturn=\"True\"\n            BorderThickness=\"0\"\n            FontSize=\"{DynamicResource StdFontSize-1}\"\n            HorizontalScrollBarVisibility=\"Auto\"\n            IsReadOnly=\"True\"\n            IsReadOnlyCaretVisible=\"True\"\n            IsUndoEnabled=\"False\"\n            TextAlignment=\"Left\"\n            TextWrapping=\"Wrap\"\n            UndoLimit=\"0\"\n            VerticalScrollBarVisibility=\"Visible\">\n            <TextBox.ContextMenu>\n                <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                    <MenuItem\n                        x:Name=\"menuMsgViewSelectAll\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuMsgViewSelectAll}\"\n                        InputGestureText=\"Ctrl+A\" />\n                    <MenuItem\n                        x:Name=\"menuMsgViewCopy\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuMsgViewCopy}\"\n                        InputGestureText=\"Ctrl+C\" />\n                    <MenuItem\n                        x:Name=\"menuMsgViewCopyAll\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuMsgViewCopyAll}\" />\n                    <MenuItem\n                        x:Name=\"menuMsgViewClear\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuMsgViewClear}\" />\n                </ContextMenu>\n            </TextBox.ContextMenu>\n        </TextBox>\n    </DockPanel>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/MsgView.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class MsgView\n{\n    public MsgView()\n    {\n        InitializeComponent();\n\n        ViewModel = new MsgViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.MsgFilter, v => v.cmbMsgFilter.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);\n        });\n\n        btnCopy.Click += menuMsgViewCopyAll_Click;\n        btnClear.Click += menuMsgViewClear_Click;\n        menuMsgViewSelectAll.Click += menuMsgViewSelectAll_Click;\n        menuMsgViewCopy.Click += menuMsgViewCopy_Click;\n        menuMsgViewCopyAll.Click += menuMsgViewCopyAll_Click;\n        menuMsgViewClear.Click += menuMsgViewClear_Click;\n\n        cmbMsgFilter.ItemsSource = Global.PresetMsgFilters;\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.DispatcherShowMsg:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                Application.Current?.Dispatcher.Invoke(() =>\n                {\n                    ShowMsg(obj);\n                }, DispatcherPriority.ApplicationIdle);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void ShowMsg(object msg)\n    {\n        if (txtMsg.LineCount > ViewModel?.NumMaxMsg)\n        {\n            ClearMsg();\n        }\n\n        txtMsg.AppendText(msg.ToString());\n        if (togScrollToEnd.IsChecked ?? true)\n        {\n            txtMsg.ScrollToEnd();\n        }\n    }\n\n    public void ClearMsg()\n    {\n        txtMsg.Clear();\n        txtMsg.AppendText(\"----- Message cleared -----\\n\");\n    }\n\n    private void menuMsgViewSelectAll_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        txtMsg.Focus();\n        txtMsg.SelectAll();\n    }\n\n    private void menuMsgViewCopy_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        var data = txtMsg.SelectedText.TrimEx();\n        WindowsUtils.SetClipboardData(data);\n    }\n\n    private void menuMsgViewCopyAll_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        var data = txtMsg.Text;\n        WindowsUtils.SetClipboardData(data);\n    }\n\n    private void menuMsgViewClear_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        ClearMsg();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/OptionSettingWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.OptionSettingWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuSetting}\"\n    Width=\"1000\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:OptionSettingViewModel\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <TabControl HorizontalContentAlignment=\"Left\">\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsCore}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid Margin=\"{StaticResource Margin8}\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"*\" />\n                        </Grid.ColumnDefinitions>\n\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSocksPort}\" />\n                        <TextBox\n                            x:Name=\"txtlocalPort\"\n                            Grid.Row=\"0\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource DefTextBox}\" />\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSocksPortTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSecondLocalPortEnabled}\" />\n                        <ToggleButton\n                            x:Name=\"togSecondLocalPortEnabled\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsUdpEnabled}\" />\n                        <ToggleButton\n                            x:Name=\"togudpEnabled\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSniffingEnabled}\" />\n                        <ToggleButton\n                            x:Name=\"togsniffingEnabled\"\n                            Grid.Row=\"4\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDestOverride}\" />\n                        <ListBox\n                            x:Name=\"clbdestOverride\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Grid.ColumnSpan=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            FontSize=\"{DynamicResource StdFontSize}\"\n                            Style=\"{StaticResource MaterialDesignFilterChipPrimaryListBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsRouteOnly}\" />\n                        <ToggleButton\n                            x:Name=\"togrouteOnly\"\n                            Grid.Row=\"6\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"7\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsAllowLAN}\" />\n                        <ToggleButton\n                            x:Name=\"togAllowLANConn\"\n                            Grid.Row=\"7\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"8\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsNewPort4LAN}\" />\n                        <ToggleButton\n                            x:Name=\"togNewPort4LAN\"\n                            Grid.Row=\"8\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"9\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsUser}\" />\n                        <TextBox\n                            x:Name=\"txtuser\"\n                            Grid.Row=\"9\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource DefTextBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"10\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsPass}\" />\n                        <TextBox\n                            x:Name=\"txtpass\"\n                            Grid.Row=\"10\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource DefTextBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"11\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                        <ToggleButton\n                            x:Name=\"togmuxEnabled\"\n                            Grid.Row=\"11\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"12\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsLogEnabledToFile}\" />\n                        <ToggleButton\n                            x:Name=\"toglogEnabled\"\n                            Grid.Row=\"12\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"13\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsLogLevel}\" />\n                        <ComboBox\n                            x:Name=\"cmbloglevel\"\n                            Grid.Row=\"13\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            materialDesign:HintAssist.Hint=\"Level\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"14\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefAllowInsecure}\" />\n                        <ToggleButton\n                            x:Name=\"togdefAllowInsecure\"\n                            Grid.Row=\"14\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"15\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefFingerprint}\" />\n                        <ComboBox\n                            x:Name=\"cmbdefFingerprint\"\n                            Grid.Row=\"15\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"16\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefUserAgent}\" />\n                        <ComboBox\n                            x:Name=\"cmbdefUserAgent\"\n                            Grid.Row=\"16\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"16\"\n                            Grid.Column=\"3\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefUserAgentTips}\" />\n\n                        <TextBlock\n                            Grid.Row=\"17\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMux4SboxProtocol}\" />\n                        <ComboBox\n                            x:Name=\"cmbmux4SboxProtocol\"\n                            Grid.Row=\"17\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"18\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableCacheFile4Sbox}\" />\n                        <ToggleButton\n                            x:Name=\"togenableCacheFile4Sbox\"\n                            Grid.Row=\"18\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"19\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsHysteriaBandwidth}\" />\n\n                        <StackPanel\n                            Grid.Row=\"19\"\n                            Grid.Column=\"1\"\n                            Orientation=\"Horizontal\">\n\n                            <TextBox\n                                x:Name=\"txtUpMbps\"\n                                Width=\"90\"\n                                Margin=\"{StaticResource Margin8}\"\n                                materialDesign:HintAssist.Hint=\"Up\"\n                                Style=\"{StaticResource DefTextBox}\" />\n                            <TextBox\n                                x:Name=\"txtDownMbps\"\n                                Width=\"90\"\n                                Margin=\"{StaticResource Margin8}\"\n                                materialDesign:HintAssist.Hint=\"Down\"\n                                Style=\"{StaticResource DefTextBox}\" />\n                        </StackPanel>\n\n                        <TextBlock\n                            Grid.Row=\"20\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableFragment}\" />\n                        <ToggleButton\n                            x:Name=\"togenableFragment\"\n                            Grid.Row=\"20\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n\n            <!--<TabItem Header=\"{x:Static resx:ResUI.TbSettingsCoreKcp}\">\n                <Grid Margin=\"{StaticResource Margin8}\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunMtu}\" />\n                    <TextBox Style=\"{StaticResource DefTextBox}\"\n                        x:Name=\"txtKcpmtu\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"tti\" />\n                    <TextBox Style=\"{StaticResource DefTextBox}\"\n                        x:Name=\"txtKcptti\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"uplinkCapacity\" />\n                    <TextBox Style=\"{StaticResource DefTextBox}\"\n                        x:Name=\"txtKcpuplinkCapacity\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"downlinkCapacity\" />\n                    <TextBox Style=\"{StaticResource DefTextBox}\"\n                        x:Name=\"txtKcpdownlinkCapacity\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"readBufferSize\" />\n                    <TextBox Style=\"{StaticResource DefTextBox}\"\n                        x:Name=\"txtKcpreadBufferSize\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\" />\n\n                    <TextBlock\n                        Grid.Row=\"6\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"writeBufferSize\" />\n                    <TextBox Style=\"{StaticResource DefTextBox}\"\n                        x:Name=\"txtKcpwriteBufferSize\"\n                        Grid.Row=\"6\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\" />\n\n                    <TextBlock\n                        Grid.Row=\"7\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"congestion\" />\n                    <ToggleButton\n                        x:Name=\"togKcpcongestion\"\n                        Grid.Row=\"7\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n            </TabItem>-->\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsN}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid Grid.Row=\"2\" Margin=\"{StaticResource Margin8}\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n                        <Grid.ColumnDefinitions>\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"Auto\" />\n                            <ColumnDefinition Width=\"*\" />\n                        </Grid.ColumnDefinitions>\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsStartBoot}\" />\n                        <ToggleButton\n                            x:Name=\"togAutoRun\"\n                            Grid.Row=\"1\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsStartBootTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsStatistics}\" />\n                        <ToggleButton\n                            x:Name=\"togEnableStatistics\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDisplayRealTimeSpeed}\" />\n                        <ToggleButton\n                            x:Name=\"togDisplayRealTimeSpeed\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsKeepOlderDedupl}\" />\n                        <ToggleButton\n                            x:Name=\"togKeepOlderDedupl\"\n                            Grid.Row=\"4\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableAutoAdjustMainLvColWidth}\" />\n                        <ToggleButton\n                            x:Name=\"togEnableAutoAdjustMainLvColWidth\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"8\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsAutoHideStartup}\" />\n                        <ToggleButton\n                            x:Name=\"togAutoHideStartup\"\n                            Grid.Row=\"8\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"10\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableDragDropSort}\" />\n                        <ToggleButton\n                            x:Name=\"togEnableDragDropSort\"\n                            Grid.Row=\"10\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"11\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDoubleClick2Activate}\" />\n                        <ToggleButton\n                            x:Name=\"togDoubleClick2Activate\"\n                            Grid.Row=\"11\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"12\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableHWA}\" />\n                        <ToggleButton\n                            x:Name=\"togEnableHWA\"\n                            Grid.Row=\"12\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"13\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsAutoUpdateInterval}\" />\n                        <TextBox\n                            x:Name=\"txtautoUpdateInterval\"\n                            Grid.Row=\"13\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\"\n                            Style=\"{StaticResource DefTextBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"14\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsTrayMenuServersLimit}\" />\n                        <TextBox\n                            x:Name=\"txttrayMenuServersLimit\"\n                            Grid.Row=\"14\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            HorizontalAlignment=\"Left\"\n                            Style=\"{StaticResource DefTextBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"15\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsCurrentFontFamily}\" />\n                        <ComboBox\n                            x:Name=\"cmbcurrentFontFamily\"\n                            Grid.Row=\"15\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            MaxDropDownHeight=\"1000\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"15\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsCurrentFontFamilyTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"16\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMixedConcurrencyCount}\" />\n                        <ComboBox\n                            x:Name=\"cmbMixedConcurrencyCount\"\n                            Grid.Row=\"16\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"17\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSpeedTestTimeout}\" />\n                        <ComboBox\n                            x:Name=\"cmbSpeedTestTimeout\"\n                            Grid.Row=\"17\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"18\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSpeedTestUrl}\" />\n                        <ComboBox\n                            x:Name=\"cmbSpeedTestUrl\"\n                            Grid.Row=\"18\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"19\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSpeedPingTestUrl}\" />\n                        <ComboBox\n                            x:Name=\"cmbSpeedPingTestUrl\"\n                            Grid.Row=\"19\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"20\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsIPAPIUrl}\" />\n                        <ComboBox\n                            x:Name=\"cmbIPAPIUrl\"\n                            Grid.Row=\"20\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"21\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSubConvert}\" />\n                        <ComboBox\n                            x:Name=\"cmbSubConvertUrl\"\n                            Grid.Row=\"21\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            materialDesign:HintAssist.Hint=\"Convert Url\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"22\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMainGirdOrientation}\" />\n                        <ComboBox\n                            x:Name=\"cmbMainGirdOrientation\"\n                            Grid.Row=\"22\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin8}\"\n                            Style=\"{StaticResource DefComboBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"23\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsGeoFilesSource}\" />\n                        <ComboBox\n                            x:Name=\"cmbGetFilesSourceUrl\"\n                            Grid.Row=\"23\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"23\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsChinaUserTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"24\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSrsFilesSource}\" />\n                        <ComboBox\n                            x:Name=\"cmbSrsFilesSourceUrl\"\n                            Grid.Row=\"24\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"24\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsChinaUserTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"25\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsRoutingRulesSource}\" />\n                        <ComboBox\n                            x:Name=\"cmbRoutingRulesSourceUrl\"\n                            Grid.Row=\"25\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin8}\"\n                            IsEditable=\"True\"\n                            Style=\"{StaticResource DefComboBox}\" />\n                        <TextBlock\n                            Grid.Row=\"25\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsChinaUserTip}\"\n                            TextWrapping=\"Wrap\" />\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsSystemproxy}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <StackPanel DockPanel.Dock=\"Bottom\" Orientation=\"Vertical\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsNotProxyLocalAddress}\" />\n                            <ToggleButton\n                                x:Name=\"tognotProxyLocalAddress\"\n                                Margin=\"{StaticResource Margin8}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsAdvancedProtocol}\" />\n                            <ComboBox\n                                x:Name=\"cmbsystemProxyAdvancedProtocol\"\n                                MinWidth=\"400\"\n                                Margin=\"{StaticResource Margin8}\"\n                                materialDesign:HintAssist.Hint=\"Protocol\"\n                                Style=\"{StaticResource DefComboBox}\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin8}\"\n                                VerticalAlignment=\"Center\"\n                                Style=\"{StaticResource ToolbarTextBlock}\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsCustomSystemProxyPacPath}\" />\n\n                            <TextBox\n                                x:Name=\"txtCustomSystemProxyPacPath\"\n                                Width=\"600\"\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                AcceptsReturn=\"True\"\n                                Style=\"{StaticResource DefTextBox}\"\n                                TextWrapping=\"Wrap\" />\n                            <Button\n                                x:Name=\"btnBrowseCustomSystemProxyPacPath\"\n                                Margin=\"{StaticResource MarginLeftRight4}\"\n                                Content=\"{x:Static resx:ResUI.TbBrowse}\"\n                                Style=\"{StaticResource DefButton}\" />\n                        </StackPanel>\n                    </StackPanel>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        DockPanel.Dock=\"Top\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsExceptionTip}\" />\n                    <TextBox\n                        x:Name=\"txtsystemProxyExceptions\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Stretch\"\n                        AcceptsReturn=\"True\"\n                        BorderThickness=\"1\"\n                        Style=\"{StaticResource DefTextBox}\"\n                        TextWrapping=\"Wrap\"\n                        VerticalScrollBarVisibility=\"Auto\" />\n                </DockPanel>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsTunMode}\">\n                <Grid Margin=\"{StaticResource Margin8}\" DockPanel.Dock=\"Top\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunAutoRoute}\" />\n                    <ToggleButton\n                        x:Name=\"togAutoRoute\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunStrictRoute}\" />\n                    <ToggleButton\n                        x:Name=\"togStrictRoute\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunStack}\" />\n                    <ComboBox\n                        x:Name=\"cmbStack\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunMtu}\" />\n                    <ComboBox\n                        x:Name=\"cmbMtu\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        HorizontalAlignment=\"Left\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"7\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsEnableIPv6Address}\" />\n                    <ToggleButton\n                        x:Name=\"togEnableIPv6Address\"\n                        Grid.Row=\"7\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin8}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsCoreType}\">\n                <Grid Margin=\"{StaticResource Margin8}\">\n                    <Grid.RowDefinitions>\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                        <RowDefinition Height=\"Auto\" />\n                    </Grid.RowDefinitions>\n                    <Grid.ColumnDefinitions>\n                        <ColumnDefinition Width=\"Auto\" />\n                        <ColumnDefinition Width=\"Auto\" />\n                    </Grid.ColumnDefinitions>\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"VMess\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType1\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"Custom\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType2\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"Shadowsocks\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType3\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"Socks\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType4\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"VLESS\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType5\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"6\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"Trojan\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType6\"\n                        Grid.Row=\"6\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"7\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"Hysteria2\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType7\"\n                        Grid.Row=\"7\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n\n                    <TextBlock\n                        Grid.Row=\"8\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"Wireguard\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType9\"\n                        Grid.Row=\"8\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin8}\"\n                        Style=\"{StaticResource DefComboBox}\" />\n                </Grid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/OptionSettingWindow.xaml.cs",
    "content": "using System.Windows.Media;\n\nnamespace v2rayN.Views;\n\npublic partial class OptionSettingWindow\n{\n    private static Config _config;\n\n    public OptionSettingWindow()\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        _config = AppManager.Instance.Config;\n\n        ViewModel = new OptionSettingViewModel(UpdateViewHandler);\n\n        clbdestOverride.SelectionChanged += ClbdestOverride_SelectionChanged;\n        btnBrowseCustomSystemProxyPacPath.Click += BtnBrowseCustomSystemProxyPacPath_Click;\n\n        clbdestOverride.ItemsSource = Global.destOverrideProtocols;\n        _config.Inbound.First().DestOverride?.ForEach(it =>\n        {\n            clbdestOverride.SelectedItems.Add(it);\n        });\n\n        cmbsystemProxyAdvancedProtocol.ItemsSource = Global.IEProxyProtocols;\n        cmbloglevel.ItemsSource = Global.LogLevels;\n        cmbdefFingerprint.ItemsSource = Global.Fingerprints;\n        cmbdefUserAgent.ItemsSource = Global.UserAgent;\n        cmbmux4SboxProtocol.ItemsSource = Global.SingboxMuxs;\n        cmbMtu.ItemsSource = Global.TunMtus;\n        cmbStack.ItemsSource = Global.TunStacks;\n\n        cmbCoreType1.ItemsSource = Global.CoreTypes;\n        cmbCoreType2.ItemsSource = Global.CoreTypes;\n        cmbCoreType3.ItemsSource = Global.CoreTypes;\n        cmbCoreType4.ItemsSource = Global.CoreTypes;\n        cmbCoreType5.ItemsSource = Global.CoreTypes;\n        cmbCoreType6.ItemsSource = Global.CoreTypes;\n        cmbCoreType7.ItemsSource = Global.CoreTypes;\n        cmbCoreType9.ItemsSource = Global.CoreTypes;\n\n        cmbMixedConcurrencyCount.ItemsSource = Enumerable.Range(2, 7).ToList();\n        cmbSpeedTestTimeout.ItemsSource = Enumerable.Range(2, 5).Select(i => i * 5).ToList();\n        cmbSpeedTestUrl.ItemsSource = Global.SpeedTestUrls;\n        cmbSpeedPingTestUrl.ItemsSource = Global.SpeedPingTestUrls;\n        cmbSubConvertUrl.ItemsSource = Global.SubConvertUrls;\n        cmbGetFilesSourceUrl.ItemsSource = Global.GeoFilesSources;\n        cmbSrsFilesSourceUrl.ItemsSource = Global.SingboxRulesetSources;\n        cmbRoutingRulesSourceUrl.ItemsSource = Global.RoutingRulesSources;\n        cmbIPAPIUrl.ItemsSource = Global.IPAPIUrls;\n\n        cmbMainGirdOrientation.ItemsSource = Utils.GetEnumNames<EGirdOrientation>();\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SecondLocalPortEnabled, v => v.togSecondLocalPortEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.udpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.sniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.routeOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.allowLANConn, v => v.togAllowLANConn.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.togNewPort4LAN.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtuser.IsEnabled).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.user, v => v.txtuser.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.pass, v => v.txtpass.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.muxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.logEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.loglevel, v => v.cmbloglevel.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.defAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.defFingerprint, v => v.cmbdefFingerprint.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.defUserAgent, v => v.cmbdefUserAgent.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.mux4SboxProtocol, v => v.cmbmux4SboxProtocol.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.enableCacheFile4Sbox, v => v.togenableCacheFile4Sbox.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.hyUpMbps, v => v.txtUpMbps.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.hyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.enableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables);\n\n            //this.Bind(ViewModel, vm => vm.Kcpmtu, v => v.txtKcpmtu.Text).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.Kcptti, v => v.txtKcptti.Text).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.KcpuplinkCapacity, v => v.txtKcpuplinkCapacity.Text).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.KcpdownlinkCapacity, v => v.txtKcpdownlinkCapacity.Text).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.KcpreadBufferSize, v => v.txtKcpreadBufferSize.Text).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.KcpwriteBufferSize, v => v.txtKcpwriteBufferSize.Text).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.Kcpcongestion, v => v.togKcpcongestion.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DisplayRealTimeSpeed, v => v.togDisplayRealTimeSpeed.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.KeepOlderDedupl, v => v.togKeepOlderDedupl.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableAutoAdjustMainLvColWidth, v => v.togEnableAutoAdjustMainLvColWidth.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableDragDropSort, v => v.togEnableDragDropSort.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TrayMenuServersLimit, v => v.txttrayMenuServersLimit.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.MixedConcurrencyCount, v => v.cmbMixedConcurrencyCount.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CustomSystemProxyPacPath, v => v.txtCustomSystemProxyPacPath.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType3, v => v.cmbCoreType3.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType4, v => v.cmbCoreType4.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType5, v => v.cmbCoreType5.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType7, v => v.cmbCoreType7.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType9, v => v.cmbCoreType9.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n\n            case EViewAction.InitSettingFont:\n                await InitSettingFont();\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private async Task InitSettingFont()\n    {\n        var lstFonts = await GetFonts(Utils.GetFontsPath());\n        cmbcurrentFontFamily.ItemsSource = lstFonts.AppendEmpty();\n    }\n\n    private async Task<List<string>> GetFonts(string path)\n    {\n        var lstFonts = new List<string>();\n        try\n        {\n            string[] searchPatterns = { \"*.ttf\", \"*.ttc\" };\n            var files = new List<string>();\n            foreach (var pattern in searchPatterns)\n            {\n                files.AddRange(Directory.GetFiles(path, pattern));\n            }\n            var culture = _config.UiItem.CurrentLanguage == Global.Languages.First() ? \"zh-cn\" : \"en-us\";\n            var culture2 = \"en-us\";\n            foreach (var ttf in files)\n            {\n                var families = Fonts.GetFontFamilies(Utils.GetFontsPath(ttf));\n                foreach (var family in families)\n                {\n                    var typefaces = family.GetTypefaces();\n                    foreach (var typeface in typefaces)\n                    {\n                        typeface.TryGetGlyphTypeface(out var glyph);\n                        //var fontFace = glyph.Win32FaceNames[new CultureInfo(\"en-us\")];\n                        //if (!fontFace.Equals(\"Regular\") && !fontFace.Equals(\"Normal\"))\n                        //{\n                        //    continue;\n                        //}\n                        var fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture)];\n                        if (fontFamily.IsNullOrEmpty())\n                        {\n                            fontFamily = glyph.Win32FamilyNames[new CultureInfo(culture2)];\n                            if (fontFamily.IsNullOrEmpty())\n                            {\n                                continue;\n                            }\n                        }\n                        lstFonts.Add(fontFamily);\n                        break;\n                    }\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"GetFonts\", ex);\n        }\n\n        var lst = lstFonts.OrderBy(t => t).ToList();\n        return await Task.FromResult(lst);\n    }\n\n    private void ClbdestOverride_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.destOverride = clbdestOverride.SelectedItems.Cast<string>().ToList();\n        }\n    }\n\n    private void BtnBrowseCustomSystemProxyPacPath_Click(object sender, RoutedEventArgs e)\n    {\n        if (UI.OpenFileDialog(out var fileName,\n              \"Txt|*.txt|All|*.*\") != true)\n        {\n            return;\n        }\n\n        txtCustomSystemProxyPacPath.Text = fileName;\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ProfilesSelectWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.ProfilesSelectWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.TbSelectProfile}\"\n    Width=\"800\"\n    Height=\"450\"\n    x:TypeArguments=\"vms:ProfilesSelectViewModel\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Click=\"BtnSave_Click\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n        <Grid>\n            <DockPanel>\n                <WrapPanel Margin=\"{StaticResource Margin4}\" DockPanel.Dock=\"Top\">\n                    <ListBox\n                        x:Name=\"lstGroup\"\n                        MaxHeight=\"200\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuSubscription}\"\n                        FontSize=\"{DynamicResource StdFontSize}\"\n                        ItemContainerStyle=\"{StaticResource MyChipListBoxItem}\"\n                        Style=\"{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}\">\n                        <ListBox.ItemTemplate>\n                            <DataTemplate>\n                                <TextBlock Text=\"{Binding Remarks}\" />\n                            </DataTemplate>\n                        </ListBox.ItemTemplate>\n                    </ListBox>\n\n                    <Button\n                        x:Name=\"btnAutofitColumnWidth\"\n                        Width=\"30\"\n                        Height=\"30\"\n                        Margin=\"{StaticResource MarginLeftRight8}\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\"\n                        Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                        ToolTip=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\">\n                        <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"ArrowSplitVertical\" />\n                    </Button>\n                    <TextBox\n                        x:Name=\"txtServerFilter\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource MarginLeftRight4}\"\n                        VerticalContentAlignment=\"Center\"\n                        materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.MsgServerTitle}\"\n                        materialDesign:TextFieldAssist.HasClearButton=\"True\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.MsgServerTitle}\"\n                        Style=\"{StaticResource DefTextBox}\" />\n                </WrapPanel>\n                <DataGrid\n                    x:Name=\"lstProfiles\"\n                    materialDesign:DataGridAssist.CellPadding=\"2,2\"\n                    AutoGenerateColumns=\"False\"\n                    BorderThickness=\"1\"\n                    CanUserAddRows=\"False\"\n                    CanUserResizeRows=\"False\"\n                    CanUserSortColumns=\"False\"\n                    EnableRowVirtualization=\"True\"\n                    Focusable=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"All\"\n                    IsReadOnly=\"True\"\n                    RowHeaderWidth=\"40\"\n                    SelectionMode=\"Single\"\n                    Style=\"{StaticResource DefDataGrid}\">\n                    <DataGrid.InputBindings>\n                        <KeyBinding Command=\"ApplicationCommands.NotACommand\" Gesture=\"Enter\" />\n                    </DataGrid.InputBindings>\n                    <DataGrid.Resources>\n                        <Style BasedOn=\"{StaticResource MaterialDesignDataGridRow}\" TargetType=\"DataGridRow\">\n                            <EventSetter Event=\"MouseDoubleClick\" Handler=\"LstProfiles_MouseDoubleClick\" />\n                        </Style>\n                        <Style BasedOn=\"{StaticResource MaterialDesignDataGridColumnHeader}\" TargetType=\"DataGridColumnHeader\">\n                            <EventSetter Event=\"Click\" Handler=\"LstProfiles_ColumnHeader_Click\" />\n                        </Style>\n\n                        <Style BasedOn=\"{StaticResource MaterialDesignDataGridCell}\" TargetType=\"DataGridCell\">\n                            <Style.Triggers>\n                                <DataTrigger Binding=\"{Binding IsActive}\" Value=\"True\">\n                                    <Setter Property=\"Background\" Value=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\" />\n                                    <Setter Property=\"Foreground\" Value=\"Black\" />\n                                    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\" />\n                                </DataTrigger>\n                            </Style.Triggers>\n                        </Style>\n                    </DataGrid.Resources>\n                    <DataGrid.Columns>\n                        <base:MyDGTextColumn\n                            Width=\"80\"\n                            Binding=\"{Binding ConfigType}\"\n                            ExName=\"ConfigType\"\n                            Header=\"{x:Static resx:ResUI.LvServiceType}\" />\n                        <base:MyDGTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Remarks}\"\n                            ExName=\"Remarks\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <base:MyDGTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Address}\"\n                            ExName=\"Address\"\n                            Header=\"{x:Static resx:ResUI.LvAddress}\" />\n                        <base:MyDGTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            ExName=\"Port\"\n                            Header=\"{x:Static resx:ResUI.LvPort}\" />\n                        <base:MyDGTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            ExName=\"Network\"\n                            Header=\"{x:Static resx:ResUI.LvTransportProtocol}\" />\n                        <base:MyDGTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding StreamSecurity}\"\n                            ExName=\"StreamSecurity\"\n                            Header=\"{x:Static resx:ResUI.LvTLS}\" />\n                        <base:MyDGTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding SubRemarks}\"\n                            ExName=\"SubRemarks\"\n                            Header=\"{x:Static resx:ResUI.LvSubscription}\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </DockPanel>\n        </Grid>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ProfilesSelectWindow.xaml.cs",
    "content": "using System.Windows.Controls;\nusing System.Windows.Controls.Primitives;\nusing v2rayN.Base;\n\nnamespace v2rayN.Views;\n\npublic partial class ProfilesSelectWindow\n{\n    private static Config _config;\n\n    public Task<ProfileItem?> ProfileItem => GetProfileItem();\n    public Task<List<ProfileItem>?> ProfileItems => GetProfileItems();\n    private bool _allowMultiSelect = false;\n\n    public ProfilesSelectWindow()\n    {\n        InitializeComponent();\n        lstGroup.MaxHeight = Math.Floor(SystemParameters.WorkArea.Height * 0.20 / 40) * 40;\n\n        _config = AppManager.Instance.Config;\n\n        btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;\n        txtServerFilter.PreviewKeyDown += TxtServerFilter_PreviewKeyDown;\n        lstProfiles.PreviewKeyDown += LstProfiles_PreviewKeyDown;\n        lstProfiles.SelectionChanged += LstProfiles_SelectionChanged;\n        lstProfiles.LoadingRow += LstProfiles_LoadingRow;\n\n        ViewModel = new ProfilesSelectViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ProfileItems, v => v.lstProfiles.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedProfile, v => v.lstProfiles.SelectedItem).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.lstGroup.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSub, v => v.lstGroup.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ServerFilter, v => v.txtServerFilter.Text).DisposeWith(disposables);\n        });\n\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    public void AllowMultiSelect(bool allow)\n    {\n        _allowMultiSelect = allow;\n        if (allow)\n        {\n            lstProfiles.SelectionMode = DataGridSelectionMode.Extended;\n            lstProfiles.SelectedItems.Clear();\n        }\n        else\n        {\n            lstProfiles.SelectionMode = DataGridSelectionMode.Single;\n            if (lstProfiles.SelectedItems.Count > 0)\n            {\n                var first = lstProfiles.SelectedItems[0];\n                lstProfiles.SelectedItems.Clear();\n                lstProfiles.SelectedItem = first;\n            }\n        }\n    }\n\n    // Expose ConfigType filter controls to callers\n    public void SetConfigTypeFilter(IEnumerable<EConfigType> types, bool exclude = false)\n        => ViewModel?.SetConfigTypeFilter(types, exclude);\n\n    #region Event\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void LstProfiles_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast<ProfileItemModel>().ToList();\n        }\n    }\n\n    private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e)\n    {\n        e.Row.Header = $\" {e.Row.GetIndex() + 1}\";\n    }\n\n    private void LstProfiles_MouseDoubleClick(object sender, MouseButtonEventArgs e)\n    {\n        ViewModel?.SelectFinish();\n    }\n\n    private void LstProfiles_ColumnHeader_Click(object sender, RoutedEventArgs e)\n    {\n        if (sender is not DataGridColumnHeader colHeader || colHeader.TabIndex < 0 || colHeader.Column == null)\n        {\n            return;\n        }\n\n        var colName = ((MyDGTextColumn)colHeader.Column).ExName;\n        ViewModel?.SortServer(colName);\n    }\n\n    private void menuSelectAll_Click(object sender, RoutedEventArgs e)\n    {\n        if (!_allowMultiSelect)\n        {\n            return;\n        }\n        lstProfiles.SelectAll();\n    }\n\n    private void LstProfiles_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))\n        {\n            switch (e.Key)\n            {\n                case Key.A:\n                    menuSelectAll_Click(null, null);\n                    e.Handled = true;\n                    break;\n            }\n        }\n        else\n        {\n            if (e.Key is Key.Enter or Key.Return)\n            {\n                ViewModel?.SelectFinish();\n                e.Handled = true;\n            }\n        }\n    }\n\n    private void BtnAutofitColumnWidth_Click(object sender, RoutedEventArgs e)\n    {\n        AutofitColumnWidth();\n    }\n\n    private void AutofitColumnWidth()\n    {\n        try\n        {\n            foreach (var it in lstProfiles.Columns)\n            {\n                it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"ProfilesView\", ex);\n        }\n    }\n\n    private void TxtServerFilter_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (e.Key is Key.Enter or Key.Return)\n        {\n            ViewModel?.RefreshServers();\n            e.Handled = true;\n        }\n    }\n\n    public async Task<ProfileItem?> GetProfileItem()\n    {\n        var item = await ViewModel?.GetProfileItem();\n        return item;\n    }\n\n    public async Task<List<ProfileItem>?> GetProfileItems()\n    {\n        var item = await ViewModel?.GetProfileItems();\n        return item;\n    }\n\n    private void BtnSave_Click(object sender, RoutedEventArgs e)\n    {\n        // Trigger selection finalize when Confirm is clicked\n        ViewModel?.SelectFinish();\n    }\n\n    #endregion Event\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ProfilesView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.ProfilesView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:conv=\"clr-namespace:v2rayN.Converters\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:ProfilesViewModel\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n    <UserControl.Resources>\n        <BooleanToVisibilityConverter x:Key=\"BoolToVisConverter\" />\n        <conv:DelayColorConverter x:Key=\"DelayColorConverter\" />\n    </UserControl.Resources>\n    <Grid>\n        <DockPanel>\n            <WrapPanel Margin=\"{StaticResource Margin4}\" DockPanel.Dock=\"Top\">\n                <ListBox\n                    x:Name=\"lstGroup\"\n                    MaxHeight=\"200\"\n                    AutomationProperties.Name=\"{x:Static resx:ResUI.menuSubscription}\"\n                    FontSize=\"{DynamicResource StdFontSize}\"\n                    ItemContainerStyle=\"{StaticResource MyChipListBoxItem}\"\n                    Style=\"{StaticResource MaterialDesignChoiceChipPrimaryOutlineListBox}\">\n                    <ListBox.ItemTemplate>\n                        <DataTemplate>\n                            <TextBlock Text=\"{Binding Remarks}\" />\n                        </DataTemplate>\n                    </ListBox.ItemTemplate>\n                </ListBox>\n\n                <Button\n                    x:Name=\"btnEditSub\"\n                    Width=\"30\"\n                    Height=\"30\"\n                    Margin=\"{StaticResource MarginLeftRight4}\"\n                    AutomationProperties.Name=\"{x:Static resx:ResUI.menuSubEdit}\"\n                    Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                    ToolTip=\"{x:Static resx:ResUI.menuSubEdit}\">\n                    <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"Edit\" />\n                </Button>\n                <Button\n                    x:Name=\"btnAddSub\"\n                    Width=\"30\"\n                    Height=\"30\"\n                    Margin=\"{StaticResource MarginLeftRight4}\"\n                    AutomationProperties.Name=\"{x:Static resx:ResUI.menuSubAdd}\"\n                    Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                    ToolTip=\"{x:Static resx:ResUI.menuSubAdd}\">\n                    <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"Plus\" />\n                </Button>\n\n                <TextBox\n                    x:Name=\"txtServerFilter\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource MarginLeftRight4}\"\n                    VerticalContentAlignment=\"Center\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.MsgServerTitle}\"\n                    materialDesign:TextFieldAssist.HasClearButton=\"True\"\n                    AutomationProperties.Name=\"{x:Static resx:ResUI.MsgServerTitle}\"\n                    Style=\"{StaticResource DefTextBox}\" />\n\n                <Button\n                    x:Name=\"btnAutofitColumnWidth\"\n                    Width=\"30\"\n                    Height=\"30\"\n                    Margin=\"{StaticResource MarginLeftRight4}\"\n                    AutomationProperties.Name=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\"\n                    Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                    ToolTip=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\">\n                    <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"ArrowSplitVertical\" />\n                </Button>\n\n                <Button\n                    x:Name=\"btnFastRealPing\"\n                    Width=\"30\"\n                    Height=\"30\"\n                    Margin=\"{StaticResource MarginLeftRight4}\"\n                    Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                    ToolTip=\"{x:Static resx:ResUI.menuFastRealPing}\">\n                    <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"LightningBolt\" />\n                </Button>\n                <Button\n                    x:Name=\"menuMixedTestServer\"\n                    Width=\"30\"\n                    Height=\"30\"\n                    Margin=\"{StaticResource MarginLeftRight4}\"\n                    Style=\"{StaticResource MaterialDesignFloatingActionMiniLightButton}\"\n                    ToolTip=\"{x:Static resx:ResUI.menuMixedTestServer}\">\n                    <materialDesign:PackIcon VerticalAlignment=\"Center\" Kind=\"Speedometer\" />\n                </Button>\n            </WrapPanel>\n            <DataGrid\n                x:Name=\"lstProfiles\"\n                materialDesign:DataGridAssist.CellPadding=\"2,2\"\n                AutoGenerateColumns=\"False\"\n                BorderThickness=\"1\"\n                CanUserAddRows=\"False\"\n                CanUserResizeRows=\"False\"\n                CanUserSortColumns=\"False\"\n                EnableRowVirtualization=\"True\"\n                Focusable=\"True\"\n                GridLinesVisibility=\"All\"\n                HeadersVisibility=\"All\"\n                IsReadOnly=\"True\"\n                RowHeaderWidth=\"40\"\n                Style=\"{StaticResource DefDataGrid}\">\n                <DataGrid.InputBindings>\n                    <KeyBinding Command=\"ApplicationCommands.NotACommand\" Gesture=\"Ctrl+C\" />\n                    <KeyBinding Command=\"ApplicationCommands.NotACommand\" Gesture=\"Ctrl+V\" />\n                    <KeyBinding Command=\"ApplicationCommands.NotACommand\" Gesture=\"Delete\" />\n                    <KeyBinding Command=\"ApplicationCommands.NotACommand\" Gesture=\"Enter\" />\n                </DataGrid.InputBindings>\n                <DataGrid.ContextMenu>\n                    <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                        <MenuItem\n                            x:Name=\"menuSetDefaultServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSetDefaultServer}\"\n                            InputGestureText=\"Enter\" />\n                        <MenuItem\n                            x:Name=\"menuEditServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuEditServer}\"\n                            InputGestureText=\"Ctrl+D\" />\n                        <MenuItem\n                            x:Name=\"menuCopyServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuCopyServer}\" />\n                        <MenuItem\n                            x:Name=\"menuRemoveServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuRemoveServer}\"\n                            InputGestureText=\"Back\" />\n                        <MenuItem\n                            x:Name=\"menuRemoveDuplicateServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuRemoveDuplicateServer}\" />\n                        <MenuItem\n                            x:Name=\"menuRemoveInvalidServerResult\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuRemoveInvalidServerResult}\" />\n                        <Separator />\n                        <MenuItem\n                            x:Name=\"menuTcpingServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuTcpingServer}\"\n                            InputGestureText=\"Ctrl+O\" />\n                        <MenuItem\n                            x:Name=\"menuRealPingServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuRealPingServer}\"\n                            InputGestureText=\"Ctrl+R\" />\n                        <MenuItem\n                            x:Name=\"menuSpeedServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSpeedServer}\"\n                            InputGestureText=\"Ctrl+T\" />\n                        <MenuItem\n                            x:Name=\"menuSortServerResult\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSortServerResult}\" />\n                        <Separator />\n                        <MenuItem\n                            x:Name=\"menuMoveToGroup\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuMoveToGroup}\">\n                            <MenuItem Height=\"Auto\">\n                                <MenuItem.Header>\n                                    <DockPanel>\n                                        <ComboBox\n                                            x:Name=\"cmbMoveToGroup\"\n                                            Width=\"200\"\n                                            materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.menuSubscription}\"\n                                            DisplayMemberPath=\"Remarks\"\n                                            FontSize=\"{DynamicResource StdFontSize}\"\n                                            Style=\"{StaticResource MaterialDesignFilledComboBox}\" />\n                                    </DockPanel>\n                                </MenuItem.Header>\n                            </MenuItem>\n                        </MenuItem>\n                        <MenuItem Header=\"{x:Static resx:ResUI.menuMoveTo}\">\n                            <MenuItem\n                                x:Name=\"menuMoveTop\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveTop}\"\n                                InputGestureText=\"T\" />\n                            <MenuItem\n                                x:Name=\"menuMoveUp\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveUp}\"\n                                InputGestureText=\"U\" />\n                            <MenuItem\n                                x:Name=\"menuMoveDown\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveDown}\"\n                                InputGestureText=\"D\" />\n                            <MenuItem\n                                x:Name=\"menuMoveBottom\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveBottom}\"\n                                InputGestureText=\"B\" />\n                        </MenuItem>\n                        <MenuItem\n                            x:Name=\"menuSelectAll\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                            InputGestureText=\"Ctrl+A\" />\n                        <Separator />\n                        <MenuItem\n                            x:Name=\"menuShareServer\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuShareServer}\"\n                            InputGestureText=\"Ctrl+F\" />\n                        <MenuItem Header=\"{x:Static resx:ResUI.menuExportConfig}\">\n                            <MenuItem\n                                x:Name=\"menuExport2ClientConfig\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuExport2ClientConfig}\" />\n                            <MenuItem\n                                x:Name=\"menuExport2ClientConfigClipboard\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuExport2ClientConfigClipboard}\" />\n                            <Separator />\n                            <MenuItem\n                                x:Name=\"menuExport2ShareUrl\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuExport2ShareUrl}\"\n                                InputGestureText=\"Ctrl+C\" />\n                            <MenuItem\n                                x:Name=\"menuExport2ShareUrlBase64\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuExport2ShareUrlBase64}\" />\n                        </MenuItem>\n                        <Separator />\n                        <MenuItem Header=\"{x:Static resx:ResUI.menuGenGroupServer}\">\n                            <MenuItem\n                                x:Name=\"menuGenGroupAllServer\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuAllServers}\" />\n                            <MenuItem\n                                x:Name=\"menuGenGroupRegionServer\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuGenRegionGroup}\" />\n                        </MenuItem>\n                    </ContextMenu>\n                </DataGrid.ContextMenu>\n                <DataGrid.Resources>\n                    <Style BasedOn=\"{StaticResource MaterialDesignDataGridRow}\" TargetType=\"DataGridRow\">\n                        <EventSetter Event=\"MouseDoubleClick\" Handler=\"LstProfiles_MouseDoubleClick\" />\n                    </Style>\n                    <Style BasedOn=\"{StaticResource MaterialDesignDataGridColumnHeader}\" TargetType=\"DataGridColumnHeader\">\n                        <EventSetter Event=\"Click\" Handler=\"LstProfiles_ColumnHeader_Click\" />\n                    </Style>\n\n                    <Style BasedOn=\"{StaticResource MaterialDesignDataGridCell}\" TargetType=\"DataGridCell\">\n                        <Style.Triggers>\n                            <DataTrigger Binding=\"{Binding IsActive}\" Value=\"True\">\n                                <Setter Property=\"Background\" Value=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\" />\n                                <Setter Property=\"Foreground\" Value=\"Black\" />\n                                <Setter Property=\"BorderBrush\" Value=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\" />\n                            </DataTrigger>\n                        </Style.Triggers>\n                    </Style>\n                </DataGrid.Resources>\n                <DataGrid.Columns>\n                    <base:MyDGTextColumn\n                        Width=\"80\"\n                        Binding=\"{Binding ConfigType}\"\n                        ExName=\"ConfigType\"\n                        Header=\"{x:Static resx:ResUI.LvServiceType}\" />\n                    <base:MyDGTextColumn\n                        Width=\"150\"\n                        Binding=\"{Binding Remarks}\"\n                        ExName=\"Remarks\"\n                        Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                    <base:MyDGTextColumn\n                        Width=\"120\"\n                        Binding=\"{Binding Address}\"\n                        ExName=\"Address\"\n                        Header=\"{x:Static resx:ResUI.LvAddress}\" />\n                    <base:MyDGTextColumn\n                        Width=\"60\"\n                        Binding=\"{Binding Port}\"\n                        ExName=\"Port\"\n                        Header=\"{x:Static resx:ResUI.LvPort}\" />\n                    <base:MyDGTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding Network}\"\n                        ExName=\"Network\"\n                        Header=\"{x:Static resx:ResUI.LvTransportProtocol}\" />\n                    <base:MyDGTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding StreamSecurity}\"\n                        ExName=\"StreamSecurity\"\n                        Header=\"{x:Static resx:ResUI.LvTLS}\" />\n                    <base:MyDGTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding SubRemarks}\"\n                        ExName=\"SubRemarks\"\n                        Header=\"{x:Static resx:ResUI.LvSubscription}\" />\n                    <base:MyDGTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding DelayVal}\"\n                        ExName=\"DelayVal\"\n                        Header=\"{x:Static resx:ResUI.LvTestDelay}\"\n                        SortMemberPath=\"Delay\">\n                        <DataGridTextColumn.ElementStyle>\n                            <Style TargetType=\"{x:Type TextBlock}\">\n                                <Setter Property=\"HorizontalAlignment\" Value=\"Right\" />\n                                <Setter Property=\"Foreground\" Value=\"{Binding Delay, Converter={StaticResource DelayColorConverter}}\" />\n                            </Style>\n                        </DataGridTextColumn.ElementStyle>\n                    </base:MyDGTextColumn>\n                    <base:MyDGTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding SpeedVal}\"\n                        ExName=\"SpeedVal\"\n                        Header=\"{x:Static resx:ResUI.LvTestSpeed}\">\n                        <DataGridTextColumn.ElementStyle>\n                            <Style TargetType=\"{x:Type TextBlock}\">\n                                <Setter Property=\"HorizontalAlignment\" Value=\"Right\" />\n                            </Style>\n                        </DataGridTextColumn.ElementStyle>\n                    </base:MyDGTextColumn>\n\n                    <base:MyDGTextColumn\n                        x:Name=\"colTodayUp\"\n                        Width=\"100\"\n                        Binding=\"{Binding TodayUp}\"\n                        ExName=\"TodayUp\"\n                        Header=\"{x:Static resx:ResUI.LvTodayUploadDataAmount}\" />\n                    <base:MyDGTextColumn\n                        x:Name=\"colTodayDown\"\n                        Width=\"100\"\n                        Binding=\"{Binding TodayDown}\"\n                        ExName=\"TodayDown\"\n                        Header=\"{x:Static resx:ResUI.LvTodayDownloadDataAmount}\" />\n                    <base:MyDGTextColumn\n                        x:Name=\"colTotalUp\"\n                        Width=\"100\"\n                        Binding=\"{Binding TotalUp}\"\n                        ExName=\"TotalUp\"\n                        Header=\"{x:Static resx:ResUI.LvTotalUploadDataAmount}\" />\n                    <base:MyDGTextColumn\n                        x:Name=\"colTotalDown\"\n                        Width=\"100\"\n                        Binding=\"{Binding TotalDown}\"\n                        ExName=\"TotalDown\"\n                        Header=\"{x:Static resx:ResUI.LvTotalDownloadDataAmount}\" />\n                </DataGrid.Columns>\n            </DataGrid>\n        </DockPanel>\n    </Grid>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ProfilesView.xaml.cs",
    "content": "using System.Windows.Controls;\nusing System.Windows.Controls.Primitives;\nusing System.Windows.Media;\nusing MaterialDesignThemes.Wpf;\nusing v2rayN.Base;\nusing Point = System.Windows.Point;\n\nnamespace v2rayN.Views;\n\npublic partial class ProfilesView\n{\n    private static Config _config;\n    private static readonly string _tag = \"ProfilesView\";\n\n    public ProfilesView()\n    {\n        InitializeComponent();\n        lstGroup.MaxHeight = Math.Floor(SystemParameters.WorkArea.Height * 0.20 / 40) * 40;\n\n        _config = AppManager.Instance.Config;\n\n        btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;\n        txtServerFilter.PreviewKeyDown += TxtServerFilter_PreviewKeyDown;\n        lstProfiles.PreviewKeyDown += LstProfiles_PreviewKeyDown;\n        lstProfiles.SelectionChanged += LstProfiles_SelectionChanged;\n        lstProfiles.LoadingRow += LstProfiles_LoadingRow;\n        menuSelectAll.Click += menuSelectAll_Click;\n\n        if (_config.UiItem.EnableDragDropSort)\n        {\n            lstProfiles.AllowDrop = true;\n            lstProfiles.PreviewMouseLeftButtonDown += LstProfiles_PreviewMouseLeftButtonDown;\n            lstProfiles.MouseMove += LstProfiles_MouseMove;\n            lstProfiles.DragEnter += LstProfiles_DragEnter;\n            lstProfiles.Drop += LstProfiles_Drop;\n        }\n\n        ViewModel = new ProfilesViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ProfileItems, v => v.lstProfiles.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedProfile, v => v.lstProfiles.SelectedItem).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.lstGroup.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSub, v => v.lstGroup.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ServerFilter, v => v.txtServerFilter.Text).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddSubCmd, v => v.btnAddSub).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.EditSubCmd, v => v.btnEditSub).DisposeWith(disposables);\n\n            //servers delete\n            this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.menuEditServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoveServerCmd, v => v.menuRemoveServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoveDuplicateServerCmd, v => v.menuRemoveDuplicateServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.CopyServerCmd, v => v.menuCopyServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SetDefaultServerCmd, v => v.menuSetDefaultServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ShareServerCmd, v => v.menuShareServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.GenGroupAllServerCmd, v => v.menuGenGroupAllServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.GenGroupRegionServerCmd, v => v.menuGenGroupRegionServer).DisposeWith(disposables);\n\n            //servers move\n            this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbMoveToGroup.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedMoveToGroup, v => v.cmbMoveToGroup.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);\n\n            //servers ping\n            this.BindCommand(ViewModel, vm => vm.MixedTestServerCmd, v => v.menuMixedTestServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.TcpingServerCmd, v => v.menuTcpingServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RealPingServerCmd, v => v.menuRealPingServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SpeedServerCmd, v => v.menuSpeedServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SortServerResultCmd, v => v.menuSortServerResult).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoveInvalidServerResultCmd, v => v.menuRemoveInvalidServerResult).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.FastRealPingCmd, v => v.btnFastRealPing).DisposeWith(disposables);\n\n            //servers export\n            this.BindCommand(ViewModel, vm => vm.Export2ClientConfigCmd, v => v.menuExport2ClientConfig).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.Export2ClientConfigClipboardCmd, v => v.menuExport2ClientConfigClipboard).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.Export2ShareUrlCmd, v => v.menuExport2ShareUrl).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.Export2ShareUrlBase64Cmd, v => v.menuExport2ShareUrlBase64).DisposeWith(disposables);\n\n            AppEvents.AppExitRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(_ => StorageUI())\n              .DisposeWith(disposables);\n\n            AppEvents.AdjustMainLvColWidthRequested\n                .AsObservable()\n                .ObserveOn(RxSchedulers.MainThreadScheduler)\n                .Subscribe(_ => AutofitColumnWidth())\n                .DisposeWith(disposables);\n        });\n\n        RestoreUI();\n    }\n\n    #region Event\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.SetClipboardData:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                WindowsUtils.SetClipboardData((string)obj);\n                break;\n\n            case EViewAction.ProfilesFocus:\n                lstProfiles.Focus();\n                break;\n\n            case EViewAction.ShowYesNo:\n                if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.SaveFileDialog:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                if (UI.SaveFileDialog(out var fileName, \"Config|*.json\") != true)\n                {\n                    return false;\n                }\n                ViewModel?.Export2ClientConfigResult(fileName, (ProfileItem)obj);\n                break;\n\n            case EViewAction.AddServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new AddServerWindow((ProfileItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.AddServer2Window:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new AddServer2Window((ProfileItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.AddGroupServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new AddGroupServerWindow((ProfileItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.ShareServer:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                ShareServer((string)obj);\n                break;\n\n            case EViewAction.SubEditWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new SubEditWindow((SubItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.DispatcherRefreshServersBiz:\n                Application.Current?.Dispatcher.Invoke(RefreshServersBiz, DispatcherPriority.Normal);\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    public async void ShareServer(string url)\n    {\n        var img = QRCodeWindowsUtils.GetQRCode(url);\n        var dialog = new QrcodeView()\n        {\n            imgQrcode = { Source = img },\n            txtContent = { Text = url },\n        };\n\n        await DialogHost.Show(dialog, \"RootDialog\");\n    }\n\n    public void RefreshServersBiz()\n    {\n        if (lstProfiles.SelectedIndex > 0)\n        {\n            lstProfiles.ScrollIntoView(lstProfiles.SelectedItem, null);\n        }\n    }\n\n    private void LstProfiles_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast<ProfileItemModel>().ToList();\n        }\n    }\n\n    private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e)\n    {\n        e.Row.Header = $\" {e.Row.GetIndex() + 1}\";\n    }\n\n    private void LstProfiles_MouseDoubleClick(object sender, MouseButtonEventArgs e)\n    {\n        if (_config.UiItem.DoubleClick2Activate)\n        {\n            ViewModel?.SetDefaultServer();\n        }\n        else\n        {\n            ViewModel?.EditServerAsync();\n        }\n    }\n\n    private void LstProfiles_ColumnHeader_Click(object sender, RoutedEventArgs e)\n    {\n        if (sender is not DataGridColumnHeader colHeader || colHeader.TabIndex < 0 || colHeader.Column == null)\n        {\n            return;\n        }\n\n        var colName = ((MyDGTextColumn)colHeader.Column).ExName;\n        ViewModel?.SortServer(colName);\n    }\n\n    private void menuSelectAll_Click(object sender, RoutedEventArgs e)\n    {\n        lstProfiles.SelectAll();\n    }\n\n    private void LstProfiles_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))\n        {\n            switch (e.Key)\n            {\n                case Key.A:\n                    menuSelectAll_Click(null, null);\n                    break;\n\n                case Key.C:\n                    ViewModel?.Export2ShareUrlAsync(false);\n                    break;\n\n                case Key.D:\n                    ViewModel?.EditServerAsync();\n                    break;\n\n                case Key.F:\n                    ViewModel?.ShareServerAsync();\n                    break;\n\n                case Key.O:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Tcping);\n                    break;\n\n                case Key.R:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Realping);\n                    break;\n\n                case Key.T:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Speedtest);\n                    break;\n\n                case Key.E:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Mixedtest);\n                    break;\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.Enter:\n                    //case Key.Return:\n                    ViewModel?.SetDefaultServer();\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.RemoveServerAsync();\n                    break;\n\n                case Key.T:\n                    ViewModel?.MoveServer(EMove.Top);\n                    break;\n\n                case Key.U:\n                    ViewModel?.MoveServer(EMove.Up);\n                    break;\n\n                case Key.D:\n                    ViewModel?.MoveServer(EMove.Down);\n                    break;\n\n                case Key.B:\n                    ViewModel?.MoveServer(EMove.Bottom);\n                    break;\n\n                case Key.Escape:\n                    ViewModel?.ServerSpeedtestStop();\n                    break;\n            }\n        }\n    }\n\n    private void BtnAutofitColumnWidth_Click(object sender, RoutedEventArgs e)\n    {\n        AutofitColumnWidth();\n    }\n\n    private void AutofitColumnWidth()\n    {\n        try\n        {\n            foreach (var it in lstProfiles.Columns)\n            {\n                it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void TxtServerFilter_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (e.Key is Key.Enter or Key.Return)\n        {\n            ViewModel?.RefreshServers();\n        }\n    }\n\n    #endregion Event\n\n    #region UI\n\n    private void RestoreUI()\n    {\n        try\n        {\n            var lvColumnItem = _config.UiItem.MainColumnItem.OrderBy(t => t.Index).ToList();\n            var displayIndex = 0;\n            foreach (var item in lvColumnItem)\n            {\n                foreach (var item2 in lstProfiles.Columns.Cast<MyDGTextColumn>())\n                {\n                    if (item2.ExName == item.Name)\n                    {\n                        if (item.Width < 0)\n                        {\n                            item2.Visibility = Visibility.Hidden;\n                        }\n                        else\n                        {\n                            item2.Width = item.Width;\n                            item2.DisplayIndex = displayIndex++;\n                        }\n                        if (item.Name.ToLower().StartsWith(\"to\"))\n                        {\n                            item2.Visibility = _config.GuiItem.EnableStatistics ? Visibility.Visible : Visibility.Hidden;\n                        }\n                    }\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void StorageUI()\n    {\n        try\n        {\n            List<ColumnItem> lvColumnItem = new();\n            foreach (var item2 in lstProfiles.Columns.Cast<MyDGTextColumn>())\n            {\n                lvColumnItem.Add(new()\n                {\n                    Name = item2.ExName,\n                    Width = (int)(item2.Visibility == Visibility.Visible ? item2.ActualWidth : -1),\n                    Index = item2.DisplayIndex\n                });\n            }\n            _config.UiItem.MainColumnItem = lvColumnItem;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    #endregion UI\n\n    #region Drag and Drop\n\n    private Point startPoint = new();\n    private int startIndex = -1;\n    private readonly string formatData = \"ProfileItemModel\";\n\n    /// <summary>\n    /// Helper to search up the VisualTree\n    /// </summary>\n    /// <typeparam name=\"T\"></typeparam>\n    /// <param name=\"current\"></param>\n    /// <returns></returns>\n    private static T? FindAncestor<T>(DependencyObject current) where T : DependencyObject\n    {\n        do\n        {\n            if (current is T)\n            {\n                return (T)current;\n            }\n            current = VisualTreeHelper.GetParent(current);\n        }\n        while (current != null);\n        return null;\n    }\n\n    private void LstProfiles_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)\n    {\n        // Get current mouse position\n        startPoint = e.GetPosition(null);\n    }\n\n    private void LstProfiles_MouseMove(object sender, MouseEventArgs e)\n    {\n        // Get the current mouse position\n        var mousePos = e.GetPosition(null);\n        var diff = startPoint - mousePos;\n\n        if (e.LeftButton == MouseButtonState.Pressed &&\n            (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||\n                   Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))\n        {\n            // Get the dragged Item\n            if (sender is not DataGrid listView)\n            {\n                return;\n            }\n\n            var listViewItem = FindAncestor<DataGridRow>((DependencyObject)e.OriginalSource);\n            if (listViewItem == null)\n            {\n                return;           // Abort\n            }\n            // Find the data behind the ListViewItem\n            var item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);\n            if (item == null)\n            {\n                return;                   // Abort\n            }\n            // Initialize the drag & drop operation\n            startIndex = lstProfiles.SelectedIndex;\n            DataObject dragData = new(formatData, item);\n            DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Copy | DragDropEffects.Move);\n        }\n    }\n\n    private void LstProfiles_DragEnter(object sender, DragEventArgs e)\n    {\n        if (!e.Data.GetDataPresent(formatData) || sender != e.Source)\n        {\n            e.Effects = DragDropEffects.None;\n        }\n    }\n\n    private void LstProfiles_Drop(object sender, DragEventArgs e)\n    {\n        if (e.Data.GetDataPresent(formatData) && sender == e.Source)\n        {\n            // Get the drop Item destination\n            if (sender is not DataGrid listView)\n            {\n                return;\n            }\n\n            var listViewItem = FindAncestor<DataGridRow>((DependencyObject)e.OriginalSource);\n            if (listViewItem == null)\n            {\n                // Abort\n                e.Effects = DragDropEffects.None;\n                return;\n            }\n            // Find the data behind the Item\n            var item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);\n            if (item == null)\n            {\n                return;\n            }\n            // Move item into observable collection\n            // (this will be automatically reflected to lstView.ItemsSource)\n            e.Effects = DragDropEffects.Move;\n\n            ViewModel?.MoveServerTo(startIndex, item);\n\n            startIndex = -1;\n        }\n    }\n\n    #endregion Drag and Drop\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/QrcodeView.xaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Views.QrcodeView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:sys=\"clr-namespace:System;assembly=mscorlib\"\n    d:DesignHeight=\"600\"\n    d:DesignWidth=\"600\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n    <UserControl.Resources>\n        <sys:Double x:Key=\"QrcodeWidth\">400</sys:Double>\n    </UserControl.Resources>\n\n    <StackPanel Margin=\"{StaticResource Margin8}\">\n        <Grid Margin=\"{StaticResource Margin8}\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n\n            <Image\n                x:Name=\"imgQrcode\"\n                Grid.Row=\"0\"\n                Width=\"{StaticResource QrcodeWidth}\"\n                Height=\"{StaticResource QrcodeWidth}\"\n                Stretch=\"UniformToFill\" />\n\n            <TextBox\n                x:Name=\"txtContent\"\n                Grid.Row=\"1\"\n                Width=\"{StaticResource QrcodeWidth}\"\n                Margin=\"0,8\"\n                VerticalAlignment=\"Center\"\n                IsReadOnly=\"True\"\n                MaxLines=\"3\"\n                TextWrapping=\"Wrap\"\n                VerticalScrollBarVisibility=\"Auto\" />\n        </Grid>\n    </StackPanel>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/QrcodeView.xaml.cs",
    "content": "using System.Windows.Controls;\n\nnamespace v2rayN.Views;\n\npublic partial class QrcodeView : UserControl\n{\n    public QrcodeView()\n    {\n        InitializeComponent();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.RoutingRuleDetailsWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuRoutingRuleDetailsSetting}\"\n    Width=\"900\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:RoutingRuleDetailsViewModel\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel>\n        <Grid Margin=\"{StaticResource Margin8}\" DockPanel.Dock=\"Top\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"Auto\" />\n                <ColumnDefinition Width=\"Auto\" />\n                <ColumnDefinition Width=\"Auto\" />\n            </Grid.ColumnDefinitions>\n\n            <TextBlock\n                Grid.Row=\"0\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.LvRemarks}\" />\n            <TextBox\n                x:Name=\"txtRemarks\"\n                Grid.Row=\"0\"\n                Grid.Column=\"1\"\n                Width=\"200\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                Style=\"{StaticResource DefTextBox}\" />\n            <StackPanel\n                Grid.Row=\"0\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Orientation=\"Horizontal\">\n                <ToggleButton\n                    x:Name=\"togEnabled\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\" />\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbRuleType}\" />\n            <ComboBox\n                x:Name=\"cmbRuleType\"\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Width=\"200\"\n                Margin=\"{StaticResource Margin4}\"\n                MaxDropDownHeight=\"1000\"\n                Style=\"{StaticResource DefComboBox}\" />\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbRuleTypeTips}\" />\n\n            <TextBlock\n                Grid.Row=\"2\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"outboundTag\" />\n            <ComboBox\n                x:Name=\"cmbOutboundTag\"\n                Grid.Row=\"2\"\n                Grid.Column=\"1\"\n                Width=\"200\"\n                Margin=\"{StaticResource Margin4}\"\n                IsEditable=\"True\"\n                MaxDropDownHeight=\"1000\"\n                Style=\"{StaticResource DefComboBox}\" />\n            <StackPanel\n                Grid.Row=\"2\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Orientation=\"Horizontal\">\n                <Button\n                    Margin=\"{StaticResource Margin4}\"\n                    Click=\"BtnSelectProfile_Click\"\n                    Content=\"{x:Static resx:ResUI.TbSelectProfile}\"\n                    Style=\"{StaticResource DefButton}\" />\n                <TextBlock\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.TbRuleOutboundTagTip}\" />\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"3\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"port\" />\n            <TextBox\n                x:Name=\"txtPort\"\n                Grid.Row=\"3\"\n                Grid.Column=\"1\"\n                Width=\"200\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                Style=\"{StaticResource DefTextBox}\" />\n            <TextBlock\n                Grid.Row=\"3\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbRuleMatchingTips}\" />\n\n            <TextBlock\n                Grid.Row=\"4\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"protocol\" />\n            <ListBox\n                x:Name=\"clbProtocol\"\n                Grid.Row=\"4\"\n                Grid.Column=\"1\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                FontSize=\"{DynamicResource StdFontSize}\"\n                Style=\"{StaticResource MaterialDesignFilterChipPrimaryListBox}\" />\n            <TextBlock\n                Grid.Row=\"4\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\">\n                <Hyperlink Click=\"linkRuleobjectDoc_Click\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.TbRuleobjectDoc}\" />\n                    <materialDesign:PackIcon Kind=\"Link\" />\n                </Hyperlink>\n            </TextBlock>\n\n            <TextBlock\n                Grid.Row=\"5\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"inboundTag\" />\n            <ListBox\n                x:Name=\"clbInboundTag\"\n                Grid.Row=\"5\"\n                Grid.Column=\"1\"\n                Margin=\"{StaticResource Margin4}\"\n                FontSize=\"{DynamicResource StdFontSize}\"\n                Style=\"{StaticResource MaterialDesignFilterChipPrimaryListBox}\" />\n            <TextBlock\n                Grid.Row=\"5\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbRoutingInboundTagTips}\" />\n\n            <TextBlock\n                Grid.Row=\"6\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"network\" />\n            <ComboBox\n                x:Name=\"cmbNetwork\"\n                Grid.Row=\"6\"\n                Grid.Column=\"1\"\n                Width=\"200\"\n                Margin=\"{StaticResource Margin4}\"\n                MaxDropDownHeight=\"1000\"\n                Style=\"{StaticResource DefComboBox}\" />\n\n            <TextBlock\n                Grid.Row=\"6\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbRoutingTips}\" />\n        </Grid>\n\n        <StackPanel\n            Margin=\"{StaticResource Margin8}\"\n            HorizontalAlignment=\"Right\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <StackPanel\n                Width=\"600\"\n                HorizontalAlignment=\"Center\"\n                VerticalAlignment=\"Center\">\n                <CheckBox x:Name=\"chkAutoSort\">\n                    <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.TbAutoSort}\" />\n                </CheckBox>\n            </StackPanel>\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <Grid Margin=\"{StaticResource Margin8}\">\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"1*\" />\n                <ColumnDefinition Width=\"10\" />\n                <ColumnDefinition Width=\"1*\" />\n                <ColumnDefinition Width=\"10\" />\n                <ColumnDefinition Width=\"1*\" />\n            </Grid.ColumnDefinitions>\n            <GroupBox\n                Grid.Column=\"0\"\n                Header=\"{x:Static resx:ResUI.TbRoutingRuleDomain}\"\n                Style=\"{StaticResource MyGroupBox}\">\n                <TextBox\n                    Name=\"txtDomain\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource DefTextBox}\"\n                    TextWrapping=\"Wrap\"\n                    VerticalScrollBarVisibility=\"Auto\" />\n            </GroupBox>\n            <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n            <GroupBox\n                Grid.Column=\"2\"\n                Header=\"{x:Static resx:ResUI.TbRoutingRuleIP}\"\n                Style=\"{StaticResource MyGroupBox}\">\n                <TextBox\n                    Name=\"txtIP\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource DefTextBox}\"\n                    TextWrapping=\"Wrap\"\n                    VerticalScrollBarVisibility=\"Auto\" />\n            </GroupBox>\n            <GridSplitter Grid.Column=\"3\" HorizontalAlignment=\"Stretch\" />\n            <GroupBox\n                Grid.Column=\"4\"\n                Header=\"{x:Static resx:ResUI.TbRoutingRuleProcess}\"\n                Style=\"{StaticResource MyGroupBox}\">\n                <TextBox\n                    Name=\"txtProcess\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource DefTextBox}\"\n                    TextWrapping=\"Wrap\"\n                    VerticalScrollBarVisibility=\"Auto\" />\n            </GroupBox>\n        </Grid>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/RoutingRuleDetailsWindow.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class RoutingRuleDetailsWindow\n{\n    public RoutingRuleDetailsWindow(RulesItem rulesItem)\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        Loaded += Window_Loaded;\n        clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;\n        clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;\n\n        ViewModel = new RoutingRuleDetailsViewModel(rulesItem, UpdateViewHandler);\n\n        cmbOutboundTag.ItemsSource = Global.OutboundTags;\n        clbProtocol.ItemsSource = Global.RuleProtocols;\n        clbInboundTag.ItemsSource = Global.InboundTags;\n        cmbNetwork.ItemsSource = Global.RuleNetworks;\n        cmbRuleType.ItemsSource = Utils.GetEnumNames<ERuleType>().AppendEmpty();\n\n        if (!rulesItem.Id.IsNullOrEmpty())\n        {\n            rulesItem.Protocol?.ForEach(it =>\n            {\n                clbProtocol.SelectedItems.Add(it);\n            });\n            rulesItem.InboundTag?.ForEach(it =>\n            {\n                clbInboundTag.SelectedItems.Add(it);\n            });\n        }\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Port, v => v.txtPort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Enabled, v => v.togEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Domain, v => v.txtDomain.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.IP, v => v.txtIP.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Process, v => v.txtProcess.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoSort, v => v.chkAutoSort.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.RuleType, v => v.cmbRuleType.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void ClbProtocol_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.ProtocolItems = clbProtocol.SelectedItems.Cast<string>().ToList();\n        }\n    }\n\n    private void ClbInboundTag_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.InboundTagItems = clbInboundTag.SelectedItems.Cast<string>().ToList();\n        }\n    }\n\n    private void linkRuleobjectDoc_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://xtls.github.io/config/routing.html#ruleobject\");\n    }\n\n    private async void BtnSelectProfile_Click(object sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);\n        if (selectWindow.ShowDialog() == true)\n        {\n            var profile = await selectWindow.ProfileItem;\n            if (profile != null)\n            {\n                cmbOutboundTag.Text = profile.Remarks;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.RoutingRuleSettingWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuRoutingRuleSetting}\"\n    Width=\"1000\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:RoutingRuleSettingViewModel\"\n    ResizeMode=\"CanResize\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel>\n        <ToolBarTray DockPanel.Dock=\"Top\">\n            <ToolBar\n                HorizontalAlignment=\"Center\"\n                VerticalAlignment=\"Center\"\n                ClipToBounds=\"True\"\n                Style=\"{StaticResource MaterialDesignToolBar}\">\n                <Button x:Name=\"menuRuleAdd\">\n                    <StackPanel Orientation=\"Horizontal\">\n                        <materialDesign:PackIcon\n                            Margin=\"{StaticResource MarginRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Kind=\"Plus\" />\n                        <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuRuleAdd}\" />\n                    </StackPanel>\n                </Button>\n                <Separator />\n                <Button x:Name=\"menuImportRulesFromFile\">\n                    <StackPanel Orientation=\"Horizontal\">\n                        <materialDesign:PackIcon\n                            Margin=\"{StaticResource MarginRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Kind=\"Import\" />\n                        <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuImportRulesFromFile}\" />\n                    </StackPanel>\n                </Button>\n                <Separator />\n                <Button x:Name=\"menuImportRulesFromClipboard\">\n                    <StackPanel Orientation=\"Horizontal\">\n                        <materialDesign:PackIcon\n                            Margin=\"{StaticResource MarginRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Kind=\"Import\" />\n                        <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuImportRulesFromClipboard}\" />\n                    </StackPanel>\n                </Button>\n                <Separator />\n                <Button x:Name=\"menuImportRulesFromUrl\">\n                    <StackPanel Orientation=\"Horizontal\">\n                        <materialDesign:PackIcon\n                            Margin=\"{StaticResource MarginRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Kind=\"Import\" />\n                        <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuImportRulesFromUrl}\" />\n                    </StackPanel>\n                </Button>\n            </ToolBar>\n        </ToolBarTray>\n\n        <StackPanel\n            Margin=\"{StaticResource Margin8}\"\n            HorizontalAlignment=\"Right\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <Grid Margin=\"{StaticResource Margin8}\" DockPanel.Dock=\"Top\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"Auto\" />\n                <ColumnDefinition Width=\"Auto\" />\n                <ColumnDefinition Width=\"Auto\" />\n            </Grid.ColumnDefinitions>\n            <TextBlock\n                Grid.Row=\"0\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.LvRemarks}\" />\n            <StackPanel\n                Grid.Row=\"0\"\n                Grid.Column=\"1\"\n                Orientation=\"Horizontal\">\n\n                <TextBox\n                    x:Name=\"txtRemarks\"\n                    Grid.Row=\"0\"\n                    Grid.Column=\"1\"\n                    Width=\"300\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource DefTextBox}\"\n                    TextWrapping=\"Wrap\" />\n\n                <TextBlock\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvSort}\" />\n                <TextBox\n                    x:Name=\"txtSort\"\n                    Width=\"100\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource DefTextBox}\" />\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbdomainStrategy}\" />\n            <StackPanel\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Orientation=\"Horizontal\">\n                <ComboBox\n                    x:Name=\"cmbdomainStrategy\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Style=\"{StaticResource DefComboBox}\" />\n                <TextBlock\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.TbdomainStrategy4Singbox}\" />\n                <ComboBox\n                    x:Name=\"cmbdomainStrategy4Singbox\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Style=\"{StaticResource DefComboBox}\" />\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"2\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.LvUrl}\" />\n            <TextBox\n                x:Name=\"txtUrl\"\n                Grid.Row=\"2\"\n                Grid.Column=\"1\"\n                Width=\"600\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                AcceptsReturn=\"True\"\n                Style=\"{StaticResource DefTextBox}\"\n                TextWrapping=\"Wrap\" />\n\n            <TextBlock\n                Grid.Row=\"3\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.LvCustomIcon}\" />\n            <TextBox\n                x:Name=\"txtCustomIcon\"\n                Grid.Row=\"3\"\n                Grid.Column=\"1\"\n                Width=\"600\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                AcceptsReturn=\"True\"\n                Style=\"{StaticResource DefTextBox}\"\n                TextWrapping=\"Wrap\" />\n            <Button\n                x:Name=\"btnBrowseCustomIcon\"\n                Grid.Row=\"3\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource MarginLeftRight4}\"\n                Content=\"{x:Static resx:ResUI.TbBrowse}\"\n                Style=\"{StaticResource DefButton}\" />\n\n            <TextBlock\n                Grid.Row=\"4\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\">\n                <Hyperlink Click=\"linkCustomRulesetPath4Singbox\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.LvCustomRulesetPath4Singbox}\" />\n                    <materialDesign:PackIcon Kind=\"Link\" />\n                </Hyperlink>\n            </TextBlock>\n            <TextBox\n                x:Name=\"txtCustomRulesetPath4Singbox\"\n                Grid.Row=\"4\"\n                Grid.Column=\"1\"\n                Width=\"600\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                AcceptsReturn=\"True\"\n                Style=\"{StaticResource DefTextBox}\"\n                TextWrapping=\"Wrap\" />\n            <Button\n                x:Name=\"btnBrowseCustomRulesetPath4Singbox\"\n                Grid.Row=\"4\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource MarginLeftRight4}\"\n                Content=\"{x:Static resx:ResUI.TbBrowse}\"\n                Style=\"{StaticResource DefButton}\" />\n        </Grid>\n\n        <TabControl x:Name=\"tabAdvanced\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuRuleList}\">\n                <DataGrid\n                    x:Name=\"lstRules\"\n                    AutoGenerateColumns=\"False\"\n                    BorderThickness=\"1\"\n                    CanUserAddRows=\"False\"\n                    CanUserResizeRows=\"False\"\n                    CanUserSortColumns=\"False\"\n                    EnableRowVirtualization=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    Style=\"{StaticResource DefDataGrid}\">\n                    <DataGrid.ContextMenu>\n                        <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                            <MenuItem\n                                x:Name=\"menuRuleAdd2\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRuleAdd}\" />\n                            <MenuItem\n                                x:Name=\"menuRuleRemove\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRuleRemove}\"\n                                InputGestureText=\"Back\" />\n                            <MenuItem\n                                x:Name=\"menuRuleSelectAll\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                                InputGestureText=\"Ctrl+A\" />\n                            <MenuItem\n                                x:Name=\"menuRuleExportSelected\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRuleExportSelected}\" />\n                            <Separator />\n                            <MenuItem\n                                x:Name=\"menuMoveTop\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveTop}\"\n                                InputGestureText=\"T\" />\n                            <MenuItem\n                                x:Name=\"menuMoveUp\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveUp}\"\n                                InputGestureText=\"U\" />\n                            <MenuItem\n                                x:Name=\"menuMoveDown\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveDown}\"\n                                InputGestureText=\"D\" />\n                            <MenuItem\n                                x:Name=\"menuMoveBottom\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuMoveBottom}\"\n                                InputGestureText=\"B\" />\n                        </ContextMenu>\n                    </DataGrid.ContextMenu>\n                    <DataGrid.Columns>\n                        <DataGridCheckBoxColumn\n                            Width=\"60\"\n                            Binding=\"{Binding Enabled}\"\n                            Header=\"\" />\n                        <DataGridTextColumn\n                            Width=\"150\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding RuleTypeName}\"\n                            Header=\"{x:Static resx:ResUI.TbRuleType}\" />\n                        <DataGridTextColumn\n                            Width=\"130\"\n                            Binding=\"{Binding OutboundTag}\"\n                            Header=\"outboundTag\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            Header=\"port\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Protocols}\"\n                            Header=\"protocol\" />\n                        <DataGridTextColumn\n                            Width=\"120\"\n                            Binding=\"{Binding InboundTags}\"\n                            Header=\"inboundTag\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            Header=\"network\" />\n                        <DataGridTextColumn\n                            Width=\"*\"\n                            Binding=\"{Binding Domains}\"\n                            Header=\"domain / ip / process\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/RoutingRuleSettingWindow.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class RoutingRuleSettingWindow\n{\n    public RoutingRuleSettingWindow(RoutingItem routingItem)\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        Loaded += Window_Loaded;\n        PreviewKeyDown += RoutingRuleSettingWindow_PreviewKeyDown;\n        lstRules.SelectionChanged += lstRules_SelectionChanged;\n        lstRules.MouseDoubleClick += LstRules_MouseDoubleClick;\n        menuRuleSelectAll.Click += menuRuleSelectAll_Click;\n        btnBrowseCustomIcon.Click += btnBrowseCustomIcon_Click;\n        btnBrowseCustomRulesetPath4Singbox.Click += btnBrowseCustomRulesetPath4Singbox_Click;\n\n        ViewModel = new RoutingRuleSettingViewModel(routingItem, UpdateViewHandler);\n\n        cmbdomainStrategy.ItemsSource = Global.DomainStrategies.AppendEmpty();\n        cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Sbox;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.RulesItems, v => v.lstRules.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRules.SelectedItem).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedRouting.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.DomainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.DomainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedRouting.Url, v => v.txtUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.CustomIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.CustomRulesetPath4Singbox, v => v.txtCustomRulesetPath4Singbox.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.Sort, v => v.txtSort.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportRulesFromFileCmd, v => v.menuImportRulesFromFile).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportRulesFromClipboardCmd, v => v.menuImportRulesFromClipboard).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportRulesFromUrlCmd, v => v.menuImportRulesFromUrl).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RuleRemoveCmd, v => v.menuRuleRemove).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RuleExportSelectedCmd, v => v.menuRuleExportSelected).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n\n            case EViewAction.ShowYesNo:\n\n                if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.AddBatchRoutingRulesYesNo:\n\n                if (UI.ShowYesNo(ResUI.AddBatchRoutingRulesYesNo) == MessageBoxResult.No)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.RoutingRuleDetailsWindow:\n\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new RoutingRuleDetailsWindow((RulesItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.ImportRulesFromFile:\n\n                if (UI.OpenFileDialog(out var fileName, \"Rules|*.json|All|*.*\") != true)\n                {\n                    return false;\n                }\n                ViewModel?.ImportRulesFromFileAsync(fileName);\n                break;\n\n            case EViewAction.SetClipboardData:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                WindowsUtils.SetClipboardData((string)obj);\n                break;\n\n            case EViewAction.ImportRulesFromClipboard:\n                var clipboardData = WindowsUtils.GetClipboardData();\n                if (clipboardData.IsNotEmpty())\n                {\n                    ViewModel?.ImportRulesFromClipboardAsync(clipboardData);\n                }\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void RoutingRuleSettingWindow_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (!lstRules.IsKeyboardFocusWithin)\n        {\n            return;\n        }\n\n        if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))\n        {\n            if (e.Key == Key.A)\n            {\n                lstRules.SelectAll();\n            }\n            else if (e.Key == Key.C)\n            {\n                ViewModel?.RuleExportSelectedAsync();\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.T:\n                    ViewModel?.MoveRule(EMove.Top);\n                    break;\n\n                case Key.U:\n                    ViewModel?.MoveRule(EMove.Up);\n                    break;\n\n                case Key.D:\n                    ViewModel?.MoveRule(EMove.Down);\n                    break;\n\n                case Key.B:\n                    ViewModel?.MoveRule(EMove.Bottom);\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.RuleRemoveAsync();\n                    break;\n            }\n        }\n    }\n\n    private void lstRules_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedSources = lstRules.SelectedItems.Cast<RulesItemModel>().ToList();\n        }\n    }\n\n    private void LstRules_MouseDoubleClick(object sender, MouseButtonEventArgs e)\n    {\n        ViewModel?.RuleEditAsync(false);\n    }\n\n    private void menuRuleSelectAll_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        lstRules.SelectAll();\n    }\n\n    private void btnBrowseCustomIcon_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        if (UI.OpenFileDialog(out var fileName,\n            \"PNG,ICO|*.png;*.ico\") != true)\n        {\n            return;\n        }\n\n        txtCustomIcon.Text = fileName;\n    }\n\n    private void btnBrowseCustomRulesetPath4Singbox_Click(object sender, RoutedEventArgs e)\n    {\n        if (UI.OpenFileDialog(out var fileName,\n              \"Config|*.json|All|*.*\") != true)\n        {\n            return;\n        }\n\n        txtCustomRulesetPath4Singbox.Text = fileName;\n    }\n\n    private void linkCustomRulesetPath4Singbox(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://github.com/2dust/v2rayCustomRoutingList/blob/master/singbox_custom_ruleset_example.json\");\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/RoutingSettingWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.RoutingSettingWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuRoutingSetting}\"\n    Width=\"1000\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:RoutingSettingViewModel\"\n    ResizeMode=\"CanResize\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <Window.Resources>\n        <ResourceDictionary>\n            <BooleanToVisibilityConverter x:Key=\"BoolToVisConverter\" />\n        </ResourceDictionary>\n    </Window.Resources>\n    <DockPanel>\n        <ToolBarTray DockPanel.Dock=\"Top\">\n            <ToolBar\n                HorizontalAlignment=\"Center\"\n                VerticalAlignment=\"Center\"\n                ClipToBounds=\"True\"\n                Style=\"{StaticResource MaterialDesignToolBar}\">\n                <Button x:Name=\"menuRoutingAdvancedAdd2\">\n                    <StackPanel Orientation=\"Horizontal\">\n                        <materialDesign:PackIcon\n                            Margin=\"{StaticResource MarginRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Kind=\"Plus\" />\n                        <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuRoutingAdvancedAdd}\" />\n                    </StackPanel>\n                </Button>\n                <Separator />\n                <Button x:Name=\"menuRoutingAdvancedImportRules2\">\n                    <StackPanel Orientation=\"Horizontal\">\n                        <materialDesign:PackIcon\n                            Margin=\"{StaticResource MarginRight8}\"\n                            VerticalAlignment=\"Center\"\n                            Kind=\"Import\" />\n                        <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuRoutingAdvancedImportRules}\" />\n                    </StackPanel>\n                </Button>\n            </ToolBar>\n        </ToolBarTray>\n\n        <StackPanel\n            Margin=\"{StaticResource Margin8}\"\n            HorizontalAlignment=\"Right\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n\n        <Grid Margin=\"{StaticResource Margin8}\" DockPanel.Dock=\"Top\">\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"Auto\" />\n                <ColumnDefinition Width=\"Auto\" />\n            </Grid.ColumnDefinitions>\n\n            <TextBlock\n                Grid.Row=\"0\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\">\n                <Hyperlink Click=\"linkdomainStrategy_Click\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.TbdomainStrategy}\" />\n                    <materialDesign:PackIcon Kind=\"Link\" />\n                </Hyperlink>\n            </TextBlock>\n            <ComboBox\n                x:Name=\"cmbdomainStrategy\"\n                Grid.Row=\"0\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                Style=\"{StaticResource DefComboBox}\" />\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\">\n                <Hyperlink Click=\"linkdomainStrategy4Singbox_Click\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.TbdomainStrategy4Singbox}\" />\n                    <materialDesign:PackIcon Kind=\"Link\" />\n                </Hyperlink>\n            </TextBlock>\n            <ComboBox\n                x:Name=\"cmbdomainStrategy4Singbox\"\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                Style=\"{StaticResource DefComboBox}\" />\n        </Grid>\n\n        <TabControl x:Name=\"tabAdvanced\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.TbRoutingTabRuleList}\">\n                <DataGrid\n                    x:Name=\"lstRoutings\"\n                    AutoGenerateColumns=\"False\"\n                    BorderThickness=\"1\"\n                    CanUserAddRows=\"False\"\n                    CanUserResizeRows=\"False\"\n                    CanUserSortColumns=\"False\"\n                    EnableRowVirtualization=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    Style=\"{StaticResource DefDataGrid}\">\n                    <DataGrid.ContextMenu>\n                        <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedAdd\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRoutingAdvancedAdd}\" />\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedRemove\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRoutingAdvancedRemove}\"\n                                InputGestureText=\"Back\" />\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedSelectAll\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                                InputGestureText=\"Ctrl+A\" />\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedSetDefault\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRoutingAdvancedSetDefault}\"\n                                InputGestureText=\"Enter\" />\n                            <Separator />\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedImportRules\"\n                                Height=\"{StaticResource MenuItemHeight}\"\n                                Header=\"{x:Static resx:ResUI.menuRoutingAdvancedImportRules}\" />\n                        </ContextMenu>\n                    </DataGrid.ContextMenu>\n                    <DataGrid.Resources>\n                        <Style BasedOn=\"{StaticResource MaterialDesignDataGridCell}\" TargetType=\"DataGridCell\">\n                            <Style.Triggers>\n                                <DataTrigger Binding=\"{Binding IsActive}\" Value=\"True\">\n                                    <Setter Property=\"Background\" Value=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\" />\n                                    <Setter Property=\"Foreground\" Value=\"Black\" />\n                                    <Setter Property=\"BorderBrush\" Value=\"{DynamicResource MaterialDesign.Brush.Primary.Light}\" />\n                                </DataTrigger>\n                            </Style.Triggers>\n                        </Style>\n                    </DataGrid.Resources>\n                    <DataGrid.Columns>\n                        <DataGridTextColumn\n                            Width=\"*\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"60\"\n                            Binding=\"{Binding RuleNum}\"\n                            Header=\"{x:Static resx:ResUI.LvCount}\" />\n                        <DataGridTextColumn\n                            Width=\"60\"\n                            Binding=\"{Binding Sort}\"\n                            Header=\"{x:Static resx:ResUI.LvSort}\" />\n                        <DataGridTextColumn\n                            Width=\"*\"\n                            Binding=\"{Binding Url}\"\n                            Header=\"{x:Static resx:ResUI.LvUrl}\" />\n                        <DataGridTextColumn\n                            Width=\"300\"\n                            Binding=\"{Binding CustomIcon}\"\n                            Header=\"{x:Static resx:ResUI.LvCustomIcon}\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/RoutingSettingWindow.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class RoutingSettingWindow\n{\n    public RoutingSettingWindow()\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        Closing += RoutingSettingWindow_Closing;\n        PreviewKeyDown += RoutingSettingWindow_PreviewKeyDown;\n        lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;\n        lstRoutings.MouseDoubleClick += LstRoutings_MouseDoubleClick;\n        menuRoutingAdvancedSelectAll.Click += menuRoutingAdvancedSelectAll_Click;\n        btnCancel.Click += btnCancel_Click;\n\n        ViewModel = new RoutingSettingViewModel(UpdateViewHandler);\n\n        cmbdomainStrategy.ItemsSource = Global.DomainStrategies;\n        cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Sbox;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.DomainStrategy, v => v.cmbdomainStrategy.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedRemoveCmd, v => v.menuRoutingAdvancedRemove).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedSetDefaultCmd, v => v.menuRoutingAdvancedSetDefault).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules2).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n\n            case EViewAction.ShowYesNo:\n                if (UI.ShowYesNo(ResUI.RemoveRules) == MessageBoxResult.No)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.RoutingRuleSettingWindow:\n\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new RoutingRuleSettingWindow((RoutingItem)obj).ShowDialog() ?? false;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void RoutingSettingWindow_Closing(object? sender, System.ComponentModel.CancelEventArgs e)\n    {\n        if (ViewModel?.IsModified == true)\n        {\n            DialogResult = true;\n        }\n    }\n\n    private void RoutingSettingWindow_PreviewKeyDown(object sender, KeyEventArgs e)\n    {\n        if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))\n        {\n            switch (e.Key)\n            {\n                case Key.A:\n                    lstRoutings.SelectAll();\n                    break;\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.Enter:\n                    //case Key.Return:\n                    ViewModel?.RoutingAdvancedSetDefault();\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.RoutingAdvancedRemoveAsync();\n                    break;\n            }\n        }\n    }\n\n    private void menuRoutingAdvancedSelectAll_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        lstRoutings.SelectAll();\n    }\n\n    private void lstRoutings_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedSources = lstRoutings.SelectedItems.Cast<RoutingItemModel>().ToList();\n        }\n    }\n\n    private void LstRoutings_MouseDoubleClick(object sender, MouseButtonEventArgs e)\n    {\n        ViewModel?.RoutingAdvancedEditAsync(false);\n    }\n\n    private void linkdomainStrategy_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://xtls.github.io/config/routing.html\");\n    }\n\n    private void linkdomainStrategy4Singbox_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://sing-box.sagernet.org/zh/configuration/route/rule_action/#strategy\");\n    }\n\n    private void btnCancel_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        if (ViewModel?.IsModified == true)\n        {\n            DialogResult = true;\n        }\n        else\n        {\n            Close();\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/StatusBarView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.StatusBarView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:tb=\"clr-namespace:H.NotifyIcon;assembly=H.NotifyIcon.Wpf\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:StatusBarViewModel\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n    <Grid>\n        <materialDesign:ColorZone\n            Height=\"auto\"\n            Margin=\"{StaticResource Margin4}\"\n            Mode=\"Standard\">\n            <DockPanel>\n                <StackPanel\n                    Margin=\"{StaticResource MarginLeftRight8}\"\n                    VerticalAlignment=\"Center\"\n                    DockPanel.Dock=\"Right\">\n                    <TextBlock\n                        x:Name=\"txtSpeedProxyDisplay\"\n                        HorizontalAlignment=\"Right\"\n                        Style=\"{StaticResource StatusbarItem}\" />\n                    <Border Margin=\"1\" />\n                    <TextBlock\n                        x:Name=\"txtSpeedDirectDisplay\"\n                        HorizontalAlignment=\"Right\"\n                        Style=\"{StaticResource StatusbarItem}\" />\n                </StackPanel>\n\n                <StackPanel\n                    Width=\"Auto\"\n                    Margin=\"{StaticResource MarginLeftRight8}\"\n                    VerticalAlignment=\"Center\"\n                    DockPanel.Dock=\"Left\">\n                    <TextBlock x:Name=\"txtInboundDisplay\" Style=\"{StaticResource StatusbarItem}\" />\n                    <Border Margin=\"1\" />\n                    <TextBlock x:Name=\"txtInboundLanDisplay\" Style=\"{StaticResource StatusbarItem}\" />\n                </StackPanel>\n\n                <StackPanel\n                    x:Name=\"spEnableTun\"\n                    Width=\"Auto\"\n                    Margin=\"{StaticResource MarginLeftRight8}\"\n                    VerticalAlignment=\"Center\"\n                    DockPanel.Dock=\"Left\"\n                    Orientation=\"Horizontal\">\n                    <TextBlock\n                        Margin=\"{StaticResource MarginLeftRight8}\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource StatusbarItem}\"\n                        Text=\"{x:Static resx:ResUI.TbEnableTunAs}\" />\n                    <ToggleButton\n                        x:Name=\"togEnableTun\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        VerticalAlignment=\"Center\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.TbEnableTunAs}\" />\n                </StackPanel>\n\n                <StackPanel\n                    Margin=\"{StaticResource MarginLeftRight8}\"\n                    VerticalAlignment=\"Center\"\n                    DockPanel.Dock=\"Left\"\n                    Orientation=\"Horizontal\">\n                    <ComboBox\n                        x:Name=\"cmbSystemProxy\"\n                        Width=\"160\"\n                        Margin=\"{StaticResource MarginLeftRight8}\"\n                        materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.menuSystemproxy}\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuSystemproxy}\"\n                        FontSize=\"{DynamicResource StdFontSize}\"\n                        Style=\"{StaticResource MaterialDesignFloatingHintComboBox}\">\n                        <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxyClear}\" />\n                        <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxySet}\" />\n                        <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxyNothing}\" />\n                        <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxyPac}\" />\n                    </ComboBox>\n\n                    <ComboBox\n                        x:Name=\"cmbRoutings2\"\n                        Width=\"160\"\n                        Margin=\"{StaticResource MarginLeftRight8}\"\n                        materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.menuRouting}\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuRouting}\"\n                        DisplayMemberPath=\"Remarks\"\n                        FontSize=\"{DynamicResource StdFontSize}\"\n                        Style=\"{StaticResource MaterialDesignFloatingHintComboBox}\" />\n                </StackPanel>\n\n                <StackPanel Margin=\"{StaticResource MarginLeftRight8}\" VerticalAlignment=\"Center\">\n                    <TextBlock x:Name=\"txtRunningServerDisplay\" Style=\"{StaticResource StatusbarItem}\" />\n                    <Border Margin=\"1\" />\n                    <TextBlock x:Name=\"txtRunningInfoDisplay\" Style=\"{StaticResource StatusbarItem}\" />\n                </StackPanel>\n            </DockPanel>\n        </materialDesign:ColorZone>\n\n        <tb:TaskbarIcon\n            x:Name=\"tbNotify\"\n            IconSource=\"/Resources/v2rayN.ico\"\n            NoLeftClickDelay=\"True\"\n            ToolTipText=\"v2rayN\">\n            <tb:TaskbarIcon.ContextMenu>\n                <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                    <MenuItem\n                        x:Name=\"menuSystemProxyClear\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuSystemProxyClear}\">\n                        <MenuItem.Header>\n                            <StackPanel Orientation=\"Horizontal\">\n                                <materialDesign:PackIcon\n                                    x:Name=\"menuSystemProxyClear2\"\n                                    Margin=\"{StaticResource MarginRight8}\"\n                                    VerticalAlignment=\"Center\"\n                                    Kind=\"Check\" />\n                                <TextBlock Text=\"{x:Static resx:ResUI.menuSystemProxyClear}\" />\n                            </StackPanel>\n                        </MenuItem.Header>\n                    </MenuItem>\n                    <MenuItem\n                        x:Name=\"menuSystemProxySet\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuSystemProxySet}\">\n                        <MenuItem.Header>\n                            <StackPanel Orientation=\"Horizontal\">\n                                <materialDesign:PackIcon\n                                    x:Name=\"menuSystemProxySet2\"\n                                    Margin=\"{StaticResource MarginRight8}\"\n                                    VerticalAlignment=\"Center\"\n                                    Kind=\"Check\" />\n                                <TextBlock Text=\"{x:Static resx:ResUI.menuSystemProxySet}\" />\n                            </StackPanel>\n                        </MenuItem.Header>\n                    </MenuItem>\n                    <MenuItem\n                        x:Name=\"menuSystemProxyNothing\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuSystemProxyNothing}\">\n                        <MenuItem.Header>\n                            <StackPanel Orientation=\"Horizontal\">\n                                <materialDesign:PackIcon\n                                    x:Name=\"menuSystemProxyNothing2\"\n                                    Margin=\"{StaticResource MarginRight8}\"\n                                    VerticalAlignment=\"Center\"\n                                    Kind=\"Check\" />\n                                <TextBlock Text=\"{x:Static resx:ResUI.menuSystemProxyNothing}\" />\n                            </StackPanel>\n                        </MenuItem.Header>\n                    </MenuItem>\n                    <MenuItem\n                        x:Name=\"menuSystemProxyPac\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuSystemProxyPac}\">\n                        <MenuItem.Header>\n                            <StackPanel Orientation=\"Horizontal\">\n                                <materialDesign:PackIcon\n                                    x:Name=\"menuSystemProxyPac2\"\n                                    Margin=\"{StaticResource MarginRight8}\"\n                                    VerticalAlignment=\"Center\"\n                                    Kind=\"Check\" />\n                                <TextBlock Text=\"{x:Static resx:ResUI.menuSystemProxyPac}\" />\n                            </StackPanel>\n                        </MenuItem.Header>\n                    </MenuItem>\n                    <Separator x:Name=\"sepRoutings\" />\n                    <MenuItem\n                        x:Name=\"menuRoutings\"\n                        Height=\"Auto\"\n                        AutomationProperties.Name=\"{x:Static resx:ResUI.menuRouting}\">\n                        <MenuItem.Header>\n                            <DockPanel>\n                                <ComboBox\n                                    x:Name=\"cmbRoutings\"\n                                    MaxWidth=\"300\"\n                                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.menuRouting}\"\n                                    AutomationProperties.Name=\"{x:Static resx:ResUI.menuRouting}\"\n                                    DisplayMemberPath=\"Remarks\"\n                                    FontSize=\"{DynamicResource StdFontSize}\"\n                                    Style=\"{StaticResource MaterialDesignFilledComboBox}\" />\n                            </DockPanel>\n                        </MenuItem.Header>\n                    </MenuItem>\n                    <MenuItem Height=\"Auto\" AutomationProperties.Name=\"{x:Static resx:ResUI.menuServers}\">\n                        <MenuItem.Header>\n                            <DockPanel>\n                                <ComboBox\n                                    x:Name=\"cmbServers\"\n                                    MaxWidth=\"300\"\n                                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.menuServers}\"\n                                    AutomationProperties.Name=\"{x:Static resx:ResUI.menuServers}\"\n                                    DisplayMemberPath=\"Text\"\n                                    FontSize=\"{DynamicResource StdFontSize}\"\n                                    Style=\"{StaticResource MaterialDesignFilledComboBox}\" />\n                            </DockPanel>\n                        </MenuItem.Header>\n                    </MenuItem>\n                    <Separator />\n                    <MenuItem\n                        x:Name=\"menuAddServerViaClipboard2\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuAddServerViaClipboard}\" />\n                    <MenuItem\n                        x:Name=\"menuAddServerViaScan2\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuAddServerViaScan}\" />\n                    <MenuItem\n                        x:Name=\"menuSubUpdate2\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuSubUpdate}\" />\n                    <MenuItem\n                        x:Name=\"menuSubUpdateViaProxy2\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuSubUpdateViaProxy}\" />\n                    <Separator />\n                    <MenuItem\n                        x:Name=\"menuCopyProxyCmdToClipboard\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuCopyProxyCmdToClipboard}\" />\n                    <Separator />\n                    <MenuItem\n                        x:Name=\"menuExit\"\n                        Height=\"{StaticResource MenuItemHeight}\"\n                        Header=\"{x:Static resx:ResUI.menuExit}\" />\n                </ContextMenu>\n            </tb:TaskbarIcon.ContextMenu>\n        </tb:TaskbarIcon>\n    </Grid>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/StatusBarView.xaml.cs",
    "content": "using v2rayN.Manager;\n\nnamespace v2rayN.Views;\n\npublic partial class StatusBarView\n{\n    private static Config _config;\n\n    public StatusBarView()\n    {\n        InitializeComponent();\n        _config = AppManager.Instance.Config;\n        ViewModel = StatusBarViewModel.Instance;\n        ViewModel?.InitUpdateView(UpdateViewHandler);\n\n        menuExit.Click += menuExit_Click;\n        txtRunningServerDisplay.PreviewMouseDown += txtRunningInfoDisplay_MouseDoubleClick;\n        txtRunningInfoDisplay.PreviewMouseDown += txtRunningInfoDisplay_MouseDoubleClick;\n\n        this.WhenActivated(disposables =>\n        {\n            //system proxy\n            this.OneWayBind(ViewModel, vm => vm.BlSystemProxyClear, v => v.menuSystemProxyClear2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlSystemProxySet, v => v.menuSystemProxySet2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlSystemProxyNothing, v => v.menuSystemProxyNothing2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlSystemProxyPac, v => v.menuSystemProxyPac2.Visibility, conversionHint: BooleanToVisibilityHint.UseHidden, vmToViewConverterOverride: new BooleanToVisibilityTypeConverter()).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SystemProxyClearCmd, v => v.menuSystemProxyClear).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SystemProxySetCmd, v => v.menuSystemProxySet).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SystemProxyNothingCmd, v => v.menuSystemProxyNothing).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SystemProxyPacCmd, v => v.menuSystemProxyPac).DisposeWith(disposables);\n\n            //routings and servers\n            this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.cmbRoutings.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings.SelectedItem).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlRouting, v => v.menuRoutings.Visibility).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlRouting, v => v.sepRoutings.Visibility).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.Servers, v => v.cmbServers.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedServer, v => v.cmbServers.SelectedItem).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlServers, v => v.cmbServers.Visibility).DisposeWith(disposables);\n\n            //tray menu\n            this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubUpdateCmd, v => v.menuSubUpdate2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy2).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.CopyProxyCmdToClipboardCmd, v => v.menuCopyProxyCmdToClipboard).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.RunningServerToolTipText, v => v.tbNotify.ToolTipText).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.NotifyLeftClickCmd, v => v.tbNotify.LeftClickCommand).DisposeWith(disposables);\n\n            //status bar\n            this.OneWayBind(ViewModel, vm => vm.InboundDisplay, v => v.txtInboundDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.InboundLanDisplay, v => v.txtInboundLanDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.RunningServerDisplay, v => v.txtRunningServerDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.RunningInfoDisplay, v => v.txtRunningInfoDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.SpeedProxyDisplay, v => v.txtSpeedProxyDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.SpeedDirectDisplay, v => v.txtSpeedDirectDisplay.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableTun, v => v.togEnableTun.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SystemProxySelected, v => v.cmbSystemProxy.SelectedIndex).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.cmbRoutings2.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlRouting, v => v.cmbRoutings2.Visibility).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.DispatcherRefreshIcon:\n                Application.Current?.Dispatcher.Invoke(async () =>\n                {\n                    tbNotify.Icon = await WindowsManager.Instance.GetNotifyIcon(_config);\n                    Application.Current.MainWindow.Icon = WindowsManager.Instance.GetAppIcon(_config);\n                }, DispatcherPriority.Normal);\n                break;\n\n            case EViewAction.SetClipboardData:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                WindowsUtils.SetClipboardData((string)obj);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private async void menuExit_Click(object sender, RoutedEventArgs e)\n    {\n        tbNotify.Dispose();\n        await AppManager.Instance.AppExitAsync(true);\n    }\n\n    private void txtRunningInfoDisplay_MouseDoubleClick(object sender, MouseButtonEventArgs e)\n    {\n        ViewModel?.TestServerAvailability();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/SubEditWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.SubEditWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuSubSetting}\"\n    Width=\"700\"\n    Height=\"650\"\n    x:TypeArguments=\"vms:SubEditViewModel\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <Window.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceDictionary Source=\"pack://application:,,,/MaterialDesignThemes.Wpf;component/Themes/MaterialDesignTheme.Popupbox.xaml\" />\n            </ResourceDictionary.MergedDictionaries>\n        </ResourceDictionary>\n    </Window.Resources>\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\"\n                Style=\"{StaticResource DefButton}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLeftRight8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"true\"\n                Style=\"{StaticResource DefButton}\" />\n        </StackPanel>\n        <ScrollViewer\n            materialDesign:ScrollViewerAssist.IsAutoHideEnabled=\"True\"\n            HorizontalScrollBarVisibility=\"Auto\"\n            VerticalScrollBarVisibility=\"Auto\">\n\n            <Grid>\n                <Grid.RowDefinitions>\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                    <RowDefinition Height=\"Auto\" />\n                </Grid.RowDefinitions>\n                <Grid.ColumnDefinitions>\n                    <ColumnDefinition Width=\"Auto\" />\n                    <ColumnDefinition Width=\"400\" />\n                    <ColumnDefinition Width=\"Auto\" />\n                </Grid.ColumnDefinitions>\n\n                <TextBlock\n                    Grid.Row=\"0\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Style=\"{StaticResource ModuleTitle}\"\n                    Text=\"{x:Static resx:ResUI.menuSubscription}\" />\n\n                <TextBlock\n                    Grid.Row=\"1\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvRemarks}\" />\n\n                <TextBox\n                    x:Name=\"txtRemarks\"\n                    Grid.Row=\"1\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\"\n                    TextWrapping=\"Wrap\" />\n\n                <TextBlock\n                    Grid.Row=\"2\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvUrl}\" />\n                <TextBox\n                    x:Name=\"txtUrl\"\n                    Grid.Row=\"2\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.SubUrlTips}\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\"\n                    TextWrapping=\"Wrap\" />\n\n                <materialDesign:PopupBox\n                    Grid.Row=\"2\"\n                    Grid.Column=\"2\"\n                    HorizontalAlignment=\"Left\"\n                    StaysOpen=\"True\"\n                    Style=\"{StaticResource MaterialDesignToolForegroundPopupBox}\">\n                    <StackPanel>\n                        <TextBlock\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Style=\"{StaticResource ToolbarTextBlock}\"\n                            Text=\"{x:Static resx:ResUI.LvMoreUrl}\" />\n                        <TextBox\n                            x:Name=\"txtMoreUrl\"\n                            Width=\"400\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.SubUrlTips}\"\n                            AcceptsReturn=\"True\"\n                            MinLines=\"4\"\n                            Style=\"{StaticResource MyOutlinedTextBox}\"\n                            TextWrapping=\"Wrap\" />\n                    </StackPanel>\n                </materialDesign:PopupBox>\n\n                <TextBlock\n                    Grid.Row=\"3\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvEnabled}\" />\n\n                <DockPanel\n                    Grid.Row=\"3\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\">\n                    <ToggleButton\n                        x:Name=\"togEnable\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        DockPanel.Dock=\"Left\" />\n\n                    <TextBox\n                        x:Name=\"txtAutoUpdateInterval\"\n                        Width=\"100\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.SubUrlTips}\"\n                        AcceptsReturn=\"True\"\n                        DockPanel.Dock=\"Right\"\n                        Style=\"{StaticResource MyOutlinedTextBox}\" />\n\n                    <TextBlock\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Center\"\n                        VerticalAlignment=\"Center\"\n                        Style=\"{StaticResource ToolbarTextBlock}\"\n                        Text=\"{x:Static resx:ResUI.LvAutoUpdateInterval}\" />\n                </DockPanel>\n\n                <TextBlock\n                    Grid.Row=\"5\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvFilter}\" />\n                <TextBox\n                    x:Name=\"txtFilter\"\n                    Grid.Row=\"5\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.SubUrlTips}\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\" />\n\n                <TextBlock\n                    Grid.Row=\"6\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvConvertTarget}\" />\n                <ComboBox\n                    x:Name=\"cmbConvertTarget\"\n                    Grid.Row=\"6\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.LvConvertTargetTip}\"\n                    MaxDropDownHeight=\"1000\"\n                    Style=\"{StaticResource MyOutlinedTextComboBox}\" />\n\n                <TextBlock\n                    Grid.Row=\"7\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvUserAgent}\" />\n                <TextBox\n                    x:Name=\"txtUserAgent\"\n                    Grid.Row=\"7\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.SubUrlTips}\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\"\n                    TextWrapping=\"Wrap\" />\n\n                <TextBlock\n                    Grid.Row=\"8\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvSort}\" />\n                <TextBox\n                    x:Name=\"txtSort\"\n                    Grid.Row=\"8\"\n                    Grid.Column=\"1\"\n                    Width=\"100\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\" />\n\n                <TextBlock\n                    Grid.Row=\"9\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvPrevProfile}\" />\n                <TextBox\n                    x:Name=\"txtPrevProfile\"\n                    Grid.Row=\"9\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.LvPrevProfileTip}\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\" />\n                <Button\n                    Grid.Row=\"9\"\n                    Grid.Column=\"2\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Click=\"BtnSelectPrevProfile_Click\"\n                    Content=\"{x:Static resx:ResUI.TbSelectProfile}\"\n                    Style=\"{StaticResource DefButton}\" />\n\n                <TextBlock\n                    Grid.Row=\"10\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvNextProfile}\" />\n                <TextBox\n                    x:Name=\"txtNextProfile\"\n                    Grid.Row=\"10\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.LvPrevProfileTip}\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\" />\n                <Button\n                    Grid.Row=\"10\"\n                    Grid.Column=\"2\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Click=\"BtnSelectNextProfile_Click\"\n                    Content=\"{x:Static resx:ResUI.TbSelectProfile}\"\n                    Style=\"{StaticResource DefButton}\" />\n\n                <TextBlock\n                    Grid.Row=\"11\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.TbPreSocksPort4Sub}\" />\n                <TextBox\n                    x:Name=\"txtPreSocksPort\"\n                    Grid.Row=\"11\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    materialDesign:HintAssist.Hint=\"{x:Static resx:ResUI.TipPreSocksPort}\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\"\n                    ToolTip=\"{x:Static resx:ResUI.TipPreSocksPort}\" />\n\n                <TextBlock\n                    Grid.Row=\"12\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Style=\"{StaticResource ToolbarTextBlock}\"\n                    Text=\"{x:Static resx:ResUI.LvMemo}\" />\n                <TextBox\n                    x:Name=\"txtMemo\"\n                    Grid.Row=\"12\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    AcceptsReturn=\"True\"\n                    Style=\"{StaticResource MyOutlinedTextBox}\"\n                    TextWrapping=\"Wrap\" />\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/SubEditWindow.xaml.cs",
    "content": "namespace v2rayN.Views;\n\npublic partial class SubEditWindow\n{\n    public SubEditWindow(SubItem subItem)\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n        Loaded += Window_Loaded;\n\n        ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);\n\n        cmbConvertTarget.ItemsSource = Global.SubConvertTargets;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Url, v => v.txtUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.MoreUrl, v => v.txtMoreUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Enabled, v => v.togEnable.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.AutoUpdateInterval, v => v.txtAutoUpdateInterval.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.UserAgent, v => v.txtUserAgent.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Sort, v => v.txtSort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Filter, v => v.txtFilter.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.ConvertTarget, v => v.cmbConvertTarget.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PrevProfile, v => v.txtPrevProfile.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.NextProfile, v => v.txtNextProfile.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Memo, v => v.txtMemo.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private async void BtnSelectPrevProfile_Click(object sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter([EConfigType.Custom], exclude: true);\n        if (selectWindow.ShowDialog() == true)\n        {\n            var profile = await selectWindow.ProfileItem;\n            if (profile != null)\n            {\n                txtPrevProfile.Text = profile.Remarks;\n            }\n        }\n    }\n\n    private async void BtnSelectNextProfile_Click(object sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter([EConfigType.Custom], exclude: true);\n        if (selectWindow.ShowDialog() == true)\n        {\n            var profile = await selectWindow.ProfileItem;\n            if (profile != null)\n            {\n                txtNextProfile.Text = profile.Remarks;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/SubSettingWindow.xaml",
    "content": "<base:WindowBase\n    x:Class=\"v2rayN.Views.SubSettingWindow\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:base=\"clr-namespace:v2rayN.Base\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:materialDesign=\"http://materialdesigninxaml.net/winfx/xaml/themes\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuSubSetting}\"\n    Width=\"1000\"\n    Height=\"700\"\n    x:TypeArguments=\"vms:SubSettingViewModel\"\n    ResizeMode=\"CanResize\"\n    ShowInTaskbar=\"False\"\n    Style=\"{StaticResource WindowGlobal}\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <materialDesign:DialogHost\n        materialDesign:TransitionAssist.DisableTransitions=\"True\"\n        CloseOnClickAway=\"True\"\n        Identifier=\"SubDialog\"\n        Style=\"{StaticResource MaterialDesignEmbeddedDialogHost}\">\n        <DockPanel>\n            <ToolBarTray DockPanel.Dock=\"Top\">\n                <ToolBar\n                    HorizontalAlignment=\"Center\"\n                    VerticalAlignment=\"Center\"\n                    ClipToBounds=\"True\"\n                    Style=\"{StaticResource MaterialDesignToolBar}\">\n                    <Button x:Name=\"menuSubAdd\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <materialDesign:PackIcon\n                                Margin=\"{StaticResource MarginRight8}\"\n                                VerticalAlignment=\"Center\"\n                                Kind=\"Plus\" />\n                            <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuSubAdd}\" />\n                        </StackPanel>\n                    </Button>\n                    <Separator />\n                    <Button x:Name=\"menuSubDelete\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <materialDesign:PackIcon\n                                Margin=\"{StaticResource MarginRight8}\"\n                                VerticalAlignment=\"Center\"\n                                Kind=\"Delete\" />\n                            <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuSubDelete}\" />\n                        </StackPanel>\n                    </Button>\n                    <Separator />\n                    <Button x:Name=\"menuSubEdit\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <materialDesign:PackIcon\n                                Margin=\"{StaticResource MarginRight8}\"\n                                VerticalAlignment=\"Center\"\n                                Kind=\"Edit\" />\n                            <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuSubEdit}\" />\n                        </StackPanel>\n                    </Button>\n                    <Separator />\n                    <Button x:Name=\"menuSubShare\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <materialDesign:PackIcon\n                                Margin=\"{StaticResource MarginRight8}\"\n                                VerticalAlignment=\"Center\"\n                                Kind=\"QrcodePlus\" />\n                            <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuSubShare}\" />\n                        </StackPanel>\n                    </Button>\n                    <Button x:Name=\"menuClose\" IsCancel=\"True\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <materialDesign:PackIcon\n                                Margin=\"{StaticResource MarginRight8}\"\n                                VerticalAlignment=\"Center\"\n                                Kind=\"Close\" />\n                            <TextBlock Style=\"{StaticResource ToolbarTextBlock}\" Text=\"{x:Static resx:ResUI.menuClose}\" />\n                        </StackPanel>\n                    </Button>\n                </ToolBar>\n            </ToolBarTray>\n\n            <DataGrid\n                x:Name=\"lstSubscription\"\n                AutoGenerateColumns=\"False\"\n                BorderThickness=\"1\"\n                CanUserAddRows=\"False\"\n                CanUserResizeRows=\"False\"\n                CanUserSortColumns=\"False\"\n                EnableRowVirtualization=\"True\"\n                GridLinesVisibility=\"All\"\n                HeadersVisibility=\"Column\"\n                IsReadOnly=\"True\"\n                Style=\"{StaticResource DefDataGrid}\">\n                <DataGrid.ContextMenu>\n                    <ContextMenu Style=\"{StaticResource DefContextMenu}\">\n                        <MenuItem\n                            x:Name=\"menuSubAdd2\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSubAdd}\" />\n                        <MenuItem\n                            x:Name=\"menuSubDelete2\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSubDelete}\" />\n                        <MenuItem\n                            x:Name=\"menuSubEdit2\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSubEdit}\" />\n                        <MenuItem\n                            x:Name=\"menuSubShare2\"\n                            Height=\"{StaticResource MenuItemHeight}\"\n                            Header=\"{x:Static resx:ResUI.menuSubShare}\" />\n                    </ContextMenu>\n                </DataGrid.ContextMenu>\n                <DataGrid.Columns>\n                    <DataGridTextColumn\n                        Width=\"*\"\n                        Binding=\"{Binding Remarks}\"\n                        Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                    <DataGridTextColumn\n                        Width=\"*\"\n                        Binding=\"{Binding Url}\"\n                        Header=\"{x:Static resx:ResUI.LvUrl}\" />\n                    <DataGridCheckBoxColumn\n                        Width=\"100\"\n                        Binding=\"{Binding Enabled}\"\n                        Header=\"{x:Static resx:ResUI.LvEnabled}\" />\n                    <DataGridTextColumn\n                        Width=\"150\"\n                        Binding=\"{Binding AutoUpdateInterval}\"\n                        Header=\"{x:Static resx:ResUI.LvAutoUpdateInterval}\" />\n                    <DataGridTextColumn\n                        Width=\"150\"\n                        Binding=\"{Binding UserAgent}\"\n                        Header=\"{x:Static resx:ResUI.LvUserAgent}\" />\n                    <DataGridTextColumn\n                        Width=\"80\"\n                        Binding=\"{Binding Sort}\"\n                        Header=\"{x:Static resx:ResUI.LvSort}\" />\n                </DataGrid.Columns>\n            </DataGrid>\n        </DockPanel>\n    </materialDesign:DialogHost>\n</base:WindowBase>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/SubSettingWindow.xaml.cs",
    "content": "using MaterialDesignThemes.Wpf;\n\nnamespace v2rayN.Views;\n\npublic partial class SubSettingWindow\n{\n    public SubSettingWindow()\n    {\n        InitializeComponent();\n\n        Owner = Application.Current.MainWindow;\n\n        ViewModel = new SubSettingViewModel(UpdateViewHandler);\n        Closing += SubSettingWindow_Closing;\n        lstSubscription.MouseDoubleClick += LstSubscription_MouseDoubleClick;\n        lstSubscription.SelectionChanged += LstSubscription_SelectionChanged;\n        menuClose.Click += menuClose_Click;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.lstSubscription.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstSubscription.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SubAddCmd, v => v.menuSubAdd).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubDeleteCmd, v => v.menuSubDelete).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubEditCmd, v => v.menuSubEdit).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubShareCmd, v => v.menuSubShare).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SubAddCmd, v => v.menuSubAdd2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubDeleteCmd, v => v.menuSubDelete2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubEditCmd, v => v.menuSubEdit2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubShareCmd, v => v.menuSubShare2).DisposeWith(disposables);\n        });\n        WindowsUtils.SetDarkBorder(this, AppManager.Instance.Config.UiItem.CurrentTheme);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                DialogResult = true;\n                break;\n\n            case EViewAction.ShowYesNo:\n                if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.SubEditWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return new SubEditWindow((SubItem)obj).ShowDialog() ?? false;\n\n            case EViewAction.ShareSub:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                ShareSub((string)obj);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private async void ShareSub(string url)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return;\n        }\n        var img = QRCodeWindowsUtils.GetQRCode(url);\n        var dialog = new QrcodeView()\n        {\n            imgQrcode = { Source = img },\n            txtContent = { Text = url },\n        };\n\n        await DialogHost.Show(dialog, \"SubDialog\");\n    }\n\n    private void SubSettingWindow_Closing(object? sender, CancelEventArgs e)\n    {\n        if (ViewModel?.IsModified == true)\n        {\n            DialogResult = true;\n        }\n    }\n\n    private void LstSubscription_MouseDoubleClick(object sender, MouseButtonEventArgs e)\n    {\n        ViewModel?.EditSubAsync(false);\n    }\n\n    private void LstSubscription_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedSources = lstSubscription.SelectedItems.Cast<SubItem>().ToList();\n        }\n    }\n\n    private void menuClose_Click(object sender, System.Windows.RoutedEventArgs e)\n    {\n        if (ViewModel?.IsModified == true)\n        {\n            DialogResult = true;\n        }\n        else\n        {\n            Close();\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ThemeSettingView.xaml",
    "content": "<reactiveui:ReactiveUserControl\n    x:Class=\"v2rayN.Views.ThemeSettingView\"\n    xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:reactiveui=\"http://reactiveui.net\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:v2rayN.ViewModels\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:TypeArguments=\"vms:ThemeSettingViewModel\"\n    Style=\"{StaticResource ViewGlobal}\"\n    mc:Ignorable=\"d\">\n    <StackPanel Margin=\"{StaticResource Margin8}\">\n        <Grid>\n            <Grid.RowDefinitions>\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n                <RowDefinition Height=\"Auto\" />\n            </Grid.RowDefinitions>\n            <Grid.ColumnDefinitions>\n                <ColumnDefinition Width=\"Auto\" />\n                <ColumnDefinition Width=\"Auto\" />\n            </Grid.ColumnDefinitions>\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbSettingsTheme}\" />\n            <ComboBox\n                x:Name=\"cmbCurrentTheme\"\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Width=\"120\"\n                Margin=\"{StaticResource Margin8}\"\n                Style=\"{StaticResource DefComboBox}\" />\n\n            <TextBlock\n                Grid.Row=\"2\"\n                Grid.Column=\"0\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbSettingsColor}\" />\n            <ComboBox\n                x:Name=\"cmbSwatches\"\n                Grid.Row=\"2\"\n                Grid.Column=\"1\"\n                Width=\"120\"\n                Margin=\"{StaticResource Margin8}\"\n                DisplayMemberPath=\"Name\"\n                Style=\"{StaticResource DefComboBox}\" />\n\n            <TextBlock\n                Grid.Row=\"3\"\n                Grid.Column=\"0\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbSettingsFontSize}\" />\n            <ComboBox\n                x:Name=\"cmbCurrentFontSize\"\n                Grid.Row=\"3\"\n                Grid.Column=\"1\"\n                Width=\"120\"\n                Margin=\"{StaticResource Margin8}\"\n                Style=\"{StaticResource DefComboBox}\" />\n\n            <TextBlock\n                Grid.Row=\"4\"\n                Grid.Column=\"0\"\n                VerticalAlignment=\"Center\"\n                Style=\"{StaticResource ToolbarTextBlock}\"\n                Text=\"{x:Static resx:ResUI.TbSettingsLanguage}\" />\n            <ComboBox\n                x:Name=\"cmbCurrentLanguage\"\n                Grid.Row=\"4\"\n                Grid.Column=\"1\"\n                Width=\"120\"\n                Margin=\"{StaticResource Margin8}\"\n                Style=\"{StaticResource DefComboBox}\" />\n        </Grid>\n    </StackPanel>\n</reactiveui:ReactiveUserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN/Views/ThemeSettingView.xaml.cs",
    "content": "using v2rayN.ViewModels;\n\nnamespace v2rayN.Views;\n\n/// <summary>\n/// ThemeSettingView.xaml\n/// </summary>\npublic partial class ThemeSettingView\n{\n    public ThemeSettingView()\n    {\n        InitializeComponent();\n        ViewModel = new ThemeSettingViewModel();\n\n        cmbCurrentTheme.ItemsSource = Utils.GetEnumNames<ETheme>().Take(3).ToList();\n        cmbCurrentFontSize.ItemsSource = Enumerable.Range(Global.MinFontSize, Global.MinFontSizeCount).ToList();\n        cmbCurrentLanguage.ItemsSource = Global.Languages;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.CurrentTheme, v => v.cmbCurrentTheme.SelectedValue).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.Swatches, v => v.cmbSwatches.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSwatch, v => v.cmbSwatches.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.Text).DisposeWith(disposables);\n        });\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN/app.manifest",
    "content": "﻿<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\" xmlns:asmv3=\"urn:schemas-microsoft-com:asm.v3\">\n  <asmv3:application>\n    <asmv3:windowsSettings>\n      <dpiAware xmlns=\"http://schemas.microsoft.com/SMI/2005/WindowsSettings\">true</dpiAware>\n      <dpiAwareness xmlns=\"http://schemas.microsoft.com/SMI/2016/WindowsSettings\">PerMonitorV2</dpiAwareness>\n    </asmv3:windowsSettings>\n  </asmv3:application>\n\t\n\t<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->\n\t<dependency>\n\t\t<dependentAssembly>\n\t\t\t<assemblyIdentity\n\t\t\t\ttype=\"win32\"\n\t\t\t\tname=\"Microsoft.Windows.Common-Controls\"\n\t\t\t\tversion=\"6.0.0.0\"\n\t\t\t\tprocessorArchitecture=\"*\"\n\t\t\t\tpublicKeyToken=\"6595b64144ccf1df\"\n\t\t\t\tlanguage=\"*\"\n        />\n\t\t</dependentAssembly>\n\t</dependency>\n</assembly>"
  },
  {
    "path": "v2rayN/v2rayN/v2rayN.csproj",
    "content": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>WinExe</OutputType>\n\t\t<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>\n\t\t<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>\n\t\t<UseWPF>true</UseWPF>\n\t\t<ApplicationIcon>Resources\\v2rayN.ico</ApplicationIcon>\n\t\t<ApplicationManifest>app.manifest</ApplicationManifest>\n\t\t<SupportedOSPlatformVersion>7.0</SupportedOSPlatformVersion>\n\t</PropertyGroup>\n\n\t<ItemGroup>\n\t\t<PackageReference Include=\"MaterialDesignThemes\" />\n\t\t<PackageReference Include=\"H.NotifyIcon.Wpf\" />\n\t\t<PackageReference Include=\"ReactiveUI.Fody\">\n\t\t\t<TreatAsUsed>true</TreatAsUsed>\n\t\t</PackageReference>\n\t\t<PackageReference Include=\"ReactiveUI.WPF\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<AdditionalFiles Include=\"app.manifest\" />\n\t\t<EmbeddedResource Include=\"Resources\\v2rayN.ico\">\n\t\t\t<CopyToOutputDirectory>Never</CopyToOutputDirectory>\n\t\t</EmbeddedResource>\n\t\t<Resource Include=\"Resources\\NotifyIcon1.ico\" />\n\t\t<Resource Include=\"Resources\\NotifyIcon2.ico\" />\n\t\t<Resource Include=\"Resources\\NotifyIcon3.ico\" />\n\t\t<Resource Include=\"Resources\\NotifyIcon4.ico\" />\n\t\t<Resource Include=\"Resources\\v2rayN.ico\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<ProjectReference Include=\"..\\ServiceLib\\ServiceLib.csproj\" />\n\t</ItemGroup>\n\n</Project>"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/App.axaml",
    "content": "<Application\n    x:Class=\"v2rayN.Desktop.App\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:dialogHost=\"clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:semi=\"https://irihi.tech/semi\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Name=\"v2rayN\"\n    x:DataType=\"vms:StatusBarViewModel\"\n    RequestedThemeVariant=\"Default\">    \n    <Application.Resources>\n        <ResourceDictionary>\n            <ResourceDictionary.MergedDictionaries>\n                <ResourceInclude Source=\"Assets/GlobalResources.axaml\" />\n            </ResourceDictionary.MergedDictionaries>\n        </ResourceDictionary>\n    </Application.Resources>\n    <Application.Styles>\n        <semi:SemiTheme />\n        <semi:AvaloniaEditSemiTheme />\n        <StyleInclude Source=\"Assets/GlobalStyles.axaml\" />\n        <StyleInclude Source=\"avares://Semi.Avalonia.DataGrid/Index.axaml\" />\n        <dialogHost:DialogHostStyles />\n    </Application.Styles>\n\n    <TrayIcon.Icons>\n        <TrayIcons>\n            <TrayIcon\n                Command=\"{Binding NotifyLeftClickCmd}\"\n                Icon=\"/Assets/NotifyIcon1.ico\"\n                ToolTipText=\"{Binding RunningServerToolTipText}\">\n                <TrayIcon.Menu>\n                    <NativeMenu>\n                        <NativeMenuItem\n                            Command=\"{Binding ShowWindowCmd}\"\n                            Header=\"{x:Static resx:ResUI.TbDisplayGUI}\"\n                            IsVisible=\"{Binding BlIsNonWindows}\" />\n                        <NativeMenuItem\n                            Command=\"{Binding NotifyLeftClickCmd}\"\n                            Header=\"{x:Static resx:ResUI.menuShowOrHideMainWindow}\"\n                            IsVisible=\"{Binding BlIsNonWindows}\" />\n                        <NativeMenuItem Command=\"{Binding CopyProxyCmdToClipboardCmd}\" Header=\"{x:Static resx:ResUI.menuCopyProxyCmdToClipboard}\" />\n                        <NativeMenuItemSeparator />\n                        <NativeMenuItem\n                            Command=\"{Binding SystemProxyClearCmd}\"\n                            Header=\"{x:Static resx:ResUI.menuSystemProxyClear}\"\n                            IsChecked=\"{Binding BlSystemProxyClear}\"\n                            ToggleType=\"Radio\" />\n                        <NativeMenuItem\n                            Command=\"{Binding SystemProxySetCmd}\"\n                            Header=\"{x:Static resx:ResUI.menuSystemProxySet}\"\n                            IsChecked=\"{Binding BlSystemProxySet}\"\n                            ToggleType=\"Radio\" />\n                        <NativeMenuItem\n                            Command=\"{Binding SystemProxyNothingCmd}\"\n                            Header=\"{x:Static resx:ResUI.menuSystemProxyNothing}\"\n                            IsChecked=\"{Binding BlSystemProxyNothing}\"\n                            ToggleType=\"Radio\" />\n                        <NativeMenuItem\n                            Command=\"{Binding SystemProxyPacCmd}\"\n                            Header=\"{x:Static resx:ResUI.menuSystemProxyPac}\"\n                            IsChecked=\"{Binding BlSystemProxyPac}\"\n                            IsVisible=\"{Binding BlSystemProxyPacVisible}\"\n                            ToggleType=\"Radio\" />\n                        <NativeMenuItemSeparator />\n                        <NativeMenuItem Click=\"MenuAddServerViaClipboardClick\" Header=\"{x:Static resx:ResUI.menuAddServerViaClipboard}\" />\n                        <NativeMenuItem Command=\"{Binding SubUpdateCmd}\" Header=\"{x:Static resx:ResUI.menuSubUpdate}\" />\n                        <NativeMenuItem Command=\"{Binding SubUpdateViaProxyCmd}\" Header=\"{x:Static resx:ResUI.menuSubUpdateViaProxy}\" />\n                        <NativeMenuItemSeparator />\n                        <NativeMenuItem Click=\"MenuExit_Click\" Header=\"{x:Static resx:ResUI.menuExit}\" />\n                    </NativeMenu>\n                </TrayIcon.Menu>\n            </TrayIcon>\n        </TrayIcons>\n    </TrayIcon.Icons>\n</Application>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/App.axaml.cs",
    "content": "using v2rayN.Desktop.Views;\n\nnamespace v2rayN.Desktop;\n\npublic partial class App : Application\n{\n    public override void Initialize()\n    {\n        AvaloniaXamlLoader.Load(this);\n\n        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;\n        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;\n    }\n\n    public override void OnFrameworkInitializationCompleted()\n    {\n        if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)\n        {\n            if (!Design.IsDesignMode)\n            {\n                AppManager.Instance.InitComponents();\n                DataContext = StatusBarViewModel.Instance;\n            }\n\n            desktop.Exit += OnExit;\n            desktop.MainWindow = new MainWindow();\n        }\n\n        base.OnFrameworkInitializationCompleted();\n    }\n\n    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)\n    {\n        if (e.ExceptionObject != null)\n        {\n            Logging.SaveLog(\"CurrentDomain_UnhandledException\", (Exception)e.ExceptionObject);\n        }\n    }\n\n    private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)\n    {\n        Logging.SaveLog(\"TaskScheduler_UnobservedTaskException\", e.Exception);\n    }\n\n    private void OnExit(object? sender, ControlledApplicationLifetimeExitEventArgs e)\n    {\n    }\n\n    private async void MenuAddServerViaClipboardClick(object? sender, EventArgs e)\n    {\n        if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)\n        {\n            if (desktop.MainWindow != null)\n            {\n                AppEvents.AddServerViaClipboardRequested.Publish();\n                await Task.Delay(1000);\n            }\n        }\n    }\n\n    private async void MenuExit_Click(object? sender, EventArgs e)\n    {\n        await AppManager.Instance.AppExitAsync(false);\n        AppManager.Instance.Shutdown(true);\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Assets/GlobalResources.axaml",
    "content": "<ResourceDictionary xmlns=\"https://github.com/avaloniaui\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n    <StreamGeometry x:Key=\"building_edit\">M512 0a512 512 0 1 0 512 512A512 512 0 0 0 512 0z m47.402667 580.906667l-50.090667 50.816q-25.045333 24.448-45.098667 44.8c-13.397333 13.610667-24.405333 24.704-33.194666 33.493333s-13.994667 13.781333-15.701334 15.018667c-4.266667 3.797333-9.002667 7.722667-14.421333 11.904a77.397333 77.397333 0 0 1-17.066667 9.984 255.232 255.232 0 0 1-25.6 10.581333 832.426667 832.426667 0 0 1-70.528 22.485333c-11.093333 2.901333-19.285333 4.821333-24.704 5.589334-11.306667 1.28-18.816-0.384-22.485333-4.992a29.397333 29.397333 0 0 1-3.114667-23.210667 198.016 198.016 0 0 1 6.016-25.6c3.114667-11.093333 6.485333-22.485333 9.984-34.389333s6.997333-22.912 10.282667-32.896a164.821333 164.821333 0 0 1 8.106667-20.693334 96.64 96.64 0 0 1 8.533333-16 101.504 101.504 0 0 1 13.482667-16c2.517333-2.517333 8.533333-8.533333 17.493333-17.792s20.693333-20.992 34.389333-34.816l231.253334-231.253333 117.12 118.016-134.741334 134.741333z m224.938666-229.333334a51.2 51.2 0 0 1-9.984 15.701334q-7.509333 7.509333-13.482666 13.184c-4.010667 3.797333-7.381333 7.082667-10.282667 9.984s-6.485333 6.314667-9.386667 8.789333l-117.290666-117.162667c4.992-4.608 11.008-10.112 17.92-16.597333s12.8-11.605333 17.066666-15.317333a54.613333 54.613333 0 0 1 18.218667-9.685334 56.917333 56.917333 0 0 1 18.517333-2.517333 71.936 71.936 0 0 1 17.493334 2.816 94.464 94.464 0 0 1 14.72 5.589333 113.536 113.536 0 0 1 29.098666 24.106667 138.666667 138.666667 0 0 1 24.704 36.010667 66.389333 66.389333 0 0 1 4.266667 13.184 79.573333 79.573333 0 0 1 1.621333 15.701333 44.330667 44.330667 0 0 1-3.114666 16.213333z m0 0</StreamGeometry>\n    <StreamGeometry x:Key=\"building_add\">M512 0C229.376 0 0 229.376 0 512s229.376 512 512 512 512-229.376 512-512S794.624 0 512 0z m238.08 570.88h-179.2v179.2c0 32.768-26.112 58.88-58.88 58.88s-58.88-26.112-58.88-58.88v-179.2h-179.2c-32.768 0-58.88-26.112-58.88-58.88s26.112-58.88 58.88-58.88h179.2v-179.2c0-32.768 26.112-58.88 58.88-58.88s58.88 26.112 58.88 58.88v179.2h179.2c32.768 0 58.88 26.112 58.88 58.88s-26.112 58.88-58.88 58.88z</StreamGeometry>\n    <StreamGeometry x:Key=\"building_fit\">M512 1024C229.248 1024 0 794.752 0 512S229.248 0 512 0s512 229.248 512 512-229.248 512-512 512zM216.576 488.789333h-23.168v46.421334h23.168v56.448c0 7.296 5.973333 13.226667 13.269333 13.226666h42.965334c7.296 0 13.226667-5.930667 13.226666-13.226666v-159.317334a13.269333 13.269333 0 0 0-13.226666-13.226666H229.845333a13.269333 13.269333 0 0 0-13.226666 13.226666v56.448z m415.104 0.426667H403.712V366.037333a13.269333 13.269333 0 0 0-13.269333-13.269333H325.802667a13.269333 13.269333 0 0 0-13.226667 13.226667v292.053333c0 7.338667 5.888 13.269333 13.226667 13.269333h64.64c7.338667 0 13.269333-5.930667 13.269333-13.226666v-123.306667h227.968v123.306667c0 7.296 5.930667 13.226667 13.226667 13.226666h64.64c7.338667 0 13.269333-5.930667 13.269333-13.226666V365.952a13.269333 13.269333 0 0 0-13.226667-13.269333h-64.64a13.269333 13.269333 0 0 0-13.269333 13.226666v123.306667z m187.093333-0.426667v-56.448a13.269333 13.269333 0 0 0-13.226666-13.226666h-42.965334a13.269333 13.269333 0 0 0-13.269333 13.226666v159.317334c0 7.296 5.973333 13.226667 13.269333 13.226666h42.922667c7.338667 0 13.269333-5.930667 13.269333-13.226666v-56.448h23.168v-46.421334h-23.168z</StreamGeometry>\n    <StreamGeometry x:Key=\"building_more\">M511.9,276.3c43.8,0 79.2,-35.5 79.2,-79.2 0,-43.8 -35.5,-79.2 -79.2,-79.2 -43.8,0 -79.2,35.5 -79.2,79.2 0,43.8 35.5,79.2 79.2,79.2zM511.9,434.8c-43.8,0 -79.2,35.5 -79.2,79.2 0,43.8 35.5,79.2 79.2,79.2 43.8,0 79.2,-35.5 79.2,-79.2 0,-43.8 -35.5,-79.2 -79.2,-79.2zM511.9,751.8c-43.8,0 -79.2,35.4 -79.2,79.2 0,43.8 35.5,79.2 79.2,79.2 43.8,0 79.2,-35.5 79.2,-79.2 0,-43.8 -35.5,-79.2 -79.2,-79.2z</StreamGeometry>\n    <StreamGeometry x:Key=\"building_delete\">M809.984 169.984l0 86.016-596.010667 0 0-86.016 148.010667 0 43.989333-41.984 212.010667 0 43.989333 41.984 148.010667 0zM256 809.984l0-512 512 0 0 512q0 34.005333-25.984 59.989333t-59.989333 25.984l-340.010667 0q-34.005333 0-59.989333-25.984t-25.984-59.989333z</StreamGeometry>\n    <StreamGeometry x:Key=\"building_copy\">M704 896v80c0 26.51-21.49 48-48 48H112c-26.51 0-48-21.49-48-48V240c0-26.51 21.49-48 48-48h144v592c0 61.758 50.242 112 112 112h336z m0-688V0H368c-26.51 0-48 21.49-48 48v736c0 26.51 21.49 48 48 48h544c26.51 0 48-21.49 48-48V256H752c-26.4 0-48-21.6-48-48z m241.942-62.058L814.058 14.058A48 48 0 0 0 780.118 0H768v192h192v-12.118a48 48 0 0 0-14.058-33.94z</StreamGeometry>\n    <StreamGeometry x:Key=\"building_refresh\">M849.652671 679.144788l111.007233-174.965917-50.615794 0C905.498584 274.107915 717.720873 88.965218 486.575446 88.965218c-233.998405 0-423.716304 189.698456-423.716304 423.707095 0 233.998405 189.716876 423.715281 423.716304 423.715281 113.936959 0 217.278605-45.079708 293.440216-118.235868l-62.46568-108.306728c-55.750745 65.205071-138.455375 106.709347-230.974535 106.709347-167.843706 0-303.882032-136.039349-303.882032-303.883055S318.732763 208.788234 486.575446 208.788234c164.951843 0 298.899554 131.522476 303.44508 295.389614l-51.357691 0L849.652671 679.144788z</StreamGeometry>\n    <StreamGeometry x:Key=\"building_ping\">M273.28 899.328c-6.4 6.4-16 9.6-25.6 9.6-6.4 0-12.8-3.2-18.56-6.4-102.4-85.76-162.56-209.92-162.56-343.68 0-245.12 200.32-445.44 445.44-445.44s445.44 200.32 445.44 445.44c0 133.76-56.96 257.92-162.56 343.68-12.16 12.8-34.56 9.6-44.16-3.2-12.8-12.8-9.6-35.2 3.2-44.8a377.152 377.152 0 0 0 136.96-292.48c0-209.92-172.16-382.08-382.08-382.08-206.72-3.2-378.88 168.96-378.88 378.88 0 114.56 51.2 222.72 140.16 295.68 12.8 12.8 16 32 3.2 44.8z m394.88-540.8c12.8-12.8 31.36-12.8 44.16 0 12.8 12.8 12.8 32 0 44.8l-138.88 138.88c1.28 5.12 2.56 10.88 2.56 16.64 0 35.2-28.8 64-64 64-5.76 0-11.52-1.28-16.64-2.56l-24.32 24.32c-6.4 6.4-12.8 9.6-22.4 9.6-9.6 0-16-3.2-22.4-9.6-12.8-12.8-12.8-31.36 0-44.16l24.32-24.96a69.76 69.76 0 0 1-1.92-16.64c0-35.2 28.16-63.36 63.36-63.36 5.76 0 11.52 0.64 16.64 1.92z</StreamGeometry>\n\n    <x:Double x:Key=\"IconButtonWidth\">32</x:Double>\n    <x:Double x:Key=\"IconButtonHeight\">32</x:Double>\n    <x:Double x:Key=\"MenuFlyoutMaxHeight\">1000</x:Double>\n\n    <Thickness x:Key=\"Margin2\">2</Thickness>\n    <Thickness x:Key=\"MarginLr4\">4,0</Thickness>\n    <Thickness x:Key=\"Margin4\">4</Thickness>\n    <Thickness x:Key=\"MarginLr8\">8,0</Thickness>\n    <Thickness x:Key=\"MarginTb8\">0,8</Thickness>\n    <Thickness x:Key=\"Margin8\">8</Thickness>\n</ResourceDictionary>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Assets/GlobalStyles.axaml",
    "content": "<Styles xmlns=\"https://github.com/avaloniaui\" xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\">\n    <Design.PreviewWith>\n        <Border Padding=\"20\">\n            <!--  Add Controls for Previewer Here  -->\n        </Border>\n    </Design.PreviewWith>\n\n    <Style Selector=\"DataGrid\">\n        <Setter Property=\"RowHeight\" Value=\"24\" />\n        <Setter Property=\"ScrollViewer.AllowAutoHide\" Value=\"False\" />\n    </Style>\n\n    <Style Selector=\"PathIcon\">\n        <Setter Property=\"Width\" Value=\"16\" />\n        <Setter Property=\"Height\" Value=\"16\" />\n        <Setter Property=\"Foreground\" Value=\"{DynamicResource ButtonDefaultTertiaryForeground}\" />\n    </Style>\n\n    <Style Selector=\"TextBox\">\n        <Setter Property=\"ScrollViewer.AllowAutoHide\" Value=\"False\" />\n    </Style>\n\n    <Style Selector=\"ScrollViewer\">\n        <Setter Property=\"AllowAutoHide\" Value=\"False\" />\n    </Style>\n\n    <Style Selector=\"TabControl\">\n        <Setter Property=\"Theme\" Value=\"{StaticResource LineTabControl}\" />\n    </Style>\n\n    <Style Selector=\"Button.IconButton\">\n        <Setter Property=\"Width\" Value=\"{StaticResource IconButtonWidth}\" />\n        <Setter Property=\"Height\" Value=\"{StaticResource IconButtonHeight}\" />\n        <Setter Property=\"MinWidth\" Value=\"{StaticResource IconButtonWidth}\" />\n        <Setter Property=\"Theme\" Value=\"{DynamicResource BorderlessButton}\" />\n    </Style>\n\n</Styles>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Base/WindowBase.cs",
    "content": "namespace v2rayN.Desktop.Base;\n\npublic class WindowBase<TViewModel> : ReactiveWindow<TViewModel> where TViewModel : class\n{\n    public WindowBase()\n    {\n        Loaded += OnLoaded;\n    }\n\n    private void ReactiveWindowBase_Closed(object? sender, EventArgs e)\n    {\n        throw new NotImplementedException();\n    }\n\n    protected virtual void OnLoaded(object? sender, RoutedEventArgs e)\n    {\n        try\n        {\n            var sizeItem = ConfigHandler.GetWindowSizeItem(AppManager.Instance.Config, GetType().Name);\n            if (sizeItem == null)\n            {\n                return;\n            }\n\n            Width = sizeItem.Width;\n            Height = sizeItem.Height;\n\n            var workingArea = (Screens.ScreenFromWindow(this) ?? Screens.Primary).WorkingArea;\n            var scaling = (Utils.IsMacOS() ? null : VisualRoot?.RenderScaling) ?? 1.0;\n\n            var x = workingArea.X + ((workingArea.Width - (Width * scaling)) / 2);\n            var y = workingArea.Y + ((workingArea.Height - (Height * scaling)) / 2);\n\n            Position = new PixelPoint((int)x, (int)y);\n        }\n        catch { }\n    }\n\n    protected override void OnClosed(EventArgs e)\n    {\n        base.OnClosed(e);\n        try\n        {\n            ConfigHandler.SaveWindowSizeItem(AppManager.Instance.Config, GetType().Name, Width, Height);\n        }\n        catch { }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Common/AppBuilderExtension.cs",
    "content": "namespace v2rayN.Desktop.Common;\n\npublic static class AppBuilderExtension\n{\n    public static AppBuilder WithFontByDefault(this AppBuilder appBuilder)\n    {\n        var fallbacks = new List<FontFallback>();\n\n        var notoSansSc = new FontFamily(Path.Combine(Global.AvaAssets, \"Fonts#Noto Sans SC\"));\n        fallbacks.Add(new FontFallback { FontFamily = notoSansSc });\n\n        if (OperatingSystem.IsLinux())\n        {\n            fallbacks.Add(new FontFallback\n            {\n                FontFamily = new FontFamily(\"Noto Color Emoji\")\n            });\n        }\n\n        return appBuilder.With(new FontManagerOptions\n        {\n            FontFallbacks = fallbacks.ToArray()\n        });\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Common/AvaUtils.cs",
    "content": "using Avalonia.Input.Platform;\n\nnamespace v2rayN.Desktop.Common;\n\ninternal class AvaUtils\n{\n    public static async Task<string?> GetClipboardData(Window owner)\n    {\n        try\n        {\n            var clipboard = TopLevel.GetTopLevel(owner)?.Clipboard;\n            if (clipboard == null)\n            {\n                return null;\n            }\n\n            return await clipboard.TryGetTextAsync();\n        }\n        catch\n        {\n            return null;\n        }\n    }\n\n    public static async Task SetClipboardData(Visual? visual, string strData)\n    {\n        try\n        {\n            var clipboard = TopLevel.GetTopLevel(visual)?.Clipboard;\n            if (clipboard == null)\n            {\n                return;\n            }\n\n            await clipboard.SetTextAsync(strData);\n        }\n        catch\n        {\n        }\n    }\n\n    public static WindowIcon GetAppIcon(ESysProxyType sysProxyType)\n    {\n        var index = (int)sysProxyType + 1;\n        var fileName = Utils.GetPath($\"NotifyIcon{index}.ico\");\n        if (File.Exists(fileName))\n        {\n            return new(fileName);\n        }\n\n        var uri = new Uri(Path.Combine(Global.AvaAssets, $\"NotifyIcon{index}.ico\"));\n        using var bitmap = new Bitmap(AssetLoader.Open(uri));\n        return new(bitmap);\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Common/TextEditorKeywordHighlighter.cs",
    "content": "using AvaloniaEdit;\nusing AvaloniaEdit.Document;\nusing AvaloniaEdit.Rendering;\n\nnamespace v2rayN.Desktop.Common;\n\npublic class KeywordColorizer : DocumentColorizingTransformer\n{\n    private readonly string[] _keywords;\n    private readonly Dictionary<string, IBrush> _brushMap;\n\n    public KeywordColorizer(IDictionary<string, IBrush> keywordBrushMap)\n    {\n        if (keywordBrushMap == null || keywordBrushMap.Count == 0)\n        {\n            throw new ArgumentException(\"keywordBrushMap must not be null or empty\", nameof(keywordBrushMap));\n        }\n\n        _brushMap = new Dictionary<string, IBrush>(StringComparer.OrdinalIgnoreCase);\n        foreach (var kvp in keywordBrushMap)\n        {\n            if (string.IsNullOrEmpty(kvp.Key) || kvp.Value == null)\n            {\n                continue;\n            }\n\n            if (!_brushMap.ContainsKey(kvp.Key))\n            {\n                _brushMap[kvp.Key] = kvp.Value;\n            }\n        }\n\n        if (_brushMap.Count == 0)\n        {\n            throw new ArgumentException(\"keywordBrushMap must contain at least one non-empty key with a non-null brush\", nameof(keywordBrushMap));\n        }\n\n        _keywords = _brushMap.Keys.ToArray();\n    }\n\n    protected override void ColorizeLine(DocumentLine line)\n    {\n        var text = CurrentContext.Document.GetText(line);\n        if (string.IsNullOrEmpty(text))\n        {\n            return;\n        }\n\n        foreach (var kw in _keywords)\n        {\n            if (string.IsNullOrEmpty(kw))\n            {\n                continue;\n            }\n\n            var searchStart = 0;\n            while (true)\n            {\n                var idx = text.IndexOf(kw, searchStart, StringComparison.OrdinalIgnoreCase);\n                if (idx < 0)\n                {\n                    break;\n                }\n\n                var kwEndIndex = idx + kw.Length;\n                if (IsWordCharBefore(text, idx) || IsWordCharAfter(text, kwEndIndex))\n                {\n                    searchStart = idx + Math.Max(1, kw.Length);\n                    continue;\n                }\n\n                var start = line.Offset + idx;\n                var end = start + kw.Length;\n\n                if (_brushMap.TryGetValue(kw, out var brush) && brush != null)\n                {\n                    ChangeLinePart(start, end, element => element.TextRunProperties.SetForegroundBrush(brush));\n                }\n\n                searchStart = idx + Math.Max(1, kw.Length);\n            }\n        }\n    }\n\n    private static bool IsWordCharBefore(string text, int idx)\n    {\n        if (idx <= 0)\n        {\n            return false;\n        }\n\n        var c = text[idx - 1];\n        return char.IsLetterOrDigit(c) || c == '_';\n    }\n\n    private static bool IsWordCharAfter(string text, int idx)\n    {\n        if (idx >= text.Length)\n        {\n            return false;\n        }\n\n        var c = text[idx];\n        return char.IsLetterOrDigit(c) || c == '_';\n    }\n}\n\npublic static class TextEditorKeywordHighlighter\n{\n    public static void Attach(TextEditor editor, IDictionary<string, IBrush> keywordBrushMap)\n    {\n        ArgumentNullException.ThrowIfNull(editor);\n\n        if (keywordBrushMap == null || keywordBrushMap.Count == 0)\n        {\n            return;\n        }\n\n        if (editor.TextArea?.TextView?.LineTransformers?.OfType<KeywordColorizer>().Any() == true)\n        {\n            return;\n        }\n\n        var colorizer = new KeywordColorizer(keywordBrushMap);\n        editor.TextArea.TextView.LineTransformers.Add(colorizer);\n        editor.TextArea.TextView.InvalidateVisual();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Common/UI.cs",
    "content": "using Avalonia.Platform.Storage;\nusing MsBox.Avalonia;\n\nnamespace v2rayN.Desktop.Common;\n\ninternal class UI\n{\n    private static readonly string caption = Global.AppName;\n\n    public static async Task<ButtonResult> ShowYesNo(Window owner, string msg)\n    {\n        var box = MessageBoxManager.GetMessageBoxStandard(caption, msg, ButtonEnum.YesNo);\n        return await box.ShowWindowDialogAsync(owner);\n    }\n\n    public static async Task<string?> OpenFileDialog(Window owner, FilePickerFileType? filter)\n    {\n        var sp = GetStorageProvider(owner);\n        if (sp is null)\n        {\n            return null;\n        }\n\n        // Start async operation to open the dialog.\n        var files = await sp.OpenFilePickerAsync(new FilePickerOpenOptions\n        {\n            AllowMultiple = false,\n            FileTypeFilter = filter is null ? [FilePickerFileTypes.All, FilePickerFileTypes.ImagePng] : [filter]\n        });\n\n        return files.FirstOrDefault()?.TryGetLocalPath();\n    }\n\n    public static async Task<string?> SaveFileDialog(Window owner, string filter)\n    {\n        var sp = GetStorageProvider(owner);\n        if (sp is null)\n        {\n            return null;\n        }\n\n        // Start async operation to open the dialog.\n        var files = await sp.SaveFilePickerAsync(new FilePickerSaveOptions\n        {\n        });\n\n        return files?.TryGetLocalPath();\n    }\n\n    private static IStorageProvider? GetStorageProvider(Window owner)\n    {\n        var topLevel = TopLevel.GetTopLevel(owner);\n        return topLevel?.StorageProvider;\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Converters/DelayColorConverter.cs",
    "content": "using Avalonia.Data.Converters;\n\nnamespace v2rayN.Desktop.Converters;\n\npublic class DelayColorConverter : IValueConverter\n{\n    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)\n    {\n        var delay = value.ToString().ToInt();\n\n        return delay switch\n        {\n            <= 0 => new SolidColorBrush(Colors.Red),\n            <= 500 => new SolidColorBrush(Colors.Green),\n            _ => new SolidColorBrush(Colors.IndianRed)\n        };\n    }\n\n    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)\n    {\n        return null;\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/FodyWeavers.xml",
    "content": "﻿<Weavers xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"FodyWeavers.xsd\">\n  <ReactiveUI />\n</Weavers>"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/GlobalUsings.cs",
    "content": "global using System;\nglobal using System.Collections.Generic;\nglobal using System.Globalization;\nglobal using System.IO;\nglobal using System.Linq;\nglobal using System.Reactive.Disposables.Fluent;\nglobal using System.Reactive.Linq;\nglobal using System.Text;\nglobal using System.Threading;\nglobal using System.Threading.Tasks;\nglobal using Avalonia;\nglobal using Avalonia.Controls;\nglobal using Avalonia.Controls.ApplicationLifetimes;\nglobal using Avalonia.Input;\nglobal using Avalonia.Interactivity;\nglobal using Avalonia.Markup.Xaml;\nglobal using Avalonia.Media;\nglobal using Avalonia.Media.Imaging;\nglobal using Avalonia.Platform;\nglobal using Avalonia.Styling;\nglobal using Avalonia.Threading;\nglobal using DynamicData;\nglobal using MsBox.Avalonia.Enums;\nglobal using ReactiveUI;\nglobal using ReactiveUI.Avalonia;\nglobal using ReactiveUI.Fody.Helpers;\nglobal using ServiceLib;\nglobal using ServiceLib.Base;\nglobal using ServiceLib.Common;\nglobal using ServiceLib.Enums;\nglobal using ServiceLib.Events;\nglobal using ServiceLib.Handler;\nglobal using ServiceLib.Manager;\nglobal using ServiceLib.Models;\nglobal using ServiceLib.Resx;\nglobal using ServiceLib.ViewModels;\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Manager/HotkeyManager.cs",
    "content": "using Avalonia.Win32.Input;\nusing GlobalHotKeys;\n\nnamespace v2rayN.Desktop.Manager;\n\npublic sealed class HotkeyManager\n{\n    private static readonly Lazy<HotkeyManager> _instance = new(() => new());\n    public static HotkeyManager Instance = _instance.Value;\n    private readonly Dictionary<int, EGlobalHotkey> _hotkeyTriggerDic = new();\n    private GlobalHotKeys.HotKeyManager? _hotKeyManager;\n\n    private Config? _config;\n\n    private event Action<EGlobalHotkey>? _updateFunc;\n\n    public bool IsPause { get; set; } = false;\n\n    public void Init(Config config, Action<EGlobalHotkey> updateFunc)\n    {\n        _config = config;\n        _updateFunc = updateFunc;\n\n        Register();\n    }\n\n    public void Dispose()\n    {\n        _hotKeyManager?.Dispose();\n    }\n\n    private void Register()\n    {\n        if (_config.GlobalHotkeys.Any(t => t.KeyCode > 0) == false)\n        {\n            return;\n        }\n        _hotKeyManager ??= new GlobalHotKeys.HotKeyManager();\n        _hotkeyTriggerDic.Clear();\n\n        foreach (var item in _config.GlobalHotkeys)\n        {\n            if (item.KeyCode is null or 0)\n            {\n                continue;\n            }\n\n            var vKey = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode);\n            var modifiers = Modifiers.None;\n            if (item.Control)\n            {\n                modifiers |= Modifiers.Control;\n            }\n            if (item.Shift)\n            {\n                modifiers |= Modifiers.Shift;\n            }\n            if (item.Alt)\n            {\n                modifiers |= Modifiers.Alt;\n            }\n\n            var result = _hotKeyManager?.Register((VirtualKeyCode)vKey, modifiers);\n            if (result?.IsSuccessful == true)\n            {\n                _hotkeyTriggerDic.Add(result.Id, item.EGlobalHotkey);\n            }\n        }\n\n        _hotKeyManager?.HotKeyPressed\n            .ObserveOn(AvaloniaScheduler.Instance)\n            .Subscribe(OnNext);\n    }\n\n    private void OnNext(HotKey key)\n    {\n        if (_updateFunc == null || IsPause)\n        {\n            return;\n        }\n\n        if (_hotkeyTriggerDic.TryGetValue(key.Id, out var value))\n        {\n            _updateFunc?.Invoke(value);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Program.cs",
    "content": "using v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop;\n\ninternal class Program\n{\n    public static EventWaitHandle ProgramStarted;\n\n    // Initialization code. Don't use any Avalonia, third-party APIs or any\n    // SynchronizationContext-reliant code before AppMain is called: things aren't initialized\n    // yet and stuff might break.\n    [STAThread]\n    public static void Main(string[] args)\n    {\n        if (OnStartup(args) == false)\n        {\n            Environment.Exit(0);\n            return;\n        }\n\n        BuildAvaloniaApp()\n            .StartWithClassicDesktopLifetime(args);\n    }\n\n    private static bool OnStartup(string[]? Args)\n    {\n        if (Utils.IsWindows())\n        {\n            var exePathKey = Utils.GetMd5(Utils.GetExePath());\n            var rebootas = (Args ?? []).Any(t => t == Global.RebootAs);\n            ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out var bCreatedNew);\n            if (!rebootas && !bCreatedNew)\n            {\n                ProgramStarted.Set();\n                return false;\n            }\n        }\n        else\n        {\n            _ = new Mutex(true, \"v2rayN\", out var bOnlyOneInstance);\n            if (!bOnlyOneInstance)\n            {\n                return false;\n            }\n        }\n\n        if (!AppManager.Instance.InitApp())\n        {\n            return false;\n        }\n        return true;\n    }\n\n    // Avalonia configuration, don't remove; also used by visual designer.\n    public static AppBuilder BuildAvaloniaApp()\n    {\n        var builder = AppBuilder.Configure<App>()\n           .UsePlatformDetect()\n           //.WithInterFont()\n           .WithFontByDefault()\n           .LogToTrace()\n           .UseReactiveUI(_ => { });\n\n        if (OperatingSystem.IsMacOS())\n        {\n            var showInDock = Design.IsDesignMode || AppManager.Instance.Config.UiItem.MacOSShowInDock;\n            builder = builder.With(new MacOSPlatformOptions { ShowInDock = showInDock });\n        }\n\n        return builder;\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs",
    "content": "using Avalonia.Controls.Notifications;\nusing Avalonia.Controls.Primitives;\nusing AvaloniaEdit;\nusing Semi.Avalonia;\n\nnamespace v2rayN.Desktop.ViewModels;\n\npublic class ThemeSettingViewModel : MyReactiveObject\n{\n    [Reactive] public string CurrentTheme { get; set; }\n\n    [Reactive] public int CurrentFontSize { get; set; }\n\n    [Reactive] public string CurrentLanguage { get; set; }\n\n    public ThemeSettingViewModel()\n    {\n        _config = AppManager.Instance.Config;\n\n        BindingUI();\n        RestoreUI();\n    }\n\n    private void RestoreUI()\n    {\n        ModifyTheme();\n        ModifyFontFamily();\n        ModifyFontSize();\n    }\n\n    private void BindingUI()\n    {\n        CurrentTheme = _config.UiItem.CurrentTheme;\n        CurrentFontSize = _config.UiItem.CurrentFontSize;\n        CurrentLanguage = _config.UiItem.CurrentLanguage;\n\n        this.WhenAnyValue(x => x.CurrentTheme)\n            .Subscribe(c =>\n            {\n                if (_config.UiItem.CurrentTheme != CurrentTheme)\n                {\n                    _config.UiItem.CurrentTheme = CurrentTheme;\n                    ModifyTheme();\n                    ConfigHandler.SaveConfig(_config);\n                }\n            });\n\n        this.WhenAnyValue(\n                x => x.CurrentFontSize,\n                y => y > 0)\n            .Subscribe(c =>\n            {\n                if (_config.UiItem.CurrentFontSize != CurrentFontSize && CurrentFontSize >= Global.MinFontSize)\n                {\n                    _config.UiItem.CurrentFontSize = CurrentFontSize;\n                    ModifyFontSize();\n                    ConfigHandler.SaveConfig(_config);\n                }\n            });\n\n        this.WhenAnyValue(\n                x => x.CurrentLanguage,\n                y => y != null && !y.IsNullOrEmpty())\n            .Subscribe(c =>\n            {\n                if (CurrentLanguage.IsNotEmpty() && _config.UiItem.CurrentLanguage != CurrentLanguage)\n                {\n                    _config.UiItem.CurrentLanguage = CurrentLanguage;\n                    Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);\n                    ConfigHandler.SaveConfig(_config);\n                    NoticeManager.Instance.Enqueue(ResUI.NeedRebootTips);\n                }\n            });\n    }\n\n    private void ModifyTheme()\n    {\n        var app = Application.Current;\n        if (app is not null)\n        {\n            app.RequestedThemeVariant = CurrentTheme switch\n            {\n                nameof(ETheme.Dark) => ThemeVariant.Dark,\n                nameof(ETheme.Light) => ThemeVariant.Light,\n                nameof(ETheme.Aquatic) => SemiTheme.Aquatic,\n                nameof(ETheme.Desert) => SemiTheme.Desert,\n                nameof(ETheme.Dusk) => SemiTheme.Dusk,\n                nameof(ETheme.NightSky) => SemiTheme.NightSky,\n                _ => ThemeVariant.Default,\n            };\n        }\n    }\n\n    private void ModifyFontSize()\n    {\n        double size = CurrentFontSize;\n        if (size < Global.MinFontSize)\n        {\n            return;\n        }\n\n        Style style = new(x => Selectors.Or(\n            x.OfType<Button>(),\n            x.OfType<TextBox>(),\n            x.OfType<TextBlock>(),\n            x.OfType<SelectableTextBlock>(),\n            x.OfType<Menu>(),\n            x.OfType<ContextMenu>(),\n            x.OfType<DataGridRow>(),\n            x.OfType<ListBoxItem>(),\n            x.OfType<HeaderedContentControl>(),\n            x.OfType<TextEditor>()\n        ));\n        style.Add(new Setter()\n        {\n            Property = TemplatedControl.FontSizeProperty,\n            Value = size,\n        });\n        Application.Current?.Styles.Add(style);\n\n        ModifyFontSizeEx(size);\n    }\n\n    private void ModifyFontSizeEx(double size)\n    {\n        //DataGrid\n        var rowHeight = 20 + (size / 2);\n        var style = new Style(x => x.OfType<DataGrid>());\n        style.Add(new Setter(DataGrid.RowHeightProperty, rowHeight));\n        Application.Current?.Styles.Add(style);\n    }\n\n    private void ModifyFontFamily()\n    {\n        var currentFontFamily = _config.UiItem.CurrentFontFamily;\n        if (currentFontFamily.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        try\n        {\n            Style style = new(x => Selectors.Or(\n                x.OfType<Button>(),\n                x.OfType<TextBox>(),\n                x.OfType<TextBlock>(),\n                x.OfType<SelectableTextBlock>(),\n                x.OfType<Menu>(),\n                x.OfType<ContextMenu>(),\n                x.OfType<DataGridRow>(),\n                x.OfType<ListBoxItem>(),\n                x.OfType<HeaderedContentControl>(),\n                x.OfType<WindowNotificationManager>(),\n                x.OfType<TextEditor>()\n            ));\n            style.Add(new Setter()\n            {\n                Property = TemplatedControl.FontFamilyProperty,\n                Value = new FontFamily(currentFontFamily),\n            });\n            Application.Current?.Styles.Add(style);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"ModifyFontFamily\", ex);\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.AddGroupServerWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuServers}\"\n    Width=\"900\"\n    Height=\"700\"\n    x:DataType=\"vms:AddGroupServerViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n\n        <Grid\n            ColumnDefinitions=\"300,Auto,Auto\"\n            DockPanel.Dock=\"Top\"\n            RowDefinitions=\"Auto,Auto,Auto,Auto\">\n            <TextBlock\n                Grid.Row=\"0\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                Text=\"{x:Static resx:ResUI.menuServers}\" />\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbRemarks}\" />\n            <TextBox\n                x:Name=\"txtRemarks\"\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Width=\"400\"\n                Margin=\"{StaticResource Margin4}\" />\n\n            <TextBlock\n                Grid.Row=\"2\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbCoreType}\" />\n            <ComboBox\n                x:Name=\"cmbCoreType\"\n                Grid.Row=\"2\"\n                Grid.Column=\"1\"\n                Width=\"200\"\n                Margin=\"{StaticResource Margin4}\" />\n\n            <Grid\n                x:Name=\"gridPolicyGroup\"\n                Grid.Row=\"3\"\n                Grid.Column=\"0\"\n                Grid.ColumnSpan=\"3\"\n                ColumnDefinitions=\"300,Auto,Auto\">\n                <TextBlock\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbPolicyGroupType}\" />\n                <ComboBox\n                    x:Name=\"cmbPolicyGroupType\"\n                    Grid.Column=\"1\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\" />\n            </Grid>\n        </Grid>\n\n        <TabControl\n            x:Name=\"tabControl\"\n            HorizontalContentAlignment=\"Stretch\"\n            DockPanel.Dock=\"Top\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuServerList}\">\n                <Grid\n                    Margin=\"{StaticResource Margin8}\"\n                    ColumnDefinitions=\"Auto,Auto,Auto\"\n                    RowDefinitions=\"Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.menuSubscription}\" />\n                    <ComboBox\n                        x:Name=\"cmbSubChildItems\"\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        Width=\"600\"\n                        Margin=\"{StaticResource Margin4}\"\n                        DisplayMemberBinding=\"{Binding Remarks}\"\n                        ItemsSource=\"{Binding SubItems}\" />\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPolicyGroupSubChildTip}\"\n                        TextWrapping=\"Wrap\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.LvFilter}\" />\n                    <ComboBox\n                        x:Name=\"cmbFilter\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"600\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        IsEditable=\"True\" />\n                </Grid>\n            </TabItem>\n\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuServerList2}\">\n                <DataGrid\n                    x:Name=\"lstChild\"\n                    AutoGenerateColumns=\"False\"\n                    Background=\"Transparent\"\n                    BorderThickness=\"1\"\n                    CanUserReorderColumns=\"False\"\n                    CanUserResizeColumns=\"True\"\n                    CanUserSortColumns=\"False\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    ItemsSource=\"{Binding ChildItemsObs}\"\n                    SelectionMode=\"Extended\">\n                    <DataGrid.ContextMenu>\n                        <ContextMenu>\n                            <MenuItem x:Name=\"menuAddChildServer\" Header=\"{x:Static resx:ResUI.menuAddChildServer}\" />\n                            <MenuItem\n                                x:Name=\"menuRemoveChildServer\"\n                                Header=\"{x:Static resx:ResUI.menuRemoveChildServer}\"\n                                InputGesture=\"Back\" />\n                            <MenuItem\n                                x:Name=\"menuSelectAllChild\"\n                                Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                                InputGesture=\"Ctrl+A\" />\n                            <Separator />\n                            <MenuItem\n                                x:Name=\"menuMoveTop\"\n                                Header=\"{x:Static resx:ResUI.menuMoveTop}\"\n                                InputGesture=\"T\" />\n                            <MenuItem\n                                x:Name=\"menuMoveUp\"\n                                Header=\"{x:Static resx:ResUI.menuMoveUp}\"\n                                InputGesture=\"U\" />\n                            <MenuItem\n                                x:Name=\"menuMoveDown\"\n                                Header=\"{x:Static resx:ResUI.menuMoveDown}\"\n                                InputGesture=\"D\" />\n                            <MenuItem\n                                x:Name=\"menuMoveBottom\"\n                                Header=\"{x:Static resx:ResUI.menuMoveBottom}\"\n                                InputGesture=\"B\" />\n                        </ContextMenu>\n                    </DataGrid.ContextMenu>\n                    <DataGrid.Columns>\n                        <DataGridTextColumn\n                            Width=\"150\"\n                            Binding=\"{Binding ConfigType}\"\n                            Header=\"{x:Static resx:ResUI.LvServiceType}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Address}\"\n                            Header=\"{x:Static resx:ResUI.LvAddress}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            Header=\"{x:Static resx:ResUI.LvPort}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            Header=\"{x:Static resx:ResUI.LvTransportProtocol}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding StreamSecurity}\"\n                            Header=\"{x:Static resx:ResUI.LvTLS}\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuServerListPreview}\">\n                <DataGrid\n                    x:Name=\"lstPreviewChild\"\n                    AutoGenerateColumns=\"False\"\n                    Background=\"Transparent\"\n                    BorderThickness=\"1\"\n                    CanUserReorderColumns=\"False\"\n                    CanUserResizeColumns=\"True\"\n                    CanUserSortColumns=\"False\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    ItemsSource=\"{Binding AllProfilePreviewItemsObs}\"\n                    SelectionMode=\"Extended\">\n                    <DataGrid.Columns>\n                        <DataGridTextColumn\n                            Width=\"150\"\n                            Binding=\"{Binding ConfigType}\"\n                            Header=\"{x:Static resx:ResUI.LvServiceType}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Address}\"\n                            Header=\"{x:Static resx:ResUI.LvAddress}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            Header=\"{x:Static resx:ResUI.LvPort}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            Header=\"{x:Static resx:ResUI.LvTransportProtocol}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding StreamSecurity}\"\n                            Header=\"{x:Static resx:ResUI.LvTLS}\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/AddGroupServerWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class AddGroupServerWindow : WindowBase<AddGroupServerViewModel>\n{\n    public AddGroupServerWindow()\n    {\n        InitializeComponent();\n    }\n\n    public AddGroupServerWindow(ProfileItem profileItem)\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        lstChild.SelectionChanged += LstChild_SelectionChanged;\n        tabControl.SelectionChanged += TabControl_SelectionChanged;\n\n        ViewModel = new AddGroupServerViewModel(profileItem, UpdateViewHandler);\n\n        cmbCoreType.ItemsSource = Global.CoreTypes;\n        cmbPolicyGroupType.ItemsSource = new List<string>\n        {\n            ResUI.TbLeastPing,\n            ResUI.TbFallback,\n            ResUI.TbRandom,\n            ResUI.TbRoundRobin,\n            ResUI.TbLeastLoad,\n        };\n        cmbFilter.ItemsSource = Global.PolicyGroupDefaultFilterList;\n\n        switch (profileItem.ConfigType)\n        {\n            case EConfigType.PolicyGroup:\n                Title = ResUI.TbConfigTypePolicyGroup;\n                break;\n\n            case EConfigType.ProxyChain:\n                Title = ResUI.TbConfigTypeProxyChain;\n                gridPolicyGroup.IsVisible = false;\n                if (tabControl.Items.Count > 0)\n                {\n                    tabControl.Items.RemoveAt(0);\n                }\n                break;\n        }\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.PolicyGroupType, v => v.cmbPolicyGroupType.SelectedValue).DisposeWith(disposables);\n            //this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbSubChildItems.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSubItem, v => v.cmbSubChildItems.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Filter, v => v.cmbFilter.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedChild, v => v.lstChild.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RemoveCmd, v => v.menuRemoveChildServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n\n        // Context menu actions that require custom logic (Add, SelectAll)\n        menuAddChildServer.Click += MenuAddChild_Click;\n        menuSelectAllChild.Click += (s, e) => lstChild.SelectAll();\n\n        // Keyboard shortcuts when focus is within grid\n        AddHandler(KeyDownEvent, AddGroupServerWindow_KeyDown, RoutingStrategies.Tunnel);\n        lstChild.LoadingRow += LstChild_LoadingRow;\n    }\n\n    private void LstChild_LoadingRow(object? sender, DataGridRowEventArgs e)\n    {\n        e.Row.Header = $\" {e.Row.Index + 1}\";\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void AddGroupServerWindow_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (!lstChild.IsKeyboardFocusWithin)\n        {\n            return;\n        }\n\n        if ((e.KeyModifiers & (KeyModifiers.Control | KeyModifiers.Meta)) != 0)\n        {\n            if (e.Key == Key.A)\n            {\n                lstChild.SelectAll();\n                e.Handled = true;\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.T:\n                    ViewModel?.MoveServer(EMove.Top);\n                    e.Handled = true;\n                    break;\n\n                case Key.U:\n                    ViewModel?.MoveServer(EMove.Up);\n                    e.Handled = true;\n                    break;\n\n                case Key.D:\n                    ViewModel?.MoveServer(EMove.Down);\n                    e.Handled = true;\n                    break;\n\n                case Key.B:\n                    ViewModel?.MoveServer(EMove.Bottom);\n                    e.Handled = true;\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.ChildRemoveAsync();\n                    e.Handled = true;\n                    break;\n            }\n        }\n    }\n\n    private async void MenuAddChild_Click(object? sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter([EConfigType.Custom], exclude: true);\n        selectWindow.AllowMultiSelect(true);\n        var result = await selectWindow.ShowDialog<bool?>(this);\n        if (result == true)\n        {\n            var profiles = await selectWindow.ProfileItems;\n            ViewModel?.ChildItemsObs.AddRange(profiles);\n        }\n    }\n\n    private void LstChild_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedChildren = lstChild.SelectedItems.Cast<ProfileItem>().ToList();\n        }\n    }\n\n    private async void TabControl_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        try\n        {\n            if (e.Source is not TabControl tc)\n            {\n                return;\n            }\n            if (!(tc.SelectedIndex == tc.Items.Count - 1 && tc.Items.Count > 0))\n            {\n                return;\n            }\n            if (ViewModel == null)\n            {\n                return;\n            }\n\n            await ViewModel.UpdatePreviewList();\n        }\n        catch\n        {\n            // ignored\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/AddServer2Window.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.AddServer2Window\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuAddCustomServer}\"\n    Width=\"700\"\n    Height=\"500\"\n    x:DataType=\"vms:AddServer2ViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n        <ScrollViewer HorizontalScrollBarVisibility=\"Auto\" VerticalScrollBarVisibility=\"Auto\">\n            <Grid ColumnDefinitions=\"Auto,Auto,Auto\" RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                <TextBlock\n                    Grid.Row=\"0\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Text=\"{x:Static resx:ResUI.menuServers}\" />\n\n                <TextBlock\n                    Grid.Row=\"1\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbRemarks}\" />\n\n                <TextBox\n                    x:Name=\"txtRemarks\"\n                    Grid.Row=\"1\"\n                    Grid.Column=\"1\"\n                    Width=\"400\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\" />\n\n                <TextBlock\n                    Grid.Row=\"2\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbAddress}\" />\n                <TextBox\n                    x:Name=\"txtAddress\"\n                    Grid.Row=\"2\"\n                    Grid.Column=\"1\"\n                    Width=\"400\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\"\n                    IsReadOnly=\"True\" />\n                <StackPanel\n                    Grid.Row=\"2\"\n                    Grid.Column=\"2\"\n                    VerticalAlignment=\"Center\"\n                    Orientation=\"Horizontal\">\n                    <Button\n                        x:Name=\"btnBrowse\"\n                        Margin=\"{StaticResource MarginLr4}\"\n                        Content=\"{x:Static resx:ResUI.TbBrowse}\" />\n                    <Button\n                        x:Name=\"btnEdit\"\n                        Margin=\"{StaticResource MarginLr4}\"\n                        Content=\"{x:Static resx:ResUI.TbEdit}\" />\n                </StackPanel>\n\n                <TextBlock\n                    Grid.Row=\"3\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbCoreType}\" />\n                <ComboBox\n                    x:Name=\"cmbCoreType\"\n                    Grid.Row=\"3\"\n                    Grid.Column=\"1\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    MaxDropDownHeight=\"1000\" />\n\n                <TextBlock\n                    Grid.Row=\"4\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbDisplayLog}\" />\n                <StackPanel\n                    Grid.Row=\"4\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Orientation=\"Horizontal\">\n                    <ToggleSwitch\n                        x:Name=\"togDisplayLog\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                    <TextBlock\n                        Margin=\"{StaticResource MarginLr8}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TipDisplayLog}\" />\n                </StackPanel>\n\n                <TextBlock\n                    Grid.Row=\"5\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbPreSocksPort}\" />\n                <TextBox\n                    x:Name=\"txtPreSocksPort\"\n                    Grid.Row=\"5\"\n                    Grid.Column=\"1\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\" />\n                <StackPanel\n                    Grid.Row=\"6\"\n                    Grid.Column=\"1\"\n                    Grid.ColumnSpan=\"2\"\n                    Margin=\"{StaticResource Margin4}\">\n                    <TextBlock\n                        Width=\"500\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TipPreSocksPort}\"\n                        TextWrapping=\"Wrap\" />\n                    <TextBlock\n                        Width=\"500\"\n                        Margin=\"{StaticResource MarginLr8}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.CustomServerTips}\"\n                        TextWrapping=\"Wrap\" />\n                </StackPanel>\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/AddServer2Window.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\nusing v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class AddServer2Window : WindowBase<AddServer2ViewModel>\n{\n    public AddServer2Window()\n    {\n        InitializeComponent();\n    }\n\n    public AddServer2Window(ProfileItem profileItem)\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        ViewModel = new AddServer2ViewModel(profileItem, UpdateViewHandler);\n\n        cmbCoreType.ItemsSource = Utils.GetEnumNames<ECoreType>().Where(t => t != ECoreType.v2rayN.ToString()).ToList().AppendEmpty();\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Address, v => v.txtAddress.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.DisplayLog, v => v.togDisplayLog.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.BrowseServerCmd, v => v.btnBrowse).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.btnEdit).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SaveServerCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n\n            case EViewAction.BrowseServer:\n                var fileName = await UI.OpenFileDialog(this, null);\n                if (fileName.IsNullOrEmpty())\n                {\n                    return false;\n                }\n                ViewModel?.BrowseServer(fileName);\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.AddServerWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuServers}\"\n    Width=\"900\"\n    Height=\"600\"\n    x:DataType=\"vms:AddServerViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n        <ScrollViewer HorizontalScrollBarVisibility=\"Auto\" VerticalScrollBarVisibility=\"Auto\">\n            <Grid RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                <Grid\n                    Grid.Row=\"0\"\n                    ColumnDefinitions=\"300,Auto,Auto\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.menuServers}\" />\n                    <StackPanel\n                        Grid.Row=\"0\"\n                        Grid.Column=\"2\"\n                        Orientation=\"Horizontal\">\n                        <ComboBox\n                            x:Name=\"cmbCoreType\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\"\n                            ToolTip.Tip=\"{x:Static resx:ResUI.TbCoreType}\" />\n                    </StackPanel>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbRemarks}\" />\n                    <TextBox\n                        x:Name=\"txtRemarks\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbAddress}\" />\n                    <TextBox\n                        x:Name=\"txtAddress\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPort}\" />\n                    <TextBox\n                        x:Name=\"txtPort\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n\n                <Separator Grid.Row=\"1\" Margin=\"{StaticResource MarginTb8}\" />\n\n                <Grid\n                    x:Name=\"gridVMess\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId}\" />\n                    <TextBox\n                        x:Name=\"txtId\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n                    <Button\n                        x:Name=\"btnGUID\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource MarginLr4}\"\n                        Content=\"{x:Static resx:ResUI.TbGUID}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbAlterId}\" />\n                    <TextBox\n                        x:Name=\"txtAlterId\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity}\" />\n                    <ComboBox\n                        x:Name=\"cmbSecurity\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleSwitch\n                        x:Name=\"togmuxEnabled\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridSs\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId3\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity3}\" />\n                    <ComboBox\n                        x:Name=\"cmbSecurity3\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"300\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleSwitch\n                        x:Name=\"togmuxEnabled3\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridSocks\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity4}\" />\n                    <TextBox\n                        x:Name=\"txtSecurity4\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId4}\" />\n                    <TextBox\n                        x:Name=\"txtId4\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridVLESS\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId5}\" />\n                    <TextBox\n                        x:Name=\"txtId5\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n                    <Button\n                        x:Name=\"btnGUID5\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource MarginLr4}\"\n                        Content=\"{x:Static resx:ResUI.TbGUID}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbFlow5}\" />\n                    <ComboBox\n                        x:Name=\"cmbFlow5\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSecurity5}\" />\n                    <TextBox\n                        x:Name=\"txtSecurity5\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleSwitch\n                        x:Name=\"togmuxEnabled5\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridTrojan\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId6\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbFlow5}\" />\n                    <ComboBox\n                        x:Name=\"cmbFlow6\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                    <ToggleSwitch\n                        x:Name=\"togmuxEnabled6\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridHysteria2\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId7\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPath7}\" />\n                    <TextBox\n                        x:Name=\"txtPath7\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPorts7}\" />\n                    <TextBox\n                        x:Name=\"txtPorts7\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Watermark=\"1000-2000,3000,4000\" />\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPorts7Tips}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbHopInt7}\" />\n                    <TextBox\n                        x:Name=\"txtHopInt7\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsHysteriaBandwidth}\" />\n                    <StackPanel\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Orientation=\"Horizontal\">\n                        <TextBox\n                            x:Name=\"txtUpMbps7\"\n                            Width=\"90\"\n                            Margin=\"{StaticResource Margin4}\"\n                            Watermark=\"Up\" />\n                        <TextBox\n                            x:Name=\"txtDownMbps7\"\n                            Width=\"90\"\n                            Margin=\"{StaticResource Margin4}\"\n                            Watermark=\"Down\" />\n                    </StackPanel>\n                </Grid>\n                <Grid\n                    x:Name=\"gridTuic\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId}\" />\n                    <TextBox\n                        x:Name=\"txtId8\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtSecurity8\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbHeaderType8}\" />\n                    <ComboBox\n                        x:Name=\"cmbHeaderType8\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridWireguard\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPrivateKey}\" />\n                    <TextBox\n                        x:Name=\"txtId9\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPublicKey}\" />\n                    <TextBox\n                        x:Name=\"txtPublicKey9\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbReserved}\" />\n                    <TextBox\n                        x:Name=\"txtPath9\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Watermark=\"2,3,4\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbLocalAddress}\" />\n                    <TextBox\n                        x:Name=\"txtRequestHost9\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Watermark=\"Ipv4,Ipv6\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunMtu}\" />\n                    <TextBox\n                        x:Name=\"txtShortId9\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\"\n                        Watermark=\"1500\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridAnytls\"\n                    Grid.Row=\"2\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbId3}\" />\n                    <TextBox\n                        x:Name=\"txtId10\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n                </Grid>\n\n                <Separator\n                    x:Name=\"sepa2\"\n                    Grid.Row=\"3\"\n                    Margin=\"{StaticResource MarginTb8}\" />\n\n                <Grid\n                    x:Name=\"gridTransport\"\n                    Grid.Row=\"4\"\n                    ColumnDefinitions=\"300,Auto,Auto\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.ColumnSpan=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.GbTransport}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbNetwork}\" />\n                    <ComboBox\n                        x:Name=\"cmbNetwork\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TipNetwork}\" />\n\n                    <TextBlock\n                        x:Name=\"labHeaderType\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbHeaderType}\" />\n                    <StackPanel\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Orientation=\"Horizontal\">\n                        <ComboBox\n                            x:Name=\"cmbHeaderType\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <Button\n                            x:Name=\"btnExtra\"\n                            Margin=\"{StaticResource MarginLr8}\"\n                            Classes=\"IconButton\">\n                            <Button.Content>\n                                <PathIcon Data=\"{StaticResource SemiIconMore}\">\n                                    <PathIcon.RenderTransform>\n                                        <RotateTransform Angle=\"90\" />\n                                    </PathIcon.RenderTransform>\n                                </PathIcon>\n                            </Button.Content>\n                            <Button.Flyout>\n                                <Flyout>\n                                    <StackPanel>\n                                        <TextBlock\n                                            Margin=\"{StaticResource Margin4}\"\n                                            VerticalAlignment=\"Center\"\n                                            Text=\"{x:Static resx:ResUI.TransportExtraTip}\" />\n                                        <TextBox\n                                            x:Name=\"txtExtra\"\n                                            Width=\"400\"\n                                            MinHeight=\"100\"\n                                            Margin=\"{StaticResource Margin4}\"\n                                            HorizontalAlignment=\"Stretch\"\n                                            VerticalAlignment=\"Center\"\n                                            Classes=\"TextArea\"\n                                            MinLines=\"6\"\n                                            TextWrapping=\"Wrap\" />\n                                    </StackPanel>\n                                </Flyout>\n                            </Button.Flyout>\n                        </Button>\n                    </StackPanel>\n                    <TextBlock\n                        x:Name=\"tipHeaderType\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbHeaderType}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbRequestHost}\" />\n                    <TextBox\n                        x:Name=\"txtRequestHost\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n                    <TextBlock\n                        x:Name=\"tipRequestHost\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbRequestHost}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPath}\" />\n                    <TextBox\n                        x:Name=\"txtPath\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\" />\n                    <TextBlock\n                        x:Name=\"tipPath\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"2\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPath}\" />\n                </Grid>\n\n                <Grid\n                    x:Name=\"gridFinalmask\"\n                    Grid.Row=\"5\"\n                    ColumnDefinitions=\"300,Auto\">\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbFinalmask}\" />\n                    <Button\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource MarginLr4}\"\n                        HorizontalAlignment=\"Left\"\n                        VerticalAlignment=\"Center\"\n                        Classes=\"IconButton\">\n                        <Button.Content>\n                            <PathIcon Data=\"{StaticResource SemiIconMore}\">\n                                <PathIcon.RenderTransform>\n                                    <RotateTransform Angle=\"90\" />\n                                </PathIcon.RenderTransform>\n                            </PathIcon>\n                        </Button.Content>\n                        <Button.Flyout>\n                            <Flyout>\n                                <StackPanel>\n                                    <TextBox\n                                        x:Name=\"txtFinalmask\"\n                                        Width=\"400\"\n                                        Margin=\"{StaticResource Margin4}\"\n                                        AcceptsReturn=\"True\"\n                                        Classes=\"TextArea\"\n                                        TextWrapping=\"NoWrap\" />\n                                </StackPanel>\n                            </Flyout>\n                        </Button.Flyout>\n                    </Button>\n                </Grid>\n\n                <Separator Grid.Row=\"6\" Margin=\"{StaticResource MarginTb8}\" />\n\n                <Grid\n                    x:Name=\"gridTls\"\n                    Grid.Row=\"7\"\n                    ColumnDefinitions=\"300,Auto\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbStreamSecurity}\" />\n                    <ComboBox\n                        x:Name=\"cmbStreamSecurity\"\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n                </Grid>\n                <Grid\n                    x:Name=\"gridTlsMore\"\n                    Grid.Row=\"8\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSNI}\" />\n                    <TextBox\n                        x:Name=\"txtSNI\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbFingerprint}\" />\n                    <ComboBox\n                        x:Name=\"cmbFingerprint\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbAlpn}\" />\n                    <ComboBox\n                        x:Name=\"cmbAlpn\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbAllowInsecure}\" />\n                    <ComboBox\n                        x:Name=\"cmbAllowInsecure\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbEchConfigList}\" />\n                    <TextBox\n                        x:Name=\"txtEchConfigList\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"6\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbEchForceQuery}\" />\n                    <ComboBox\n                        x:Name=\"cmbEchForceQuery\"\n                        Grid.Row=\"6\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"7\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbCertPinning}\" />\n                    <StackPanel\n                        Grid.Row=\"7\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Orientation=\"Horizontal\">\n                        <TextBlock\n                            x:Name=\"labCertPinning\"\n                            Margin=\"{StaticResource Margin8}\"\n                            VerticalAlignment=\"Center\" />\n                        <Button\n                            Margin=\"{StaticResource MarginLr4}\"\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\"\n                            Classes=\"IconButton\">\n                            <Button.Content>\n                                <PathIcon Data=\"{StaticResource SemiIconMore}\">\n                                    <PathIcon.RenderTransform>\n                                        <RotateTransform Angle=\"90\" />\n                                    </PathIcon.RenderTransform>\n                                </PathIcon>\n                            </Button.Content>\n                            <Button.Flyout>\n                                <Flyout>\n                                    <StackPanel>\n                                        <TextBlock\n                                            Width=\"400\"\n                                            Margin=\"{StaticResource Margin4}\"\n                                            VerticalAlignment=\"Center\"\n                                            Text=\"{x:Static resx:ResUI.TbCertPinningTips}\"\n                                            TextWrapping=\"Wrap\" />\n                                        <StackPanel HorizontalAlignment=\"Left\" Orientation=\"Horizontal\">\n                                            <Button\n                                                x:Name=\"btnFetchCert\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                Content=\"{x:Static resx:ResUI.TbFetchCert}\" />\n                                            <Button\n                                                x:Name=\"btnFetchCertChain\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                Content=\"{x:Static resx:ResUI.TbFetchCertChain}\" />\n                                        </StackPanel>\n                                        <TextBlock\n                                            Width=\"400\"\n                                            Margin=\"{StaticResource Margin4}\"\n                                            VerticalAlignment=\"Center\"\n                                            Text=\"{x:Static resx:ResUI.TbCertSha256Tips}\"\n                                            TextWrapping=\"Wrap\" />\n                                        <TextBox\n                                            x:Name=\"txtCertSha256Pinning\"\n                                            Width=\"400\"\n                                            Margin=\"{StaticResource Margin4}\"\n                                            HorizontalAlignment=\"Left\" />\n                                        <TextBlock\n                                            Width=\"400\"\n                                            Margin=\"{StaticResource Margin4}\"\n                                            VerticalAlignment=\"Center\"\n                                            Text=\"{x:Static resx:ResUI.TbFullCertTips}\"\n                                            TextWrapping=\"Wrap\" />\n                                        <TextBox\n                                            x:Name=\"txtCert\"\n                                            Width=\"400\"\n                                            Margin=\"{StaticResource Margin4}\"\n                                            AcceptsReturn=\"True\"\n                                            Classes=\"TextArea\"\n                                            TextWrapping=\"NoWrap\" />\n                                    </StackPanel>\n                                </Flyout>\n                            </Button.Flyout>\n                        </Button>\n                    </StackPanel>\n                </Grid>\n                <Grid\n                    x:Name=\"gridRealityMore\"\n                    Grid.Row=\"8\"\n                    ColumnDefinitions=\"300,Auto\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSNI}\" />\n                    <TextBox\n                        x:Name=\"txtSNI2\"\n                        Grid.Row=\"0\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbFingerprint}\" />\n                    <ComboBox\n                        x:Name=\"cmbFingerprint2\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbPublicKey}\" />\n                    <TextBox\n                        x:Name=\"txtPublicKey\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbShortId}\" />\n                    <TextBox\n                        x:Name=\"txtShortId\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSpiderX}\" />\n                    <TextBox\n                        x:Name=\"txtSpiderX\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbMldsa65Verify}\" />\n                    <TextBox\n                        x:Name=\"txtMldsa65Verify\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"400\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n                </Grid>\n                <Separator Grid.Row=\"9\" Margin=\"{StaticResource MarginTb8}\" />\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class AddServerWindow : WindowBase<AddServerViewModel>\n{\n    public AddServerWindow()\n    {\n        InitializeComponent();\n    }\n\n    public AddServerWindow(ProfileItem profileItem)\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        cmbNetwork.SelectionChanged += CmbNetwork_SelectionChanged;\n        cmbStreamSecurity.SelectionChanged += CmbStreamSecurity_SelectionChanged;\n        btnGUID.Click += btnGUID_Click;\n        btnGUID5.Click += btnGUID_Click;\n\n        ViewModel = new AddServerViewModel(profileItem, UpdateViewHandler);\n\n        cmbCoreType.ItemsSource = Global.CoreTypes.AppendEmpty();\n        cmbNetwork.ItemsSource = Global.Networks;\n        cmbFingerprint.ItemsSource = Global.Fingerprints;\n        cmbFingerprint2.ItemsSource = Global.Fingerprints;\n        cmbAllowInsecure.ItemsSource = Global.AllowInsecure;\n        cmbAlpn.ItemsSource = Global.Alpns;\n        cmbEchForceQuery.ItemsSource = Global.EchForceQuerys;\n\n        var lstStreamSecurity = new List<string>();\n        lstStreamSecurity.Add(string.Empty);\n        lstStreamSecurity.Add(Global.StreamSecurity);\n\n        switch (profileItem.ConfigType)\n        {\n            case EConfigType.VMess:\n                gridVMess.IsVisible = true;\n                cmbSecurity.ItemsSource = Global.VmessSecurities;\n                break;\n\n            case EConfigType.Shadowsocks:\n                gridSs.IsVisible = true;\n                cmbSecurity3.ItemsSource = AppManager.Instance.GetShadowsocksSecurities(profileItem);\n                break;\n\n            case EConfigType.SOCKS:\n            case EConfigType.HTTP:\n                gridSocks.IsVisible = true;\n                break;\n\n            case EConfigType.VLESS:\n                gridVLESS.IsVisible = true;\n                lstStreamSecurity.Add(Global.StreamSecurityReality);\n                cmbFlow5.ItemsSource = Global.Flows;\n                break;\n\n            case EConfigType.Trojan:\n                gridTrojan.IsVisible = true;\n                lstStreamSecurity.Add(Global.StreamSecurityReality);\n                cmbFlow6.ItemsSource = Global.Flows;\n                break;\n\n            case EConfigType.Hysteria2:\n                gridHysteria2.IsVisible = true;\n                sepa2.IsVisible = false;\n                gridTransport.IsVisible = false;\n                cmbFingerprint.IsEnabled = false;\n                cmbFingerprint.SelectedValue = string.Empty;\n                break;\n\n            case EConfigType.TUIC:\n                gridTuic.IsVisible = true;\n                sepa2.IsVisible = false;\n                gridTransport.IsVisible = false;\n                cmbCoreType.IsEnabled = false;\n                cmbFingerprint.IsEnabled = false;\n                cmbFingerprint.SelectedValue = string.Empty;\n                gridFinalmask.IsVisible = false;\n\n                cmbHeaderType8.ItemsSource = Global.TuicCongestionControls;\n                break;\n\n            case EConfigType.WireGuard:\n                gridWireguard.IsVisible = true;\n\n                sepa2.IsVisible = false;\n                gridTransport.IsVisible = false;\n                gridTls.IsVisible = false;\n\n                break;\n\n            case EConfigType.Anytls:\n                gridAnytls.IsVisible = true;\n                lstStreamSecurity.Add(Global.StreamSecurityReality);\n                cmbCoreType.IsEnabled = false;\n                gridFinalmask.IsVisible = false;\n                break;\n        }\n        cmbStreamSecurity.ItemsSource = lstStreamSecurity;\n\n        gridTlsMore.IsVisible = false;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.CoreType, v => v.cmbCoreType.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Address, v => v.txtAddress.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Port, v => v.txtPort.Text).DisposeWith(disposables);\n\n            switch (profileItem.ConfigType)\n            {\n                case EConfigType.VMess:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.AlterId, v => v.txtAlterId.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.VmessSecurity, v => v.cmbSecurity.SelectedValue).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Shadowsocks:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId3.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SsMethod, v => v.cmbSecurity3.SelectedValue).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled3.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.SOCKS:\n                case EConfigType.HTTP:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId4.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtSecurity4.Text).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.VLESS:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId5.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.Flow, v => v.cmbFlow5.SelectedValue).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.VlessEncryption, v => v.txtSecurity5.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled5.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Trojan:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId6.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.Flow, v => v.cmbFlow6.SelectedValue).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.MuxEnabled, v => v.togmuxEnabled6.IsChecked).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Hysteria2:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SalamanderPass, v => v.txtPath7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.Ports, v => v.txtPorts7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.HopInterval, v => v.txtHopInt7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.UpMbps, v => v.txtUpMbps7.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.DownMbps, v => v.txtDownMbps7.Text).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.TUIC:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Username, v => v.txtId8.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtSecurity8.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType8.SelectedValue).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.WireGuard:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgPublicKey, v => v.txtPublicKey9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgReserved, v => v.txtPath9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgInterfaceAddress, v => v.txtRequestHost9.Text).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.WgMtu, v => v.txtShortId9.Text).DisposeWith(disposables);\n                    break;\n\n                case EConfigType.Anytls:\n                    this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtId10.Text).DisposeWith(disposables);\n                    break;\n            }\n            this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.HeaderType, v => v.cmbHeaderType.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Alpn, v => v.cmbAlpn.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CertSha, v => v.txtCertSha256Pinning.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CertTip, v => v.labCertPinning.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Cert, v => v.txtCert.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.EchConfigList, v => v.txtEchConfigList.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.EchForceQuery, v => v.cmbEchForceQuery.SelectedValue).DisposeWith(disposables);\n\n            //reality\n            this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI2.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Fingerprint, v => v.cmbFingerprint2.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PublicKey, v => v.txtPublicKey.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.ShortId, v => v.txtShortId.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.SpiderX, v => v.txtSpiderX.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Mldsa65Verify, v => v.txtMldsa65Verify.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedSource.Finalmask, v => v.txtFinalmask.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.FetchCertCmd, v => v.btnFetchCert).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.FetchCertChainCmd, v => v.btnFetchCertChain).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n\n        Title = $\"{profileItem.ConfigType}\";\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void CmbNetwork_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        SetHeaderType();\n        SetTips();\n    }\n\n    private void CmbStreamSecurity_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        var security = cmbStreamSecurity.SelectedItem.ToString();\n        if (security == Global.StreamSecurityReality)\n        {\n            gridRealityMore.IsVisible = true;\n            gridTlsMore.IsVisible = false;\n        }\n        else if (security == Global.StreamSecurity)\n        {\n            gridRealityMore.IsVisible = false;\n            gridTlsMore.IsVisible = true;\n        }\n        else\n        {\n            gridRealityMore.IsVisible = false;\n            gridTlsMore.IsVisible = false;\n        }\n    }\n\n    private void btnGUID_Click(object? sender, RoutedEventArgs e)\n    {\n        txtId.Text =\n        txtId5.Text = Utils.GetGuid();\n    }\n\n    private void SetHeaderType()\n    {\n        var lstHeaderType = new List<string>();\n\n        var network = cmbNetwork.SelectedItem.ToString();\n        if (network.IsNullOrEmpty())\n        {\n            lstHeaderType.Add(Global.None);\n            cmbHeaderType.ItemsSource = lstHeaderType;\n            cmbHeaderType.SelectedIndex = 0;\n            return;\n        }\n\n        if (network == nameof(ETransport.tcp))\n        {\n            lstHeaderType.Add(Global.None);\n            lstHeaderType.Add(Global.TcpHeaderHttp);\n        }\n        else if (network is nameof(ETransport.kcp) or nameof(ETransport.quic))\n        {\n            lstHeaderType.Add(Global.None);\n            lstHeaderType.AddRange(Global.KcpHeaderTypes);\n        }\n        else if (network is nameof(ETransport.xhttp))\n        {\n            lstHeaderType.AddRange(Global.XhttpMode);\n        }\n        else if (network == nameof(ETransport.grpc))\n        {\n            lstHeaderType.Add(Global.GrpcGunMode);\n            lstHeaderType.Add(Global.GrpcMultiMode);\n        }\n        else\n        {\n            lstHeaderType.Add(Global.None);\n        }\n        cmbHeaderType.ItemsSource = lstHeaderType;\n        cmbHeaderType.SelectedIndex = 0;\n    }\n\n    private void SetTips()\n    {\n        var network = cmbNetwork.SelectedItem.ToString();\n        if (network.IsNullOrEmpty())\n        {\n            network = Global.DefaultNetwork;\n        }\n        labHeaderType.IsVisible = true;\n        btnExtra.IsVisible = false;\n        tipRequestHost.Text =\n        tipPath.Text =\n        tipHeaderType.Text = string.Empty;\n\n        switch (network)\n        {\n            case nameof(ETransport.tcp):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip1;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip1;\n                break;\n\n            case nameof(ETransport.kcp):\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip2;\n                tipPath.Text = ResUI.TransportPathTip5;\n                break;\n\n            case nameof(ETransport.ws):\n            case nameof(ETransport.httpupgrade):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip2;\n                tipPath.Text = ResUI.TransportPathTip1;\n                break;\n\n            case nameof(ETransport.xhttp):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip2;\n                tipPath.Text = ResUI.TransportPathTip1;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip5;\n                labHeaderType.IsVisible = false;\n                btnExtra.IsVisible = true;\n                break;\n\n            case nameof(ETransport.h2):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip3;\n                tipPath.Text = ResUI.TransportPathTip2;\n                break;\n\n            case nameof(ETransport.quic):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip4;\n                tipPath.Text = ResUI.TransportPathTip3;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip3;\n                break;\n\n            case nameof(ETransport.grpc):\n                tipRequestHost.Text = ResUI.TransportRequestHostTip5;\n                tipPath.Text = ResUI.TransportPathTip4;\n                tipHeaderType.Text = ResUI.TransportHeaderTypeTip4;\n                labHeaderType.IsVisible = false;\n                break;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/BackupAndRestoreView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.BackupAndRestoreView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    mc:Ignorable=\"d\">\n    <UserControl.Styles>\n        <Style Selector=\"Button\">\n            <Setter Property=\"MinWidth\" Value=\"180\" />\n        </Style>\n    </UserControl.Styles>\n\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel Margin=\"{StaticResource Margin4}\" DockPanel.Dock=\"Bottom\">\n            <TextBlock\n                Name=\"txtMsg\"\n                HorizontalAlignment=\"Left\"\n                Margin=\"{StaticResource Margin4}\" />\n        </StackPanel>\n\n        <StackPanel>\n            <Border\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Theme=\"{DynamicResource CardBorder}\">\n\n                <Grid\n                    Margin=\"{StaticResource Margin4}\"\n                    ColumnDefinitions=\"300,200\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto\">\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.menuLocalBackupAndRestore}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.menuLocalBackup}\" />\n                    <Button\n                        Name=\"menuLocalBackup\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Content=\"{x:Static resx:ResUI.menuLocalBackup}\" />\n\n                    <Separator\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Grid.ColumnSpan=\"2\"\n                        Margin=\"{StaticResource MarginTb8}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.menuLocalRestore}\" />\n                    <Button\n                        Name=\"menuLocalRestore\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Content=\"{x:Static resx:ResUI.menuLocalRestore}\" />\n                </Grid>\n            </Border>\n            <Border\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Theme=\"{DynamicResource CardBorder}\">\n                <Grid\n                    Margin=\"{StaticResource Margin4}\"\n                    ColumnDefinitions=\"300,200\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto\">\n                    <StackPanel\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Orientation=\"Horizontal\">\n                        <TextBlock Margin=\"{StaticResource Margin4}\" Text=\"{x:Static resx:ResUI.menuRemoteBackupAndRestore}\" />\n\n                        <Button\n                            Classes=\"IconButton\"\n                            Margin=\"{StaticResource MarginLr8}\">\n                            <Button.Content>\n                                <PathIcon Data=\"{StaticResource SemiIconMore}\" >\n                                    <PathIcon.RenderTransform>\n                                        <RotateTransform Angle=\"90\" />\n                                    </PathIcon.RenderTransform>\n                                </PathIcon>\n                            </Button.Content>\n                            <Button.Flyout>\n                                <Flyout>\n                                    <StackPanel>\n                                        <Grid ColumnDefinitions=\"Auto,300\" RowDefinitions=\"Auto,Auto,Auto,Auto,Auto\">\n                                            <TextBlock\n                                                Grid.Row=\"0\"\n                                                Grid.Column=\"0\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                Text=\"{x:Static resx:ResUI.LvWebDavUrl}\" />\n\n                                            <TextBox\n                                                x:Name=\"txtWebDavUrl\"\n                                                Grid.Row=\"0\"\n                                                Grid.Column=\"1\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                TextWrapping=\"Wrap\" />\n\n                                            <TextBlock\n                                                Grid.Row=\"1\"\n                                                Grid.Column=\"0\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                Text=\"{x:Static resx:ResUI.LvWebDavUserName}\" />\n\n                                            <TextBox\n                                                x:Name=\"txtWebDavUserName\"\n                                                Grid.Row=\"1\"\n                                                Grid.Column=\"1\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\" />\n\n                                            <TextBlock\n                                                Grid.Row=\"2\"\n                                                Grid.Column=\"0\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                Text=\"{x:Static resx:ResUI.LvWebDavPassword}\" />\n\n                                            <TextBox\n                                                x:Name=\"txtWebDavPassword\"\n                                                Grid.Row=\"2\"\n                                                Grid.Column=\"1\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\" />\n\n                                            <TextBlock\n                                                Grid.Row=\"3\"\n                                                Grid.Column=\"0\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                Text=\"{x:Static resx:ResUI.LvWebDavDirName}\" />\n\n                                            <TextBox\n                                                x:Name=\"txtWebDavDirName\"\n                                                Grid.Row=\"3\"\n                                                Grid.Column=\"1\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\" />\n\n                                            <Button\n                                                x:Name=\"menuWebDavCheck\"\n                                                Grid.Row=\"4\"\n                                                Grid.Column=\"1\"\n                                                HorizontalAlignment=\"Right\"\n                                                VerticalAlignment=\"Center\"\n                                                Margin=\"{StaticResource Margin4}\"\n                                                Content=\"{x:Static resx:ResUI.LvWebDavCheck}\" />\n                                        </Grid>\n                                    </StackPanel>\n                                </Flyout>\n                            </Button.Flyout>\n                        </Button>\n\n                    </StackPanel>\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.menuRemoteBackup}\" />\n                    <Button\n                        Name=\"menuRemoteBackup\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Content=\"{x:Static resx:ResUI.menuRemoteBackup}\" />\n\n                    <Separator\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Grid.ColumnSpan=\"2\"\n                        Margin=\"{StaticResource MarginTb8}\" />\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.menuRemoteRestore}\" />\n                    <Button\n                        Name=\"menuRemoteRestore\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        VerticalAlignment=\"Center\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Content=\"{x:Static resx:ResUI.menuRemoteRestore}\" />\n                </Grid>\n            </Border>\n        </StackPanel>\n    </DockPanel>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/BackupAndRestoreView.axaml.cs",
    "content": "using v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class BackupAndRestoreView : ReactiveUserControl<BackupAndRestoreViewModel>\n{\n    private Window? _window;\n\n    public BackupAndRestoreView()\n    {\n        InitializeComponent();\n    }\n\n    public BackupAndRestoreView(Window window)\n    {\n        _window = window;\n\n        InitializeComponent();\n        menuLocalBackup.Click += MenuLocalBackup_Click;\n        menuLocalRestore.Click += MenuLocalRestore_Click;\n\n        ViewModel = new BackupAndRestoreViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.OperationMsg, v => v.txtMsg.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedSource.Url, v => v.txtWebDavUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.UserName, v => v.txtWebDavUserName.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Password, v => v.txtWebDavPassword.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.DirName, v => v.txtWebDavDirName.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.WebDavCheckCmd, v => v.menuWebDavCheck).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RemoteBackupCmd, v => v.menuRemoteBackup).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoteRestoreCmd, v => v.menuRemoteRestore).DisposeWith(disposables);\n        });\n    }\n\n    private async void MenuLocalBackup_Click(object? sender, RoutedEventArgs e)\n    {\n        var fileName = await UI.SaveFileDialog(_window, \"Zip|*.zip\");\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        ViewModel?.LocalBackup(fileName);\n    }\n\n    private async void MenuLocalRestore_Click(object? sender, RoutedEventArgs e)\n    {\n        var fileName = await UI.OpenFileDialog(_window, null);\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        ViewModel?.LocalRestore(fileName);\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/CheckUpdateView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.CheckUpdateView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"600\"\n    d:DesignWidth=\"800\"\n    x:DataType=\"vms:CheckUpdateViewModel\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <Border\n            Margin=\"{StaticResource Margin4}\"\n            VerticalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Theme=\"{DynamicResource CardBorder}\">\n\n            <StackPanel\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Center\"\n                Orientation=\"Horizontal\">\n\n                <TextBlock\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbSettingsEnableCheckPreReleaseUpdate}\" />\n                <ToggleSwitch\n                    x:Name=\"togEnableCheckPreReleaseUpdate\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\" />\n\n                <Button\n                    x:Name=\"btnCheckUpdate\"\n                    Width=\"100\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Content=\"{x:Static resx:ResUI.menuCheckUpdate}\" />\n            </StackPanel>\n        </Border>\n\n        <Border\n            Margin=\"{StaticResource Margin4}\"\n            VerticalAlignment=\"Center\"\n            Theme=\"{DynamicResource CardBorder}\">\n\n            <ListBox\n                x:Name=\"lstCheckUpdates\"\n                BorderThickness=\"1\"\n                ItemsSource=\"{Binding CheckUpdateModels}\">\n                <ItemsControl.ItemsPanel>\n                    <ItemsPanelTemplate>\n                        <StackPanel Orientation=\"Vertical\" />\n                    </ItemsPanelTemplate>\n                </ItemsControl.ItemsPanel>\n                <ItemsControl.ItemTemplate>\n                    <DataTemplate>\n                        <Panel Width=\"500\" VerticalAlignment=\"Center\">\n                            <Grid ColumnDefinitions=\"1*,1*,3*\" RowDefinitions=\"Auto\">\n                                <ToggleSwitch\n                                    x:Name=\"togAutoRefresh\"\n                                    Grid.Column=\"0\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    HorizontalAlignment=\"Left\"\n                                    VerticalAlignment=\"Center\"\n                                    IsChecked=\"{Binding IsSelected}\" />\n                                <TextBlock\n                                    Grid.Column=\"1\"\n                                    HorizontalAlignment=\"Left\"\n                                    VerticalAlignment=\"Center\"\n                                    Text=\"{Binding CoreType}\" />\n                                <TextBlock\n                                    Grid.Column=\"2\"\n                                    HorizontalAlignment=\"Left\"\n                                    VerticalAlignment=\"Center\"\n                                    Text=\"{Binding Remarks}\"\n                                    TextWrapping=\"WrapWithOverflow\" />\n                            </Grid>\n                        </Panel>\n                    </DataTemplate>\n                </ItemsControl.ItemTemplate>\n            </ListBox>\n        </Border>\n    </DockPanel>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/CheckUpdateView.axaml.cs",
    "content": "namespace v2rayN.Desktop.Views;\n\npublic partial class CheckUpdateView : ReactiveUserControl<CheckUpdateViewModel>\n{\n    public CheckUpdateView()\n    {\n        InitializeComponent();\n\n        ViewModel = new CheckUpdateViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.CheckUpdateModels, v => v.lstCheckUpdates.ItemsSource).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.EnableCheckPreReleaseUpdate, v => v.togEnableCheckPreReleaseUpdate.IsChecked).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.CheckUpdateCmd, v => v.btnCheckUpdate).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.ClashConnectionsView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:DataType=\"vms:ClashConnectionsViewModel\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"2\">\n        <WrapPanel\n            VerticalAlignment=\"Center\"\n            Margin=\"{StaticResource Margin4}\"\n            DockPanel.Dock=\"Top\"\n            Orientation=\"Horizontal\">\n\n            <TextBox\n                x:Name=\"txtHostFilter\"\n                Width=\"200\"\n                VerticalContentAlignment=\"Center\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Watermark=\"{x:Static resx:ResUI.ConnectionsHostFilterTitle}\" />\n\n            <Button\n                x:Name=\"btnConnectionCloseAll\"\n                Classes=\"IconButton Success\"\n                Margin=\"{StaticResource MarginLr8}\"\n                ToolTip.Tip=\"{x:Static resx:ResUI.menuConnectionCloseAll}\">\n                <Button.Content>\n                    <PathIcon Data=\"{StaticResource SemiIconClose}\" />\n                </Button.Content>\n            </Button>\n\n            <Button\n                x:Name=\"btnAutofitColumnWidth\"\n                Classes=\"IconButton Success\"\n                Margin=\"{StaticResource MarginLr8}\"\n                ToolTip.Tip=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\">\n                <Button.Content>\n                    <PathIcon Data=\"{StaticResource SemiIconExpand}\" />\n                </Button.Content>\n            </Button>\n\n            <TextBlock\n                VerticalAlignment=\"Center\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Text=\"{x:Static resx:ResUI.TbAutoRefresh}\" />\n            <ToggleSwitch\n                x:Name=\"togAutoRefresh\"\n                HorizontalAlignment=\"Left\"\n                Margin=\"{StaticResource MarginLr8}\" />\n        </WrapPanel>\n\n        <DataGrid\n            x:Name=\"lstConnections\"\n            AutoGenerateColumns=\"False\"\n            BorderThickness=\"1\"\n            CanUserResizeColumns=\"True\"\n            GridLinesVisibility=\"All\"\n            HeadersVisibility=\"Column\"\n            IsReadOnly=\"True\"\n            ItemsSource=\"{Binding ConnectionItems}\">\n            <DataGrid.ContextMenu>\n                <ContextMenu>\n                    <MenuItem x:Name=\"menuConnectionClose\" Header=\"{x:Static resx:ResUI.menuConnectionClose}\" />\n                    <MenuItem x:Name=\"menuConnectionCloseAll\" Header=\"{x:Static resx:ResUI.menuConnectionCloseAll}\" />\n                </ContextMenu>\n            </DataGrid.ContextMenu>\n            <DataGrid.Columns>\n                <DataGridTextColumn\n                    Width=\"300\"\n                    Binding=\"{Binding Host}\"\n                    Header=\"{x:Static resx:ResUI.TbSortingHost}\"\n                    Tag=\"Host\" />\n                <DataGridTextColumn\n                    Width=\"500\"\n                    Binding=\"{Binding Chain}\"\n                    Header=\"{x:Static resx:ResUI.TbSortingChain}\"\n                    Tag=\"Chain\" />\n                <DataGridTextColumn\n                    Width=\"80\"\n                    Binding=\"{Binding Network}\"\n                    Header=\"{x:Static resx:ResUI.TbSortingNetwork}\"\n                    Tag=\"Network\" />\n                <DataGridTextColumn\n                    Width=\"160\"\n                    Binding=\"{Binding Type}\"\n                    Header=\"{x:Static resx:ResUI.TbSortingType}\"\n                    Tag=\"Type\" />\n                <DataGridTextColumn\n                    Width=\"100\"\n                    Binding=\"{Binding Elapsed}\"\n                    Header=\"{x:Static resx:ResUI.TbSortingTime}\"\n                    Tag=\"Elapsed\" />\n            </DataGrid.Columns>\n        </DataGrid>\n    </DockPanel>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ClashConnectionsView.axaml.cs",
    "content": "namespace v2rayN.Desktop.Views;\n\npublic partial class ClashConnectionsView : ReactiveUserControl<ClashConnectionsViewModel>\n{\n    private static Config _config;\n    private static readonly string _tag = \"ClashConnectionsView\";\n\n    public ClashConnectionsView()\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n\n        ViewModel = new ClashConnectionsViewModel(UpdateViewHandler);\n        btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ConnectionItems, v => v.lstConnections.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstConnections.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ConnectionCloseCmd, v => v.menuConnectionClose).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.menuConnectionCloseAll).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.HostFilter, v => v.txtHostFilter.Text).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ConnectionCloseAllCmd, v => v.btnConnectionCloseAll).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);\n\n            AppEvents.AppExitRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(_ => StorageUI())\n              .DisposeWith(disposables);\n        });\n\n        RestoreUI();\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n\n    private void BtnAutofitColumnWidth_Click(object? sender, RoutedEventArgs e)\n    {\n        AutofitColumnWidth();\n    }\n\n    private void AutofitColumnWidth()\n    {\n        try\n        {\n            foreach (var it in lstConnections.Columns)\n            {\n                it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"ClashConnectionsView\", ex);\n        }\n    }\n\n    private void btnClose_Click(object? sender, RoutedEventArgs e)\n    {\n        ViewModel?.ClashConnectionClose(false);\n    }\n\n    #region UI\n\n    private void RestoreUI()\n    {\n        try\n        {\n            var lvColumnItem = _config.ClashUIItem?.ConnectionsColumnItem?.OrderBy(t => t.Index).ToList();\n            if (lvColumnItem == null)\n            {\n                return;\n            }\n\n            var displayIndex = 0;\n            foreach (var item in lvColumnItem)\n            {\n                foreach (var item2 in lstConnections.Columns)\n                {\n                    if (item2.Tag == null)\n                    {\n                        continue;\n                    }\n                    if (item2.Tag.Equals(item.Name))\n                    {\n                        if (item.Width < 0)\n                        {\n                            item2.IsVisible = false;\n                        }\n                        else\n                        {\n                            item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);\n                            item2.DisplayIndex = displayIndex++;\n                        }\n                    }\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void StorageUI()\n    {\n        try\n        {\n            List<ColumnItem> lvColumnItem = new();\n            foreach (var item2 in lstConnections.Columns)\n            {\n                if (item2.Tag == null)\n                {\n                    continue;\n                }\n                lvColumnItem.Add(new()\n                {\n                    Name = (string)item2.Tag,\n                    Width = (int)(item2.IsVisible == true ? item2.ActualWidth : -1),\n                    Index = item2.DisplayIndex\n                });\n            }\n            _config.ClashUIItem.ConnectionsColumnItem = lvColumnItem;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    #endregion UI\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ClashProxiesView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.ClashProxiesView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:conv=\"using:v2rayN.Desktop.Converters\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:DataType=\"vms:ClashProxiesViewModel\"\n    mc:Ignorable=\"d\">\n    <UserControl.Resources>\n        <conv:DelayColorConverter x:Key=\"DelayColorConverter\" />\n    </UserControl.Resources>\n\n    <DockPanel Margin=\"2\">\n        <WrapPanel\n            Margin=\"{StaticResource Margin4}\"\n            VerticalAlignment=\"Center\"\n            DockPanel.Dock=\"Top\"\n            Orientation=\"Horizontal\">\n\n            <TextBlock\n                Margin=\"{StaticResource MarginLr8}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.menuRulemode}\" />\n            <ComboBox\n                x:Name=\"cmbRulemode\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\">\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.menuModeRule}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.menuModeGlobal}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.menuModeDirect}\" />\n            </ComboBox>\n\n            <TextBlock\n                Margin=\"{StaticResource MarginLr8}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbSorting}\" />\n            <ComboBox\n                x:Name=\"cmbSorting\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\">\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.TbSortingDelay}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.TbSortingName}\" />\n                <ComboBoxItem Content=\"{x:Static resx:ResUI.TbSortingDefault}\" />\n            </ComboBox>\n\n            <Button\n                x:Name=\"menuProxiesReload\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Classes=\"IconButton Success\"\n                ToolTip.Tip=\"{x:Static resx:ResUI.menuProxiesReload}\">\n                <Button.Content>\n                    <PathIcon Data=\"{StaticResource SemiIconRefresh}\" />\n                </Button.Content>\n            </Button>\n\n            <Button\n                x:Name=\"menuProxiesDelaytest\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Classes=\"IconButton Success\"\n                ToolTip.Tip=\"{x:Static resx:ResUI.menuProxiesDelaytest}\">\n                <Button.Content>\n                    <PathIcon Data=\"{StaticResource SemiIconBolt}\" />\n                </Button.Content>\n            </Button>\n\n            <TextBlock\n                Margin=\"{StaticResource MarginLr8}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbAutoRefresh}\" />\n            <ToggleSwitch\n                x:Name=\"togAutoRefresh\"\n                Margin=\"{StaticResource MarginLr8}\"\n                HorizontalAlignment=\"Left\" />\n        </WrapPanel>\n        <DockPanel>\n            <ListBox\n                x:Name=\"lstProxyGroups\"\n                DockPanel.Dock=\"Left\"\n                ItemsSource=\"{Binding ProxyGroups}\">\n                <ItemsControl.ItemsPanel>\n                    <ItemsPanelTemplate>\n                        <StackPanel Orientation=\"Vertical\" />\n                    </ItemsPanelTemplate>\n                </ItemsControl.ItemsPanel>\n                <ItemsControl.ItemTemplate>\n                    <DataTemplate>\n                        <Label\n                            Width=\"160\"\n                            Margin=\"-4,-6\"\n                            Padding=\"0\"\n                            Theme=\"{DynamicResource TagLabel}\">\n                            <Grid Margin=\"{StaticResource Margin4}\" RowDefinitions=\"1*,8,1*\">\n                                <DockPanel Grid.Row=\"0\">\n                                    <TextBlock DockPanel.Dock=\"Right\" Text=\"{Binding Type}\" />\n                                    <TextBlock Text=\"{Binding Name}\" />\n                                </DockPanel>\n                                <TextBlock Grid.Row=\"2\" Text=\"{Binding Now}\" />\n                            </Grid>\n                        </Label>\n                    </DataTemplate>\n                </ItemsControl.ItemTemplate>\n            </ListBox>\n\n            <ListBox x:Name=\"lstProxyDetails\" ItemsSource=\"{Binding ProxyDetails}\">\n                <ItemsControl.ContextMenu>\n                    <ContextMenu>\n                        <MenuItem x:Name=\"menuProxiesDelaytestPart\" Header=\"{x:Static resx:ResUI.menuProxiesDelaytestPart}\" />\n                        <MenuItem\n                            x:Name=\"menuProxiesSelectActivity\"\n                            Header=\"{x:Static resx:ResUI.menuProxiesSelectActivity}\"\n                            InputGesture=\"Enter\" />\n                    </ContextMenu>\n                </ItemsControl.ContextMenu>\n                <ItemsControl.ItemsPanel>\n                    <ItemsPanelTemplate>\n                        <WrapPanel Orientation=\"Horizontal\" />\n                    </ItemsPanelTemplate>\n                </ItemsControl.ItemsPanel>\n                <ItemsControl.ItemTemplate>\n                    <DataTemplate>\n                        <Label\n                            Width=\"160\"\n                            Margin=\"-10,-6\"\n                            Padding=\"0\"\n                            Theme=\"{DynamicResource TagLabel}\">\n                            <DockPanel>\n                                <Border\n                                    Width=\"5\"\n                                    Margin=\"0,1\"\n                                    Background=\"YellowGreen\"\n                                    CornerRadius=\"4\"\n                                    DockPanel.Dock=\"Left\"\n                                    IsVisible=\"{Binding IsActive}\" />\n                                <Grid Margin=\"{StaticResource Margin4}\" RowDefinitions=\"1*,8,1*\">\n                                    <TextBlock Grid.Row=\"0\" Text=\"{Binding Name}\" />\n                                    <DockPanel Grid.Row=\"2\">\n                                        <TextBlock\n                                            DockPanel.Dock=\"Right\"\n                                            Foreground=\"{Binding Path=Delay, Converter={StaticResource DelayColorConverter}}\"\n                                            Text=\"{Binding DelayName}\" />\n                                        <TextBlock Text=\"{Binding Type}\" />\n                                    </DockPanel>\n                                </Grid>\n                            </DockPanel>\n                        </Label>\n                    </DataTemplate>\n                </ItemsControl.ItemTemplate>\n            </ListBox>\n        </DockPanel>\n    </DockPanel>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ClashProxiesView.axaml.cs",
    "content": "namespace v2rayN.Desktop.Views;\n\npublic partial class ClashProxiesView : ReactiveUserControl<ClashProxiesViewModel>\n{\n    public ClashProxiesView()\n    {\n        InitializeComponent();\n        ViewModel = new ClashProxiesViewModel(UpdateViewHandler);\n        lstProxyDetails.DoubleTapped += LstProxyDetails_DoubleTapped;\n        KeyDown += ClashProxiesView_KeyDown;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ProxyGroups, v => v.lstProxyGroups.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedGroup, v => v.lstProxyGroups.SelectedItem).DisposeWith(disposables);\n\n            this.OneWayBind(ViewModel, vm => vm.ProxyDetails, v => v.lstProxyDetails.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedDetail, v => v.lstProxyDetails.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ProxiesReloadCmd, v => v.menuProxiesReload).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ProxiesDelayTestCmd, v => v.menuProxiesDelaytest).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ProxiesDelayTestPartCmd, v => v.menuProxiesDelaytestPart).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ProxiesSelectActivityCmd, v => v.menuProxiesSelectActivity).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.RuleModeSelected, v => v.cmbRulemode.SelectedIndex).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SortingSelected, v => v.cmbSorting.SelectedIndex).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        return await Task.FromResult(true);\n    }\n\n    private void ClashProxiesView_KeyDown(object? sender, KeyEventArgs e)\n    {\n        switch (e.Key)\n        {\n            case Key.F5:\n                ViewModel?.ProxiesReload();\n                break;\n\n            case Key.Enter:\n                ViewModel?.SetActiveProxy();\n                break;\n        }\n    }\n\n    private void LstProxyDetails_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)\n    {\n        ViewModel?.SetActiveProxy();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.DNSSettingWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuDNSSetting}\"\n    Width=\"900\"\n    Height=\"600\"\n    x:DataType=\"vms:DNSSettingViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n\n        <TabControl HorizontalContentAlignment=\"Stretch\">\n            <TabItem Header=\"{x:Static resx:ResUI.ThBasicDNSSettings}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid\n                        x:Name=\"gridBasicDNSSettings\"\n                        Margin=\"{StaticResource Margin8}\"\n                        ColumnDefinitions=\"Auto,Auto,*\"\n                        RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                        <TextBlock\n                            x:Name=\"txtBasicDNSSettingsInvalid\"\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbDomesticDNS}\" />\n                        <ComboBox\n                            x:Name=\"cmbDirectDNS\"\n                            Grid.Row=\"1\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbDomesticDNSTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteDNS}\" />\n                        <ComboBox\n                            x:Name=\"cmbRemoteDNS\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteDNSTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbBootstrapDNS}\" />\n                        <ComboBox\n                            x:Name=\"cmbBootstrapDNS\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbBootstrapDNSTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbDirectResolveStrategy}\" />\n                        <ComboBox\n                            x:Name=\"cmbDirectDNSStrategy\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            PlaceholderText=\"Default\" />\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbDirectResolveStrategyTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteResolveStrategy}\" />\n                        <ComboBox\n                            x:Name=\"cmbRemoteDNSStrategy\"\n                            Grid.Row=\"6\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            PlaceholderText=\"Default\" />\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbRemoteResolveStrategyTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"7\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbParallelQuery}\" />\n                        <ToggleSwitch\n                            x:Name=\"togParallelQuery\"\n                            Grid.Row=\"7\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\" />\n\n                        <TextBlock\n                            Grid.Row=\"8\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbServeStale}\" />\n                        <ToggleSwitch\n                            x:Name=\"togServeStale\"\n                            Grid.Row=\"8\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\" />\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.ThAdvancedDNSSettings}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid\n                        x:Name=\"gridAdvancedDNSSettings\"\n                        Margin=\"{StaticResource Margin8}\"\n                        ColumnDefinitions=\"Auto,Auto,*\"\n                        RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,*\">\n\n                        <TextBlock\n                            x:Name=\"txtAdvancedDNSSettingsInvalid\"\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbCustomDNSEnabledPageInvalid}\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsUseSystemHosts}\" />\n                        <ToggleSwitch\n                            x:Name=\"togUseSystemHosts\"\n                            Grid.Row=\"1\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbAddCommonDNSHosts}\" />\n                        <ToggleSwitch\n                            x:Name=\"togAddCommonHosts\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbFakeIP}\" />\n                        <ToggleSwitch\n                            x:Name=\"togFakeIP\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\" />\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbFakeIPTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbBlockSVCBHTTPSQueries}\" />\n                        <ToggleSwitch\n                            x:Name=\"togBlockBindingQuery\"\n                            Grid.Row=\"4\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            VerticalAlignment=\"Center\" />\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbBlockSVCBHTTPSQueriesTips}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbValidateDirectExpectedIPs}\" />\n                        <ComboBox\n                            x:Name=\"cmbDirectExpectedIPs\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbValidateDirectExpectedIPsDesc}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"0\"\n                            Grid.ColumnSpan=\"3\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbDNSHostsConfig}\" />\n\n                        <TextBox\n                            x:Name=\"txtHosts\"\n                            Grid.Row=\"7\"\n                            Grid.Column=\"0\"\n                            Grid.ColumnSpan=\"3\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Stretch\"\n                            BorderThickness=\"1\"\n                            Classes=\"TextArea\"\n                            TextWrapping=\"Wrap\"\n                            Watermark=\"{x:Static resx:ResUI.TbDNSHostsConfig}\" />\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbCustomDnsRay}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <Grid DockPanel.Dock=\"Top\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n\n                        <StackPanel Grid.Row=\"0\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbCustomDNSEnable}\" />\n                            <ToggleSwitch\n                                x:Name=\"togRayCustomDNSEnableCompatible\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsRemoteDNS}\" />\n\n                            <TextBlock Margin=\"{StaticResource Margin4}\" VerticalAlignment=\"Center\">\n                                <HyperlinkButton Classes=\"WithIcon\" Click=\"linkDnsObjectDoc_Click\">\n                                    <TextBlock Text=\"{x:Static resx:ResUI.TbDnsObjectDoc}\" />\n                                </HyperlinkButton>\n                            </TextBlock>\n                            <Button\n                                x:Name=\"btnImportDefConfig4V2rayCompatible\"\n                                Margin=\"{StaticResource Margin4}\"\n                                Content=\"{x:Static resx:ResUI.TbSettingDnsImportDefConfig}\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsUseSystemHosts}\" />\n                            <ToggleSwitch\n                                x:Name=\"togUseSystemHostsCompatible\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainStrategy4FreedomCompatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin4}\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainDNSAddress}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainDNSAddressCompatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin4}\"\n                                IsEditable=\"True\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <HeaderedContentControl\n                        Margin=\"{StaticResource Margin4}\"\n                        BorderBrush=\"Gray\"\n                        BorderThickness=\"1\"\n                        Header=\"HTTP/SOCKS\">\n                        <TextBox\n                            Name=\"txtnormalDNSCompatible\"\n                            VerticalAlignment=\"Stretch\"\n                            Classes=\"TextArea\"\n                            MinLines=\"10\"\n                            TextWrapping=\"Wrap\" />\n                    </HeaderedContentControl>\n                </DockPanel>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbCustomDnsSingbox}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <Grid DockPanel.Dock=\"Top\">\n                        <Grid.RowDefinitions>\n                            <RowDefinition Height=\"Auto\" />\n                            <RowDefinition Height=\"Auto\" />\n                        </Grid.RowDefinitions>\n\n                        <StackPanel Grid.Row=\"0\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbCustomDNSEnable}\" />\n                            <ToggleSwitch\n                                x:Name=\"togSBCustomDNSEnableCompatible\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Grid.Row=\"1\" Orientation=\"Horizontal\">\n                            <TextBlock Margin=\"{StaticResource Margin4}\" VerticalAlignment=\"Center\">\n                                <HyperlinkButton Classes=\"WithIcon\" Click=\"linkDnsSingboxObjectDoc_Click\">\n                                    <TextBlock Text=\"{x:Static resx:ResUI.TbDnsSingboxObjectDoc}\" />\n                                </HyperlinkButton>\n                            </TextBlock>\n                            <Button\n                                x:Name=\"btnImportDefConfig4SingboxCompatible\"\n                                Margin=\"{StaticResource Margin4}\"\n                                Content=\"{x:Static resx:ResUI.TbSettingDnsImportDefConfig}\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainStrategy4OutCompatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin4}\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsDomainDNSAddress}\" />\n                            <ComboBox\n                                x:Name=\"cmbdomainDNSAddress2Compatible\"\n                                Width=\"150\"\n                                Margin=\"{StaticResource Margin4}\"\n                                IsEditable=\"True\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <Grid Margin=\"{StaticResource Margin4}\" ColumnDefinitions=\"*,10,*\">\n\n                        <HeaderedContentControl\n                            Grid.Column=\"0\"\n                            BorderBrush=\"Gray\"\n                            BorderThickness=\"1\"\n                            Header=\"HTTP/SOCKS\">\n                            <TextBox\n                                Name=\"txtnormalDNS2Compatible\"\n                                VerticalAlignment=\"Stretch\"\n                                Classes=\"TextArea\"\n                                MinLines=\"10\"\n                                TextWrapping=\"Wrap\" />\n                        </HeaderedContentControl>\n\n                        <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n\n                        <HeaderedContentControl\n                            Grid.Column=\"2\"\n                            BorderBrush=\"Gray\"\n                            BorderThickness=\"1\"\n                            Header=\"{x:Static resx:ResUI.TbSettingsTunMode}\">\n                            <TextBox\n                                Name=\"txttunDNS2Compatible\"\n                                VerticalAlignment=\"Stretch\"\n                                Classes=\"TextArea\"\n                                MinLines=\"10\"\n                                TextWrapping=\"Wrap\" />\n                        </HeaderedContentControl>\n\n                    </Grid>\n                </DockPanel>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/DNSSettingWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class DNSSettingWindow : WindowBase<DNSSettingViewModel>\n{\n    private static Config _config;\n\n    public DNSSettingWindow()\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        ViewModel = new DNSSettingViewModel(UpdateViewHandler);\n\n        cmbDirectDNSStrategy.ItemsSource = Global.DomainStrategy;\n        cmbRemoteDNSStrategy.ItemsSource = Global.DomainStrategy;\n        cmbDirectDNS.ItemsSource = Global.DomainDirectDNSAddress;\n        cmbRemoteDNS.ItemsSource = Global.DomainRemoteDNSAddress;\n        cmbBootstrapDNS.ItemsSource = Global.DomainPureIPDNSAddress;\n        cmbDirectExpectedIPs.ItemsSource = Global.ExpectedIPs;\n\n        cmbdomainStrategy4FreedomCompatible.ItemsSource = Global.DomainStrategy;\n        cmbdomainStrategy4OutCompatible.ItemsSource = Global.DomainStrategies4Sbox;\n        cmbdomainDNSAddressCompatible.ItemsSource = Global.DomainPureIPDNSAddress;\n        cmbdomainDNSAddress2Compatible.ItemsSource = Global.DomainPureIPDNSAddress;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.UseSystemHosts, v => v.togUseSystemHosts.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AddCommonHosts, v => v.togAddCommonHosts.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FakeIP, v => v.togFakeIP.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.BlockBindingQuery, v => v.togBlockBindingQuery.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DirectDNS, v => v.cmbDirectDNS.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.RemoteDNS, v => v.cmbRemoteDNS.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.BootstrapDNS, v => v.cmbBootstrapDNS.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Strategy4Freedom, v => v.cmbDirectDNSStrategy.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Strategy4Proxy, v => v.cmbRemoteDNSStrategy.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Hosts, v => v.txtHosts.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DirectExpectedIPs, v => v.cmbDirectExpectedIPs.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ParallelQuery, v => v.togParallelQuery.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ServeStale, v => v.togServeStale.IsChecked).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.RayCustomDNSEnableCompatible, v => v.togRayCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SBCustomDNSEnableCompatible, v => v.togSBCustomDNSEnableCompatible.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.UseSystemHostsCompatible, v => v.togUseSystemHostsCompatible.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainStrategy4FreedomCompatible, v => v.cmbdomainStrategy4FreedomCompatible.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainDNSAddressCompatible, v => v.cmbdomainDNSAddressCompatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.NormalDNSCompatible, v => v.txtnormalDNSCompatible.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.DomainStrategy4Freedom2Compatible, v => v.cmbdomainStrategy4OutCompatible.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainDNSAddress2Compatible, v => v.cmbdomainDNSAddress2Compatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.NormalDNS2Compatible, v => v.txtnormalDNS2Compatible.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunDNS2Compatible, v => v.txttunDNS2Compatible.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ImportDefConfig4V2rayCompatibleCmd, v => v.btnImportDefConfig4V2rayCompatible).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportDefConfig4SingboxCompatibleCmd, v => v.btnImportDefConfig4SingboxCompatible).DisposeWith(disposables);\n\n            this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)\n                .Select(b => !b)\n                .BindTo(this.FindControl<TextBlock>(\"txtBasicDNSSettingsInvalid\"), t => t.IsVisible);\n            this.WhenAnyValue(x => x.ViewModel.IsSimpleDNSEnabled)\n                .Select(b => !b)\n                .BindTo(this.FindControl<TextBlock>(\"txtAdvancedDNSSettingsInvalid\"), t => t.IsVisible);\n            this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridBasicDNSSettings.IsEnabled).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.IsSimpleDNSEnabled, v => v.gridAdvancedDNSSettings.IsEnabled).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void linkDnsObjectDoc_Click(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://xtls.github.io/config/dns.html#dnsobject\");\n    }\n\n    private void linkDnsSingboxObjectDoc_Click(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://sing-box.sagernet.org/zh/configuration/dns/\");\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        btnCancel.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.FullConfigTemplateWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuFullConfigTemplate}\"\n    Width=\"900\"\n    Height=\"600\"\n    x:DataType=\"vms:FullConfigTemplateViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n\n        <TabControl HorizontalContentAlignment=\"Stretch\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.TbRayFullConfigTemplate}\">\n                <DockPanel Margin=\"{StaticResource Margin4}\">\n                    <Grid DockPanel.Dock=\"Top\" RowDefinitions=\"Auto,Auto,Auto\">\n\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbFullConfigTemplateDesc}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\">\n                            <HyperlinkButton Classes=\"WithIcon\" Click=\"linkFullConfigTemplateDoc_Click\">\n                                <TextBlock Text=\"{x:Static resx:ResUI.TbRayFullConfigTemplateDesc}\" />\n                            </HyperlinkButton>\n                        </TextBlock>\n\n                        <StackPanel Grid.Row=\"2\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbFullConfigTemplateEnable}\" />\n                            <ToggleSwitch\n                                x:Name=\"rayFullConfigTemplateEnable\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}\" />\n                            <ToggleSwitch\n                                x:Name=\"togAddProxyProtocolOutboundOnly4Ray\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSetUpstreamProxyDetour}\" />\n                            <TextBox\n                                x:Name=\"txtProxyDetour4Ray\"\n                                Width=\"200\"\n                                Margin=\"{StaticResource Margin4}\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <HeaderedContentControl\n                        Margin=\"{StaticResource Margin4}\"\n                        BorderBrush=\"Gray\"\n                        BorderThickness=\"1\"\n                        Header=\"xray config template json\">\n                        <TextBox\n                            x:Name=\"rayFullConfigTemplate\"\n                            VerticalAlignment=\"Stretch\"\n                            Classes=\"TextArea\"\n                            MinLines=\"10\"\n                            TextWrapping=\"Wrap\" />\n                    </HeaderedContentControl>\n                </DockPanel>\n            </TabItem>\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.TbSBFullConfigTemplate}\">\n                <DockPanel Margin=\"{StaticResource Margin4}\">\n                    <Grid DockPanel.Dock=\"Top\" RowDefinitions=\"Auto,Auto,Auto\">\n\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbFullConfigTemplateDesc}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\">\n                            <HyperlinkButton Classes=\"WithIcon\" Click=\"linkFullConfigTemplateDoc_Click\">\n                                <TextBlock Text=\"{x:Static resx:ResUI.TbSBFullConfigTemplateDesc}\" />\n                            </HyperlinkButton>\n                        </TextBlock>\n\n                        <StackPanel Grid.Row=\"2\" Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbFullConfigTemplateEnable}\" />\n                            <ToggleSwitch\n                                x:Name=\"sbFullConfigTemplateEnable\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n                    </Grid>\n\n                    <WrapPanel DockPanel.Dock=\"Bottom\" Orientation=\"Horizontal\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbAddProxyProtocolOutboundOnly}\" />\n                            <ToggleSwitch\n                                x:Name=\"togAddProxyProtocolOutboundOnly4Singbox\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSetUpstreamProxyDetour}\" />\n                            <TextBox\n                                x:Name=\"txtProxyDetour4Singbox\"\n                                Width=\"200\"\n                                Margin=\"{StaticResource Margin4}\" />\n                        </StackPanel>\n                    </WrapPanel>\n\n                    <Grid Margin=\"{StaticResource Margin4}\" ColumnDefinitions=\"*,10,*\">\n\n                        <HeaderedContentControl\n                            Grid.Column=\"0\"\n                            BorderBrush=\"Gray\"\n                            BorderThickness=\"1\"\n                            Header=\"sing-box config template json\">\n                            <TextBox\n                                x:Name=\"sbFullConfigTemplate\"\n                                VerticalAlignment=\"Stretch\"\n                                Classes=\"TextArea\"\n                                MinLines=\"10\"\n                                TextWrapping=\"Wrap\" />\n                        </HeaderedContentControl>\n\n                        <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n\n                        <HeaderedContentControl\n                            Grid.Column=\"2\"\n                            BorderBrush=\"Gray\"\n                            BorderThickness=\"1\"\n                            Header=\"sing-box tun config template json\">\n                            <TextBox\n                                x:Name=\"sbFullTunConfigTemplate\"\n                                VerticalAlignment=\"Stretch\"\n                                Classes=\"TextArea\"\n                                MinLines=\"10\"\n                                TextWrapping=\"Wrap\" />\n                        </HeaderedContentControl>\n                    </Grid>\n                </DockPanel>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/FullConfigTemplateWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class FullConfigTemplateWindow : WindowBase<FullConfigTemplateViewModel>\n{\n    private static Config _config;\n\n    public FullConfigTemplateWindow()\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        ViewModel = new FullConfigTemplateViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Ray, v => v.rayFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FullConfigTemplate4Ray, v => v.rayFullConfigTemplate.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AddProxyOnly4Ray, v => v.togAddProxyProtocolOutboundOnly4Ray.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ProxyDetour4Ray, v => v.txtProxyDetour4Ray.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableFullConfigTemplate4Singbox, v => v.sbFullConfigTemplateEnable.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FullConfigTemplate4Singbox, v => v.sbFullConfigTemplate.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.FullTunConfigTemplate4Singbox, v => v.sbFullTunConfigTemplate.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AddProxyOnly4Singbox, v => v.togAddProxyProtocolOutboundOnly4Singbox.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ProxyDetour4Singbox, v => v.txtProxyDetour4Singbox.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void linkFullConfigTemplateDoc_Click(object sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://github.com/2dust/v2rayN/wiki/Description-of-some-ui#%E5%AE%8C%E6%95%B4%E9%85%8D%E7%BD%AE%E6%A8%A1%E6%9D%BF%E8%AE%BE%E7%BD%AE\");\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        btnCancel.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/GlobalHotkeySettingWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.GlobalHotkeySettingWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuGlobalHotkeySetting}\"\n    Width=\"700\"\n    Height=\"500\"\n    x:DataType=\"vms:GlobalHotkeySettingViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnReset\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbReset}\" />\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n        <ScrollViewer HorizontalScrollBarVisibility=\"Auto\" VerticalScrollBarVisibility=\"Auto\">\n            <Grid RowDefinitions=\"Auto,Auto,Auto\">\n                <Grid\n                    x:Name=\"gridText\"\n                    Grid.Row=\"0\"\n                    ColumnDefinitions=\"Auto,400\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"0\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        Text=\"{x:Static resx:ResUI.TbGlobalHotkeySetting}\" />\n\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbDisplayGUI}\" />\n\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey0\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        IsReadOnly=\"True\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbClearSystemProxy}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey1\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        IsReadOnly=\"True\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSetSystemProxy}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey2\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        IsReadOnly=\"True\" />\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbNotChangeSystemProxy}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey3\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        IsReadOnly=\"True\" />\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSystemProxyPac}\" />\n                    <TextBox\n                        x:Name=\"txtGlobalHotkey4\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        IsReadOnly=\"True\" />\n                </Grid>\n\n                <TextBlock\n                    Grid.Row=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbGlobalHotkeySettingTip}\" />\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/GlobalHotkeySettingWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\nusing v2rayN.Desktop.Manager;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class GlobalHotkeySettingWindow : WindowBase<GlobalHotkeySettingViewModel>\n{\n    private readonly List<object> _textBoxKeyEventItem = new();\n\n    public GlobalHotkeySettingWindow()\n    {\n        InitializeComponent();\n\n        ViewModel = new GlobalHotkeySettingViewModel(UpdateViewHandler);\n\n        btnReset.Click += btnReset_Click;\n\n        HotkeyManager.Instance.IsPause = true;\n        Loaded += Window_Loaded;\n        Closing += (s, e) => HotkeyManager.Instance.IsPause = false;\n        btnCancel.Click += (s, e) => Close();\n\n        this.WhenActivated(disposables =>\n        {\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n\n        Init();\n        BindingData();\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Init()\n    {\n        _textBoxKeyEventItem.Add(txtGlobalHotkey0);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey1);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey2);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey3);\n        _textBoxKeyEventItem.Add(txtGlobalHotkey4);\n\n        for (var index = 0; index < _textBoxKeyEventItem.Count; index++)\n        {\n            var sender = _textBoxKeyEventItem[index];\n            if (sender is not TextBox txtBox)\n            {\n                continue;\n            }\n            txtBox.Tag = (EGlobalHotkey)index;\n            txtBox.KeyDown += TxtGlobalHotkey_PreviewKeyDown;\n        }\n    }\n\n    private void TxtGlobalHotkey_PreviewKeyDown(object? sender, KeyEventArgs e)\n    {\n        e.Handled = true;\n        if (sender is not TextBox txtBox)\n        {\n            return;\n        }\n\n        var item = ViewModel?.GetKeyEventItem((EGlobalHotkey)txtBox.Tag);\n        var modifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin };\n\n        item.KeyCode = (int)(e.Key == Key.System ? modifierKeys.Contains(Key.System) ? Key.None : Key.System : modifierKeys.Contains(e.Key) ? Key.None : e.Key);\n        item.Alt = (e.KeyModifiers & KeyModifiers.Alt) == KeyModifiers.Alt;\n        item.Control = (e.KeyModifiers & KeyModifiers.Control) == KeyModifiers.Control;\n        item.Shift = (e.KeyModifiers & KeyModifiers.Shift) == KeyModifiers.Shift;\n\n        txtBox.Text = KeyEventItemToString(item);\n    }\n\n    private void BindingData()\n    {\n        foreach (var sender in _textBoxKeyEventItem)\n        {\n            if (sender is not TextBox txtBox)\n            {\n                continue;\n            }\n\n            var item = ViewModel?.GetKeyEventItem((EGlobalHotkey)txtBox.Tag);\n            txtBox.Text = KeyEventItemToString(item);\n        }\n    }\n\n    private void btnReset_Click(object sender, RoutedEventArgs e)\n    {\n        ViewModel?.ResetKeyEventItem();\n        BindingData();\n    }\n\n    private string KeyEventItemToString(KeyEventItem? item)\n    {\n        if (item == null)\n        {\n            return string.Empty;\n        }\n        var res = new StringBuilder();\n\n        if (item.Control)\n        {\n            res.Append($\"{KeyModifiers.Control} +\");\n        }\n\n        if (item.Shift)\n        {\n            res.Append($\"{KeyModifiers.Shift} +\");\n        }\n\n        if (item.Alt)\n        {\n            res.Append($\"{KeyModifiers.Alt} +\");\n        }\n\n        if (item.KeyCode != null && (Key)item.KeyCode != Key.None)\n        {\n            res.Append($\"{(Key)item.KeyCode}\");\n        }\n\n        return res.ToString();\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        btnCancel.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/MainWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.MainWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:dialogHost=\"clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:view=\"using:v2rayN.Desktop.Views\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"v2rayN\"\n    Width=\"1200\"\n    Height=\"800\"\n    MinWidth=\"600\"\n    x:DataType=\"vms:MainWindowViewModel\"\n    Icon=\"/Assets/NotifyIcon1.ico\"\n    ShowInTaskbar=\"True\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <dialogHost:DialogHost\n        Background=\"Gray\"\n        CloseOnClickAway=\"True\"\n        DisableOpeningAnimation=\"True\">\n        <DockPanel>\n            <DockPanel Margin=\"{StaticResource Margin8}\" DockPanel.Dock=\"Top\">\n                <ContentControl x:Name=\"conTheme\" DockPanel.Dock=\"Right\" />\n                <Menu Margin=\"{StaticResource Margin4}\">\n                    <MenuItem Header=\"{x:Static resx:ResUI.menuServers}\">\n                        <MenuItem\n                            x:Name=\"menuAddServerViaClipboard\"\n                            Header=\"{x:Static resx:ResUI.menuAddServerViaClipboard}\"\n                            InputGesture=\"Ctrl+V\" />\n                        <MenuItem\n                            x:Name=\"menuAddServerViaScan\"\n                            Header=\"{x:Static resx:ResUI.menuAddServerViaScan}\"\n                            InputGesture=\"Ctrl+S\" />\n                        <MenuItem x:Name=\"menuAddServerViaImage\" Header=\"{x:Static resx:ResUI.menuAddServerViaImage}\" />\n                        <MenuItem x:Name=\"menuAddCustomServer\" Header=\"{x:Static resx:ResUI.menuAddCustomServer}\" />\n                        <MenuItem x:Name=\"menuAddPolicyGroupServer\" Header=\"{x:Static resx:ResUI.menuAddPolicyGroupServer}\" />\n                        <MenuItem x:Name=\"menuAddProxyChainServer\" Header=\"{x:Static resx:ResUI.menuAddProxyChainServer}\" />\n                        <Separator />\n                        <MenuItem x:Name=\"menuAddVmessServer\" Header=\"{x:Static resx:ResUI.menuAddVmessServer}\" />\n                        <MenuItem x:Name=\"menuAddVlessServer\" Header=\"{x:Static resx:ResUI.menuAddVlessServer}\" />\n                        <MenuItem x:Name=\"menuAddShadowsocksServer\" Header=\"{x:Static resx:ResUI.menuAddShadowsocksServer}\" />\n                        <MenuItem x:Name=\"menuAddTrojanServer\" Header=\"{x:Static resx:ResUI.menuAddTrojanServer}\" />\n                        <MenuItem x:Name=\"menuAddHysteria2Server\" Header=\"{x:Static resx:ResUI.menuAddHysteria2Server}\" />\n                        <MenuItem x:Name=\"menuAddWireguardServer\" Header=\"{x:Static resx:ResUI.menuAddWireguardServer}\" />\n                        <MenuItem x:Name=\"menuAddSocksServer\" Header=\"{x:Static resx:ResUI.menuAddSocksServer}\" />\n                        <MenuItem x:Name=\"menuAddHttpServer\" Header=\"{x:Static resx:ResUI.menuAddHttpServer}\" />\n                        <Separator />\n                        <MenuItem x:Name=\"menuAddTuicServer\" Header=\"{x:Static resx:ResUI.menuAddTuicServer}\" />\n                        <MenuItem x:Name=\"menuAddAnytlsServer\" Header=\"{x:Static resx:ResUI.menuAddAnytlsServer}\" />\n                    </MenuItem>\n\n                    <MenuItem Header=\"{x:Static resx:ResUI.menuSubscription}\">\n                        <MenuItem x:Name=\"menuSubSetting\" Header=\"{x:Static resx:ResUI.menuSubSetting}\" />\n                        <Separator />\n                        <MenuItem x:Name=\"menuSubUpdate\" Header=\"{x:Static resx:ResUI.menuSubUpdate}\" />\n                        <MenuItem x:Name=\"menuSubUpdateViaProxy\" Header=\"{x:Static resx:ResUI.menuSubUpdateViaProxy}\" />\n                        <MenuItem x:Name=\"menuSubGroupUpdate\" Header=\"{x:Static resx:ResUI.menuSubGroupUpdate}\" />\n                        <MenuItem x:Name=\"menuSubGroupUpdateViaProxy\" Header=\"{x:Static resx:ResUI.menuSubGroupUpdateViaProxy}\" />\n                    </MenuItem>\n\n                    <MenuItem Header=\"{x:Static resx:ResUI.menuSetting}\">\n                        <MenuItem x:Name=\"menuOptionSetting\" Header=\"{x:Static resx:ResUI.menuOptionSetting}\" />\n                        <MenuItem x:Name=\"menuRoutingSetting\" Header=\"{x:Static resx:ResUI.menuRoutingSetting}\" />\n                        <MenuItem x:Name=\"menuDNSSetting\" Header=\"{x:Static resx:ResUI.menuDNSSetting}\" />\n                        <MenuItem x:Name=\"menuFullConfigTemplate\" Header=\"{x:Static resx:ResUI.menuFullConfigTemplate}\" />\n                        <MenuItem\n                            x:Name=\"menuGlobalHotkeySetting\"\n                            Header=\"{x:Static resx:ResUI.menuGlobalHotkeySetting}\"\n                            IsVisible=\"{Binding BlIsWindows}\" />\n                        <Separator />\n                        <MenuItem\n                            x:Name=\"menuRebootAsAdmin\"\n                            Header=\"{x:Static resx:ResUI.menuRebootAsAdmin}\"\n                            IsVisible=\"{Binding BlIsWindows}\" />\n                        <MenuItem\n                            x:Name=\"menuSettingsSetUWP\"\n                            Header=\"{x:Static resx:ResUI.TbSettingsSetUWP}\"\n                            IsVisible=\"{Binding BlIsWindows}\" />\n                        <MenuItem x:Name=\"menuClearServerStatistics\" Header=\"{x:Static resx:ResUI.menuClearServerStatistics}\" />\n                        <Separator />\n                        <MenuItem Header=\"{x:Static resx:ResUI.menuRegionalPresets}\">\n                            <MenuItem x:Name=\"menuRegionalPresetsDefault\" Header=\"{x:Static resx:ResUI.menuRegionalPresetsDefault}\" />\n                            <MenuItem x:Name=\"menuRegionalPresetsRussia\" Header=\"{x:Static resx:ResUI.menuRegionalPresetsRussia}\" />\n                            <MenuItem x:Name=\"menuRegionalPresetsIran\" Header=\"{x:Static resx:ResUI.menuRegionalPresetsIran}\" />\n                        </MenuItem>\n                        <MenuItem x:Name=\"menuBackupAndRestore\" Header=\"{x:Static resx:ResUI.menuBackupAndRestore}\" />\n                        <MenuItem x:Name=\"menuOpenTheFileLocation\" Header=\"{x:Static resx:ResUI.menuOpenTheFileLocation}\" />\n                    </MenuItem>\n\n                    <MenuItem x:Name=\"menuHelp\" Header=\"{x:Static resx:ResUI.menuHelp}\">\n                        <MenuItem x:Name=\"menuCheckUpdate\" Header=\"{x:Static resx:ResUI.menuCheckUpdate}\" />\n                        <Separator />\n                    </MenuItem>\n\n                    <MenuItem x:Name=\"menuReload\" Header=\"{x:Static resx:ResUI.menuReload}\" />\n\n                    <MenuItem x:Name=\"menuPromotion\" Header=\"{x:Static resx:ResUI.menuPromotion}\" />\n\n                    <MenuItem x:Name=\"menuClose\" Header=\"{x:Static resx:ResUI.menuExit}\" />\n                </Menu>\n            </DockPanel>\n\n            <view:StatusBarView DockPanel.Dock=\"Bottom\" />\n\n            <Grid>\n                <Grid\n                    x:Name=\"gridMain\"\n                    ColumnDefinitions=\"1*,10,1*\"\n                    IsVisible=\"False\">\n                    <ContentControl x:Name=\"tabProfiles\" Grid.Column=\"0\" />\n                    <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n                    <TabControl\n                        x:Name=\"tabMain\"\n                        Grid.Column=\"2\"\n                        HorizontalContentAlignment=\"Left\">\n                        <TabItem x:Name=\"tabMsgView\" Header=\"{x:Static resx:ResUI.MsgInformationTitle}\" />\n                        <TabItem x:Name=\"tabClashProxies\" Header=\"{x:Static resx:ResUI.TbProxies}\" />\n                        <TabItem x:Name=\"tabClashConnections\" Header=\"{x:Static resx:ResUI.TbConnections}\" />\n                    </TabControl>\n                </Grid>\n                <Grid\n                    x:Name=\"gridMain1\"\n                    IsVisible=\"False\"\n                    RowDefinitions=\"1*,10,1*\">\n                    <ContentControl x:Name=\"tabProfiles1\" Grid.Row=\"0\" />\n                    <GridSplitter Grid.Row=\"1\" HorizontalAlignment=\"Stretch\" />\n                    <TabControl\n                        x:Name=\"tabMain1\"\n                        Grid.Row=\"2\"\n                        TabStripPlacement=\"Left\">\n                        <TabItem x:Name=\"tabMsgView1\" Header=\"{x:Static resx:ResUI.MsgInformationTitle}\" />\n                        <TabItem x:Name=\"tabClashProxies1\" Header=\"{x:Static resx:ResUI.TbProxies}\" />\n                        <TabItem x:Name=\"tabClashConnections1\" Header=\"{x:Static resx:ResUI.TbConnections}\" />\n                    </TabControl>\n                </Grid>\n                <Grid x:Name=\"gridMain2\" IsVisible=\"False\">\n                    <TabControl x:Name=\"tabMain2\" TabStripPlacement=\"Left\">\n                        <TabItem x:Name=\"tabProfiles2\" Header=\"{x:Static resx:ResUI.menuServers}\" />\n                        <TabItem x:Name=\"tabMsgView2\" Header=\"{x:Static resx:ResUI.MsgInformationTitle}\" />\n                        <TabItem x:Name=\"tabClashProxies2\" Header=\"{x:Static resx:ResUI.TbProxies}\" />\n                        <TabItem x:Name=\"tabClashConnections2\" Header=\"{x:Static resx:ResUI.TbConnections}\" />\n                    </TabControl>\n                </Grid>\n            </Grid>\n        </DockPanel>\n    </dialogHost:DialogHost>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs",
    "content": "using Avalonia.Controls.Notifications;\nusing DialogHostAvalonia;\nusing v2rayN.Desktop.Base;\nusing v2rayN.Desktop.Common;\nusing v2rayN.Desktop.Manager;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class MainWindow : WindowBase<MainWindowViewModel>\n{\n    private static Config _config;\n    private readonly WindowNotificationManager? _manager;\n    private CheckUpdateView? _checkUpdateView;\n    private BackupAndRestoreView? _backupAndRestoreView;\n    private bool _blCloseByUser = false;\n\n    public MainWindow()\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n        _manager = new WindowNotificationManager(TopLevel.GetTopLevel(this)) { MaxItems = 3, Position = NotificationPosition.TopRight };\n\n        KeyDown += MainWindow_KeyDown;\n        menuSettingsSetUWP.Click += MenuSettingsSetUWP_Click;\n        menuPromotion.Click += MenuPromotion_Click;\n        menuCheckUpdate.Click += MenuCheckUpdate_Click;\n        menuBackupAndRestore.Click += MenuBackupAndRestore_Click;\n        menuClose.Click += MenuClose_Click;\n\n        ViewModel = new MainWindowViewModel(UpdateViewHandler);\n\n        switch (_config.UiItem.MainGirdOrientation)\n        {\n            case EGirdOrientation.Horizontal:\n                tabProfiles.Content ??= new ProfilesView(this);\n                tabMsgView.Content ??= new MsgView();\n                tabClashProxies.Content ??= new ClashProxiesView();\n                tabClashConnections.Content ??= new ClashConnectionsView();\n                gridMain.IsVisible = true;\n                break;\n\n            case EGirdOrientation.Vertical:\n                tabProfiles1.Content ??= new ProfilesView(this);\n                tabMsgView1.Content ??= new MsgView();\n                tabClashProxies1.Content ??= new ClashProxiesView();\n                tabClashConnections1.Content ??= new ClashConnectionsView();\n                gridMain1.IsVisible = true;\n                break;\n\n            case EGirdOrientation.Tab:\n            default:\n                tabProfiles2.Content ??= new ProfilesView(this);\n                tabMsgView2.Content ??= new MsgView();\n                tabClashProxies2.Content ??= new ClashProxiesView();\n                tabClashConnections2.Content ??= new ClashConnectionsView();\n                gridMain2.IsVisible = true;\n                break;\n        }\n        conTheme.Content ??= new ThemeSettingView();\n\n        this.WhenActivated(disposables =>\n        {\n            //servers\n            this.BindCommand(ViewModel, vm => vm.AddVmessServerCmd, v => v.menuAddVmessServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddVlessServerCmd, v => v.menuAddVlessServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddShadowsocksServerCmd, v => v.menuAddShadowsocksServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddSocksServerCmd, v => v.menuAddSocksServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddHttpServerCmd, v => v.menuAddHttpServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddTrojanServerCmd, v => v.menuAddTrojanServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddHysteria2ServerCmd, v => v.menuAddHysteria2Server).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddTuicServerCmd, v => v.menuAddTuicServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddWireguardServerCmd, v => v.menuAddWireguardServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddAnytlsServerCmd, v => v.menuAddAnytlsServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddCustomServerCmd, v => v.menuAddCustomServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddPolicyGroupServerCmd, v => v.menuAddPolicyGroupServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddProxyChainServerCmd, v => v.menuAddProxyChainServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddServerViaClipboardCmd, v => v.menuAddServerViaClipboard).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddServerViaScanCmd, v => v.menuAddServerViaScan).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddServerViaImageCmd, v => v.menuAddServerViaImage).DisposeWith(disposables);\n\n            //sub\n            this.BindCommand(ViewModel, vm => vm.SubSettingCmd, v => v.menuSubSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubUpdateCmd, v => v.menuSubUpdate).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubUpdateViaProxyCmd, v => v.menuSubUpdateViaProxy).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubGroupUpdateCmd, v => v.menuSubGroupUpdate).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubGroupUpdateViaProxyCmd, v => v.menuSubGroupUpdateViaProxy).DisposeWith(disposables);\n\n            //setting\n            this.BindCommand(ViewModel, vm => vm.OptionSettingCmd, v => v.menuOptionSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingSettingCmd, v => v.menuRoutingSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.DNSSettingCmd, v => v.menuDNSSetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.FullConfigTemplateCmd, v => v.menuFullConfigTemplate).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.GlobalHotkeySettingCmd, v => v.menuGlobalHotkeySetting).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RebootAsAdminCmd, v => v.menuRebootAsAdmin).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ClearServerStatisticsCmd, v => v.menuClearServerStatistics).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.OpenTheFileLocationCmd, v => v.menuOpenTheFileLocation).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RegionalPresetDefaultCmd, v => v.menuRegionalPresetsDefault).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RegionalPresetRussiaCmd, v => v.menuRegionalPresetsRussia).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RegionalPresetIranCmd, v => v.menuRegionalPresetsIran).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);\n\n            switch (_config.UiItem.MainGirdOrientation)\n            {\n                case EGirdOrientation.Horizontal:\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView.IsVisible).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.IsVisible).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.IsVisible).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);\n                    break;\n\n                case EGirdOrientation.Vertical:\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView1.IsVisible).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies1.IsVisible).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections1.IsVisible).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain1.SelectedIndex).DisposeWith(disposables);\n                    break;\n\n                case EGirdOrientation.Tab:\n                default:\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies2.IsVisible).DisposeWith(disposables);\n                    this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections2.IsVisible).DisposeWith(disposables);\n                    this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain2.SelectedIndex).DisposeWith(disposables);\n                    break;\n            }\n\n            AppEvents.SendSnackMsgRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(async content => await DelegateSnackMsg(content))\n              .DisposeWith(disposables);\n\n            AppEvents.AppExitRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(_ => StorageUI())\n              .DisposeWith(disposables);\n\n            AppEvents.ShutdownRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(content => Shutdown(content))\n              .DisposeWith(disposables);\n\n            AppEvents.ShowHideWindowRequested\n             .AsObservable()\n             .ObserveOn(RxSchedulers.MainThreadScheduler)\n             .Subscribe(blShow => ShowHideWindow(blShow))\n             .DisposeWith(disposables);\n        });\n\n        if (Utils.IsWindows())\n        {\n            Title = $\"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}\";\n\n            ThreadPool.RegisterWaitForSingleObject(Program.ProgramStarted, OnProgramStarted, null, -1, false);\n            HotkeyManager.Instance.Init(_config, OnHotkeyHandler);\n        }\n        else\n        {\n            Title = $\"{Utils.GetVersion()}\";\n        }\n        menuAddServerViaScan.IsVisible = false;\n\n        if (_config.UiItem.AutoHideStartup && Utils.IsWindows())\n        {\n            WindowState = WindowState.Minimized;\n        }\n\n        AddHelpMenuItem();\n    }\n\n    #region Event\n\n    private void OnProgramStarted(object state, bool timeout)\n    {\n        Dispatcher.UIThread.Post(() =>\n                ShowHideWindow(true),\n            DispatcherPriority.Default);\n    }\n\n    private async Task DelegateSnackMsg(string content)\n    {\n        _manager?.Show(new Notification(null, content, NotificationType.Information));\n        await Task.CompletedTask;\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.AddServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new AddServerWindow((ProfileItem)obj).ShowDialog<bool>(this);\n\n            case EViewAction.AddServer2Window:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new AddServer2Window((ProfileItem)obj).ShowDialog<bool>(this);\n\n            case EViewAction.AddGroupServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new AddGroupServerWindow((ProfileItem)obj).ShowDialog<bool>(this);\n\n            case EViewAction.DNSSettingWindow:\n                return await new DNSSettingWindow().ShowDialog<bool>(this);\n\n            case EViewAction.FullConfigTemplateWindow:\n                return await new FullConfigTemplateWindow().ShowDialog<bool>(this);\n\n            case EViewAction.RoutingSettingWindow:\n                return await new RoutingSettingWindow().ShowDialog<bool>(this);\n\n            case EViewAction.OptionSettingWindow:\n                return await new OptionSettingWindow().ShowDialog<bool>(this);\n\n            case EViewAction.GlobalHotkeySettingWindow:\n                return await new GlobalHotkeySettingWindow().ShowDialog<bool>(this);\n\n            case EViewAction.SubSettingWindow:\n                return await new SubSettingWindow().ShowDialog<bool>(this);\n\n            case EViewAction.ScanScreenTask:\n                await ScanScreenTaskAsync();\n                break;\n\n            case EViewAction.ScanImageTask:\n                await ScanImageTaskAsync();\n                break;\n\n            case EViewAction.AddServerViaClipboard:\n                await AddServerViaClipboardAsync();\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    private void OnHotkeyHandler(EGlobalHotkey e)\n    {\n        switch (e)\n        {\n            case EGlobalHotkey.ShowForm:\n                ShowHideWindow(null);\n                break;\n\n            case EGlobalHotkey.SystemProxyClear:\n            case EGlobalHotkey.SystemProxySet:\n            case EGlobalHotkey.SystemProxyUnchanged:\n            case EGlobalHotkey.SystemProxyPac:\n                AppEvents.SysProxyChangeRequested.Publish((ESysProxyType)((int)e - 1));\n                break;\n        }\n    }\n\n    protected override async void OnClosing(WindowClosingEventArgs e)\n    {\n        if (_blCloseByUser)\n        {\n            return;\n        }\n\n        Logging.SaveLog(\"OnClosing -> \" + e.CloseReason.ToString());\n\n        switch (e.CloseReason)\n        {\n            case WindowCloseReason.OwnerWindowClosing or WindowCloseReason.WindowClosing:\n                e.Cancel = true;\n                ShowHideWindow(false);\n                break;\n\n            case WindowCloseReason.ApplicationShutdown or WindowCloseReason.OSShutdown:\n                await AppManager.Instance.AppExitAsync(false);\n                break;\n        }\n\n        base.OnClosing(e);\n    }\n\n    private async void MainWindow_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)\n        {\n            switch (e.Key)\n            {\n                case Key.V:\n                    await AddServerViaClipboardAsync();\n                    break;\n\n                case Key.S:\n                    await ScanScreenTaskAsync();\n                    break;\n            }\n        }\n        else\n        {\n            if (e.Key == Key.F5)\n            {\n                ViewModel?.Reload();\n            }\n        }\n    }\n\n    private void MenuPromotion_Click(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart($\"{Utils.Base64Decode(Global.PromotionUrl)}?t={DateTime.Now.Ticks}\");\n    }\n\n    private void MenuSettingsSetUWP_Click(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(Utils.GetBinPath(\"EnableLoopback.exe\"));\n    }\n\n    public async Task AddServerViaClipboardAsync()\n    {\n        var clipboardData = await AvaUtils.GetClipboardData(this);\n        if (clipboardData.IsNotEmpty() && ViewModel != null)\n        {\n            await ViewModel.AddServerViaClipboardAsync(clipboardData);\n        }\n    }\n\n    public async Task ScanScreenTaskAsync()\n    {\n        //ShowHideWindow(false);\n\n        NoticeManager.Instance.SendMessageAndEnqueue(\"Not yet implemented.(还未实现)\");\n        await Task.CompletedTask;\n        //if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)\n        //{\n        //    //var bytes = QRCodeHelper.CaptureScreen(desktop);\n        //    //await ViewModel?.ScanScreenResult(bytes);\n        //}\n\n        //ShowHideWindow(true);\n    }\n\n    private async Task ScanImageTaskAsync()\n    {\n        var fileName = await UI.OpenFileDialog(this, null);\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        if (ViewModel != null)\n        {\n            await ViewModel.ScanImageResult(fileName);\n        }\n    }\n\n    private void MenuCheckUpdate_Click(object? sender, RoutedEventArgs e)\n    {\n        _checkUpdateView ??= new CheckUpdateView();\n        DialogHost.Show(_checkUpdateView);\n    }\n\n    private void MenuBackupAndRestore_Click(object? sender, RoutedEventArgs e)\n    {\n        _backupAndRestoreView ??= new BackupAndRestoreView(this);\n        DialogHost.Show(_backupAndRestoreView);\n    }\n\n    private async void MenuClose_Click(object? sender, RoutedEventArgs e)\n    {\n        if (await UI.ShowYesNo(this, ResUI.menuExitTips) != ButtonResult.Yes)\n        {\n            return;\n        }\n\n        _blCloseByUser = true;\n        StorageUI();\n\n        await AppManager.Instance.AppExitAsync(true);\n    }\n\n    private void Shutdown(bool obj)\n    {\n        if (obj is bool b && _blCloseByUser == false)\n        {\n            _blCloseByUser = b;\n        }\n        StorageUI();\n        if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)\n        {\n            HotkeyManager.Instance.Dispose();\n            desktop.Shutdown();\n        }\n    }\n\n    #endregion Event\n\n    #region UI\n\n    public void ShowHideWindow(bool? blShow)\n    {\n        var bl = blShow ??\n                    (Utils.IsLinux()\n                    ? (!AppManager.Instance.ShowInTaskbar ^ (WindowState == WindowState.Minimized))\n                    : !AppManager.Instance.ShowInTaskbar);\n        if (bl)\n        {\n            Show();\n            if (WindowState == WindowState.Minimized)\n            {\n                WindowState = WindowState.Normal;\n            }\n            Activate();\n            Focus();\n        }\n        else\n        {\n            if (Utils.IsLinux() && _config.UiItem.Hide2TrayWhenClose == false)\n            {\n                WindowState = WindowState.Minimized;\n                return;\n            }\n\n            foreach (var ownedWindow in OwnedWindows)\n            {\n                ownedWindow.Close();\n            }\n            Hide();\n        }\n\n        AppManager.Instance.ShowInTaskbar = bl;\n    }\n\n    protected override void OnLoaded(object? sender, RoutedEventArgs e)\n    {\n        base.OnLoaded(sender, e);\n        if (_config.UiItem.AutoHideStartup)\n        {\n            ShowHideWindow(false);\n        }\n        RestoreUI();\n    }\n\n    private void RestoreUI()\n    {\n        if (_config.UiItem.MainGirdHeight1 > 0 && _config.UiItem.MainGirdHeight2 > 0)\n        {\n            if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)\n            {\n                gridMain.ColumnDefinitions[0].Width = new GridLength(_config.UiItem.MainGirdHeight1, GridUnitType.Star);\n                gridMain.ColumnDefinitions[2].Width = new GridLength(_config.UiItem.MainGirdHeight2, GridUnitType.Star);\n            }\n            else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)\n            {\n                gridMain1.RowDefinitions[0].Height = new GridLength(_config.UiItem.MainGirdHeight1, GridUnitType.Star);\n                gridMain1.RowDefinitions[2].Height = new GridLength(_config.UiItem.MainGirdHeight2, GridUnitType.Star);\n            }\n        }\n    }\n\n    private void StorageUI()\n    {\n        ConfigHandler.SaveWindowSizeItem(_config, GetType().Name, Width, Height);\n\n        if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Horizontal)\n        {\n            ConfigHandler.SaveMainGirdHeight(_config, gridMain.ColumnDefinitions[0].ActualWidth, gridMain.ColumnDefinitions[2].ActualWidth);\n        }\n        else if (_config.UiItem.MainGirdOrientation == EGirdOrientation.Vertical)\n        {\n            ConfigHandler.SaveMainGirdHeight(_config, gridMain1.RowDefinitions[0].ActualHeight, gridMain1.RowDefinitions[2].ActualHeight);\n        }\n    }\n\n    private void AddHelpMenuItem()\n    {\n        var coreInfo = CoreInfoManager.Instance.GetCoreInfo();\n        foreach (var it in coreInfo\n            .Where(t => t.CoreType is not ECoreType.v2fly\n                        and not ECoreType.hysteria))\n        {\n            var item = new MenuItem()\n            {\n                Tag = it.Url?.Replace(@\"/releases\", \"\"),\n                Header = string.Format(ResUI.menuWebsiteItem, it.CoreType.ToString().Replace(\"_\", \" \")).UpperFirstChar()\n            };\n            item.Click += MenuItem_Click;\n            menuHelp.Items.Add(item);\n        }\n    }\n\n    private void MenuItem_Click(object? sender, RoutedEventArgs e)\n    {\n        if (sender is MenuItem item)\n        {\n            ProcUtils.ProcessStart(item.Tag?.ToString());\n        }\n    }\n\n    #endregion UI\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/MsgView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.MsgView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:avaloniaEdit=\"clr-namespace:AvaloniaEdit;assembly=AvaloniaEdit\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"2\">\n        <WrapPanel\n            Margin=\"{StaticResource Margin4}\"\n            VerticalAlignment=\"Center\"\n            DockPanel.Dock=\"Top\"\n            Orientation=\"Horizontal\">\n\n            <TextBox\n                x:Name=\"cmbMsgFilter\"\n                Width=\"200\"\n                Margin=\"{StaticResource MarginLr8}\"\n                VerticalContentAlignment=\"Center\"\n                Watermark=\"{x:Static resx:ResUI.MsgFilterTitle}\" />\n\n            <Button\n                x:Name=\"btnCopy\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Classes=\"IconButton Success\"\n                Click=\"menuMsgViewCopyAll_Click\"\n                ToolTip.Tip=\"{x:Static resx:ResUI.menuMsgViewCopyAll}\">\n                <Button.Content>\n                    <PathIcon Data=\"{StaticResource SemiIconCopy}\" />\n                </Button.Content>\n            </Button>\n            <Button\n                x:Name=\"btnClear\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Classes=\"IconButton Success\"\n                Click=\"menuMsgViewClear_Click\"\n                ToolTip.Tip=\"{x:Static resx:ResUI.menuMsgViewClear}\">\n                <Button.Content>\n                    <PathIcon Data=\"{StaticResource SemiIconDelete}\" />\n                </Button.Content>\n            </Button>\n            <TextBlock\n                Margin=\"{StaticResource MarginLr8}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbAutoRefresh}\" />\n            <ToggleSwitch\n                x:Name=\"togAutoRefresh\"\n                Margin=\"{StaticResource MarginLr8}\"\n                HorizontalAlignment=\"Left\"\n                IsChecked=\"True\"\n                Theme=\"{DynamicResource SimpleToggleSwitch}\" />\n            <TextBlock\n                Margin=\"{StaticResource MarginLr8}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbAutoScrollToEnd}\" />\n            <ToggleSwitch\n                x:Name=\"togScrollToEnd\"\n                Margin=\"{StaticResource MarginLr8}\"\n                HorizontalAlignment=\"Left\"\n                IsChecked=\"True\"\n                Theme=\"{DynamicResource SimpleToggleSwitch}\" />\n        </WrapPanel>\n\n        <avaloniaEdit:TextEditor\n            Name=\"txtMsg\"\n            Margin=\"{StaticResource Margin8}\"\n            IsReadOnly=\"True\"\n            VerticalScrollBarVisibility=\"Auto\"\n            WordWrap=\"True\">\n            <avaloniaEdit:TextEditor.Options>\n                <avaloniaEdit:TextEditorOptions AllowScrollBelowDocument=\"False\" />\n            </avaloniaEdit:TextEditor.Options>\n            <avaloniaEdit:TextEditor.ContextFlyout>\n                <MenuFlyout>\n                    <MenuItem\n                        x:Name=\"menuMsgViewSelectAll\"\n                        Click=\"menuMsgViewSelectAll_Click\"\n                        InputGesture=\"Ctrl+A\" \n                        Header=\"{x:Static resx:ResUI.menuMsgViewSelectAll}\" />\n                    <MenuItem\n                        x:Name=\"menuMsgViewCopy\"\n                        Click=\"menuMsgViewCopy_Click\"\n                        Header=\"{x:Static resx:ResUI.menuMsgViewCopy}\"\n                        InputGesture=\"Ctrl+C\" />\n                    <MenuItem\n                        x:Name=\"menuMsgViewCopyAll\"\n                        Click=\"menuMsgViewCopyAll_Click\"\n                        Header=\"{x:Static resx:ResUI.menuMsgViewCopyAll}\" />\n                    <MenuItem\n                        x:Name=\"menuMsgViewClear\"\n                        Click=\"menuMsgViewClear_Click\"\n                        Header=\"{x:Static resx:ResUI.menuMsgViewClear}\" />\n                </MenuFlyout>\n            </avaloniaEdit:TextEditor.ContextFlyout>\n        </avaloniaEdit:TextEditor>\n\n    </DockPanel>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/MsgView.axaml.cs",
    "content": "using v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class MsgView : ReactiveUserControl<MsgViewModel>\n{\n    //private const int KeepLines = 30;\n\n    public MsgView()\n    {\n        InitializeComponent();\n        txtMsg.TextArea.TextView.Options.EnableHyperlinks = false;\n        ViewModel = new MsgViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.MsgFilter, v => v.cmbMsgFilter.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoRefresh, v => v.togAutoRefresh.IsChecked).DisposeWith(disposables);\n        });\n\n        TextEditorKeywordHighlighter.Attach(txtMsg, Global.LogLevelColors.ToDictionary(\n                kv => kv.Key,\n                kv => (IBrush)new SolidColorBrush(Color.Parse(kv.Value))\n            ));\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.DispatcherShowMsg:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                Dispatcher.UIThread.Post(() => ShowMsg(obj),\n                    DispatcherPriority.ApplicationIdle);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void ShowMsg(object msg)\n    {\n        //var lineCount = txtMsg.LineCount;\n        //if (lineCount > ViewModel?.NumMaxMsg)\n        //{\n        //    var cutLine = txtMsg.Document.GetLineByNumber(lineCount - KeepLines);\n        //    txtMsg.Document.Remove(0, cutLine.Offset);\n        //}\n        if (txtMsg.LineCount > ViewModel?.NumMaxMsg)\n        {\n            ClearMsg();\n        }\n\n        txtMsg.AppendText(msg.ToString());\n        if (togScrollToEnd.IsChecked ?? true)\n        {\n            txtMsg.ScrollToEnd();\n        }\n    }\n\n    public void ClearMsg()\n    {\n        txtMsg.Clear();\n        txtMsg.AppendText(\"----- Message cleared -----\\n\");\n    }\n\n    private void menuMsgViewSelectAll_Click(object? sender, RoutedEventArgs e)\n    {\n        Dispatcher.UIThread.Post(() =>\n        {\n            txtMsg.TextArea.Focus();\n            txtMsg.SelectAll();\n        }, DispatcherPriority.Render);\n    }\n\n    private async void menuMsgViewCopy_Click(object? sender, RoutedEventArgs e)\n    {\n        var data = txtMsg.SelectedText.TrimEx();\n        await AvaUtils.SetClipboardData(this, data);\n    }\n\n    private async void menuMsgViewCopyAll_Click(object? sender, RoutedEventArgs e)\n    {\n        var data = txtMsg.Text.TrimEx();\n        await AvaUtils.SetClipboardData(this, data);\n    }\n\n    private void menuMsgViewClear_Click(object? sender, RoutedEventArgs e)\n    {\n        ClearMsg();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.OptionSettingWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuSetting}\"\n    Width=\"1000\"\n    Height=\"600\"\n    x:DataType=\"vms:OptionSettingViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n\n        <TabControl HorizontalContentAlignment=\"Stretch\">\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsCore}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid\n                        Margin=\"{StaticResource Margin4}\"\n                        ColumnDefinitions=\"Auto,Auto,Auto\"\n                        RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSocksPort}\" />\n                        <TextBox\n                            x:Name=\"txtlocalPort\"\n                            Grid.Row=\"0\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n                        <TextBlock\n                            Grid.Row=\"0\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSocksPortTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSecondLocalPortEnabled}\" />\n                        <ToggleSwitch\n                            x:Name=\"togSecondLocalPortEnabled\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsUdpEnabled}\" />\n                        <ToggleSwitch\n                            x:Name=\"togudpEnabled\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSniffingEnabled}\" />\n                        <ToggleSwitch\n                            x:Name=\"togsniffingEnabled\"\n                            Grid.Row=\"4\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDestOverride}\" />\n                        <ListBox\n                            x:Name=\"clbdestOverride\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Grid.ColumnSpan=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            SelectionMode=\"Multiple,Toggle\"\n                            Theme=\"{DynamicResource CardCheckGroupListBox}\" />\n\n                        <TextBlock\n                            Grid.Row=\"6\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsRouteOnly}\" />\n                        <ToggleSwitch\n                            x:Name=\"togrouteOnly\"\n                            Grid.Row=\"6\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"7\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsAllowLAN}\" />\n                        <ToggleSwitch\n                            x:Name=\"togAllowLANConn\"\n                            Grid.Row=\"7\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"8\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsNewPort4LAN}\" />\n                        <ToggleSwitch\n                            x:Name=\"togNewPort4LAN\"\n                            Grid.Row=\"8\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"9\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsUser}\" />\n                        <TextBox\n                            x:Name=\"txtuser\"\n                            Grid.Row=\"9\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"10\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsPass}\" />\n                        <TextBox\n                            x:Name=\"txtpass\"\n                            Grid.Row=\"10\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"11\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMuxEnabled}\" />\n                        <ToggleSwitch\n                            x:Name=\"togmuxEnabled\"\n                            Grid.Row=\"11\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"12\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsLogEnabledToFile}\" />\n                        <ToggleSwitch\n                            x:Name=\"toglogEnabled\"\n                            Grid.Row=\"12\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"13\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsLogLevel}\" />\n                        <ComboBox\n                            x:Name=\"cmbloglevel\"\n                            Grid.Row=\"13\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"14\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefAllowInsecure}\" />\n                        <ToggleSwitch\n                            x:Name=\"togdefAllowInsecure\"\n                            Grid.Row=\"14\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"15\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefFingerprint}\" />\n                        <ComboBox\n                            x:Name=\"cmbdefFingerprint\"\n                            Grid.Row=\"15\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"16\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefUserAgent}\" />\n                        <ComboBox\n                            x:Name=\"cmbdefUserAgent\"\n                            Grid.Row=\"16\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n                        <TextBlock\n                            Grid.Row=\"16\"\n                            Grid.Column=\"3\"\n                            Margin=\"{StaticResource Margin4}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDefUserAgentTips}\" />\n\n                        <TextBlock\n                            Grid.Row=\"17\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMux4SboxProtocol}\" />\n                        <ComboBox\n                            x:Name=\"cmbmux4SboxProtocol\"\n                            Grid.Row=\"17\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"18\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableCacheFile4Sbox}\" />\n                        <ToggleSwitch\n                            x:Name=\"togenableCacheFile4Sbox\"\n                            Grid.Row=\"18\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"19\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsHysteriaBandwidth}\" />\n\n                        <StackPanel\n                            Grid.Row=\"19\"\n                            Grid.Column=\"1\"\n                            Orientation=\"Horizontal\">\n\n                            <TextBox\n                                x:Name=\"txtUpMbps\"\n                                Width=\"90\"\n                                Margin=\"{StaticResource Margin4}\"\n                                Watermark=\"Up\" />\n                            <TextBox\n                                x:Name=\"txtDownMbps\"\n                                Width=\"90\"\n                                Margin=\"{StaticResource Margin4}\"\n                                Watermark=\"Down\" />\n                        </StackPanel>\n\n                        <TextBlock\n                            Grid.Row=\"20\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableFragment}\" />\n                        <ToggleSwitch\n                            x:Name=\"togenableFragment\"\n                            Grid.Row=\"20\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsN}\">\n                <ScrollViewer VerticalScrollBarVisibility=\"Visible\">\n                    <Grid\n                        Margin=\"{StaticResource Margin4}\"\n                        ColumnDefinitions=\"Auto,Auto,*\"\n                        RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                        <TextBlock\n                            x:Name=\"tbAutoRun\"\n                            Grid.Row=\"1\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsStartBoot}\" />\n                        <ToggleSwitch\n                            x:Name=\"togAutoRun\"\n                            Grid.Row=\"1\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n                        <TextBlock\n                            Grid.Row=\"1\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsVisible=\"{Binding BlIsWindows}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsStartBootTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"2\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsStatistics}\" />\n                        <ToggleSwitch\n                            x:Name=\"togEnableStatistics\"\n                            Grid.Row=\"2\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"3\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDisplayRealTimeSpeed}\" />\n                        <ToggleSwitch\n                            x:Name=\"togDisplayRealTimeSpeed\"\n                            Grid.Row=\"3\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"4\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsKeepOlderDedupl}\" />\n                        <ToggleSwitch\n                            x:Name=\"togKeepOlderDedupl\"\n                            Grid.Row=\"4\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"5\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsEnableAutoAdjustMainLvColWidth}\" />\n                        <ToggleSwitch\n                            x:Name=\"togEnableAutoAdjustMainLvColWidth\"\n                            Grid.Row=\"5\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"8\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsAutoHideStartup}\" />\n                        <ToggleSwitch\n                            x:Name=\"togAutoHideStartup\"\n                            Grid.Row=\"8\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"9\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsVisible=\"{Binding BlIsLinux}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsHide2TrayWhenClose}\" />\n                        <ToggleSwitch\n                            x:Name=\"togHide2TrayWhenClose\"\n                            Grid.Row=\"9\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            IsVisible=\"{Binding BlIsLinux}\" />\n                        <TextBlock\n                            Grid.Row=\"9\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsVisible=\"{Binding BlIsLinux}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsHide2TrayWhenCloseTip}\" />\n\n                        <TextBlock\n                            Grid.Row=\"10\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            IsVisible=\"{Binding BlIsIsMacOS}\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMacOSShowInDock}\" />\n                        <ToggleSwitch\n                            x:Name=\"togMacOSShowInDock\"\n                            Grid.Row=\"10\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\"\n                            IsVisible=\"{Binding BlIsIsMacOS}\" />\n\n                        <TextBlock\n                            Grid.Row=\"11\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsDoubleClick2Activate}\" />\n                        <ToggleSwitch\n                            x:Name=\"togDoubleClick2Activate\"\n                            Grid.Row=\"11\"\n                            Grid.Column=\"1\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"14\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsAutoUpdateInterval}\" />\n                        <TextBox\n                            x:Name=\"txtautoUpdateInterval\"\n                            Grid.Row=\"14\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Left\" />\n\n                        <TextBlock\n                            Grid.Row=\"15\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsCurrentFontFamily}\" />\n                        <ComboBox\n                            x:Name=\"cmbcurrentFontFamily\"\n                            Grid.Row=\"15\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"15\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsCurrentFontFamilyLinuxTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"16\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMixedConcurrencyCount}\" />\n                        <ComboBox\n                            x:Name=\"cmbMixedConcurrencyCount\"\n                            Grid.Row=\"16\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"17\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSpeedTestTimeout}\" />\n                        <ComboBox\n                            x:Name=\"cmbSpeedTestTimeout\"\n                            Grid.Row=\"17\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"18\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSpeedTestUrl}\" />\n                        <ComboBox\n                            Name=\"cmbSpeedTestUrl\"\n                            Grid.Row=\"18\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n\n                        <TextBlock\n                            Grid.Row=\"19\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSpeedPingTestUrl}\" />\n                        <ComboBox\n                            x:Name=\"cmbSpeedPingTestUrl\"\n                            Grid.Row=\"19\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n\n                        <TextBlock\n                            Grid.Row=\"20\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsIPAPIUrl}\" />\n                        <ComboBox\n                            x:Name=\"cmbIPAPIUrl\"\n                            Grid.Row=\"20\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n\n                        <TextBlock\n                            Grid.Row=\"21\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSubConvert}\" />\n                        <ComboBox\n                            x:Name=\"cmbSubConvertUrl\"\n                            Grid.Row=\"21\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n\n                        <TextBlock\n                            Grid.Row=\"22\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsMainGirdOrientation}\" />\n                        <ComboBox\n                            x:Name=\"cmbMainGirdOrientation\"\n                            Grid.Row=\"22\"\n                            Grid.Column=\"1\"\n                            Width=\"200\"\n                            Margin=\"{StaticResource Margin4}\" />\n\n                        <TextBlock\n                            Grid.Row=\"23\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsGeoFilesSource}\" />\n                        <ComboBox\n                            x:Name=\"cmbGetFilesSourceUrl\"\n                            Grid.Row=\"23\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"23\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsChinaUserTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"24\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsSrsFilesSource}\" />\n                        <ComboBox\n                            x:Name=\"cmbSrsFilesSourceUrl\"\n                            Grid.Row=\"24\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"24\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsChinaUserTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                        <TextBlock\n                            Grid.Row=\"25\"\n                            Grid.Column=\"0\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsRoutingRulesSource}\" />\n                        <ComboBox\n                            x:Name=\"cmbRoutingRulesSourceUrl\"\n                            Grid.Row=\"25\"\n                            Grid.Column=\"1\"\n                            Width=\"300\"\n                            Margin=\"{StaticResource Margin4}\"\n                            IsEditable=\"True\" />\n                        <TextBlock\n                            Grid.Row=\"25\"\n                            Grid.Column=\"2\"\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsChinaUserTip}\"\n                            TextWrapping=\"Wrap\" />\n\n                    </Grid>\n                </ScrollViewer>\n            </TabItem>\n\n            <TabItem Name=\"tabSystemproxy\" Header=\"{x:Static resx:ResUI.TbSettingsSystemproxy}\">\n                <DockPanel Margin=\"{StaticResource Margin8}\">\n                    <StackPanel\n                        DockPanel.Dock=\"Bottom\"\n                        IsVisible=\"{Binding BlIsNonWindows}\"\n                        Orientation=\"Vertical\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsCustomSystemProxyScriptPath}\" />\n                            <TextBox\n                                x:Name=\"txtCustomSystemProxyScriptPath\"\n                                Width=\"600\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\"\n                                VerticalAlignment=\"Center\"\n                                TextWrapping=\"Wrap\"\n                                Watermark=\"proxy_set.sh\" />\n                            <Button\n                                x:Name=\"btnBrowseCustomSystemProxyScriptPath\"\n                                Margin=\"{StaticResource Margin4}\"\n                                Content=\"{x:Static resx:ResUI.TbBrowse}\" />\n                        </StackPanel>\n                    </StackPanel>\n                    <StackPanel\n                        DockPanel.Dock=\"Bottom\"\n                        IsVisible=\"{Binding BlIsWindows}\"\n                        Orientation=\"Vertical\">\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsNotProxyLocalAddress}\" />\n                            <ToggleSwitch\n                                x:Name=\"tognotProxyLocalAddress\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsAdvancedProtocol}\" />\n                            <ComboBox\n                                x:Name=\"cmbsystemProxyAdvancedProtocol\"\n                                MinWidth=\"400\"\n                                Margin=\"{StaticResource Margin4}\" />\n                        </StackPanel>\n\n                        <StackPanel Orientation=\"Horizontal\">\n                            <TextBlock\n                                Margin=\"{StaticResource Margin4}\"\n                                VerticalAlignment=\"Center\"\n                                Text=\"{x:Static resx:ResUI.TbSettingsCustomSystemProxyPacPath}\" />\n                            <TextBox\n                                x:Name=\"txtCustomSystemProxyPacPath\"\n                                Width=\"600\"\n                                Margin=\"{StaticResource Margin4}\"\n                                HorizontalAlignment=\"Left\"\n                                VerticalAlignment=\"Center\"\n                                TextWrapping=\"Wrap\"\n                                Watermark=\"pac.txt\" />\n                            <Button\n                                x:Name=\"btnBrowseCustomSystemProxyPacPath\"\n                                Margin=\"{StaticResource Margin4}\"\n                                Content=\"{x:Static resx:ResUI.TbBrowse}\" />\n                        </StackPanel>\n                    </StackPanel>\n\n                    <TextBlock\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        DockPanel.Dock=\"Top\"\n                        IsVisible=\"{Binding BlIsWindows}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsExceptionTip}\" />\n                    <TextBlock\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        DockPanel.Dock=\"Top\"\n                        IsVisible=\"{Binding BlIsNonWindows}\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsExceptionTip2}\" />\n                    <TextBox\n                        x:Name=\"txtsystemProxyExceptions\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Stretch\"\n                        BorderThickness=\"1\"\n                        Classes=\"TextArea\"\n                        TextWrapping=\"Wrap\" />\n                </DockPanel>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsTunMode}\">\n                <Grid\n                    Margin=\"{StaticResource Margin4}\"\n                    ColumnDefinitions=\"Auto,Auto,Auto\"\n                    DockPanel.Dock=\"Top\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunAutoRoute}\" />\n                    <ToggleSwitch\n                        x:Name=\"togAutoRoute\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunStrictRoute}\" />\n                    <ToggleSwitch\n                        x:Name=\"togStrictRoute\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunStack}\" />\n                    <ComboBox\n                        x:Name=\"cmbStack\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsTunMtu}\" />\n                    <ComboBox\n                        x:Name=\"cmbMtu\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                    <TextBlock\n                        Grid.Row=\"7\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.TbSettingsEnableIPv6Address}\" />\n                    <ToggleSwitch\n                        x:Name=\"togEnableIPv6Address\"\n                        Grid.Row=\"7\"\n                        Grid.Column=\"1\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Left\" />\n\n                </Grid>\n            </TabItem>\n\n            <TabItem Header=\"{x:Static resx:ResUI.TbSettingsCoreType}\">\n                <Grid\n                    Margin=\"{StaticResource Margin4}\"\n                    ColumnDefinitions=\"Auto,Auto\"\n                    RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n                    <TextBlock\n                        Grid.Row=\"1\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"VMess\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType1\"\n                        Grid.Row=\"1\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"2\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"Custom\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType2\"\n                        Grid.Row=\"2\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"3\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"Shadowsocks\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType3\"\n                        Grid.Row=\"3\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"4\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"Socks\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType4\"\n                        Grid.Row=\"4\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"5\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"VLESS\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType5\"\n                        Grid.Row=\"5\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"6\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"Trojan\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType6\"\n                        Grid.Row=\"6\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"7\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"Hysteria2\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType7\"\n                        Grid.Row=\"7\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n\n                    <TextBlock\n                        Grid.Row=\"8\"\n                        Grid.Column=\"0\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"Wireguard\" />\n                    <ComboBox\n                        x:Name=\"cmbCoreType9\"\n                        Grid.Row=\"8\"\n                        Grid.Column=\"1\"\n                        Width=\"200\"\n                        Margin=\"{StaticResource Margin4}\" />\n                </Grid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/OptionSettingWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\nusing v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class OptionSettingWindow : WindowBase<OptionSettingViewModel>\n{\n    private static Config _config;\n\n    public OptionSettingWindow()\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        _config = AppManager.Instance.Config;\n\n        ViewModel = new OptionSettingViewModel(UpdateViewHandler);\n\n        clbdestOverride.SelectionChanged += ClbdestOverride_SelectionChanged;\n        btnBrowseCustomSystemProxyPacPath.Click += BtnBrowseCustomSystemProxyPacPath_Click;\n        btnBrowseCustomSystemProxyScriptPath.Click += BtnBrowseCustomSystemProxyScriptPath_Click;\n\n        clbdestOverride.ItemsSource = Global.destOverrideProtocols;\n        _config.Inbound.First().DestOverride?.ForEach(it =>\n        {\n            clbdestOverride.SelectedItems.Add(it);\n        });\n\n        cmbsystemProxyAdvancedProtocol.ItemsSource = Global.IEProxyProtocols;\n        cmbloglevel.ItemsSource = Global.LogLevels;\n        cmbdefFingerprint.ItemsSource = Global.Fingerprints;\n        cmbdefUserAgent.ItemsSource = Global.UserAgent;\n        cmbmux4SboxProtocol.ItemsSource = Global.SingboxMuxs;\n        cmbMtu.ItemsSource = Global.TunMtus;\n        cmbStack.ItemsSource = Global.TunStacks;\n\n        cmbCoreType1.ItemsSource = Global.CoreTypes;\n        cmbCoreType2.ItemsSource = Global.CoreTypes;\n        cmbCoreType3.ItemsSource = Global.CoreTypes;\n        cmbCoreType4.ItemsSource = Global.CoreTypes;\n        cmbCoreType5.ItemsSource = Global.CoreTypes;\n        cmbCoreType6.ItemsSource = Global.CoreTypes;\n        cmbCoreType7.ItemsSource = Global.CoreTypes;\n        cmbCoreType9.ItemsSource = Global.CoreTypes;\n\n        cmbMixedConcurrencyCount.ItemsSource = Enumerable.Range(2, 7).ToList();\n        cmbSpeedTestTimeout.ItemsSource = Enumerable.Range(2, 5).Select(i => i * 5).ToList();\n        cmbSpeedTestUrl.ItemsSource = Global.SpeedTestUrls;\n        cmbSpeedPingTestUrl.ItemsSource = Global.SpeedPingTestUrls;\n        cmbSubConvertUrl.ItemsSource = Global.SubConvertUrls;\n        cmbGetFilesSourceUrl.ItemsSource = Global.GeoFilesSources;\n        cmbSrsFilesSourceUrl.ItemsSource = Global.SingboxRulesetSources;\n        cmbRoutingRulesSourceUrl.ItemsSource = Global.RoutingRulesSources;\n        cmbIPAPIUrl.ItemsSource = Global.IPAPIUrls;\n\n        cmbMainGirdOrientation.ItemsSource = Utils.GetEnumNames<EGirdOrientation>();\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.localPort, v => v.txtlocalPort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SecondLocalPortEnabled, v => v.togSecondLocalPortEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.udpEnabled, v => v.togudpEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.sniffingEnabled, v => v.togsniffingEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.routeOnly, v => v.togrouteOnly.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.allowLANConn, v => v.togAllowLANConn.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.togNewPort4LAN.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtuser.IsEnabled).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.newPort4LAN, v => v.txtpass.IsEnabled).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.user, v => v.txtuser.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.pass, v => v.txtpass.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.muxEnabled, v => v.togmuxEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.logEnabled, v => v.toglogEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.loglevel, v => v.cmbloglevel.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.defAllowInsecure, v => v.togdefAllowInsecure.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.defFingerprint, v => v.cmbdefFingerprint.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.defUserAgent, v => v.cmbdefUserAgent.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.mux4SboxProtocol, v => v.cmbmux4SboxProtocol.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.enableCacheFile4Sbox, v => v.togenableCacheFile4Sbox.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.hyUpMbps, v => v.txtUpMbps.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.hyDownMbps, v => v.txtDownMbps.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.enableFragment, v => v.togenableFragment.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.AutoRun, v => v.togAutoRun.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableStatistics, v => v.togEnableStatistics.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DisplayRealTimeSpeed, v => v.togDisplayRealTimeSpeed.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.KeepOlderDedupl, v => v.togKeepOlderDedupl.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableAutoAdjustMainLvColWidth, v => v.togEnableAutoAdjustMainLvColWidth.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoHideStartup, v => v.togAutoHideStartup.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Hide2TrayWhenClose, v => v.togHide2TrayWhenClose.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.MacOSShowInDock, v => v.togMacOSShowInDock.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DoubleClick2Activate, v => v.togDoubleClick2Activate.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoUpdateInterval, v => v.txtautoUpdateInterval.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CurrentFontFamily, v => v.cmbcurrentFontFamily.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SpeedTestTimeout, v => v.cmbSpeedTestTimeout.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SpeedTestUrl, v => v.cmbSpeedTestUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.MixedConcurrencyCount, v => v.cmbMixedConcurrencyCount.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SrsFileSourceUrl, v => v.cmbSrsFilesSourceUrl.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.RoutingRulesSourceUrl, v => v.cmbRoutingRulesSourceUrl.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.IPAPIUrl, v => v.cmbIPAPIUrl.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.systemProxyExceptions, v => v.txtsystemProxyExceptions.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CustomSystemProxyPacPath, v => v.txtCustomSystemProxyPacPath.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CustomSystemProxyScriptPath, v => v.txtCustomSystemProxyScriptPath.Text).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.TunAutoRoute, v => v.togAutoRoute.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunStrictRoute, v => v.togStrictRoute.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunStack, v => v.cmbStack.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunMtu, v => v.cmbMtu.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.TunEnableIPv6Address, v => v.togEnableIPv6Address.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.CoreType1, v => v.cmbCoreType1.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType2, v => v.cmbCoreType2.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType3, v => v.cmbCoreType3.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType4, v => v.cmbCoreType4.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType5, v => v.cmbCoreType5.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType6, v => v.cmbCoreType6.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType7, v => v.cmbCoreType7.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CoreType9, v => v.cmbCoreType9.SelectedValue).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n\n            case EViewAction.InitSettingFont:\n                await InitSettingFont();\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private async Task InitSettingFont()\n    {\n        var lstFonts = await GetFonts();\n\n        lstFonts.Add(string.Empty);\n        cmbcurrentFontFamily.ItemsSource = lstFonts;\n    }\n\n    private async Task<List<string>> GetFonts()\n    {\n        var lstFonts = new List<string>();\n        try\n        {\n            if (Utils.IsWindows())\n            {\n                return lstFonts;\n            }\n            else if (Utils.IsNonWindows())\n            {\n                var result = await Utils.GetLinuxFontFamily(\"zh\");\n                if (result.IsNullOrEmpty())\n                {\n                    return lstFonts;\n                }\n\n                var lst = result.Split(Environment.NewLine)\n                    .Where(t => t.IsNotEmpty())\n                    .ToList()\n                    .Select(t => t.Split(\",\").FirstOrDefault() ?? \"\")\n                    .OrderBy(t => t)\n                    .ToList();\n                return lst;\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"GetFonts\", ex);\n        }\n        return lstFonts;\n    }\n\n    private void ClbdestOverride_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.destOverride = clbdestOverride.SelectedItems.Cast<string>().ToList();\n        }\n    }\n\n    private async void BtnBrowseCustomSystemProxyPacPath_Click(object? sender, RoutedEventArgs e)\n    {\n        var fileName = await UI.OpenFileDialog(this, null);\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        txtCustomSystemProxyPacPath.Text = fileName;\n    }\n\n    private async void BtnBrowseCustomSystemProxyScriptPath_Click(object? sender, RoutedEventArgs e)\n    {\n        var fileName = await UI.OpenFileDialog(this, null);\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        txtCustomSystemProxyScriptPath.Text = fileName;\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        btnCancel.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ProfilesSelectWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.ProfilesSelectWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.TbSelectProfile}\"\n    Width=\"800\"\n    Height=\"450\"\n    x:DataType=\"vms:ProfilesSelectViewModel\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel Margin=\"8\">\n        <!--  Bottom buttons  -->\n        <StackPanel\n            Margin=\"4\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Click=\"BtnSave_Click\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"8,0\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\" />\n        </StackPanel>\n\n        <Grid>\n            <DockPanel>\n                <!--  Top tools  -->\n                <WrapPanel Margin=\"4\" DockPanel.Dock=\"Top\">\n                    <ListBox\n                        x:Name=\"lstGroup\"\n                        Margin=\"{StaticResource MarginLr4}\"\n                        DisplayMemberBinding=\"{Binding Remarks}\"\n                        ItemsSource=\"{Binding SubItems}\"\n                        Theme=\"{DynamicResource ButtonRadioGroupListBox}\">\n                        <ListBox.ItemsPanel>\n                            <ItemsPanelTemplate>\n                                <WrapPanel />\n                            </ItemsPanelTemplate>\n                        </ListBox.ItemsPanel>\n                    </ListBox>\n\n                    <Button\n                        x:Name=\"btnAutofitColumnWidth\"\n                        Margin=\"{StaticResource MarginLr4}\"\n                        Classes=\"IconButton Success\"\n                        ToolTip.Tip=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\">\n                        <Button.Content>\n                            <PathIcon Data=\"{StaticResource SemiIconExpand}\" />\n                        </Button.Content>\n                    </Button>\n\n                    <TextBox\n                        x:Name=\"txtServerFilter\"\n                        Width=\"200\"\n                        Margin=\"8,0\"\n                        VerticalContentAlignment=\"Center\"\n                        Text=\"{Binding ServerFilter, Mode=TwoWay}\"\n                        Watermark=\"{x:Static resx:ResUI.MsgServerTitle}\" />\n                </WrapPanel>\n\n                <!--  Profiles grid  -->\n                <DataGrid\n                    x:Name=\"lstProfiles\"\n                    AutoGenerateColumns=\"False\"\n                    BorderThickness=\"1\"\n                    CanUserReorderColumns=\"True\"\n                    CanUserResizeColumns=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"All\"\n                    IsReadOnly=\"True\"\n                    ItemsSource=\"{Binding ProfileItems}\"\n                    SelectionMode=\"Single\">\n                    <DataGrid.KeyBindings>\n                        <KeyBinding Command=\"{Binding SelectFinish}\" Gesture=\"Enter\" />\n                    </DataGrid.KeyBindings>\n                    <DataGrid.Columns>\n                        <DataGridTextColumn\n                            Width=\"80\"\n                            Binding=\"{Binding ConfigType}\"\n                            Header=\"{x:Static resx:ResUI.LvServiceType}\"\n                            Tag=\"ConfigType\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\"\n                            Tag=\"Remarks\" />\n                        <DataGridTextColumn\n                            Width=\"200\"\n                            Binding=\"{Binding Address}\"\n                            Header=\"{x:Static resx:ResUI.LvAddress}\"\n                            Tag=\"Address\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            Header=\"{x:Static resx:ResUI.LvPort}\"\n                            Tag=\"Port\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            Header=\"{x:Static resx:ResUI.LvTransportProtocol}\"\n                            Tag=\"Network\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding StreamSecurity}\"\n                            Header=\"{x:Static resx:ResUI.LvTLS}\"\n                            Tag=\"StreamSecurity\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding SubRemarks}\"\n                            Header=\"{x:Static resx:ResUI.LvSubscription}\"\n                            Tag=\"SubRemarks\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </DockPanel>\n        </Grid>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ProfilesSelectWindow.axaml.cs",
    "content": "using Avalonia.VisualTree;\nusing v2rayN.Desktop.Base;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class ProfilesSelectWindow : WindowBase<ProfilesSelectViewModel>\n{\n    private static Config _config;\n\n    public Task<ProfileItem?> ProfileItem => GetProfileItem();\n    public Task<List<ProfileItem>?> ProfileItems => GetProfileItems();\n    private bool _allowMultiSelect = false;\n\n    public ProfilesSelectWindow()\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n\n        btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;\n        txtServerFilter.KeyDown += TxtServerFilter_KeyDown;\n        lstProfiles.KeyDown += LstProfiles_KeyDown;\n        lstProfiles.SelectionChanged += LstProfiles_SelectionChanged;\n        lstProfiles.LoadingRow += LstProfiles_LoadingRow;\n        lstProfiles.Sorting += LstProfiles_Sorting;\n        lstProfiles.DoubleTapped += LstProfiles_DoubleTapped;\n\n        ViewModel = new ProfilesSelectViewModel(UpdateViewHandler);\n        DataContext = ViewModel;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ProfileItems, v => v.lstProfiles.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedProfile, v => v.lstProfiles.SelectedItem).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedSub, v => v.lstGroup.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ServerFilter, v => v.txtServerFilter.Text).DisposeWith(disposables);\n        });\n\n        btnCancel.Click += (s, e) => Close(false);\n    }\n\n    public void AllowMultiSelect(bool allow)\n    {\n        _allowMultiSelect = allow;\n        if (allow)\n        {\n            lstProfiles.SelectionMode = DataGridSelectionMode.Extended;\n            lstProfiles.SelectedItems.Clear();\n        }\n        else\n        {\n            lstProfiles.SelectionMode = DataGridSelectionMode.Single;\n            if (lstProfiles.SelectedItems.Count > 0)\n            {\n                var first = lstProfiles.SelectedItems[0];\n                lstProfiles.SelectedItems.Clear();\n                lstProfiles.SelectedItem = first;\n            }\n        }\n    }\n\n    // Expose ConfigType filter controls to callers\n    public void SetConfigTypeFilter(IEnumerable<EConfigType> types, bool exclude = false)\n        => ViewModel?.SetConfigTypeFilter(types, exclude);\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void LstProfiles_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast<ProfileItemModel>().ToList();\n        }\n    }\n\n    private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e)\n    {\n        e.Row.Header = $\" {e.Row.Index + 1}\";\n    }\n\n    private void LstProfiles_DoubleTapped(object? sender, TappedEventArgs e)\n    {\n        // Ignore double-taps on the column header area\n        if (e.Source is Control src)\n        {\n            if (src.FindAncestorOfType<DataGridColumnHeader>() != null)\n            {\n                e.Handled = true;\n                return;\n            }\n\n            // Only trigger selection when double-tapped on a data row or its child element\n            if (src.FindAncestorOfType<DataGridRow>() != null)\n            {\n                ViewModel?.SelectFinish();\n                e.Handled = true;\n            }\n        }\n    }\n\n    private void LstProfiles_Sorting(object? sender, DataGridColumnEventArgs e)\n    {\n        // Custom sort to prevent unintended default behavior\n        e.Handled = true;\n        if (ViewModel != null && e.Column?.Tag?.ToString() != null)\n        {\n            ViewModel.SortServer(e.Column.Tag.ToString());\n        }\n    }\n\n    private void LstProfiles_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)\n        {\n            if (e.Key == Key.A)\n            {\n                if (_allowMultiSelect)\n                {\n                    lstProfiles.SelectAll();\n                }\n                e.Handled = true;\n            }\n        }\n        else\n        {\n            if (e.Key is Key.Enter or Key.Return)\n            {\n                ViewModel?.SelectFinish();\n                e.Handled = true;\n            }\n        }\n    }\n\n    private void BtnAutofitColumnWidth_Click(object? sender, RoutedEventArgs e)\n    {\n        AutofitColumnWidth();\n    }\n\n    private void AutofitColumnWidth()\n    {\n        try\n        {\n            foreach (var col in lstProfiles.Columns)\n            {\n                col.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);\n            }\n        }\n        catch\n        {\n        }\n    }\n\n    private void TxtServerFilter_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.Key is Key.Enter or Key.Return)\n        {\n            ViewModel?.RefreshServers();\n        }\n    }\n\n    public async Task<ProfileItem?> GetProfileItem()\n    {\n        var item = await ViewModel?.GetProfileItem();\n        return item;\n    }\n\n    public async Task<List<ProfileItem>?> GetProfileItems()\n    {\n        var item = await ViewModel?.GetProfileItems();\n        return item;\n    }\n\n    private void BtnSave_Click(object sender, RoutedEventArgs e)\n    {\n        // Trigger selection finalize when Confirm is clicked\n        ViewModel?.SelectFinish();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.ProfilesView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:conv=\"using:v2rayN.Desktop.Converters\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    x:Name=\"Root\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:DataType=\"vms:ProfilesViewModel\"\n    mc:Ignorable=\"d\">\n    <UserControl.Resources>\n        <conv:DelayColorConverter x:Key=\"DelayColorConverter\" />\n    </UserControl.Resources>\n    <Grid>\n        <DockPanel>\n            <WrapPanel Margin=\"2\" DockPanel.Dock=\"Top\">\n                <ListBox\n                    x:Name=\"lstGroup\"\n                    Margin=\"{StaticResource MarginLr4}\"\n                    DisplayMemberBinding=\"{Binding Remarks}\"\n                    ItemsSource=\"{Binding SubItems}\"\n                    Theme=\"{DynamicResource PureCardRadioGroupListBox}\">\n                    <ListBox.ItemsPanel>\n                        <ItemsPanelTemplate>\n                            <WrapPanel />\n                        </ItemsPanelTemplate>\n                    </ListBox.ItemsPanel>\n\n                    <ListBox.ContextMenu>\n                        <ContextMenu>\n                            <MenuItem x:Name=\"menuSubEdit\" Header=\"{x:Static resx:ResUI.menuSubEdit}\" />\n                            <MenuItem x:Name=\"menuSubAdd\" Header=\"{x:Static resx:ResUI.menuSubAdd}\" />\n                            <MenuItem x:Name=\"menuSubDelete\" Header=\"{x:Static resx:ResUI.menuSubDelete}\" />\n                        </ContextMenu>\n                    </ListBox.ContextMenu>\n                </ListBox>\n\n                <Button\n                    x:Name=\"btnEditSub\"\n                    Margin=\"{StaticResource MarginLr4}\"\n                    Classes=\"IconButton Success\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.menuSubEdit}\">\n                    <Button.Content>\n                        <PathIcon Data=\"{StaticResource SemiIconEdit}\" />\n                    </Button.Content>\n                </Button>\n                <Button\n                    x:Name=\"btnAddSub\"\n                    Margin=\"{StaticResource MarginLr4}\"\n                    Classes=\"IconButton Success\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.menuSubAdd}\">\n                    <Button.Content>\n                        <PathIcon Data=\"{StaticResource SemiIconPlus}\" />\n                    </Button.Content>\n                </Button>\n\n                <TextBox\n                    x:Name=\"txtServerFilter\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource MarginLr4}\"\n                    VerticalContentAlignment=\"Center\"\n                    Watermark=\"{x:Static resx:ResUI.MsgServerTitle}\" />\n\n                <Button\n                    x:Name=\"btnAutofitColumnWidth\"\n                    Margin=\"{StaticResource MarginLr4}\"\n                    Classes=\"IconButton Success\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.menuProfileAutofitColumnWidth}\">\n                    <Button.Content>\n                        <PathIcon Data=\"{StaticResource SemiIconExpand}\" />\n                    </Button.Content>\n                </Button>\n\n                <Button\n                    x:Name=\"btnFastRealPing\"\n                    Margin=\"{StaticResource MarginLr4}\"\n                    Classes=\"IconButton Success\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.menuFastRealPing}\">\n                    <Button.Content>\n                        <PathIcon Data=\"{StaticResource SemiIconBolt}\" />\n                    </Button.Content>\n                </Button>\n                <Button\n                    x:Name=\"menuMixedTestServer\"\n                    Margin=\"{StaticResource MarginLr4}\"\n                    Classes=\"IconButton Success\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.menuMixedTestServer}\">\n                    <Button.Content>\n                        <PathIcon Data=\"{StaticResource building_ping}\" />\n                    </Button.Content>\n                </Button>\n\n            </WrapPanel>\n            <DataGrid\n                x:Name=\"lstProfiles\"\n                AutoGenerateColumns=\"False\"\n                BorderThickness=\"1\"\n                CanUserReorderColumns=\"True\"\n                CanUserResizeColumns=\"True\"\n                Classes.InsetContent=\"True\"\n                GridLinesVisibility=\"All\"\n                HeadersVisibility=\"All\"\n                IsReadOnly=\"True\"\n                ItemsSource=\"{Binding ProfileItems}\">\n                <DataGrid.KeyBindings>\n                    <KeyBinding Command=\"{Binding Export2ShareUrlCmd}\" Gesture=\"Ctrl+C\" />\n                    <KeyBinding Command=\"{Binding SetDefaultServerCmd}\" Gesture=\"Enter\" />\n                </DataGrid.KeyBindings>\n                <DataGrid.ContextMenu>\n                    <ContextMenu>\n                        <MenuItem\n                            x:Name=\"menuSetDefaultServer\"\n                            Header=\"{x:Static resx:ResUI.menuSetDefaultServer}\"\n                            InputGesture=\"Enter\" />\n                        <MenuItem\n                            x:Name=\"menuEditServer\"\n                            Header=\"{x:Static resx:ResUI.menuEditServer}\"\n                            InputGesture=\"Ctrl+D\" />\n                        <MenuItem x:Name=\"menuCopyServer\" Header=\"{x:Static resx:ResUI.menuCopyServer}\" />\n                        <MenuItem\n                            x:Name=\"menuRemoveServer\"\n                            Header=\"{x:Static resx:ResUI.menuRemoveServer}\"\n                            InputGesture=\"Back\" />\n                        <MenuItem x:Name=\"menuRemoveDuplicateServer\" Header=\"{x:Static resx:ResUI.menuRemoveDuplicateServer}\" />\n                        <MenuItem x:Name=\"menuRemoveInvalidServerResult\" Header=\"{x:Static resx:ResUI.menuRemoveInvalidServerResult}\" />\n                        <Separator />\n                        <MenuItem\n                            x:Name=\"menuTcpingServer\"\n                            Header=\"{x:Static resx:ResUI.menuTcpingServer}\"\n                            InputGesture=\"Ctrl+O\" />\n                        <MenuItem\n                            x:Name=\"menuRealPingServer\"\n                            Header=\"{x:Static resx:ResUI.menuRealPingServer}\"\n                            InputGesture=\"Ctrl+R\" />\n                        <MenuItem\n                            x:Name=\"menuSpeedServer\"\n                            Header=\"{x:Static resx:ResUI.menuSpeedServer}\"\n                            InputGesture=\"Ctrl+T\" />\n                        <MenuItem x:Name=\"menuSortServerResult\" Header=\"{x:Static resx:ResUI.menuSortServerResult}\" />\n                        <Separator />\n                        <MenuItem\n                            x:Name=\"menuMoveToGroup\"\n                            Header=\"{x:Static resx:ResUI.menuMoveToGroup}\"\n                            ItemsSource=\"{Binding DataContext.SubItems, ElementName=Root}\">\n                            <MenuItem.ItemTemplate>\n                                <DataTemplate>\n                                    <MenuItem\n                                        Command=\"{Binding DataContext.MoveToGroupCmd, ElementName=Root}\"\n                                        CommandParameter=\"{Binding}\"\n                                        Header=\"{Binding Remarks}\" />\n                                </DataTemplate>\n                            </MenuItem.ItemTemplate>\n                        </MenuItem>\n                        <MenuItem Header=\"{x:Static resx:ResUI.menuMoveTo}\">\n                            <MenuItem\n                                x:Name=\"menuMoveTop\"\n                                Header=\"{x:Static resx:ResUI.menuMoveTop}\"\n                                InputGesture=\"T\" />\n                            <MenuItem\n                                x:Name=\"menuMoveUp\"\n                                Header=\"{x:Static resx:ResUI.menuMoveUp}\"\n                                InputGesture=\"U\" />\n                            <MenuItem\n                                x:Name=\"menuMoveDown\"\n                                Header=\"{x:Static resx:ResUI.menuMoveDown}\"\n                                InputGesture=\"D\" />\n                            <MenuItem\n                                x:Name=\"menuMoveBottom\"\n                                Header=\"{x:Static resx:ResUI.menuMoveBottom}\"\n                                InputGesture=\"B\" />\n                        </MenuItem>\n                        <MenuItem\n                            x:Name=\"menuSelectAll\"\n                            Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                            InputGesture=\"Ctrl+A\" />\n                        <Separator />\n                        <MenuItem\n                            x:Name=\"menuShareServer\"\n                            Header=\"{x:Static resx:ResUI.menuShareServer}\"\n                            InputGesture=\"Ctrl+F\" />\n                        <MenuItem Header=\"{x:Static resx:ResUI.menuExportConfig}\">\n                            <MenuItem x:Name=\"menuExport2ClientConfig\" Header=\"{x:Static resx:ResUI.menuExport2ClientConfig}\" />\n                            <MenuItem x:Name=\"menuExport2ClientConfigClipboard\" Header=\"{x:Static resx:ResUI.menuExport2ClientConfigClipboard}\" />\n                            <Separator />\n                            <MenuItem\n                                x:Name=\"menuExport2ShareUrl\"\n                                Header=\"{x:Static resx:ResUI.menuExport2ShareUrl}\"\n                                InputGesture=\"Ctrl+C\" />\n                            <MenuItem x:Name=\"menuExport2ShareUrlBase64\" Header=\"{x:Static resx:ResUI.menuExport2ShareUrlBase64}\" />\n                        </MenuItem>\n                        <Separator />\n                        <MenuItem Header=\"{x:Static resx:ResUI.menuGenGroupServer}\">\n                            <MenuItem x:Name=\"menuGenGroupAllServer\" Header=\"{x:Static resx:ResUI.menuAllServers}\" />\n                            <MenuItem x:Name=\"menuGenGroupRegionServer\" Header=\"{x:Static resx:ResUI.menuGenRegionGroup}\" />\n                        </MenuItem>\n                    </ContextMenu>\n                </DataGrid.ContextMenu>\n\n                <DataGrid.Columns>\n                    <DataGridTextColumn\n                        Width=\"80\"\n                        Binding=\"{Binding ConfigType}\"\n                        Header=\"{x:Static resx:ResUI.LvServiceType}\"\n                        Tag=\"ConfigType\" />\n\n                    <DataGridTemplateColumn SortMemberPath=\"Remarks\" Tag=\"Remarks\">\n                        <DataGridTemplateColumn.Header>\n                            <TextBlock Text=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        </DataGridTemplateColumn.Header>\n                        <DataGridTemplateColumn.CellTemplate>\n                            <DataTemplate>\n                                <StackPanel Margin=\"{StaticResource MarginLr8}\" Orientation=\"Horizontal\">\n                                    <Label\n                                        Margin=\"{StaticResource MarginLr4}\"\n                                        Classes=\"Solid Red\"\n                                        Content=\"{x:Static resx:ResUI.TipActiveServer}\"\n                                        IsVisible=\"{Binding IsActive}\"\n                                        Theme=\"{DynamicResource TagLabel}\" />\n                                    <TextBlock\n                                        HorizontalAlignment=\"Center\"\n                                        VerticalAlignment=\"Center\"\n                                        Text=\"{Binding Remarks}\" />\n                                </StackPanel>\n                            </DataTemplate>\n                        </DataGridTemplateColumn.CellTemplate>\n                    </DataGridTemplateColumn>\n\n                    <DataGridTextColumn\n                        Width=\"120\"\n                        Binding=\"{Binding Address}\"\n                        Header=\"{x:Static resx:ResUI.LvAddress}\"\n                        Tag=\"Address\" />\n                    <DataGridTextColumn\n                        Width=\"60\"\n                        Binding=\"{Binding Port}\"\n                        Header=\"{x:Static resx:ResUI.LvPort}\"\n                        Tag=\"Port\" />\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding Network}\"\n                        Header=\"{x:Static resx:ResUI.LvTransportProtocol}\"\n                        Tag=\"Network\" />\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding StreamSecurity}\"\n                        Header=\"{x:Static resx:ResUI.LvTLS}\"\n                        Tag=\"StreamSecurity\" />\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding SubRemarks}\"\n                        Header=\"{x:Static resx:ResUI.LvSubscription}\"\n                        Tag=\"SubRemarks\" />\n                    <DataGridTemplateColumn SortMemberPath=\"Delay\" Tag=\"DelayVal\">\n                        <DataGridTemplateColumn.Header>\n                            <TextBlock Text=\"{x:Static resx:ResUI.LvTestDelay}\" />\n                        </DataGridTemplateColumn.Header>\n                        <DataGridTemplateColumn.CellTemplate>\n                            <DataTemplate>\n                                <TextBlock\n                                    Margin=\"{StaticResource MarginLr8}\"\n                                    HorizontalAlignment=\"Right\"\n                                    VerticalAlignment=\"Center\"\n                                    Foreground=\"{Binding Delay, Converter={StaticResource DelayColorConverter}}\"\n                                    Text=\"{Binding Path=DelayVal, Mode=OneWay}\" />\n                            </DataTemplate>\n                        </DataGridTemplateColumn.CellTemplate>\n                    </DataGridTemplateColumn>\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding SpeedVal}\"\n                        Header=\"{x:Static resx:ResUI.LvTestSpeed}\"\n                        Tag=\"SpeedVal\" />\n\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding TodayUp}\"\n                        Header=\"{x:Static resx:ResUI.LvTodayUploadDataAmount}\"\n                        Tag=\"TodayUp\" />\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding TodayDown}\"\n                        Header=\"{x:Static resx:ResUI.LvTodayDownloadDataAmount}\"\n                        Tag=\"TodayDown\" />\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding TotalUp}\"\n                        Header=\"{x:Static resx:ResUI.LvTotalUploadDataAmount}\"\n                        Tag=\"TotalUp\" />\n                    <DataGridTextColumn\n                        Width=\"100\"\n                        Binding=\"{Binding TotalDown}\"\n                        Header=\"{x:Static resx:ResUI.LvTotalDownloadDataAmount}\"\n                        Tag=\"TotalDown\" />\n                </DataGrid.Columns>\n            </DataGrid>\n        </DockPanel>\n    </Grid>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs",
    "content": "using DialogHostAvalonia;\nusing v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class ProfilesView : ReactiveUserControl<ProfilesViewModel>\n{\n    private static Config _config;\n    private Window? _window;\n    private static readonly string _tag = \"ProfilesView\";\n\n    public ProfilesView()\n    {\n        InitializeComponent();\n    }\n\n    public ProfilesView(Window window)\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n        _window = window;\n\n        menuSelectAll.Click += menuSelectAll_Click;\n        btnAutofitColumnWidth.Click += BtnAutofitColumnWidth_Click;\n        txtServerFilter.KeyDown += TxtServerFilter_KeyDown;\n        lstProfiles.KeyDown += LstProfiles_KeyDown;\n        lstProfiles.SelectionChanged += lstProfiles_SelectionChanged;\n        lstProfiles.DoubleTapped += LstProfiles_DoubleTapped;\n        lstProfiles.LoadingRow += LstProfiles_LoadingRow;\n        lstProfiles.Sorting += LstProfiles_Sorting;\n        //if (_config.uiItem.enableDragDropSort)\n        //{\n        //    lstProfiles.AllowDrop = true;\n        //    lstProfiles.PreviewMouseLeftButtonDown += LstProfiles_PreviewMouseLeftButtonDown;\n        //    lstProfiles.MouseMove += LstProfiles_MouseMove;\n        //    lstProfiles.DragEnter += LstProfiles_DragEnter;\n        //    lstProfiles.Drop += LstProfiles_Drop;\n        //}\n\n        ViewModel = new ProfilesViewModel(UpdateViewHandler);\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.ProfileItems, v => v.lstProfiles.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedProfile, v => v.lstProfiles.SelectedItem).DisposeWith(disposables);\n\n            // this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.lstGroup.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSub, v => v.lstGroup.SelectedItem).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.ServerFilter, v => v.txtServerFilter.Text).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddSubCmd, v => v.btnAddSub).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.EditSubCmd, v => v.btnEditSub).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.EditSubCmd, v => v.menuSubEdit).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.AddSubCmd, v => v.menuSubAdd).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.DeleteSubCmd, v => v.menuSubDelete).DisposeWith(disposables);\n\n            //servers delete\n            this.BindCommand(ViewModel, vm => vm.EditServerCmd, v => v.menuEditServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoveServerCmd, v => v.menuRemoveServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoveDuplicateServerCmd, v => v.menuRemoveDuplicateServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.CopyServerCmd, v => v.menuCopyServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SetDefaultServerCmd, v => v.menuSetDefaultServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ShareServerCmd, v => v.menuShareServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.GenGroupAllServerCmd, v => v.menuGenGroupAllServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.GenGroupRegionServerCmd, v => v.menuGenGroupRegionServer).DisposeWith(disposables);\n\n            //servers move\n            //this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.cmbMoveToGroup.ItemsSource).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.SelectedMoveToGroup, v => v.cmbMoveToGroup.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);\n\n            //servers ping\n            this.BindCommand(ViewModel, vm => vm.MixedTestServerCmd, v => v.menuMixedTestServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.TcpingServerCmd, v => v.menuTcpingServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RealPingServerCmd, v => v.menuRealPingServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SpeedServerCmd, v => v.menuSpeedServer).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SortServerResultCmd, v => v.menuSortServerResult).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RemoveInvalidServerResultCmd, v => v.menuRemoveInvalidServerResult).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.FastRealPingCmd, v => v.btnFastRealPing).DisposeWith(disposables);\n\n            //servers export\n            this.BindCommand(ViewModel, vm => vm.Export2ClientConfigCmd, v => v.menuExport2ClientConfig).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.Export2ClientConfigClipboardCmd, v => v.menuExport2ClientConfigClipboard).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.Export2ShareUrlCmd, v => v.menuExport2ShareUrl).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.Export2ShareUrlBase64Cmd, v => v.menuExport2ShareUrlBase64).DisposeWith(disposables);\n\n            AppEvents.AppExitRequested\n              .AsObservable()\n              .ObserveOn(RxSchedulers.MainThreadScheduler)\n              .Subscribe(_ => StorageUI())\n              .DisposeWith(disposables);\n\n            AppEvents.AdjustMainLvColWidthRequested\n                .AsObservable()\n                .ObserveOn(RxSchedulers.MainThreadScheduler)\n                .Subscribe(_ => AutofitColumnWidth())\n                .DisposeWith(disposables);\n        });\n\n        RestoreUI();\n    }\n\n    private async void LstProfiles_Sorting(object? sender, DataGridColumnEventArgs e)\n    {\n        e.Handled = true;\n\n        if (ViewModel != null && e.Column?.Tag?.ToString() != null)\n        {\n            await ViewModel.SortServer(e.Column.Tag.ToString());\n        }\n\n        e.Handled = false;\n    }\n\n    #region Event\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.SetClipboardData:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                await AvaUtils.SetClipboardData(this, (string)obj);\n                break;\n\n            case EViewAction.ProfilesFocus:\n                lstProfiles.Focus();\n                break;\n\n            case EViewAction.ShowYesNo:\n                if (await UI.ShowYesNo(_window, ResUI.RemoveServer) != ButtonResult.Yes)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.SaveFileDialog:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                var fileName = await UI.SaveFileDialog(_window, \"\");\n                if (fileName.IsNullOrEmpty())\n                {\n                    return false;\n                }\n                ViewModel?.Export2ClientConfigResult(fileName, (ProfileItem)obj);\n                break;\n\n            case EViewAction.AddServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new AddServerWindow((ProfileItem)obj).ShowDialog<bool>(_window);\n\n            case EViewAction.AddServer2Window:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new AddServer2Window((ProfileItem)obj).ShowDialog<bool>(_window);\n\n            case EViewAction.AddGroupServerWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new AddGroupServerWindow((ProfileItem)obj).ShowDialog<bool>(_window);\n\n            case EViewAction.ShareServer:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                await ShareServer((string)obj);\n                break;\n\n            case EViewAction.SubEditWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new SubEditWindow((SubItem)obj).ShowDialog<bool>(_window);\n\n            case EViewAction.DispatcherRefreshServersBiz:\n                Dispatcher.UIThread.Post(RefreshServersBiz, DispatcherPriority.Default);\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    public async Task ShareServer(string url)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        var dialog = new QrcodeView(url);\n        await DialogHost.Show(dialog);\n    }\n\n    public void RefreshServersBiz()\n    {\n        if (lstProfiles.SelectedIndex >= 0)\n        {\n            lstProfiles.ScrollIntoView(lstProfiles.SelectedItem, null);\n        }\n    }\n\n    private void lstProfiles_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedProfiles = lstProfiles.SelectedItems.Cast<ProfileItemModel>().ToList();\n        }\n    }\n\n    private void LstProfiles_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)\n    {\n        var source = e.Source as Border;\n        if (source?.Name == \"HeaderBackground\")\n        {\n            return;\n        }\n\n        if (_config.UiItem.DoubleClick2Activate)\n        {\n            ViewModel?.SetDefaultServer();\n        }\n        else\n        {\n            ViewModel?.EditServerAsync();\n        }\n    }\n\n    private void LstProfiles_LoadingRow(object? sender, DataGridRowEventArgs e)\n    {\n        e.Row.Header = $\" {e.Row.Index + 1}\";\n    }\n\n    //private void LstProfiles_ColumnHeader_Click(object? sender, RoutedEventArgs e)\n    //{\n    //    var colHeader = sender as DataGridColumnHeader;\n    //    if (colHeader == null || colHeader.TabIndex < 0 || colHeader.Column == null)\n    //    {\n    //        return;\n    //    }\n\n    //    var colName = ((MyDGTextColumn)colHeader.Column).ExName;\n    //    ViewModel?.SortServer(colName);\n    //}\n\n    private void menuSelectAll_Click(object? sender, RoutedEventArgs e)\n    {\n        lstProfiles.SelectAll();\n    }\n\n    private void LstProfiles_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)\n        {\n            switch (e.Key)\n            {\n                case Key.A:\n                    menuSelectAll_Click(null, null);\n                    break;\n\n                case Key.C:\n                    ViewModel?.Export2ShareUrlAsync(false);\n                    break;\n\n                case Key.D:\n                    ViewModel?.EditServerAsync();\n                    break;\n\n                case Key.F:\n                    ViewModel?.ShareServerAsync();\n                    break;\n\n                case Key.O:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Tcping);\n                    break;\n\n                case Key.R:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Realping);\n                    break;\n\n                case Key.T:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Speedtest);\n                    break;\n\n                case Key.E:\n                    ViewModel?.ServerSpeedtest(ESpeedActionType.Mixedtest);\n                    break;\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.Enter:\n                    //case Key.Return:\n                    ViewModel?.SetDefaultServer();\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.RemoveServerAsync();\n                    break;\n\n                case Key.T:\n                    ViewModel?.MoveServer(EMove.Top);\n                    break;\n\n                case Key.U:\n                    ViewModel?.MoveServer(EMove.Up);\n                    break;\n\n                case Key.D:\n                    ViewModel?.MoveServer(EMove.Down);\n                    break;\n\n                case Key.B:\n                    ViewModel?.MoveServer(EMove.Bottom);\n                    break;\n\n                case Key.Escape:\n                    ViewModel?.ServerSpeedtestStop();\n                    break;\n            }\n        }\n    }\n\n    private void BtnAutofitColumnWidth_Click(object? sender, RoutedEventArgs e)\n    {\n        AutofitColumnWidth();\n    }\n\n    private void AutofitColumnWidth()\n    {\n        try\n        {\n            //First scroll horizontally to the initial position to avoid the control crash bug\n            if (lstProfiles.SelectedIndex >= 0)\n            {\n                lstProfiles.ScrollIntoView(lstProfiles.SelectedItem, lstProfiles.Columns[0]);\n            }\n            else\n            {\n                var model = lstProfiles.ItemsSource.Cast<ProfileItemModel>();\n                if (model.Any())\n                {\n                    lstProfiles.ScrollIntoView(model.First(), lstProfiles.Columns[0]);\n                }\n                else\n                {\n                    return;\n                }\n            }\n\n            foreach (var it in lstProfiles.Columns)\n            {\n                it.Width = new DataGridLength(1, DataGridLengthUnitType.Auto);\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void TxtServerFilter_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.Key is Key.Enter or Key.Return)\n        {\n            ViewModel?.RefreshServers();\n        }\n    }\n\n    #endregion Event\n\n    #region UI\n\n    private void RestoreUI()\n    {\n        try\n        {\n            var lvColumnItem = _config.UiItem.MainColumnItem.OrderBy(t => t.Index).ToList();\n            var displayIndex = 0;\n            foreach (var item in lvColumnItem)\n            {\n                foreach (var item2 in lstProfiles.Columns)\n                {\n                    if (item2.Tag == null)\n                    {\n                        continue;\n                    }\n                    if (item2.Tag.Equals(item.Name))\n                    {\n                        if (item.Width < 0)\n                        {\n                            item2.IsVisible = false;\n                        }\n                        else\n                        {\n                            item2.Width = new DataGridLength(item.Width, DataGridLengthUnitType.Pixel);\n                            item2.DisplayIndex = displayIndex++;\n                        }\n                        if (item.Name.ToLower().StartsWith(\"to\"))\n                        {\n                            item2.IsVisible = _config.GuiItem.EnableStatistics;\n                        }\n                    }\n                }\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    private void StorageUI()\n    {\n        try\n        {\n            List<ColumnItem> lvColumnItem = new();\n            foreach (var item2 in lstProfiles.Columns)\n            {\n                if (item2.Tag == null)\n                {\n                    continue;\n                }\n                lvColumnItem.Add(new()\n                {\n                    Name = (string)item2.Tag,\n                    Width = (int)(item2.IsVisible == true ? item2.ActualWidth : -1),\n                    Index = item2.DisplayIndex\n                });\n            }\n            _config.UiItem.MainColumnItem = lvColumnItem;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(_tag, ex);\n        }\n    }\n\n    #endregion UI\n\n    #region Drag and Drop\n\n    //private Point startPoint = new();\n    //private int startIndex = -1;\n    //private string formatData = \"ProfileItemModel\";\n\n    ///// <summary>\n    ///// Helper to search up the VisualTree\n    ///// </summary>\n    ///// <typeparam name=\"T\"></typeparam>\n    ///// <param name=\"current\"></param>\n    ///// <returns></returns>\n    //private static T? FindAncestor<T>(DependencyObject current) where T : DependencyObject\n    //{\n    //    do\n    //    {\n    //        if (current is T)\n    //        {\n    //            return (T)current;\n    //        }\n    //        current = VisualTreeHelper.GetParent(current);\n    //    }\n    //    while (current != null);\n    //    return null;\n    //}\n\n    //private void LstProfiles_PreviewMouseLeftButtonDown(object? sender, MouseButtonEventArgs e)\n    //{\n    //    // Get current mouse position\n    //    startPoint = e.GetPosition(null);\n    //}\n\n    //private void LstProfiles_MouseMove(object? sender, MouseEventArgs e)\n    //{\n    //    // Get the current mouse position\n    //    Point mousePos = e.GetPosition(null);\n    //    Vector diff = startPoint - mousePos;\n\n    //    if (e.LeftButton == MouseButtonState.Pressed &&\n    //        (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||\n    //               Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))\n    //    {\n    //        // Get the dragged Item\n    //        if (sender is not DataGrid listView) return;\n    //        var listViewItem = FindAncestor<DataGridRow>((DependencyObject)e.OriginalSource);\n    //        if (listViewItem == null) return;           // Abort\n    //                                                    // Find the data behind the ListViewItem\n    //        ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);\n    //        if (item == null) return;                   // Abort\n    //                                                    // Initialize the drag & drop operation\n    //        startIndex = lstProfiles.SelectedIndex;\n    //        DataObject dragData = new(formatData, item);\n    //        DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Copy | DragDropEffects.Move);\n    //    }\n    //}\n\n    //private void LstProfiles_DragEnter(object? sender, DragEventArgs e)\n    //{\n    //    if (!e.Data.GetDataPresent(formatData) || sender != e.Source)\n    //    {\n    //        e.Effects = DragDropEffects.None;\n    //    }\n    //}\n\n    //private void LstProfiles_Drop(object? sender, DragEventArgs e)\n    //{\n    //    if (e.Data.GetDataPresent(formatData) && sender == e.Source)\n    //    {\n    //        // Get the drop Item destination\n    //        if (sender is not DataGrid listView) return;\n    //        var listViewItem = FindAncestor<DataGridRow>((DependencyObject)e.OriginalSource);\n    //        if (listViewItem == null)\n    //        {\n    //            // Abort\n    //            e.Effects = DragDropEffects.None;\n    //            return;\n    //        }\n    //        // Find the data behind the Item\n    //        ProfileItemModel item = (ProfileItemModel)listView.ItemContainerGenerator.ItemFromContainer(listViewItem);\n    //        if (item == null) return;\n    //        // Move item into observable collection\n    //        // (this will be automatically reflected to lstView.ItemsSource)\n    //        e.Effects = DragDropEffects.Move;\n\n    //        ViewModel?.MoveServerTo(startIndex, item);\n\n    //        startIndex = -1;\n    //    }\n    //}\n\n    #endregion Drag and Drop\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/QrcodeView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.QrcodeView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:sys=\"clr-namespace:System;assembly=netstandard\"\n    d:DesignHeight=\"600\"\n    d:DesignWidth=\"600\"\n    mc:Ignorable=\"d\">\n\n    <UserControl.Resources>\n        <sys:Double x:Key=\"QrcodeWidth\">400</sys:Double>\n    </UserControl.Resources>\n\n    <Grid Margin=\"{StaticResource Margin8}\" RowDefinitions=\"Auto,Auto\">\n        <Image\n            Name=\"imgQrcode\"\n            Width=\"{StaticResource QrcodeWidth}\"\n            Height=\"{StaticResource QrcodeWidth}\" />\n\n        <TextBox\n            x:Name=\"txtContent\"\n            Grid.Row=\"1\"\n            Width=\"{StaticResource QrcodeWidth}\"\n            MaxHeight=\"100\"\n            Margin=\"{StaticResource MarginTb8}\"\n            VerticalAlignment=\"Center\"\n            IsReadOnly=\"True\"\n            TextWrapping=\"WrapWithOverflow\" />\n\n    </Grid>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/QrcodeView.axaml.cs",
    "content": "namespace v2rayN.Desktop.Views;\n\npublic partial class QrcodeView : UserControl\n{\n    public QrcodeView()\n    {\n        InitializeComponent();\n    }\n\n    public QrcodeView(string? url)\n    {\n        InitializeComponent();\n\n        txtContent.Text = url;\n        imgQrcode.Source = GetQRCode(url);\n\n        txtContent.GotFocus += (_, _) => Dispatcher.UIThread.Post(() => { txtContent.SelectAll(); });\n    }\n\n    private Bitmap? GetQRCode(string? url)\n    {\n        try\n        {\n            var bytes = QRCodeUtils.GenQRCode(url);\n            return ByteToBitmap(bytes);\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"GetQRCode\", ex);\n            return null;\n        }\n    }\n\n    private Bitmap? ByteToBitmap(byte[]? bytes)\n    {\n        if (bytes is null)\n        {\n            return null;\n        }\n\n        using var ms = new MemoryStream(bytes);\n        return new Bitmap(ms);\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/RoutingRuleDetailsWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.RoutingRuleDetailsWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuRoutingRuleDetailsSetting}\"\n    Width=\"900\"\n    Height=\"600\"\n    x:DataType=\"vms:RoutingRuleDetailsViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel>\n        <Grid\n            Margin=\"{StaticResource Margin4}\"\n            ColumnDefinitions=\"Auto,Auto,Auto\"\n            DockPanel.Dock=\"Top\"\n            RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n            <TextBlock\n                Grid.Row=\"0\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.LvRemarks}\" />\n            <TextBox\n                x:Name=\"txtRemarks\"\n                Grid.Row=\"0\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\" />\n            <StackPanel\n                Grid.Row=\"0\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Orientation=\"Horizontal\">\n                <ToggleSwitch\n                    x:Name=\"togEnabled\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\" />\n\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbRuleType}\" />\n            <ComboBox\n                x:Name=\"cmbRuleType\"\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                MaxDropDownHeight=\"1000\" />\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbRuleTypeTips}\" />\n\n            <TextBlock\n                Grid.Row=\"2\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"outboundTag\" />\n            <ComboBox\n                Name=\"cmbOutboundTag\"\n                Grid.Row=\"2\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                IsEditable=\"True\" />\n            <StackPanel\n                Grid.Row=\"2\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Orientation=\"Horizontal\">\n                <Button\n                    x:Name=\"btnSelectProfile\"\n                    Margin=\"0,0,8,0\"\n                    Click=\"BtnSelectProfile_Click\"\n                    Content=\"{x:Static resx:ResUI.TbSelectProfile}\" />\n                <TextBlock VerticalAlignment=\"Center\" Text=\"{x:Static resx:ResUI.TbRuleOutboundTagTip}\" />\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"3\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"port\" />\n            <TextBox\n                x:Name=\"txtPort\"\n                Grid.Row=\"3\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\" />\n            <TextBlock\n                Grid.Row=\"3\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbRuleMatchingTips}\" />\n\n            <TextBlock\n                Grid.Row=\"4\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"protocol\" />\n            <ListBox\n                x:Name=\"clbProtocol\"\n                Grid.Row=\"4\"\n                Grid.Column=\"1\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                SelectionMode=\"Multiple,Toggle\"\n                Theme=\"{DynamicResource CardCheckGroupListBox}\" />\n            <TextBlock\n                Grid.Row=\"4\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\">\n                <HyperlinkButton Classes=\"WithIcon\" Click=\"linkRuleobjectDoc_Click\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.TbRuleobjectDoc}\" />\n                </HyperlinkButton>\n            </TextBlock>\n\n            <TextBlock\n                Grid.Row=\"5\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"inboundTag\" />\n            <ListBox\n                x:Name=\"clbInboundTag\"\n                Grid.Row=\"5\"\n                Grid.Column=\"1\"\n                Margin=\"{StaticResource Margin4}\"\n                SelectionMode=\"Multiple,Toggle\"\n                Theme=\"{DynamicResource CardCheckGroupListBox}\" />\n            <TextBlock\n                Grid.Row=\"5\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbRoutingInboundTagTips}\" />\n\n            <TextBlock\n                Grid.Row=\"6\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"network\" />\n            <ComboBox\n                x:Name=\"cmbNetwork\"\n                Grid.Row=\"6\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                MaxDropDownHeight=\"1000\" />\n            <TextBlock\n                Grid.Row=\"6\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbRoutingTips}\" />\n        </Grid>\n\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Right\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <StackPanel\n                Width=\"600\"\n                HorizontalAlignment=\"Center\"\n                VerticalAlignment=\"Center\">\n                <CheckBox x:Name=\"chkAutoSort\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.TbAutoSort}\" />\n                </CheckBox>\n            </StackPanel>\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n\n        <Grid Margin=\"{StaticResource Margin4}\" ColumnDefinitions=\"1*,10,1*,10,1*\">\n            <HeaderedContentControl\n                Grid.Column=\"0\"\n                BorderBrush=\"Gray\"\n                BorderThickness=\"1\"\n                Header=\"{x:Static resx:ResUI.TbRoutingRuleDomain}\">\n                <TextBox\n                    Name=\"txtDomain\"\n                    VerticalAlignment=\"Stretch\"\n                    Classes=\"TextArea\"\n                    MinLines=\"10\"\n                    TextWrapping=\"Wrap\" />\n            </HeaderedContentControl>\n            <GridSplitter Grid.Column=\"1\" HorizontalAlignment=\"Stretch\" />\n            <HeaderedContentControl\n                Grid.Column=\"2\"\n                BorderBrush=\"Gray\"\n                BorderThickness=\"1\"\n                Header=\"{x:Static resx:ResUI.TbRoutingRuleIP}\">\n                <TextBox\n                    Name=\"txtIP\"\n                    VerticalAlignment=\"Stretch\"\n                    Classes=\"TextArea\"\n                    MinLines=\"10\"\n                    TextWrapping=\"Wrap\" />\n            </HeaderedContentControl>\n            <GridSplitter Grid.Column=\"3\" HorizontalAlignment=\"Stretch\" />\n            <HeaderedContentControl\n                Grid.Column=\"4\"\n                BorderBrush=\"Gray\"\n                BorderThickness=\"1\"\n                Header=\"{x:Static resx:ResUI.TbRoutingRuleProcess}\">\n                <TextBox\n                    Name=\"txtProcess\"\n                    VerticalAlignment=\"Stretch\"\n                    Classes=\"TextArea\"\n                    MinLines=\"10\"\n                    TextWrapping=\"Wrap\" />\n            </HeaderedContentControl>\n        </Grid>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/RoutingRuleDetailsWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class RoutingRuleDetailsWindow : WindowBase<RoutingRuleDetailsViewModel>\n{\n    public RoutingRuleDetailsWindow()\n    {\n        InitializeComponent();\n    }\n\n    public RoutingRuleDetailsWindow(RulesItem rulesItem)\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        clbProtocol.SelectionChanged += ClbProtocol_SelectionChanged;\n        clbInboundTag.SelectionChanged += ClbInboundTag_SelectionChanged;\n\n        ViewModel = new RoutingRuleDetailsViewModel(rulesItem, UpdateViewHandler);\n\n        cmbOutboundTag.ItemsSource = Global.OutboundTags;\n        clbProtocol.ItemsSource = Global.RuleProtocols;\n        clbInboundTag.ItemsSource = Global.InboundTags;\n        cmbNetwork.ItemsSource = Global.RuleNetworks;\n        cmbRuleType.ItemsSource = Utils.GetEnumNames<ERuleType>().AppendEmpty();\n\n        if (!rulesItem.Id.IsNullOrEmpty())\n        {\n            rulesItem.Protocol?.ForEach(it =>\n            {\n                clbProtocol?.SelectedItems?.Add(it);\n            });\n            rulesItem.InboundTag?.ForEach(it =>\n            {\n                clbInboundTag?.SelectedItems?.Add(it);\n            });\n        }\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.OutboundTag, v => v.cmbOutboundTag.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Port, v => v.txtPort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Network, v => v.cmbNetwork.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Enabled, v => v.togEnabled.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Domain, v => v.txtDomain.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.IP, v => v.txtIP.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.Process, v => v.txtProcess.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.AutoSort, v => v.chkAutoSort.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.RuleType, v => v.cmbRuleType.SelectedValue).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void ClbProtocol_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.ProtocolItems = clbProtocol.SelectedItems.Cast<string>().ToList();\n        }\n    }\n\n    private void ClbInboundTag_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.InboundTagItems = clbInboundTag.SelectedItems.Cast<string>().ToList();\n        }\n    }\n\n    private void linkRuleobjectDoc_Click(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://xtls.github.io/config/routing.html#ruleobject\");\n    }\n\n    private async void BtnSelectProfile_Click(object? sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter(new[] { EConfigType.Custom }, exclude: true);\n        var result = await selectWindow.ShowDialog<bool?>(this);\n        if (result == true)\n        {\n            var profile = await selectWindow.ProfileItem;\n            if (profile != null)\n            {\n                cmbOutboundTag.Text = profile.Remarks;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.RoutingRuleSettingWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuRoutingRuleSetting}\"\n    Width=\"900\"\n    Height=\"600\"\n    x:DataType=\"vms:RoutingRuleSettingViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel>\n        <Menu Margin=\"{StaticResource Margin4}\" DockPanel.Dock=\"Top\">\n            <MenuItem x:Name=\"menuRuleAdd\" Header=\"{x:Static resx:ResUI.menuRuleAdd}\" />\n            <MenuItem x:Name=\"menuImportRulesFromFile\" Header=\"{x:Static resx:ResUI.menuImportRulesFromFile}\" />\n            <MenuItem x:Name=\"menuImportRulesFromClipboard\" Header=\"{x:Static resx:ResUI.menuImportRulesFromClipboard}\" />\n            <MenuItem x:Name=\"menuImportRulesFromUrl\" Header=\"{x:Static resx:ResUI.menuImportRulesFromUrl}\" />\n        </Menu>\n\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Right\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n\n        <Grid\n            Margin=\"{StaticResource Margin4}\"\n            ColumnDefinitions=\"Auto,Auto,Auto\"\n            DockPanel.Dock=\"Top\"\n            RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto\">\n            <TextBlock\n                Grid.Row=\"0\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.LvRemarks}\" />\n            <StackPanel\n                Grid.Row=\"0\"\n                Grid.Column=\"1\"\n                Orientation=\"Horizontal\">\n\n                <TextBox\n                    x:Name=\"txtRemarks\"\n                    Grid.Row=\"0\"\n                    Grid.Column=\"1\"\n                    Width=\"300\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    VerticalAlignment=\"Center\"\n                    TextWrapping=\"Wrap\" />\n\n                <TextBlock\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvSort}\" />\n                <TextBox\n                    x:Name=\"txtSort\"\n                    Width=\"100\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\" />\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.TbdomainStrategy}\" />\n            <StackPanel\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Orientation=\"Horizontal\">\n                <ComboBox\n                    x:Name=\"cmbdomainStrategy\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\" />\n                <TextBlock\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbdomainStrategy4Singbox}\" />\n                <ComboBox\n                    x:Name=\"cmbdomainStrategy4Singbox\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\" />\n            </StackPanel>\n\n            <TextBlock\n                Grid.Row=\"2\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\"\n                Text=\"{x:Static resx:ResUI.LvUrl}\" />\n            <TextBox\n                x:Name=\"txtUrl\"\n                Grid.Row=\"2\"\n                Grid.Column=\"1\"\n                Width=\"600\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                TextWrapping=\"Wrap\" />\n\n            <!--\n            <TextBlock\n                Grid.Row=\"3\"\n                Grid.Column=\"0\"\n                VerticalAlignment=\"Center\"\n                Margin=\"{StaticResource Margin4}\"\n                Text=\"{x:Static resx:ResUI.LvCustomIcon}\" />\n            <TextBox\n                x:Name=\"txtCustomIcon\"\n                Grid.Row=\"3\"\n                Grid.Column=\"1\"\n                Width=\"600\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                Margin=\"{StaticResource Margin4}\"\n                TextWrapping=\"Wrap\" />\n            <Button\n                x:Name=\"btnBrowseCustomIcon\"\n                Grid.Row=\"3\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                Content=\"{x:Static resx:ResUI.TbBrowse}\" />\n            -->\n\n            <TextBlock\n                Grid.Row=\"4\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\">\n                <HyperlinkButton Classes=\"WithIcon\" Click=\"linkCustomRulesetPath4Singbox\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.LvCustomRulesetPath4Singbox}\" />\n                </HyperlinkButton>\n            </TextBlock>\n            <TextBox\n                x:Name=\"txtCustomRulesetPath4Singbox\"\n                Grid.Row=\"4\"\n                Grid.Column=\"1\"\n                Width=\"600\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\"\n                TextWrapping=\"Wrap\" />\n            <Button\n                x:Name=\"btnBrowseCustomRulesetPath4Singbox\"\n                Grid.Row=\"4\"\n                Grid.Column=\"2\"\n                Margin=\"{StaticResource Margin4}\"\n                Content=\"{x:Static resx:ResUI.TbBrowse}\" />\n        </Grid>\n\n        <TabControl x:Name=\"tabAdvanced\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.menuRuleList}\">\n                <DataGrid\n                    x:Name=\"lstRules\"\n                    AutoGenerateColumns=\"False\"\n                    Background=\"Transparent\"\n                    BorderThickness=\"1\"\n                    CanUserResizeColumns=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    ItemsSource=\"{Binding RulesItems}\">\n                    <DataGrid.KeyBindings>\n                        <KeyBinding Command=\"{Binding RuleExportSelectedCmd}\" Gesture=\"Ctrl+C\" />\n                    </DataGrid.KeyBindings>\n                    <DataGrid.ContextMenu>\n                        <ContextMenu>\n                            <MenuItem x:Name=\"menuRuleAdd2\" Header=\"{x:Static resx:ResUI.menuRuleAdd}\" />\n                            <MenuItem\n                                x:Name=\"menuRuleRemove\"\n                                Header=\"{x:Static resx:ResUI.menuRuleRemove}\"\n                                InputGesture=\"Back\" />\n                            <MenuItem\n                                x:Name=\"menuRuleSelectAll\"\n                                Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                                InputGesture=\"Ctrl+A\" />\n                            <MenuItem x:Name=\"menuRuleExportSelected\" Header=\"{x:Static resx:ResUI.menuRuleExportSelected}\" />\n                            <Separator />\n                            <MenuItem\n                                x:Name=\"menuMoveTop\"\n                                Header=\"{x:Static resx:ResUI.menuMoveTop}\"\n                                InputGesture=\"T\" />\n                            <MenuItem\n                                x:Name=\"menuMoveUp\"\n                                Header=\"{x:Static resx:ResUI.menuMoveUp}\"\n                                InputGesture=\"U\" />\n                            <MenuItem\n                                x:Name=\"menuMoveDown\"\n                                Header=\"{x:Static resx:ResUI.menuMoveDown}\"\n                                InputGesture=\"D\" />\n                            <MenuItem\n                                x:Name=\"menuMoveBottom\"\n                                Header=\"{x:Static resx:ResUI.menuMoveBottom}\"\n                                InputGesture=\"B\" />\n                        </ContextMenu>\n                    </DataGrid.ContextMenu>\n                    <DataGrid.Columns>\n                        <DataGridCheckBoxColumn\n                            Width=\"60\"\n                            Binding=\"{Binding Enabled}\"\n                            Header=\"\" />\n                        <DataGridTextColumn\n                            Width=\"150\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding RuleTypeName}\"\n                            Header=\"{x:Static resx:ResUI.TbRuleType}\" />\n                        <DataGridTextColumn\n                            Width=\"130\"\n                            Binding=\"{Binding OutboundTag}\"\n                            Header=\"outboundTag\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Port}\"\n                            Header=\"port\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Protocols}\"\n                            Header=\"protocol\" />\n                        <DataGridTextColumn\n                            Width=\"120\"\n                            Binding=\"{Binding InboundTags}\"\n                            Header=\"inboundTag\" />\n                        <DataGridTextColumn\n                            Width=\"100\"\n                            Binding=\"{Binding Network}\"\n                            Header=\"network\" />\n                        <DataGridTextColumn\n                            Width=\"*\"\n                            Binding=\"{Binding Domains}\"\n                            Header=\"domain / ip / process\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/RoutingRuleSettingWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\nusing v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class RoutingRuleSettingWindow : WindowBase<RoutingRuleSettingViewModel>\n{\n    public RoutingRuleSettingWindow()\n    {\n        InitializeComponent();\n    }\n\n    public RoutingRuleSettingWindow(RoutingItem routingItem)\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n        KeyDown += RoutingRuleSettingWindow_KeyDown;\n        lstRules.SelectionChanged += lstRules_SelectionChanged;\n        lstRules.DoubleTapped += LstRules_DoubleTapped;\n        menuRuleSelectAll.Click += menuRuleSelectAll_Click;\n        //btnBrowseCustomIcon.Click += btnBrowseCustomIcon_Click;\n        btnBrowseCustomRulesetPath4Singbox.Click += btnBrowseCustomRulesetPath4Singbox_ClickAsync;\n\n        ViewModel = new RoutingRuleSettingViewModel(routingItem, UpdateViewHandler);\n\n        cmbdomainStrategy.ItemsSource = Global.DomainStrategies.AppendEmpty();\n        cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Sbox;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.RulesItems, v => v.lstRules.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRules.SelectedItem).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedRouting.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.DomainStrategy, v => v.cmbdomainStrategy.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.DomainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.SelectedValue).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SelectedRouting.Url, v => v.txtUrl.Text).DisposeWith(disposables);\n            //this.Bind(ViewModel, vm => vm.SelectedRouting.CustomIcon, v => v.txtCustomIcon.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.CustomRulesetPath4Singbox, v => v.txtCustomRulesetPath4Singbox.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting.Sort, v => v.txtSort.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportRulesFromFileCmd, v => v.menuImportRulesFromFile).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportRulesFromClipboardCmd, v => v.menuImportRulesFromClipboard).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.ImportRulesFromUrlCmd, v => v.menuImportRulesFromUrl).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RuleAddCmd, v => v.menuRuleAdd2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RuleRemoveCmd, v => v.menuRuleRemove).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RuleExportSelectedCmd, v => v.menuRuleExportSelected).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveTopCmd, v => v.menuMoveTop).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveUpCmd, v => v.menuMoveUp).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveDownCmd, v => v.menuMoveDown).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.MoveBottomCmd, v => v.menuMoveBottom).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n\n            case EViewAction.ShowYesNo:\n                if (await UI.ShowYesNo(this, ResUI.RemoveServer) != ButtonResult.Yes)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.AddBatchRoutingRulesYesNo:\n                if (await UI.ShowYesNo(this, ResUI.AddBatchRoutingRulesYesNo) != ButtonResult.Yes)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.RoutingRuleDetailsWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new RoutingRuleDetailsWindow((RulesItem)obj).ShowDialog<bool>(this);\n\n            case EViewAction.ImportRulesFromFile:\n                var fileName = await UI.OpenFileDialog(this, null);\n                if (fileName.IsNullOrEmpty())\n                {\n                    return false;\n                }\n                ViewModel?.ImportRulesFromFileAsync(fileName);\n                break;\n\n            case EViewAction.SetClipboardData:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                await AvaUtils.SetClipboardData(this, (string)obj);\n                break;\n\n            case EViewAction.ImportRulesFromClipboard:\n                var clipboardData = await AvaUtils.GetClipboardData(this);\n                if (clipboardData.IsNotEmpty())\n                {\n                    ViewModel?.ImportRulesFromClipboardAsync(clipboardData);\n                }\n\n                break;\n        }\n\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private void RoutingRuleSettingWindow_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)\n        {\n            if (e.Key == Key.A)\n            {\n                lstRules.SelectAll();\n            }\n            else if (e.Key == Key.C)\n            {\n                ViewModel?.RuleExportSelectedAsync();\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.T:\n                    ViewModel?.MoveRule(EMove.Top);\n                    break;\n\n                case Key.U:\n                    ViewModel?.MoveRule(EMove.Up);\n                    break;\n\n                case Key.D:\n                    ViewModel?.MoveRule(EMove.Down);\n                    break;\n\n                case Key.B:\n                    ViewModel?.MoveRule(EMove.Bottom);\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.RuleRemoveAsync();\n                    break;\n            }\n        }\n    }\n\n    private void lstRules_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedSources = lstRules.SelectedItems.Cast<RulesItemModel>().ToList();\n        }\n    }\n\n    private void LstRules_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)\n    {\n        ViewModel?.RuleEditAsync(false);\n    }\n\n    private void menuRuleSelectAll_Click(object? sender, RoutedEventArgs e)\n    {\n        lstRules.SelectAll();\n    }\n\n    //private async void btnBrowseCustomIcon_Click(object? sender, RoutedEventArgs e)\n    //{\n    //    var fileName = await UI.OpenFileDialog(this, FilePickerFileTypes.ImagePng);\n    //    if (fileName.IsNullOrEmpty())\n    //    {\n    //        return;\n    //    }\n\n    //    txtCustomIcon.Text = fileName;\n    //}\n\n    private async void btnBrowseCustomRulesetPath4Singbox_ClickAsync(object? sender, RoutedEventArgs e)\n    {\n        var fileName = await UI.OpenFileDialog(this, null);\n        if (fileName.IsNullOrEmpty())\n        {\n            return;\n        }\n\n        txtCustomRulesetPath4Singbox.Text = fileName;\n    }\n\n    private void linkCustomRulesetPath4Singbox(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://github.com/2dust/v2rayCustomRoutingList/blob/master/singbox_custom_ruleset_example.json\");\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.RoutingSettingWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuRoutingSetting}\"\n    Width=\"900\"\n    Height=\"600\"\n    x:DataType=\"vms:RoutingSettingViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n\n    <DockPanel>\n        <Menu Margin=\"{StaticResource Margin4}\" DockPanel.Dock=\"Top\">\n            <MenuItem x:Name=\"menuRoutingAdvancedAdd2\" Header=\"{x:Static resx:ResUI.menuRoutingAdvancedAdd}\" />\n            <MenuItem x:Name=\"menuRoutingAdvancedImportRules2\" Header=\"{x:Static resx:ResUI.menuRoutingAdvancedImportRules}\" />\n        </Menu>\n\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Right\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n\n        <Grid\n            Margin=\"{StaticResource Margin4}\"\n            ColumnDefinitions=\"Auto,Auto\"\n            DockPanel.Dock=\"Top\"\n            RowDefinitions=\"Auto,Auto\">\n\n            <TextBlock\n                Grid.Row=\"0\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\">\n                <HyperlinkButton Classes=\"WithIcon\" Click=\"linkdomainStrategy_Click\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.TbdomainStrategy}\" />\n                </HyperlinkButton>\n            </TextBlock>\n            <ComboBox\n                x:Name=\"cmbdomainStrategy\"\n                Grid.Row=\"0\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\" />\n\n            <TextBlock\n                Grid.Row=\"1\"\n                Grid.Column=\"0\"\n                Margin=\"{StaticResource Margin4}\"\n                VerticalAlignment=\"Center\">\n                <HyperlinkButton Classes=\"WithIcon\" Click=\"linkdomainStrategy4Singbox_Click\">\n                    <TextBlock Text=\"{x:Static resx:ResUI.TbdomainStrategy4Singbox}\" />\n                </HyperlinkButton>\n            </TextBlock>\n            <ComboBox\n                x:Name=\"cmbdomainStrategy4Singbox\"\n                Grid.Row=\"1\"\n                Grid.Column=\"1\"\n                Width=\"300\"\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Left\"\n                VerticalAlignment=\"Center\" />\n        </Grid>\n\n        <TabControl x:Name=\"tabAdvanced\">\n            <TabItem HorizontalAlignment=\"Left\" Header=\"{x:Static resx:ResUI.TbRoutingTabRuleList}\">\n                <DataGrid\n                    x:Name=\"lstRoutings\"\n                    AutoGenerateColumns=\"False\"\n                    Background=\"Transparent\"\n                    BorderThickness=\"1\"\n                    CanUserResizeColumns=\"True\"\n                    GridLinesVisibility=\"All\"\n                    HeadersVisibility=\"Column\"\n                    IsReadOnly=\"True\"\n                    ItemsSource=\"{Binding RoutingItems}\">\n                    <DataGrid.KeyBindings>\n                        <KeyBinding Command=\"{Binding RoutingAdvancedSetDefaultCmd}\" Gesture=\"Enter\" />\n                    </DataGrid.KeyBindings>\n                    <DataGrid.ContextMenu>\n                        <ContextMenu>\n                            <MenuItem x:Name=\"menuRoutingAdvancedAdd\" Header=\"{x:Static resx:ResUI.menuRoutingAdvancedAdd}\" />\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedRemove\"\n                                Header=\"{x:Static resx:ResUI.menuRoutingAdvancedRemove}\"\n                                InputGesture=\"Back\" />\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedSelectAll\"\n                                Header=\"{x:Static resx:ResUI.menuSelectAll}\"\n                                InputGesture=\"Ctrl+A\" />\n                            <MenuItem\n                                x:Name=\"menuRoutingAdvancedSetDefault\"\n                                Header=\"{x:Static resx:ResUI.menuRoutingAdvancedSetDefault}\"\n                                InputGesture=\"Enter\" />\n                            <Separator />\n                            <MenuItem x:Name=\"menuRoutingAdvancedImportRules\" Header=\"{x:Static resx:ResUI.menuRoutingAdvancedImportRules}\" />\n                        </ContextMenu>\n                    </DataGrid.ContextMenu>\n\n                    <DataGrid.Columns>\n                        <DataGridCheckBoxColumn Width=\"40\" Binding=\"{Binding IsActive}\" />\n                        <DataGridTextColumn\n                            Width=\"*\"\n                            Binding=\"{Binding Remarks}\"\n                            Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                        <DataGridTextColumn\n                            Width=\"60\"\n                            Binding=\"{Binding RuleNum}\"\n                            Header=\"{x:Static resx:ResUI.LvCount}\" />\n                        <DataGridTextColumn\n                            Width=\"60\"\n                            Binding=\"{Binding Sort}\"\n                            Header=\"{x:Static resx:ResUI.LvSort}\" />\n                        <DataGridTextColumn\n                            Width=\"*\"\n                            Binding=\"{Binding Url}\"\n                            Header=\"{x:Static resx:ResUI.LvUrl}\" />\n                    </DataGrid.Columns>\n                </DataGrid>\n            </TabItem>\n        </TabControl>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/RoutingSettingWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\nusing v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class RoutingSettingWindow : WindowBase<RoutingSettingViewModel>\n{\n    private bool _manualClose = false;\n\n    public RoutingSettingWindow()\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        Closing += RoutingSettingWindow_Closing;\n        btnCancel.Click += (s, e) => Close();\n        KeyDown += RoutingSettingWindow_KeyDown;\n        lstRoutings.SelectionChanged += lstRoutings_SelectionChanged;\n        lstRoutings.DoubleTapped += LstRoutings_DoubleTapped;\n        menuRoutingAdvancedSelectAll.Click += menuRoutingAdvancedSelectAll_Click;\n\n        ViewModel = new RoutingSettingViewModel(UpdateViewHandler);\n\n        cmbdomainStrategy.ItemsSource = Global.DomainStrategies;\n        cmbdomainStrategy4Singbox.ItemsSource = Global.DomainStrategies4Sbox;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.RoutingItems, v => v.lstRoutings.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstRoutings.SelectedItem).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.DomainStrategy, v => v.cmbdomainStrategy.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.DomainStrategy4Singbox, v => v.cmbdomainStrategy4Singbox.SelectedValue).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedAddCmd, v => v.menuRoutingAdvancedAdd2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedRemoveCmd, v => v.menuRoutingAdvancedRemove).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedSetDefaultCmd, v => v.menuRoutingAdvancedSetDefault).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.RoutingAdvancedImportRulesCmd, v => v.menuRoutingAdvancedImportRules2).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n\n            case EViewAction.ShowYesNo:\n                if (await UI.ShowYesNo(this, ResUI.RemoveRules) != ButtonResult.Yes)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.RoutingRuleSettingWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                return await new RoutingRuleSettingWindow((RoutingItem)obj).ShowDialog<bool>(this);\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void RoutingSettingWindow_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.KeyModifiers is KeyModifiers.Control or KeyModifiers.Meta)\n        {\n            switch (e.Key)\n            {\n                case Key.A:\n                    lstRoutings.SelectAll();\n                    break;\n            }\n        }\n        else\n        {\n            switch (e.Key)\n            {\n                case Key.Enter:\n                    //case Key.Return:\n                    ViewModel?.RoutingAdvancedSetDefault();\n                    break;\n\n                case Key.Delete:\n                case Key.Back:\n                    ViewModel?.RoutingAdvancedRemoveAsync();\n                    break;\n            }\n        }\n    }\n\n    private void menuRoutingAdvancedSelectAll_Click(object? sender, RoutedEventArgs e)\n    {\n        lstRoutings.SelectAll();\n    }\n\n    private void lstRoutings_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedSources = lstRoutings.SelectedItems.Cast<RoutingItemModel>().ToList();\n        }\n    }\n\n    private void LstRoutings_DoubleTapped(object? sender, TappedEventArgs e)\n    {\n        ViewModel?.RoutingAdvancedEditAsync(false);\n    }\n\n    private void linkdomainStrategy_Click(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://xtls.github.io/config/routing.html\");\n    }\n\n    private void linkdomainStrategy4Singbox_Click(object? sender, RoutedEventArgs e)\n    {\n        ProcUtils.ProcessStart(\"https://sing-box.sagernet.org/zh/configuration/route/rule_action/#strategy\");\n    }\n\n    private void btnCancel_Click(object? sender, RoutedEventArgs e)\n    {\n        _manualClose = true;\n        Close(ViewModel?.IsModified);\n    }\n\n    private void RoutingSettingWindow_Closing(object? sender, WindowClosingEventArgs e)\n    {\n        if (ViewModel?.IsModified == true)\n        {\n            if (!_manualClose)\n            {\n                btnCancel_Click(null, null);\n            }\n        }\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        btnCancel.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.StatusBarView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:DataType=\"vms:StatusBarViewModel\"\n    mc:Ignorable=\"d\">\n    <Grid>\n        <DockPanel Margin=\"{StaticResource Margin8}\">\n            <StackPanel\n                VerticalAlignment=\"Center\"\n                Margin=\"{StaticResource MarginLr8}\"\n                DockPanel.Dock=\"Right\">\n                <TextBlock x:Name=\"txtSpeedProxyDisplay\" HorizontalAlignment=\"Right\" />\n                <Border Margin=\"1\" />\n                <TextBlock x:Name=\"txtSpeedDirectDisplay\" HorizontalAlignment=\"Right\" />\n            </StackPanel>\n\n            <StackPanel\n                VerticalAlignment=\"Center\"\n                Margin=\"{StaticResource MarginLr8}\"\n                DockPanel.Dock=\"Left\">\n                <TextBlock x:Name=\"txtInboundDisplay\" />\n                <Border Margin=\"1\" />\n                <TextBlock x:Name=\"txtInboundLanDisplay\" />\n            </StackPanel>\n\n            <StackPanel\n                x:Name=\"spEnableTun\"\n                VerticalAlignment=\"Center\"\n                Margin=\"{StaticResource MarginLr8}\"\n                DockPanel.Dock=\"Left\"\n                Orientation=\"Horizontal\">\n                <TextBlock\n                    VerticalAlignment=\"Center\"\n                    Margin=\"{StaticResource MarginLr8}\"\n                    Text=\"{x:Static resx:ResUI.TbEnableTunAs}\" />\n                <ToggleSwitch\n                    x:Name=\"togEnableTun\"\n                    HorizontalAlignment=\"Center\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Theme=\"{DynamicResource SimpleToggleSwitch}\" />\n            </StackPanel>\n\n            <StackPanel\n                VerticalAlignment=\"Center\"\n                Margin=\"{StaticResource MarginLr8}\"\n                DockPanel.Dock=\"Left\"\n                Orientation=\"Horizontal\">\n                <ComboBox\n                    x:Name=\"cmbSystemProxy\"\n                    Width=\"160\"\n                    Margin=\"{StaticResource MarginLr8}\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.menuSystemproxy}\">\n                    <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxyClear}\" />\n                    <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxySet}\" />\n                    <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxyNothing}\" />\n                    <ComboBoxItem Content=\"{x:Static resx:ResUI.menuSystemProxyPac}\" />\n                </ComboBox>\n\n                <ComboBox\n                    x:Name=\"cmbRoutings2\"\n                    Width=\"160\"\n                    Margin=\"{StaticResource MarginLr8}\"\n                    DisplayMemberBinding=\"{Binding Remarks}\"\n                    ItemsSource=\"{Binding RoutingItems}\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.menuRouting}\" />\n            </StackPanel>\n\n            <StackPanel VerticalAlignment=\"Center\" Margin=\"{StaticResource MarginLr8}\">\n                <TextBlock x:Name=\"txtRunningServerDisplay\" />\n                <Border Margin=\"1\" />\n                <TextBlock x:Name=\"txtRunningInfoDisplay\" />\n            </StackPanel>\n        </DockPanel>\n    </Grid>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/StatusBarView.axaml.cs",
    "content": "using DialogHostAvalonia;\nusing v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class StatusBarView : ReactiveUserControl<StatusBarViewModel>\n{\n    private static Config _config;\n\n    public StatusBarView()\n    {\n        InitializeComponent();\n\n        _config = AppManager.Instance.Config;\n\n        ViewModel = StatusBarViewModel.Instance;\n        ViewModel?.InitUpdateView(UpdateViewHandler);\n\n        txtRunningServerDisplay.Tapped += TxtRunningServerDisplay_Tapped;\n        txtRunningInfoDisplay.Tapped += TxtRunningServerDisplay_Tapped;\n\n        this.WhenActivated(disposables =>\n        {\n            //status bar\n            this.OneWayBind(ViewModel, vm => vm.InboundDisplay, v => v.txtInboundDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.InboundLanDisplay, v => v.txtInboundLanDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.RunningServerDisplay, v => v.txtRunningServerDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.RunningInfoDisplay, v => v.txtRunningInfoDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.SpeedProxyDisplay, v => v.txtSpeedProxyDisplay.Text).DisposeWith(disposables);\n            this.OneWayBind(ViewModel, vm => vm.SpeedDirectDisplay, v => v.txtSpeedDirectDisplay.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.EnableTun, v => v.togEnableTun.IsChecked).DisposeWith(disposables);\n\n            this.Bind(ViewModel, vm => vm.SystemProxySelected, v => v.cmbSystemProxy.SelectedIndex).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedRouting, v => v.cmbRoutings2.SelectedItem).DisposeWith(disposables);\n        });\n\n        //spEnableTun.IsVisible = (Utils.IsWindows() || AppHandler.Instance.IsAdministrator);\n\n        if (Utils.IsNonWindows() && cmbSystemProxy.Items.IsReadOnly == false)\n        {\n            cmbSystemProxy.Items.RemoveAt(cmbSystemProxy.Items.Count - 1);\n        }\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.DispatcherRefreshIcon:\n                Dispatcher.UIThread.Post(() =>\n                {\n                    RefreshIcon();\n                },\n                DispatcherPriority.Default);\n                break;\n\n            case EViewAction.SetClipboardData:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                await AvaUtils.SetClipboardData(this, (string)obj);\n                break;\n\n            case EViewAction.PasswordInput:\n                return await PasswordInputAsync();\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void RefreshIcon()\n    {\n        if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)\n        {\n            desktop.MainWindow.Icon = AvaUtils.GetAppIcon(_config.SystemProxyItem.SysProxyType);\n            var iconslist = TrayIcon.GetIcons(Application.Current);\n            iconslist[0].Icon = desktop.MainWindow.Icon;\n            TrayIcon.SetIcons(Application.Current, iconslist);\n        }\n    }\n\n    private async Task<bool> PasswordInputAsync()\n    {\n        var dialog = new SudoPasswordInputView();\n        var obj = await DialogHost.Show(dialog);\n\n        var password = obj?.ToString();\n        if (password.IsNullOrEmpty())\n        {\n            togEnableTun.IsChecked = false;\n            return false;\n        }\n\n        AppManager.Instance.LinuxSudoPwd = password;\n        return true;\n    }\n\n    private void TxtRunningServerDisplay_Tapped(object? sender, Avalonia.Input.TappedEventArgs e)\n    {\n        ViewModel?.TestServerAvailability();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/SubEditWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.SubEditWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuSubSetting}\"\n    Width=\"700\"\n    Height=\"600\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n        <StackPanel\n            Margin=\"{StaticResource Margin4}\"\n            HorizontalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Orientation=\"Horizontal\">\n            <Button\n                x:Name=\"btnSave\"\n                Width=\"100\"\n                Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                IsDefault=\"True\" />\n            <Button\n                x:Name=\"btnCancel\"\n                Width=\"100\"\n                Margin=\"{StaticResource MarginLr8}\"\n                Content=\"{x:Static resx:ResUI.TbCancel}\"\n                IsCancel=\"True\" />\n        </StackPanel>\n        <ScrollViewer HorizontalScrollBarVisibility=\"Auto\" VerticalScrollBarVisibility=\"Auto\">\n\n            <Grid ColumnDefinitions=\"Auto,400,Auto\" RowDefinitions=\"Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto,Auto\">\n\n                <TextBlock\n                    Grid.Row=\"0\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Text=\"{x:Static resx:ResUI.menuSubscription}\" />\n\n                <TextBlock\n                    Grid.Row=\"1\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvRemarks}\" />\n\n                <TextBox\n                    x:Name=\"txtRemarks\"\n                    Grid.Row=\"1\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    TextWrapping=\"Wrap\" />\n\n                <TextBlock\n                    Grid.Row=\"2\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvUrl}\" />\n                <TextBox\n                    x:Name=\"txtUrl\"\n                    Grid.Row=\"2\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    TextWrapping=\"Wrap\"\n                    Watermark=\"{x:Static resx:ResUI.SubUrlTips}\" />\n                <Button\n                    Grid.Row=\"2\"\n                    Grid.Column=\"2\"\n                    Classes=\"IconButton\"\n                    HorizontalAlignment=\"Left\"\n                    Margin=\"{StaticResource MarginLr8}\">\n                    <Button.Content>\n                        <PathIcon Data=\"{StaticResource SemiIconMore}\" >\n                            <PathIcon.RenderTransform>\n                                <RotateTransform Angle=\"90\" />\n                            </PathIcon.RenderTransform>\n                        </PathIcon>\n                    </Button.Content>\n                    <Button.Flyout>\n                        <Flyout>\n                            <StackPanel>\n                                <TextBlock\n                                    Margin=\"{StaticResource Margin4}\"\n                                    VerticalAlignment=\"Center\"\n                                    Text=\"{x:Static resx:ResUI.LvMoreUrl}\" />\n                                <TextBox\n                                    x:Name=\"txtMoreUrl\"\n                                    Width=\"400\"\n                                    MinHeight=\"100\"\n                                    Margin=\"{StaticResource Margin4}\"\n                                    HorizontalAlignment=\"Stretch\"\n                                    VerticalAlignment=\"Center\"\n                                    Classes=\"TextArea\"\n                                    MinLines=\"4\"\n                                    TextWrapping=\"Wrap\"\n                                    Watermark=\"{x:Static resx:ResUI.SubUrlTips}\" />\n                            </StackPanel>\n                        </Flyout>\n                    </Button.Flyout>\n                </Button>\n\n                <TextBlock\n                    Grid.Row=\"3\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvEnabled}\" />\n\n                <DockPanel\n                    Grid.Row=\"3\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\">\n                    <ToggleSwitch\n                        x:Name=\"togEnable\"\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Center\"\n                        DockPanel.Dock=\"Left\" />\n\n                    <TextBox\n                        x:Name=\"txtAutoUpdateInterval\"\n                        Width=\"100\"\n                        Margin=\"{StaticResource Margin4}\"\n                        VerticalAlignment=\"Center\"\n                        DockPanel.Dock=\"Right\"\n                        Watermark=\"{x:Static resx:ResUI.SubUrlTips}\" />\n\n                    <TextBlock\n                        Margin=\"{StaticResource Margin4}\"\n                        HorizontalAlignment=\"Center\"\n                        VerticalAlignment=\"Center\"\n                        Text=\"{x:Static resx:ResUI.LvAutoUpdateInterval}\" />\n                </DockPanel>\n\n                <TextBlock\n                    Grid.Row=\"5\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvFilter}\" />\n                <TextBox\n                    x:Name=\"txtFilter\"\n                    Grid.Row=\"5\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Watermark=\"{x:Static resx:ResUI.SubUrlTips}\" />\n\n                <TextBlock\n                    Grid.Row=\"6\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvConvertTarget}\" />\n                <ComboBox\n                    x:Name=\"cmbConvertTarget\"\n                    Grid.Row=\"6\"\n                    Grid.Column=\"1\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.LvConvertTargetTip}\" />\n\n                <TextBlock\n                    Grid.Row=\"7\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvUserAgent}\" />\n                <TextBox\n                    x:Name=\"txtUserAgent\"\n                    Grid.Row=\"7\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    TextWrapping=\"Wrap\"\n                    Watermark=\"{x:Static resx:ResUI.SubUrlTips}\" />\n\n                <TextBlock\n                    Grid.Row=\"8\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvSort}\" />\n                <TextBox\n                    x:Name=\"txtSort\"\n                    Grid.Row=\"8\"\n                    Grid.Column=\"1\"\n                    Width=\"100\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\" />\n\n                <TextBlock\n                    Grid.Row=\"9\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvPrevProfile}\" />\n                <TextBox\n                    x:Name=\"txtPrevProfile\"\n                    Grid.Row=\"9\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Watermark=\"{x:Static resx:ResUI.LvPrevProfileTip}\" />\n                <Button\n                    Grid.Row=\"9\"\n                    Grid.Column=\"2\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Click=\"BtnSelectPrevProfile_Click\"\n                    Content=\"{x:Static resx:ResUI.TbSelectProfile}\" />\n\n                <TextBlock\n                    Grid.Row=\"10\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvNextProfile}\" />\n                <TextBox\n                    x:Name=\"txtNextProfile\"\n                    Grid.Row=\"10\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Watermark=\"{x:Static resx:ResUI.LvPrevProfileTip}\" />\n                <Button\n                    Grid.Row=\"10\"\n                    Grid.Column=\"2\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Click=\"BtnSelectNextProfile_Click\"\n                    Content=\"{x:Static resx:ResUI.TbSelectProfile}\" />\n\n                <TextBlock\n                    Grid.Row=\"11\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbPreSocksPort4Sub}\" />\n                <TextBox\n                    x:Name=\"txtPreSocksPort\"\n                    Grid.Row=\"11\"\n                    Grid.Column=\"1\"\n                    Width=\"200\"\n                    Margin=\"{StaticResource Margin4}\"\n                    HorizontalAlignment=\"Left\"\n                    ToolTip.Tip=\"{x:Static resx:ResUI.TipPreSocksPort}\"\n                    Watermark=\"{x:Static resx:ResUI.TipPreSocksPort}\" />\n\n                <TextBlock\n                    Grid.Row=\"12\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.LvMemo}\" />\n                <TextBox\n                    x:Name=\"txtMemo\"\n                    Grid.Row=\"12\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    TextWrapping=\"Wrap\" />\n\n            </Grid>\n        </ScrollViewer>\n    </DockPanel>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/SubEditWindow.axaml.cs",
    "content": "using v2rayN.Desktop.Base;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class SubEditWindow : WindowBase<SubEditViewModel>\n{\n    public SubEditWindow()\n    {\n        InitializeComponent();\n    }\n\n    public SubEditWindow(SubItem subItem)\n    {\n        InitializeComponent();\n\n        Loaded += Window_Loaded;\n        btnCancel.Click += (s, e) => Close();\n\n        ViewModel = new SubEditViewModel(subItem, UpdateViewHandler);\n\n        cmbConvertTarget.ItemsSource = Global.SubConvertTargets;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.SelectedSource.Remarks, v => v.txtRemarks.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Url, v => v.txtUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.MoreUrl, v => v.txtMoreUrl.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Enabled, v => v.togEnable.IsChecked).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.AutoUpdateInterval, v => v.txtAutoUpdateInterval.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.UserAgent, v => v.txtUserAgent.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Sort, v => v.txtSort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Filter, v => v.txtFilter.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.ConvertTarget, v => v.cmbConvertTarget.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PrevProfile, v => v.txtPrevProfile.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.NextProfile, v => v.txtNextProfile.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.PreSocksPort, v => v.txtPreSocksPort.Text).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource.Memo, v => v.txtMemo.Text).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SaveCmd, v => v.btnSave).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close(true);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        txtRemarks.Focus();\n    }\n\n    private async void BtnSelectPrevProfile_Click(object? sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter([EConfigType.Custom], exclude: true);\n        var result = await selectWindow.ShowDialog<bool?>(this);\n        if (result == true)\n        {\n            var profile = await selectWindow.ProfileItem;\n            if (profile != null)\n            {\n                txtPrevProfile.Text = profile.Remarks;\n            }\n        }\n    }\n\n    private async void BtnSelectNextProfile_Click(object? sender, RoutedEventArgs e)\n    {\n        var selectWindow = new ProfilesSelectWindow();\n        selectWindow.SetConfigTypeFilter([EConfigType.Custom], exclude: true);\n        var result = await selectWindow.ShowDialog<bool?>(this);\n        if (result == true)\n        {\n            var profile = await selectWindow.ProfileItem;\n            if (profile != null)\n            {\n                txtNextProfile.Text = profile.Remarks;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/SubSettingWindow.axaml",
    "content": "<Window\n    x:Class=\"v2rayN.Desktop.Views.SubSettingWindow\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:dialogHost=\"clr-namespace:DialogHostAvalonia;assembly=DialogHost.Avalonia\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib\"\n    Title=\"{x:Static resx:ResUI.menuSubSetting}\"\n    Width=\"900\"\n    Height=\"600\"\n    x:DataType=\"vms:SubSettingViewModel\"\n    ShowInTaskbar=\"False\"\n    WindowStartupLocation=\"CenterScreen\"\n    mc:Ignorable=\"d\">\n    <dialogHost:DialogHost\n        Background=\"Gray\"\n        CloseOnClickAway=\"True\"\n        DisableOpeningAnimation=\"True\"\n        Identifier=\"dialogHostSub\">\n        <DockPanel Margin=\"{StaticResource Margin8}\">\n            <Menu Margin=\"{StaticResource Margin4}\" DockPanel.Dock=\"Top\">\n                <MenuItem x:Name=\"menuSubAdd\" Header=\"{x:Static resx:ResUI.menuSubAdd}\" />\n                <MenuItem x:Name=\"menuSubDelete\" Header=\"{x:Static resx:ResUI.menuSubDelete}\" />\n                <MenuItem x:Name=\"menuSubEdit\" Header=\"{x:Static resx:ResUI.menuSubEdit}\" />\n                <MenuItem x:Name=\"menuSubShare\" Header=\"{x:Static resx:ResUI.menuSubShare}\" />\n                <MenuItem x:Name=\"menuClose\" Header=\"{x:Static resx:ResUI.menuClose}\" />\n            </Menu>\n\n            <DataGrid\n                x:Name=\"lstSubscription\"\n                AutoGenerateColumns=\"False\"\n                BorderThickness=\"1\"\n                CanUserResizeColumns=\"True\"\n                GridLinesVisibility=\"All\"\n                HeadersVisibility=\"Column\"\n                IsReadOnly=\"True\"\n                ItemsSource=\"{Binding SubItems}\">\n                <DataGrid.KeyBindings>\n                    <KeyBinding Command=\"{Binding SubDeleteCmd}\" Gesture=\"Delete\" />\n                </DataGrid.KeyBindings>\n                <DataGrid.ContextMenu>\n                    <ContextMenu>\n                        <MenuItem x:Name=\"menuSubAdd2\" Header=\"{x:Static resx:ResUI.menuSubAdd}\" />\n                        <MenuItem x:Name=\"menuSubDelete2\" Header=\"{x:Static resx:ResUI.menuSubDelete}\" />\n                        <MenuItem x:Name=\"menuSubEdit2\" Header=\"{x:Static resx:ResUI.menuSubEdit}\" />\n                        <MenuItem x:Name=\"menuSubShare2\" Header=\"{x:Static resx:ResUI.menuSubShare}\" />\n                    </ContextMenu>\n                </DataGrid.ContextMenu>\n                <DataGrid.Columns>\n                    <DataGridTextColumn\n                        Width=\"*\"\n                        Binding=\"{Binding Remarks}\"\n                        Header=\"{x:Static resx:ResUI.LvRemarks}\" />\n                    <DataGridTextColumn\n                        Width=\"*\"\n                        Binding=\"{Binding Url}\"\n                        Header=\"{x:Static resx:ResUI.LvUrl}\" />\n                    <DataGridCheckBoxColumn\n                        Width=\"100\"\n                        Binding=\"{Binding Enabled}\"\n                        Header=\"{x:Static resx:ResUI.LvEnabled}\" />\n                    <DataGridTextColumn\n                        Width=\"150\"\n                        Binding=\"{Binding AutoUpdateInterval}\"\n                        Header=\"{x:Static resx:ResUI.LvAutoUpdateInterval}\" />\n                    <DataGridTextColumn\n                        Width=\"150\"\n                        Binding=\"{Binding UserAgent}\"\n                        Header=\"{x:Static resx:ResUI.LvUserAgent}\" />\n                    <DataGridTextColumn\n                        Width=\"80\"\n                        Binding=\"{Binding Sort}\"\n                        Header=\"{x:Static resx:ResUI.LvSort}\" />\n                </DataGrid.Columns>\n            </DataGrid>\n        </DockPanel>\n    </dialogHost:DialogHost>\n</Window>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/SubSettingWindow.axaml.cs",
    "content": "using DialogHostAvalonia;\nusing v2rayN.Desktop.Base;\nusing v2rayN.Desktop.Common;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class SubSettingWindow : WindowBase<SubSettingViewModel>\n{\n    private bool _manualClose = false;\n\n    public SubSettingWindow()\n    {\n        InitializeComponent();\n\n        menuClose.Click += menuClose_Click;\n        Loaded += Window_Loaded;\n        Closing += SubSettingWindow_Closing;\n        KeyDown += SubSettingWindow_KeyDown;\n        ViewModel = new SubSettingViewModel(UpdateViewHandler);\n        lstSubscription.DoubleTapped += LstSubscription_DoubleTapped;\n        lstSubscription.SelectionChanged += LstSubscription_SelectionChanged;\n\n        this.WhenActivated(disposables =>\n        {\n            this.OneWayBind(ViewModel, vm => vm.SubItems, v => v.lstSubscription.ItemsSource).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.SelectedSource, v => v.lstSubscription.SelectedItem).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SubAddCmd, v => v.menuSubAdd).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubDeleteCmd, v => v.menuSubDelete).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubEditCmd, v => v.menuSubEdit).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubShareCmd, v => v.menuSubShare).DisposeWith(disposables);\n\n            this.BindCommand(ViewModel, vm => vm.SubAddCmd, v => v.menuSubAdd2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubDeleteCmd, v => v.menuSubDelete2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubEditCmd, v => v.menuSubEdit2).DisposeWith(disposables);\n            this.BindCommand(ViewModel, vm => vm.SubShareCmd, v => v.menuSubShare2).DisposeWith(disposables);\n        });\n    }\n\n    private async Task<bool> UpdateViewHandler(EViewAction action, object? obj)\n    {\n        switch (action)\n        {\n            case EViewAction.CloseWindow:\n                Close();\n                break;\n\n            case EViewAction.ShowYesNo:\n                if (await UI.ShowYesNo(this, ResUI.RemoveServer) != ButtonResult.Yes)\n                {\n                    return false;\n                }\n                break;\n\n            case EViewAction.SubEditWindow:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                var window = new SubEditWindow((SubItem)obj);\n                await window.ShowDialog(this);\n                break;\n\n            case EViewAction.ShareSub:\n                if (obj is null)\n                {\n                    return false;\n                }\n\n                await ShareSub((string)obj);\n                break;\n        }\n        return await Task.FromResult(true);\n    }\n\n    private async Task ShareSub(string url)\n    {\n        if (url.IsNullOrEmpty())\n        {\n            return;\n        }\n        var dialog = new QrcodeView(url);\n        await DialogHost.Show(dialog, \"dialogHostSub\");\n    }\n\n    private void LstSubscription_DoubleTapped(object? sender, Avalonia.Input.TappedEventArgs e)\n    {\n        ViewModel?.EditSubAsync(false);\n    }\n\n    private void LstSubscription_SelectionChanged(object? sender, SelectionChangedEventArgs e)\n    {\n        if (ViewModel != null)\n        {\n            ViewModel.SelectedSources = lstSubscription.SelectedItems.Cast<SubItem>().ToList();\n        }\n    }\n\n    private void menuClose_Click(object? sender, RoutedEventArgs e)\n    {\n        _manualClose = true;\n        Close(ViewModel?.IsModified);\n    }\n\n    private void SubSettingWindow_Closing(object? sender, WindowClosingEventArgs e)\n    {\n        if (ViewModel?.IsModified == true)\n        {\n            if (!_manualClose)\n            {\n                menuClose_Click(null, null);\n            }\n        }\n    }\n\n    private void SubSettingWindow_KeyDown(object? sender, KeyEventArgs e)\n    {\n        if (e.Key == Key.Escape)\n        {\n            menuClose_Click(null, null);\n        }\n    }\n\n    private void Window_Loaded(object? sender, RoutedEventArgs e)\n    {\n        lstSubscription.Focus();\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/SudoPasswordInputView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.SudoPasswordInputView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    d:DesignHeight=\"200\"\n    d:DesignWidth=\"400\"\n    mc:Ignorable=\"d\">\n    <DockPanel Margin=\"{StaticResource Margin8}\">\n\n        <Border\n            Margin=\"{StaticResource Margin4}\"\n            VerticalAlignment=\"Center\"\n            DockPanel.Dock=\"Bottom\"\n            Theme=\"{DynamicResource CardBorder}\">\n\n            <StackPanel\n                Margin=\"{StaticResource Margin4}\"\n                HorizontalAlignment=\"Center\"\n                Orientation=\"Horizontal\">\n                <Button\n                    x:Name=\"btnSave\"\n                    Width=\"100\"\n                    Content=\"{x:Static resx:ResUI.TbConfirm}\"\n                    IsDefault=\"True\" />\n                <Button\n                    x:Name=\"btnCancel\"\n                    Width=\"100\"\n                    Margin=\"{StaticResource MarginLr8}\"\n                    Content=\"{x:Static resx:ResUI.TbCancel}\"\n                    IsCancel=\"True\" />\n            </StackPanel>\n        </Border>\n\n        <Border\n            Margin=\"{StaticResource Margin4}\"\n            VerticalAlignment=\"Center\"\n            Theme=\"{DynamicResource CardBorder}\">\n\n            <Grid ColumnDefinitions=\"Auto,400\" RowDefinitions=\"Auto,Auto,Auto\">\n                <TextBlock\n                    Grid.Row=\"1\"\n                    Grid.Column=\"0\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbSettingsLinuxSudoPassword}\" />\n\n                <TextBox\n                    x:Name=\"txtPassword\"\n                    Grid.Row=\"1\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    Classes=\"revealPasswordButton\"\n                    Focusable=\"True\" />\n\n                <TextBlock\n                    Grid.Row=\"2\"\n                    Grid.Column=\"1\"\n                    Margin=\"{StaticResource Margin4}\"\n                    VerticalAlignment=\"Center\"\n                    Text=\"{x:Static resx:ResUI.TbSettingsLinuxSudoPasswordTip}\"\n                    TextWrapping=\"Wrap\" />\n            </Grid>\n        </Border>\n    </DockPanel>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/SudoPasswordInputView.axaml.cs",
    "content": "using CliWrap.Buffered;\nusing DialogHostAvalonia;\n\nnamespace v2rayN.Desktop.Views;\n\npublic partial class SudoPasswordInputView : UserControl\n{\n    public SudoPasswordInputView()\n    {\n        InitializeComponent();\n\n        Loaded += (s, e) => txtPassword.Focus();\n\n        btnSave.Click += async (_, _) => await SavePasswordAsync();\n\n        btnCancel.Click += (_, _) =>\n        {\n            DialogHost.Close(null);\n        };\n    }\n\n    private async Task SavePasswordAsync()\n    {\n        if (txtPassword.Text.IsNullOrEmpty())\n        {\n            txtPassword.Focus();\n            return;\n        }\n\n        var password = txtPassword.Text;\n        btnSave.IsEnabled = false;\n\n        try\n        {\n            // Verify if the password is correct\n            if (await CheckSudoPasswordAsync(password))\n            {\n                // Password verification successful, return password and close dialog\n                await Dispatcher.UIThread.InvokeAsync(() =>\n                {\n                    DialogHost.Close(null, password);\n                });\n            }\n            else\n            {\n                // Password verification failed, display error and let user try again\n                NoticeManager.Instance.Enqueue(ResUI.SudoIncorrectPasswordTip);\n                txtPassword.Focus();\n            }\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"SudoPassword\", ex);\n        }\n        finally\n        {\n            btnSave.IsEnabled = true;\n        }\n    }\n\n    private async Task<bool> CheckSudoPasswordAsync(string password)\n    {\n        try\n        {\n            // Use sudo echo command to verify password\n            var arg = new List<string>() { \"-c\", \"sudo -S echo SUDO_CHECK\" };\n            var result = await CliWrap.Cli.Wrap(Global.LinuxBash)\n                .WithArguments(arg)\n                .WithStandardInputPipe(CliWrap.PipeSource.FromString(password))\n                .ExecuteBufferedAsync();\n\n            return result.ExitCode == 0;\n        }\n        catch (Exception ex)\n        {\n            Logging.SaveLog(\"CheckSudoPassword\", ex);\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ThemeSettingView.axaml",
    "content": "<UserControl\n    x:Class=\"v2rayN.Desktop.Views.ThemeSettingView\"\n    xmlns=\"https://github.com/avaloniaui\"\n    xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"\n    xmlns:d=\"http://schemas.microsoft.com/expression/blend/2008\"\n    xmlns:mc=\"http://schemas.openxmlformats.org/markup-compatibility/2006\"\n    xmlns:resx=\"clr-namespace:ServiceLib.Resx;assembly=ServiceLib\"\n    xmlns:vms=\"clr-namespace:v2rayN.Desktop.ViewModels\"\n    d:DesignHeight=\"450\"\n    d:DesignWidth=\"800\"\n    x:DataType=\"vms:ThemeSettingViewModel\"\n    mc:Ignorable=\"d\">\n    <UserControl.Styles>\n        <Style Selector=\"TextBlock\">\n            <Setter Property=\"Width\" Value=\"100\" />\n        </Style>\n        <Style Selector=\"ComboBox\">\n            <Setter Property=\"Width\" Value=\"130\" />\n        </Style>\n    </UserControl.Styles>\n\n    <Button Margin=\"{StaticResource MarginLr8}\" Classes=\"IconButton\">\n        <Button.Content>\n            <PathIcon Data=\"{StaticResource SemiIconMore}\">\n                <PathIcon.RenderTransform>\n                    <RotateTransform Angle=\"90\" />\n                </PathIcon.RenderTransform>\n            </PathIcon>\n        </Button.Content>\n        <Button.Flyout>\n            <Flyout>\n                <StackPanel Margin=\"{StaticResource MarginTb8}\">\n                    <StackPanel Orientation=\"Horizontal\">\n                        <TextBlock\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsTheme}\" />\n                        <ComboBox\n                            x:Name=\"cmbCurrentTheme\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Center\" />\n                    </StackPanel>\n                    <StackPanel Orientation=\"Horizontal\">\n                        <TextBlock\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsFontSize}\" />\n                        <ComboBox\n                            x:Name=\"cmbCurrentFontSize\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Center\" />\n                    </StackPanel>\n                    <StackPanel Orientation=\"Horizontal\">\n                        <TextBlock\n                            Margin=\"{StaticResource Margin4}\"\n                            VerticalAlignment=\"Center\"\n                            Text=\"{x:Static resx:ResUI.TbSettingsLanguage}\" />\n                        <ComboBox\n                            x:Name=\"cmbCurrentLanguage\"\n                            Margin=\"{StaticResource Margin4}\"\n                            HorizontalAlignment=\"Center\" />\n                    </StackPanel>\n                </StackPanel>\n            </Flyout>\n        </Button.Flyout>\n    </Button>\n</UserControl>\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/Views/ThemeSettingView.axaml.cs",
    "content": "using v2rayN.Desktop.ViewModels;\n\nnamespace v2rayN.Desktop.Views;\n\n/// <summary>\n/// ThemeSettingView.xaml\n/// </summary>\npublic partial class ThemeSettingView : ReactiveUserControl<ThemeSettingViewModel>\n{\n    public ThemeSettingView()\n    {\n        InitializeComponent();\n        ViewModel = new ThemeSettingViewModel();\n\n        cmbCurrentTheme.ItemsSource = Utils.GetEnumNames<ETheme>();\n        cmbCurrentFontSize.ItemsSource = Enumerable.Range(Global.MinFontSize, Global.MinFontSizeCount).ToList();\n        cmbCurrentLanguage.ItemsSource = Global.Languages;\n\n        this.WhenActivated(disposables =>\n        {\n            this.Bind(ViewModel, vm => vm.CurrentTheme, v => v.cmbCurrentTheme.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CurrentFontSize, v => v.cmbCurrentFontSize.SelectedValue).DisposeWith(disposables);\n            this.Bind(ViewModel, vm => vm.CurrentLanguage, v => v.cmbCurrentLanguage.SelectedValue).DisposeWith(disposables);\n        });\n    }\n}\n"
  },
  {
    "path": "v2rayN/v2rayN.Desktop/v2rayN.Desktop.csproj",
    "content": "﻿<Project Sdk=\"Microsoft.NET.Sdk\">\n\n\t<PropertyGroup>\n\t\t<OutputType>WinExe</OutputType>\n\t\t<ApplicationIcon>Assets\\v2rayN.ico</ApplicationIcon>\n\t\t<BuiltInComInteropSupport>true</BuiltInComInteropSupport>\n\t\t<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>\n\t\t<AssemblyName>v2rayN</AssemblyName>\n\t</PropertyGroup>\n\n\t<ItemGroup>\n\t\t<PackageReference Include=\"Avalonia.AvaloniaEdit\" />\n\t\t<PackageReference Include=\"Avalonia.Controls.DataGrid\">\n\t\t\t<TreatAsUsed>true</TreatAsUsed>\n\t\t</PackageReference>\n\t\t<PackageReference Include=\"Avalonia.Desktop\" />\n\t\t<PackageReference Condition=\"'$(Configuration)' == 'Debug'\" Include=\"Avalonia.Diagnostics\" />\n\t\t<PackageReference Include=\"ReactiveUI.Avalonia\" />\n\t\t<PackageReference Include=\"MessageBox.Avalonia\" />\n\t\t<PackageReference Include=\"Semi.Avalonia\" />\n\t\t<PackageReference Include=\"Semi.Avalonia.AvaloniaEdit\" />\n\t\t<PackageReference Include=\"Semi.Avalonia.DataGrid\">\n\t\t\t<TreatAsUsed>true</TreatAsUsed>\n\t\t</PackageReference>\n\t\t<PackageReference Include=\"ReactiveUI\">\n\t\t\t<TreatAsUsed>true</TreatAsUsed>\n\t\t</PackageReference>\n\t\t<PackageReference Include=\"ReactiveUI.Fody\">\n\t\t\t<TreatAsUsed>true</TreatAsUsed>\n\t\t</PackageReference>\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<ProjectCapability Include=\"Avalonia\" />\n\t\t<AvaloniaResource Include=\"Assets\\**\" />\n\t\t<ProjectReference Include=\"..\\GlobalHotKeys\\src\\GlobalHotKeys\\GlobalHotKeys.csproj\" />\n\t\t<ProjectReference Include=\"..\\ServiceLib\\ServiceLib.csproj\" />\n\t</ItemGroup>\n\n\t<ItemGroup>\n\t\t<EmbeddedResource Include=\"Assets\\v2rayN.ico\">\n\t\t\t<CopyToOutputDirectory>Never</CopyToOutputDirectory>\n\t\t</EmbeddedResource>\n\t\t<Compile Update=\"Views\\FullConfigTemplateWindow.axaml.cs\">\n\t\t  <DependentUpon>FullConfigTemplateWindow.axaml</DependentUpon>\n\t\t</Compile>\n\t\t<None Update=\"v2rayN.png\">\n\t\t\t<CopyToOutputDirectory>Always</CopyToOutputDirectory>\n\t\t</None>\n\t\t<None Update=\"v2rayN.icns\">\n\t\t\t<CopyToOutputDirectory>Always</CopyToOutputDirectory>\n\t\t</None>\n\t</ItemGroup>\n\n</Project>"
  },
  {
    "path": "v2rayN/v2rayN.sln",
    "content": "﻿\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio Version 17\nVisualStudioVersion = 17.3.32811.315\nMinimumVisualStudioVersion = 10.0.40219.1\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"v2rayN\", \"v2rayN\\v2rayN.csproj\", \"{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"ServiceLib\", \"ServiceLib\\ServiceLib.csproj\", \"{1B6456C4-FFAA-4298-80F6-7B689A6E9243}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"v2rayN.Desktop\", \"v2rayN.Desktop\\v2rayN.Desktop.csproj\", \"{5D16541A-F971-4C17-9315-BB8955E3F984}\"\nEndProject\nProject(\"{9A19103F-16F7-4668-BE54-9A1E7A4F7556}\") = \"AmazTool\", \"AmazTool\\AmazTool.csproj\", \"{47D68B1C-601C-4C69-873B-FFF0DC13EC97}\"\nEndProject\nProject(\"{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\") = \"GlobalHotKeys\", \"GlobalHotKeys\\src\\GlobalHotKeys\\GlobalHotKeys.csproj\", \"{CB3DE54F-3A26-AE02-1299-311132C32156}\"\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"Solution Files\", \"Solution Files\", \"{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}\"\n\tProjectSection(SolutionItems) = preProject\n\t\tDirectory.Build.props = Directory.Build.props\n\t\tDirectory.Packages.props = Directory.Packages.props\n\tEndProjectSection\nEndProject\nProject(\"{2150E333-8FDC-42A3-9474-1A3956D46DE8}\") = \"GitHub Action\", \"GitHub Action\", \"{1EACFDC8-ADD8-4F29-AF60-92AA55D59908}\"\n\tProjectSection(SolutionItems) = preProject\n\t\t..\\.github\\workflows\\build-all.yml = ..\\.github\\workflows\\build-all.yml\n\t\t..\\.github\\workflows\\build-linux.yml = ..\\.github\\workflows\\build-linux.yml\n\t\t..\\.github\\workflows\\build-osx.yml = ..\\.github\\workflows\\build-osx.yml\n\t\t..\\.github\\workflows\\build-windows-desktop.yml = ..\\.github\\workflows\\build-windows-desktop.yml\n\t\t..\\.github\\workflows\\build-windows.yml = ..\\.github\\workflows\\build-windows.yml\n\t\t..\\package-debian.sh = ..\\package-debian.sh\n\t\t..\\package-osx.sh = ..\\package-osx.sh\n\t\t..\\package-release-zip.sh = ..\\package-release-zip.sh\n\t\t..\\.github\\workflows\\winget-publish.yml = ..\\.github\\workflows\\winget-publish.yml\n\tEndProjectSection\nEndProject\nGlobal\n\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n\t\tDebug|Any CPU = Debug|Any CPU\n\t\tRelease|Any CPU = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n\t\t{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{1B6456C4-FFAA-4298-80F6-7B689A6E9243}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{1B6456C4-FFAA-4298-80F6-7B689A6E9243}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{1B6456C4-FFAA-4298-80F6-7B689A6E9243}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{1B6456C4-FFAA-4298-80F6-7B689A6E9243}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{5D16541A-F971-4C17-9315-BB8955E3F984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{5D16541A-F971-4C17-9315-BB8955E3F984}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{5D16541A-F971-4C17-9315-BB8955E3F984}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{5D16541A-F971-4C17-9315-BB8955E3F984}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{47D68B1C-601C-4C69-873B-FFF0DC13EC97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{47D68B1C-601C-4C69-873B-FFF0DC13EC97}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{47D68B1C-601C-4C69-873B-FFF0DC13EC97}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{47D68B1C-601C-4C69-873B-FFF0DC13EC97}.Release|Any CPU.Build.0 = Release|Any CPU\n\t\t{CB3DE54F-3A26-AE02-1299-311132C32156}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\n\t\t{CB3DE54F-3A26-AE02-1299-311132C32156}.Debug|Any CPU.Build.0 = Debug|Any CPU\n\t\t{CB3DE54F-3A26-AE02-1299-311132C32156}.Release|Any CPU.ActiveCfg = Release|Any CPU\n\t\t{CB3DE54F-3A26-AE02-1299-311132C32156}.Release|Any CPU.Build.0 = Release|Any CPU\n\tEndGlobalSection\n\tGlobalSection(SolutionProperties) = preSolution\n\t\tHideSolutionNode = FALSE\n\tEndGlobalSection\n\tGlobalSection(ExtensibilityGlobals) = postSolution\n\t\tSolutionGuid = {43E06CBD-3DA9-40A3-8E4D-F0943CB0DD32}\n\tEndGlobalSection\nEndGlobal\n"
  },
  {
    "path": "v2rayN/v2rayN.slnx",
    "content": "<Solution>\n  <Folder Name=\"/GitHub Action/\">\n    <File Path=\"../.github/workflows/build-all.yml\" />\n    <File Path=\"../.github/workflows/build-linux.yml\" />\n    <File Path=\"../.github/workflows/build-osx.yml\" />\n    <File Path=\"../.github/workflows/build-windows-desktop.yml\" />\n    <File Path=\"../.github/workflows/build-windows.yml\" />\n    <File Path=\"../.github/workflows/winget-publish.yml\" />\n    <File Path=\"../package-debian.sh\" />\n    <File Path=\"../package-osx.sh\" />\n    <File Path=\"../package-release-zip.sh\" />\n  </Folder>\n  <Folder Name=\"/Solution Files/\">\n    <File Path=\"Directory.Build.props\" />\n    <File Path=\"Directory.Packages.props\" />\n  </Folder>\n  <Project Path=\"AmazTool/AmazTool.csproj\" />\n  <Project Path=\"GlobalHotKeys/src/GlobalHotKeys/GlobalHotKeys.csproj\" />\n  <Project Path=\"ServiceLib/ServiceLib.csproj\" />\n  <Project Path=\"v2rayN.Desktop/v2rayN.Desktop.csproj\" />\n  <Project Path=\"v2rayN/v2rayN.csproj\" />\n</Solution>\n"
  }
]