├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_request.yml ├── config.yaml ├── dependabot.yml └── workflows │ ├── build_pull_request.yml │ ├── open_pull_request.yml │ ├── release.yml │ ├── sync_crowdin.yml │ └── update_documentation.yml ├── .gitignore ├── .metadata ├── .releaserc ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── analysis_options.yaml ├── android ├── .gitignore ├── app │ ├── build.gradle.kts │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── jniLibs │ │ │ ├── arm64-v8a │ │ │ │ └── libaapt2.so │ │ │ ├── armeabi-v7a │ │ │ │ └── libaapt2.so │ │ │ ├── x86 │ │ │ │ └── libaapt2.so │ │ │ └── x86_64 │ │ │ │ └── libaapt2.so │ │ ├── kotlin │ │ │ └── app │ │ │ │ └── revanced │ │ │ │ └── manager │ │ │ │ └── flutter │ │ │ │ ├── ExportSettingsActivity.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ └── utils │ │ │ │ ├── Aapt.kt │ │ │ │ └── packageInstaller │ │ │ │ ├── InstallerReceiver.kt │ │ │ │ └── UninstallerReceiver.kt │ │ └── res │ │ │ ├── drawable-v21 │ │ │ └── launch_background.xml │ │ │ ├── drawable │ │ │ ├── ic_launcher_foreground.xml │ │ │ ├── ic_launcher_round.png │ │ │ ├── ic_notification.png │ │ │ └── launch_background.xml │ │ │ ├── mipmap-anydpi-v26 │ │ │ └── ic_launcher.xml │ │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ │ ├── raw │ │ │ └── revanced_manager_keep.xml │ │ │ ├── values-night-v31 │ │ │ └── styles.xml │ │ │ ├── values-night │ │ │ └── styles.xml │ │ │ ├── values-v31 │ │ │ └── styles.xml │ │ │ ├── values │ │ │ ├── ic_launcher_background.xml │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── file_paths.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle.kts ├── gradle.properties ├── gradle │ ├── libs.versions.toml │ └── wrapper │ │ └── gradle-wrapper.properties └── settings.gradle.kts ├── assets ├── i18n │ ├── ar_SA.i18n.json │ ├── as_IN.i18n.json │ ├── az_AZ.i18n.json │ ├── be_BY.i18n.json │ ├── bg_BG.i18n.json │ ├── bn_BD.i18n.json │ ├── ca_ES.i18n.json │ ├── cs_CZ.i18n.json │ ├── da_DK.i18n.json │ ├── de_DE.i18n.json │ ├── el_GR.i18n.json │ ├── en.i18n.json │ ├── es_AR.i18n.json │ ├── es_ES.i18n.json │ ├── es_MX.i18n.json │ ├── et_EE.i18n.json │ ├── fa_IR.i18n.json │ ├── fi_FI.i18n.json │ ├── fil_PH.i18n.json │ ├── fr_FR.i18n.json │ ├── ga_IE.i18n.json │ ├── he_IL.i18n.json │ ├── hi_IN.i18n.json │ ├── hr_HR.i18n.json │ ├── hu_HU.i18n.json │ ├── hy_AM.i18n.json │ ├── id_ID.i18n.json │ ├── is_IS.i18n.json │ ├── it_IT.i18n.json │ ├── ja_JP.i18n.json │ ├── kk_KZ.i18n.json │ ├── km_KH.i18n.json │ ├── ko_KR.i18n.json │ ├── lt_LT.i18n.json │ ├── lv_LV.i18n.json │ ├── ms_MY.i18n.json │ ├── my_MM.i18n.json │ ├── nb_NO.i18n.json │ ├── nl_NL.i18n.json │ ├── no_NO.i18n.json │ ├── nuke.dart │ ├── or_IN.i18n.json │ ├── pl_PL.i18n.json │ ├── pt_BR.i18n.json │ ├── pt_PT.i18n.json │ ├── ro_RO.i18n.json │ ├── ru_RU.i18n.json │ ├── sk_SK.i18n.json │ ├── sl_SI.i18n.json │ ├── sq_AL.i18n.json │ ├── sr_CS.i18n.json │ ├── sr_SP.i18n.json │ ├── sv_SE.i18n.json │ ├── sw_KE.i18n.json │ ├── ta_IN.i18n.json │ ├── te_IN.i18n.json │ ├── th_TH.i18n.json │ ├── tr_TR.i18n.json │ ├── uk_UA.i18n.json │ ├── ur_PK.i18n.json │ ├── uz_UZ.i18n.json │ ├── vi_VN.i18n.json │ ├── zh_CN.i18n.json │ ├── zh_HK.i18n.json │ └── zh_TW.i18n.json ├── revanced-headline │ ├── revanced-headline-vertical-dark.svg │ └── revanced-headline-vertical-light.svg └── revanced-logo │ └── revanced-logo.svg ├── crowdin.yml ├── docs ├── 0_prerequisites.md ├── 1_installation.md ├── 2_1_patching.md ├── 2_2_managing.md ├── 2_3_updating.md ├── 2_4_settings.md ├── 2_usage.md ├── 3_troubleshooting.md ├── 4_building.md └── README.md ├── fonts └── custom-icons.ttf ├── lib ├── app │ └── app.dart ├── main.dart ├── models │ ├── patch.dart │ └── patched_application.dart ├── services │ ├── download_manager.dart │ ├── github_api.dart │ ├── manager_api.dart │ ├── patcher_api.dart │ ├── revanced_api.dart │ ├── root_api.dart │ ├── third_party_services_modules.dart │ └── toast.dart ├── theme.dart ├── ui │ ├── theme │ │ └── dynamic_theme_builder.dart │ ├── views │ │ ├── app_selector │ │ │ ├── app_selector_view.dart │ │ │ └── app_selector_viewmodel.dart │ │ ├── contributors │ │ │ ├── contributors_view.dart │ │ │ └── contributors_viewmodel.dart │ │ ├── home │ │ │ ├── home_view.dart │ │ │ └── home_viewmodel.dart │ │ ├── installer │ │ │ ├── installer_view.dart │ │ │ └── installer_viewmodel.dart │ │ ├── navigation │ │ │ ├── navigation_view.dart │ │ │ └── navigation_viewmodel.dart │ │ ├── patch_options │ │ │ ├── patch_options_view.dart │ │ │ └── patch_options_viewmodel.dart │ │ ├── patcher │ │ │ ├── patcher_view.dart │ │ │ └── patcher_viewmodel.dart │ │ ├── patches_selector │ │ │ ├── patches_selector_view.dart │ │ │ └── patches_selector_viewmodel.dart │ │ └── settings │ │ │ ├── settingsFragment │ │ │ ├── settings_manage_api_url.dart │ │ │ ├── settings_manage_keystore_password.dart │ │ │ ├── settings_manage_sources.dart │ │ │ ├── settings_update_language.dart │ │ │ └── settings_update_theme.dart │ │ │ ├── settings_view.dart │ │ │ └── settings_viewmodel.dart │ └── widgets │ │ ├── appInfoView │ │ ├── app_info_view.dart │ │ └── app_info_viewmodel.dart │ │ ├── appSelectorView │ │ ├── app_skeleton_loader.dart │ │ ├── installed_app_item.dart │ │ └── not_installed_app_item.dart │ │ ├── contributorsView │ │ └── contributors_card.dart │ │ ├── homeView │ │ ├── installed_apps_card.dart │ │ ├── last_patched_app_card.dart │ │ ├── latest_commit_card.dart │ │ └── update_confirmation_sheet.dart │ │ ├── installerView │ │ └── gradient_progress_indicator.dart │ │ ├── patcherView │ │ ├── app_selector_card.dart │ │ └── patch_selector_card.dart │ │ ├── patchesSelectorView │ │ ├── patch_item.dart │ │ └── patch_options_fields.dart │ │ ├── settingsView │ │ ├── about_widget.dart │ │ ├── settings_advanced_section.dart │ │ ├── settings_auto_update_patches.dart │ │ ├── settings_data_section.dart │ │ ├── settings_debug_section.dart │ │ ├── settings_enable_patches_selection.dart │ │ ├── settings_export_section.dart │ │ ├── settings_last_patched_app.dart │ │ ├── settings_require_suggested_app_version.dart │ │ ├── settings_section.dart │ │ ├── settings_show_update_dialog.dart │ │ ├── settings_team_section.dart │ │ ├── settings_tile_dialog.dart │ │ ├── settings_universal_patches.dart │ │ ├── settings_use_alternative_sources.dart │ │ ├── settings_version_compatibility_check.dart │ │ ├── social_media_item.dart │ │ └── social_media_widget.dart │ │ └── shared │ │ ├── application_item.dart │ │ ├── custom_card.dart │ │ ├── custom_chip.dart │ │ ├── custom_icon.dart │ │ ├── custom_sliver_app_bar.dart │ │ ├── haptics │ │ ├── haptic_checkbox.dart │ │ ├── haptic_checkbox_list_tile.dart │ │ ├── haptic_custom_card.dart │ │ ├── haptic_floating_action_button_extended.dart │ │ ├── haptic_radio_list_tile.dart │ │ └── haptic_switch_list_tile.dart │ │ ├── open_container_wrapper.dart │ │ └── search_bar.dart └── utils │ ├── about_info.dart │ ├── check_for_supported_patch.dart │ └── string.dart ├── package-lock.json ├── package.json ├── pubspec.lock ├── pubspec.yaml └── slang.yaml /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 🗨 Discussions 4 | url: https://github.com/revanced/revanced-suggestions/discussions 5 | about: Have something unspecific to ReVanced Manager in mind? Search for or start a new discussion! 6 | -------------------------------------------------------------------------------- /.github/config.yaml: -------------------------------------------------------------------------------- 1 | firstPRMergeComment: > 2 | Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) to receive a role for your contribution. 3 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: github-actions 4 | labels: [] 5 | directory: / 6 | target-branch: dev 7 | schedule: 8 | interval: monthly 9 | groups: 10 | gh-actions: 11 | applies-to: version-updates 12 | patterns: 13 | - "*" 14 | update-types: 15 | - "minor" 16 | - "patch" 17 | 18 | - package-ecosystem: npm 19 | labels: [] 20 | directory: / 21 | target-branch: dev 22 | schedule: 23 | interval: monthly 24 | groups: 25 | npm: 26 | applies-to: version-updates 27 | patterns: 28 | - "*" 29 | update-types: 30 | - "minor" 31 | - "patch" 32 | 33 | # ReVanced Manager Flutter 34 | - package-ecosystem: pub 35 | labels: [] 36 | directory: / 37 | target-branch: dev 38 | schedule: 39 | interval: monthly 40 | groups: 41 | pubspec: 42 | applies-to: version-updates 43 | patterns: 44 | - "*" 45 | update-types: 46 | - "minor" 47 | - "patch" 48 | 49 | - package-ecosystem: gradle 50 | labels: [] 51 | directory: /android 52 | target-branch: dev 53 | schedule: 54 | interval: monthly 55 | groups: 56 | gradle: 57 | applies-to: version-updates 58 | patterns: 59 | - "*" 60 | update-types: 61 | - "minor" 62 | - "patch" 63 | 64 | # ReVanced Manager Compose 65 | - package-ecosystem: gradle 66 | labels: [ "ReVanced Manager Compose" ] 67 | directory: / 68 | target-branch: compose-dev 69 | schedule: 70 | interval: monthly 71 | groups: 72 | gradle-compose: 73 | applies-to: version-updates 74 | patterns: 75 | - "*" 76 | update-types: 77 | - "minor" 78 | - "patch" 79 | -------------------------------------------------------------------------------- /.github/workflows/open_pull_request.yml: -------------------------------------------------------------------------------- 1 | name: Open a PR to main 2 | 3 | on: 4 | push: 5 | branches: 6 | - dev 7 | workflow_dispatch: 8 | 9 | env: 10 | MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main` 11 | 12 | jobs: 13 | pull-request: 14 | name: Open pull request 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | 20 | - name: Open pull request 21 | uses: repo-sync/pull-request@v2 22 | with: 23 | destination_branch: 'main' 24 | pr_title: 'chore: ${{ env.MESSAGE }}' 25 | pr_body: | 26 | This pull request will ${{ env.MESSAGE }}. 27 | pr_draft: true 28 | github_token: ${{ secrets.REPOSITORY_PUSH_ACCESS }} 29 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - main 8 | - dev 9 | paths: 10 | - ".github/workflows/release.yml" 11 | - "android/**" 12 | - "assets/**" 13 | - "lib/**" 14 | - "pubspec.yaml" 15 | 16 | jobs: 17 | release: 18 | name: Release 19 | permissions: 20 | id-token: write 21 | contents: write 22 | attestations: write 23 | runs-on: ubuntu-latest 24 | steps: 25 | - name: Checkout 26 | uses: actions/checkout@v4 27 | with: 28 | fetch-depth: 0 29 | 30 | - name: Setup Java 31 | run: echo "JAVA_HOME=$JAVA_HOME_17_X64" >> $GITHUB_ENV 32 | 33 | - name: Setup Node.js 34 | uses: actions/setup-node@v4 35 | with: 36 | node-version: "lts/*" 37 | cache: 'npm' 38 | 39 | - name: Set up Flutter 40 | uses: subosito/flutter-action@v2 41 | with: 42 | channel: stable 43 | 44 | - name: Install dependencies 45 | run: npm ci 46 | 47 | - name: Get dependencies 48 | run: flutter pub get 49 | 50 | - name: Generate translations 51 | run: dart run slang 52 | 53 | - name: Generate code files 54 | run: dart run build_runner build --delete-conflicting-outputs 55 | 56 | - name: Setup keystore 57 | run: | 58 | echo "${{ secrets.KEYSTORE }}" | base64 --decode > "android/app/keystore.jks" 59 | 60 | - name: Release 61 | env: 62 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 63 | KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }} 64 | KEYSTORE_ENTRY_ALIAS: ${{ secrets.KEYSTORE_ENTRY_ALIAS }} 65 | KEYSTORE_ENTRY_PASSWORD: ${{ secrets.KEYSTORE_ENTRY_PASSWORD }} 66 | run: | 67 | npx semantic-release 68 | 69 | - name: Generate artifact attestation 70 | if: github.ref == 'refs/heads/main' 71 | uses: actions/attest-build-provenance@v1 72 | with: 73 | subject-path: build/app/outputs/apk/release/revanced-manager-*.apk 74 | -------------------------------------------------------------------------------- /.github/workflows/sync_crowdin.yml: -------------------------------------------------------------------------------- 1 | name: Sync Crowdin 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: 00 12 * * 1 7 | push: 8 | branches: dev 9 | paths: 10 | - assets/i18n/*.json 11 | - assets/i18n/*.dart 12 | - .github/workflows/sync_crowdin.yml 13 | 14 | jobs: 15 | sync: 16 | name: Sync 17 | runs-on: ubuntu-latest 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | with: 22 | fetch-depth: 0 23 | 24 | - name: Setup Flutter 25 | uses: subosito/flutter-action@v2 26 | with: 27 | cache: true 28 | 29 | - name: Sync translations from Crowdin 30 | uses: crowdin/github-action@v2 31 | with: 32 | config: crowdin.yml 33 | upload_sources: true 34 | upload_translations: false 35 | download_translations: true 36 | localization_branch_name: feat/translations 37 | create_pull_request: true 38 | pull_request_title: "chore: Sync translations" 39 | pull_request_body: "Sync translations from [crowdin.com/project/revanced](https://crowdin.com/project/revanced)" 40 | pull_request_base_branch_name: "dev" 41 | commit_message: "chore: Sync translations" 42 | github_user_name: revanced-bot 43 | github_user_email: github@revanced.app 44 | env: 45 | GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }} 46 | CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }} 47 | CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }} 48 | 49 | - name: Validation of synced translations 50 | run: | 51 | dart pub get 52 | dart run slang validate 53 | 54 | - name: Normalization of Translation Strings 55 | run: | 56 | sudo chmod 766 assets/i18n/*.i18n.json 57 | 58 | dart run slang analyze 59 | dart run slang clean 60 | dart run slang normalize 61 | 62 | dart run slang 63 | 64 | cd assets/i18n 65 | dart nuke.dart >> $GITHUB_STEP_SUMMARY 66 | cd ../.. 67 | 68 | flutter analyze lib/gen/strings.g.dart --no-fatal-infos --no-fatal-warnings 69 | 70 | - name: Commit translations 71 | run: | 72 | git config user.name revanced-bot 73 | git config user.email github@revanced.app 74 | sudo chown -R $USER:$USER .git 75 | git commit -m "chore: Remove empty values from JSON" assets/i18n/*.i18n.json 76 | git push origin HEAD:feat/translations 77 | -------------------------------------------------------------------------------- /.github/workflows/update_documentation.yml: -------------------------------------------------------------------------------- 1 | name: Update documentation 2 | 3 | on: 4 | push: 5 | paths: 6 | - docs/** 7 | 8 | jobs: 9 | trigger: 10 | runs-on: ubuntu-latest 11 | name: Dispatch event to documentation repository 12 | if: github.ref == 'refs/heads/main' 13 | steps: 14 | - uses: peter-evans/repository-dispatch@v3 15 | with: 16 | token: ${{ secrets.DOCUMENTATION_REPO_ACCESS_TOKEN }} 17 | repository: revanced/revanced-documentation 18 | event-type: update-documentation 19 | client-payload: '{"repo": "${{ github.event.repository.name }}", "ref": "${{ github.ref }}"}' 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Symbolication related 35 | app.*.symbols 36 | 37 | # Obfuscation related 38 | app.*.map.json 39 | 40 | # Android Studio will place build artifacts here 41 | /android/app/debug 42 | /android/app/profile 43 | /android/app/release 44 | 45 | # Generated files 46 | **/*.g.dart 47 | **/*.locator.dart 48 | **/*.router.dart 49 | 50 | # Project specific 51 | node_modules/ 52 | .vscode/ 53 | 54 | 55 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: "2663184aa79047d0a33a14a3b607954f8fdd8730" 8 | channel: "stable" 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 17 | base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 18 | - platform: android 19 | create_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 20 | base_revision: 2663184aa79047d0a33a14a3b607954f8fdd8730 21 | 22 | # User provided section 23 | 24 | # List of Local paths (relative to this file) that should be 25 | # ignored by the migrate tool. 26 | # 27 | # Files that are not part of the templates will be ignored by default. 28 | unmanaged_files: 29 | - 'lib/main.dart' 30 | - 'ios/Runner.xcodeproj/project.pbxproj' 31 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "branches": [ 3 | "main", 4 | { 5 | "name": "dev", 6 | "prerelease": true 7 | } 8 | ], 9 | "plugins": [ 10 | [ 11 | "@semantic-release/commit-analyzer", { 12 | "releaseRules": [ 13 | { "type": "build", "scope": "Needs bump", "release": "patch" } 14 | ] 15 | } 16 | ], 17 | "@semantic-release/changelog", 18 | "@semantic-release/release-notes-generator", 19 | [ 20 | "semantic-release-pub", 21 | { 22 | "publishPub": false, 23 | "updateBuildNumber": true 24 | } 25 | ], 26 | [ 27 | "@semantic-release/exec", 28 | { 29 | "prepareCmd": "flutter build apk" 30 | } 31 | ], 32 | [ 33 | "@semantic-release/git", 34 | { 35 | "assets": [ 36 | "pubspec.yaml" 37 | ] 38 | } 39 | ], 40 | [ 41 | "@semantic-release/github", 42 | { 43 | "assets": [ 44 | { 45 | "path": "build/app/outputs/apk/release/revanced-manager*.apk" 46 | }, 47 | ], 48 | "commits": [ 49 | "message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 50 | ], 51 | "successComment": false 52 | } 53 | ], 54 | [ 55 | "@saithodev/semantic-release-backmerge", 56 | { 57 | "backmergeBranches": [{"from": "main", "to": "dev"}], 58 | "clearWorkspace": true 59 | } 60 | ] 61 | ] 62 | } 63 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | 8 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 |     20 | 21 | 22 | 23 | 24 | 25 |     26 | 27 | 28 | 29 | 30 | 31 |     32 | 33 | 34 | 35 | 36 | 37 |     38 | 39 | 40 | 41 | 42 | 43 |     44 | 45 | 46 | 47 | 48 | 49 |     50 | 51 | 52 | 53 | 54 | 55 | 56 |
57 |
58 | Continuing the legacy of Vanced 59 |

60 | 61 | # 🔒 Security Policy 62 | 63 | This document describes how to report security vulnerabilities for ReVanced Manager. 64 | 65 | ## 🚨 Reporting a Vulnerability 66 | 67 | Please open an issue in our [advisory tracker](https://github.com/ReVanced/revanced-manager/security/advisories/new) or reach out privately to us on [Discord](https://discord.gg/revanced). 68 | 69 | If a vulnerability is confirmed and accepted, you can join our [Discord](https://discord.gg/revanced) server to receive a special contributor role. 70 | 71 | ### ⏳ Supported Versions 72 | 73 | | Version | Branch | Supported | 74 | | --------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------------ | 75 | | ![Latest stable release](https://img.shields.io/github/v/release/ReVanced/revanced-manager?style=for-the-badge "Latest stable release") | main | :white_check_mark: | 76 | | ![Latest version](https://img.shields.io/badge/version-latest-brightgreen?style=for-the-badge "Latest version") | dev | :white_check_mark: | 77 | | ![Latest version](https://img.shields.io/badge/version-latest-brightgreen?style=for-the-badge "Latest version") | compose-dev | :white_check_mark: | 78 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | 9 | # Remember to never publicly share your keystore. 10 | # See https://flutter.dev/to/reference-keystore 11 | key.properties 12 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /android/app/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.android.application") 3 | id("kotlin-android") 4 | // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. 5 | id("dev.flutter.flutter-gradle-plugin") 6 | } 7 | 8 | android { 9 | namespace = "app.revanced.manager.flutter" 10 | compileSdk = 35 11 | 12 | compileOptions { 13 | isCoreLibraryDesugaringEnabled = true 14 | 15 | sourceCompatibility = JavaVersion.VERSION_17 16 | targetCompatibility = JavaVersion.VERSION_17 17 | } 18 | 19 | kotlinOptions { 20 | jvmTarget = JavaVersion.VERSION_17.toString() 21 | } 22 | 23 | defaultConfig { 24 | applicationId = "app.revanced.manager.flutter" 25 | minSdk = 26 26 | targetSdk = 35 27 | versionCode = flutter.versionCode 28 | versionName = flutter.versionName 29 | 30 | resValue("string", "app_name", "ReVanced Manager") 31 | } 32 | 33 | applicationVariants.all { 34 | outputs.all { 35 | this as com.android.build.gradle.internal.api.ApkVariantOutputImpl 36 | 37 | outputFileName = "revanced-manager-$versionName.apk" 38 | } 39 | } 40 | 41 | buildTypes { 42 | configureEach { 43 | isShrinkResources = false 44 | isMinifyEnabled = false 45 | 46 | signingConfig = signingConfigs["debug"] 47 | 48 | ndk.abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86_64") 49 | } 50 | 51 | release { 52 | isShrinkResources = true 53 | isMinifyEnabled = true 54 | 55 | val keystoreFile = file("keystore.jks") 56 | if (keystoreFile.exists()) { 57 | signingConfig = signingConfigs.create("release") { 58 | storeFile = keystoreFile 59 | storePassword = System.getenv("KEYSTORE_PASSWORD") 60 | keyAlias = System.getenv("KEYSTORE_ENTRY_ALIAS") 61 | keyPassword = System.getenv("KEYSTORE_ENTRY_PASSWORD") 62 | } 63 | 64 | resValue("string", "app_name", "ReVanced Manager") 65 | } else { 66 | applicationIdSuffix = ".development" 67 | resValue("string", "app_name", "ReVanced Manager (Development)") 68 | signingConfig = signingConfigs["debug"] 69 | } 70 | } 71 | 72 | debug { 73 | applicationIdSuffix = ".debug" 74 | resValue("string", "app_name", "ReVanced Manager (Debug)") 75 | } 76 | 77 | named("profile") { 78 | initWith(getByName("debug")) 79 | applicationIdSuffix = ".profile" 80 | resValue("string", "app_name", "ReVanced Manager (Profile)") 81 | } 82 | } 83 | 84 | packaging { 85 | jniLibs { 86 | useLegacyPackaging = true 87 | excludes.add("/prebuilt/**") 88 | } 89 | 90 | resources { 91 | excludes.add("/prebuilt/**") 92 | } 93 | } 94 | } 95 | 96 | flutter { 97 | source = "../.." 98 | } 99 | 100 | dependencies { 101 | coreLibraryDesugaring(libs.desugar.jdk.libs) // https://pub.dev/packages/flutter_local_notifications#gradle-setup 102 | implementation(libs.revanced.patcher) 103 | implementation(libs.revanced.library) 104 | } 105 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -dontobfuscate 2 | 3 | -keep class app.revanced.** { *; } 4 | -keep class com.android.tools.smali.** { *; } 5 | -keep class kotlin.** { *; } 6 | -keep class com.google.auto.value.** { *; } 7 | -keep class com.android.apksig.internal.** { *; } 8 | -keepnames class com.google.common.collect.** 9 | -keepnames class org.xmlpull.** { *; } 10 | 11 | -dontwarn com.google.auto.value.** 12 | -dontwarn com.google.j2objc.annotations.* 13 | -dontwarn java.awt.** 14 | -dontwarn javax.** 15 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | 24 | 31 | 39 | 42 | 43 | 44 | 45 | 46 | 47 | 51 | 54 | 55 | 58 | 63 | 66 | 67 | 68 | 72 | 73 | 74 | 75 | 76 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /android/app/src/main/jniLibs/arm64-v8a/libaapt2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/jniLibs/arm64-v8a/libaapt2.so -------------------------------------------------------------------------------- /android/app/src/main/jniLibs/armeabi-v7a/libaapt2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/jniLibs/armeabi-v7a/libaapt2.so -------------------------------------------------------------------------------- /android/app/src/main/jniLibs/x86/libaapt2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/jniLibs/x86/libaapt2.so -------------------------------------------------------------------------------- /android/app/src/main/jniLibs/x86_64/libaapt2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/jniLibs/x86_64/libaapt2.so -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/revanced/manager/flutter/ExportSettingsActivity.kt: -------------------------------------------------------------------------------- 1 | package app.revanced.manager.flutter 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.pm.PackageManager 7 | import android.os.Bundle 8 | import android.util.Base64 9 | import org.json.JSONObject 10 | import java.io.ByteArrayInputStream 11 | import java.io.File 12 | import java.security.cert.CertificateFactory 13 | import java.security.cert.X509Certificate 14 | import java.security.MessageDigest 15 | 16 | class ExportSettingsActivity : Activity() { 17 | override fun onCreate(savedInstanceState: Bundle?) { 18 | super.onCreate(savedInstanceState) 19 | 20 | if (getFingerprint(callingPackage!!) == getFingerprint(packageName)) { 21 | // Create JSON Object 22 | val json = JSONObject() 23 | 24 | // Default Data 25 | json.put("keystorePassword", "s3cur3p@ssw0rd") 26 | 27 | // Load Shared Preferences 28 | val sharedPreferences = getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) 29 | val allEntries: Map = sharedPreferences.getAll() 30 | for ((key, value) in allEntries.entries) { 31 | json.put(key.replace("flutter.", ""), value) 32 | } 33 | 34 | // Load keystore 35 | val keystoreFile = File(getExternalFilesDir(null), "/revanced-manager.keystore") 36 | if (keystoreFile.exists()) { 37 | val keystoreBytes = keystoreFile.readBytes() 38 | val keystoreBase64 = Base64.encodeToString(keystoreBytes, Base64.DEFAULT) 39 | json.put("keystore", keystoreBase64) 40 | } 41 | 42 | // Load saved patches 43 | val storedPatchesFile = File(filesDir.parentFile.absolutePath, "/app_flutter/selected-patches.json") 44 | if (storedPatchesFile.exists()) { 45 | val patchesBytes = storedPatchesFile.readBytes() 46 | val patches = String(patchesBytes, Charsets.UTF_8) 47 | json.put("patches", JSONObject(patches)) 48 | } 49 | 50 | // Send data back 51 | val resultIntent = Intent() 52 | resultIntent.putExtra("data", json.toString()) 53 | setResult(Activity.RESULT_OK, resultIntent) 54 | finish() 55 | } else { 56 | val resultIntent = Intent() 57 | setResult(Activity.RESULT_CANCELED) 58 | finish() 59 | } 60 | } 61 | 62 | fun getFingerprint(packageName: String): String { 63 | // Get the signature of the app that matches the package name 64 | val packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES) 65 | val signature = packageInfo.signatures!![0] 66 | 67 | // Get the raw certificate data 68 | val rawCert = signature.toByteArray() 69 | 70 | // Generate an X509Certificate from the data 71 | val certFactory = CertificateFactory.getInstance("X509") 72 | val x509Cert = certFactory.generateCertificate(ByteArrayInputStream(rawCert)) as X509Certificate 73 | 74 | // Get the SHA256 fingerprint 75 | val fingerprint = MessageDigest.getInstance("SHA256").digest(x509Cert.encoded).joinToString("") { 76 | "%02x".format(it) 77 | } 78 | 79 | return fingerprint 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/revanced/manager/flutter/utils/Aapt.kt: -------------------------------------------------------------------------------- 1 | package app.revanced.manager.flutter.utils 2 | 3 | import android.content.Context 4 | import java.io.File 5 | 6 | object Aapt { 7 | fun binary(context: Context): File { 8 | return File(context.applicationInfo.nativeLibraryDir).resolveAapt() 9 | } 10 | } 11 | 12 | private fun File.resolveAapt() = resolve(list { _, f -> !File(f).isDirectory && f.contains("aapt") }!!.first()) -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/revanced/manager/flutter/utils/packageInstaller/InstallerReceiver.kt: -------------------------------------------------------------------------------- 1 | package app.revanced.manager.flutter.utils.packageInstaller 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.pm.PackageInstaller 7 | import app.revanced.manager.flutter.MainActivity 8 | 9 | class InstallerReceiver : BroadcastReceiver() { 10 | override fun onReceive(context: Context, intent: Intent) { 11 | when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)) { 12 | PackageInstaller.STATUS_PENDING_USER_ACTION -> { 13 | val confirmationIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT) 14 | if (confirmationIntent != null) { 15 | context.startActivity(confirmationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) 16 | } 17 | } 18 | 19 | else -> { 20 | val packageName = intent.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME) 21 | val message = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) 22 | val otherPackageName = intent.getStringExtra(PackageInstaller.EXTRA_OTHER_PACKAGE_NAME) 23 | MainActivity.PackageInstallerManager.result!!.success(mapOf( 24 | "status" to status, 25 | "packageName" to packageName, 26 | "message" to message, 27 | "otherPackageName" to otherPackageName 28 | )) 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /android/app/src/main/kotlin/app/revanced/manager/flutter/utils/packageInstaller/UninstallerReceiver.kt: -------------------------------------------------------------------------------- 1 | package app.revanced.manager.flutter.utils.packageInstaller 2 | 3 | import android.content.BroadcastReceiver 4 | import android.content.Context 5 | import android.content.Intent 6 | import android.content.pm.PackageInstaller 7 | import app.revanced.manager.flutter.MainActivity 8 | 9 | class UninstallerReceiver : BroadcastReceiver() { 10 | override fun onReceive(context: Context, intent: Intent) { 11 | when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1)) { 12 | PackageInstaller.STATUS_PENDING_USER_ACTION -> { 13 | val confirmationIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT) 14 | if (confirmationIntent != null) { 15 | context.startActivity(confirmationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)) 16 | } 17 | } 18 | 19 | else -> { 20 | MainActivity.PackageInstallerManager.result!!.success(status) 21 | } 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 11 | 14 | 16 | 17 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/res/drawable/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/res/drawable/ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/raw/revanced_manager_keep.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night-v31/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 16 | 19 | 20 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-v31/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #1B1B1B 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/xml/file_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.android.build.api.dsl.CommonExtension 2 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 3 | 4 | allprojects { 5 | repositories { 6 | google() 7 | mavenCentral() 8 | maven { 9 | name = "GitHubPackages" 10 | url = uri("https://maven.pkg.github.com/revanced/registry") 11 | credentials { 12 | username = providers.gradleProperty("gpr.user").orNull ?: System.getenv("GITHUB_ACTOR") 13 | password = providers.gradleProperty("gpr.key").orNull ?: System.getenv("GITHUB_TOKEN") 14 | } 15 | } 16 | } 17 | } 18 | 19 | layout.buildDirectory = File("../build") 20 | 21 | project(":screenshot_callback") { 22 | tasks.withType().configureEach { 23 | kotlinOptions { 24 | jvmTarget = "17" 25 | } 26 | } 27 | } 28 | 29 | subprojects { 30 | afterEvaluate { 31 | extensions.findByName("android")?.let { 32 | it as CommonExtension<*, *, *, *, *, *> 33 | if (it.compileSdk != null && it.compileSdk!! < 31) 34 | it.compileSdk = 34 35 | } 36 | } 37 | 38 | layout.buildDirectory = rootProject.layout.buildDirectory.file(name).get().asFile 39 | evaluationDependsOn(":app") 40 | } 41 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4G -XX:MaxMetaspaceSize=2G -XX:+HeapDumpOnOutOfMemoryError 2 | android.useAndroidX=true 3 | org.gradle.parallel=true 4 | org.gradle.daemon=true 5 | org.gradle.caching=true 6 | android.nonTransitiveRClass=false 7 | android.nonFinalResIds=false 8 | -------------------------------------------------------------------------------- /android/gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | revanced-patcher = "21.0.0" 3 | revanced-library = "3.1.0" 4 | desugar_jdk_libs = "2.1.4" 5 | 6 | [libraries] 7 | revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" } 8 | revanced-library = { module = "app.revanced:revanced-library", version.ref = "revanced-library" } 9 | desugar_jdk_libs = { module = "com.android.tools:desugar_jdk_libs", version.ref = "desugar_jdk_libs" } 10 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip 5 | networkTimeout=10000 6 | validateDistributionUrl=true 7 | zipStoreBase=GRADLE_USER_HOME 8 | zipStorePath=wrapper/dists 9 | -------------------------------------------------------------------------------- /android/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | val properties = java.util.Properties().apply { 3 | load(file("local.properties").inputStream()) 4 | } 5 | 6 | val flutterSdkPath = properties.getProperty("flutter.sdk") 7 | assert(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } 8 | 9 | includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") 10 | 11 | repositories { 12 | google() 13 | mavenCentral() 14 | gradlePluginPortal() 15 | } 16 | } 17 | 18 | plugins { 19 | id("dev.flutter.flutter-plugin-loader") version "1.0.0" 20 | id("com.android.application") version "8.9.0" apply false 21 | id("org.jetbrains.kotlin.android") version "2.1.10" apply false 22 | } 23 | 24 | include(":app") 25 | -------------------------------------------------------------------------------- /assets/i18n/as_IN.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "okButton": "বাৰু", 3 | "cancelButton": "বাতিল কৰক", 4 | "dismissButton": "খাৰিজ কৰক", 5 | "quitButton": "বন্ধ কৰক", 6 | "updateButton": "আপডে’ট কৰক", 7 | "suggested": "পৰামৰ্শমূলক: ${version}", 8 | "yesButton": "হয়", 9 | "noButton": "নহয়", 10 | "warning": "সকীয়নি", 11 | "notice": "জাননী", 12 | "noShowAgain": "এইটো আকৌ নেদেখুৱাব", 13 | "add": "যোগ কৰক", 14 | "remove": "আঁতৰাওক", 15 | "showChangelogButton": "সলনি-পঞ্জী দেখুৱাওক", 16 | "showUpdateButton": "আপডে’ট দেখুৱাওক", 17 | "navigationView": { 18 | "dashboardTab": "ডেশ্বব’ৰ্ড", 19 | "patcherTab": "পেট্‌চাৰ", 20 | "settingsTab": "ছেটিংছ" 21 | }, 22 | "homeView": { 23 | "refreshSuccess": "সফলতাৰে সতেজ কৰা হ’ল", 24 | "widgetTitle": "ডেশ্বব’ৰ্ড", 25 | "updatesSubtitle": "আপডে’টবোৰ", 26 | "lastPatchedAppSubtitle": "অন্তিমবাৰ পেট্‌চ কৰা এপ", 27 | "patchedSubtitle": "ইনষ্টল কৰা এপবোৰ", 28 | "changeLaterSubtitle": "আপুনি এইটো পাছত ছেটিংছত সলনি কৰিব পাৰিব।", 29 | "noSavedAppFound": "কোনো এপ পোৱা নগ’ল", 30 | "noInstallations": "পেট্‌চ কৰা কোনো এপ ইনষ্টল কৰা নাই", 31 | "installUpdate": "আপডে’ট ইনষ্টল কৰা অব্যাহত ৰাখিবনে?", 32 | "updateSheetTitle": "ReVanced Manager আপডে’ট কৰক", 33 | "updateDialogTitle": "নতুন আপডে’ট উপলব্ধ", 34 | "updatePatchesSheetTitle": "ReVanced পেট্‌চবোৰ আপডে’ট কৰক", 35 | "updateChangelogTitle": "সলনি-পঞ্জী", 36 | "updateDialogText": "${file}-ৰ এটা নতুন আপডে’ট উপলব্ধ।\n\nবৰ্তমানে ইনষ্টল কৰা সংস্কৰণটো হৈছে ${version}।", 37 | "downloadConsentDialogTitle": "প্ৰয়োজনীয় ফাইলবোৰ ডাউনল’ড কৰিবনে?" 38 | }, 39 | "applicationItem": {}, 40 | "latestCommitCard": {}, 41 | "patcherView": {}, 42 | "appSelectorCard": {}, 43 | "patchSelectorCard": {}, 44 | "socialMediaCard": {}, 45 | "appSelectorView": {}, 46 | "patchesSelectorView": {}, 47 | "patchOptionsView": { 48 | "saveOptions": "ছে’ভ কৰক", 49 | "unselectPatch": "পেট্‌চ বাছনি-মুক্ত কৰক", 50 | "tooltip": "অধিক ইনপুটৰ বিকল্প", 51 | "selectFilePath": "ফাইলৰ পথ বাছনি কৰক", 52 | "selectFolder": "ফ’ল্ডাৰ বাছনি কৰক" 53 | }, 54 | "patchItem": {}, 55 | "installerView": {}, 56 | "settingsView": { 57 | "themeModeLabel": "এপৰ থীম", 58 | "systemThemeLabel": "ছিষ্টেমৰ", 59 | "lightThemeLabel": "পাতল", 60 | "darkThemeLabel": "গাঢ়", 61 | "dynamicThemeLabel": "মেটেৰিয়েল ইউ", 62 | "languageLabel": "ভাষা", 63 | "languageUpdated": "ভাষা আপডে’ট কৰা হ’ল" 64 | }, 65 | "appInfoView": { 66 | "removeAppDialogTitle": "এপ মচিবনে?", 67 | "removeAppDialogText": "আপুনি এই বেকআপ মচি পেলাব বিচৰাটো নিশ্চিতনে?", 68 | "packageNameLabel": "পেকেজৰ নাম", 69 | "installTypeLabel": "ইনষ্টলেশ্যনৰ প্ৰকাৰ", 70 | "mountTypeLabel": "মাউণ্ট", 71 | "regularTypeLabel": "সাধাৰণ", 72 | "patchedDateLabel": "পেট্‌চ কৰা তাৰিখ", 73 | "appliedPatchesLabel": "প্ৰয়োগ কৰা পেট্‌চবোৰ", 74 | "sizeLabel": "ফাইলৰ আকাৰ", 75 | "patchedDateHint": "${date}ৰ ${time} বজাত", 76 | "appliedPatchesHint": "${quantity}টা প্ৰয়োগ কৰা পেট্‌চ", 77 | "updateNotImplemented": "এই সুবিধা এতিয়ালৈকে প্ৰণয়ন কৰা হোৱা নাই" 78 | }, 79 | "contributorsView": { 80 | "widgetTitle": "অৱদানকাৰীসকল" 81 | }, 82 | "installErrorDialog": { 83 | "mount_version_mismatch": "সংস্কৰণৰ অমিল", 84 | "mount_no_root": "ৰুট এক্সেছ নাই", 85 | "mount_missing_installation": "ইনষ্টলেশ্যন পোৱা নগ’ল", 86 | "status_failure_blocked": "ইনষ্টলেশ্যন অৱৰুদ্ধ", 87 | "install_failed_verification_failure": "ভেৰিফিকেশ্যন বিফল", 88 | "install_failed_version_downgrade": "ডাউনগ্ৰে’ড কৰিব নোৱাৰি", 89 | "status_failure_conflict": "ইনষ্টলেশ্যনৰ সংঘাত", 90 | "status_failure_storage": "ইনষ্টলেশ্যন ষ্ট’ৰেজৰ সমস্যা", 91 | "status_failure_incompatible": "ইনষ্টলেশ্যন নিমিলে", 92 | "status_failure_timeout": "ইনষ্টলেশ্যনৰ সময় উকলিল", 93 | "status_unknown": "ইনষ্টলেশ্যন বিফল", 94 | "status_failure_conflict_description": "এপটোৰ এটা মজুত থকা ইনষ্টলেশ্যনৰ ফলত ইনষ্টলেশ্যনত বাধা আহিছিল।\n\n ইনষ্টল কৰা এপটো আনইনষ্টল কৰি পুনৰ চেষ্টা কৰিবনে?", 95 | "status_failure_blocked_description": "ইনষ্টলেশ্যনটো ${packageName}-ৰ দ্বাৰা অৱৰোধ কৰা হৈছে।\n\nআপোনাৰ সুৰক্ষা-সম্বন্ধীয় ছেটিংছ মিলাই লৈ পুনৰ চেষ্টা কৰক।", 96 | "install_failed_verification_failure_description": "ভেৰিফিকেশ্যন-সম্বন্ধীয় সমস্যা এটাৰ কাৰণে ইনষ্টলেশ্যন বিফল হ’ল।\n\nআপোনাৰ সুৰক্ষা-সম্বন্ধীয় ছেটিংছ মিলাই লৈ পুনৰ চেষ্টা কৰক।" 97 | } 98 | } -------------------------------------------------------------------------------- /assets/i18n/kk_KZ.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "cancelButton": "Болдырмау", 3 | "dismissButton": "Елемеу", 4 | "quitButton": "Шығу", 5 | "updateButton": "Жаңарту", 6 | "suggested": "Ұсынылған: ${version}", 7 | "yesButton": "Иә", 8 | "noButton": "Жоқ", 9 | "warning": "Назар аударыңыз", 10 | "notice": "Ескерту", 11 | "noShowAgain": "Енді көрсетілмесін", 12 | "add": "Қосу", 13 | "remove": "Жою", 14 | "showChangelogButton": "Өзгерту тарихын көрсету", 15 | "showUpdateButton": "Жаңартуды көрсету", 16 | "navigationView": { 17 | "dashboardTab": "Басқару тақтасы", 18 | "patcherTab": "Patcher", 19 | "settingsTab": "Баптау" 20 | }, 21 | "homeView": { 22 | "refreshSuccess": "Сәтті жаңартылды", 23 | "widgetTitle": "Бақылау тақтасы", 24 | "updatesSubtitle": "Жаңартулар", 25 | "changeLaterSubtitle": "Мұны кейінірек баптауда өзгертіп ала аласыз.", 26 | "noInstallations": "Патчталған қолданбалар орнатылмаған", 27 | "installUpdate": "Жаңартуды әрі қарай орната берейік пе?", 28 | "updateSheetTitle": "ReVanced Manager-ді жаңарту", 29 | "updateDialogTitle": "Жаңарту қолжетімді", 30 | "updatePatchesSheetTitle": "ReVanced патчін жаңарту", 31 | "updateChangelogTitle": "Өзгерту тарихы", 32 | "updateDialogText": "${file} үшін жаңарту қолжетімді.\n\nҚазіргі ${version} нұсқасы орнатылып тұр.", 33 | "downloadedMessage": "Жаңарту жүктелген", 34 | "noConnection": "Интернет байланысы жоқ" 35 | }, 36 | "applicationItem": { 37 | "infoButton": "Ақпарат" 38 | }, 39 | "latestCommitCard": { 40 | "loadingLabel": "Ju'ktely'de..." 41 | }, 42 | "patcherView": { 43 | "widgetTitle": "Патчер", 44 | "patchButton": "Патч" 45 | }, 46 | "appSelectorCard": { 47 | "widgetTitle": "Қолданбаны таңдаңыз" 48 | }, 49 | "patchSelectorCard": {}, 50 | "socialMediaCard": {}, 51 | "appSelectorView": { 52 | "viewTitle": "Қолданбаны таңдаңыз" 53 | }, 54 | "patchesSelectorView": { 55 | "doneButton": "Дайын", 56 | "noneChip": "Жоқ" 57 | }, 58 | "patchOptionsView": { 59 | "selectFolder": "Буманы таңдаңыз" 60 | }, 61 | "patchItem": {}, 62 | "installerView": { 63 | "installButton": "Орнату", 64 | "installNonRootType": "Қалыпты" 65 | }, 66 | "settingsView": { 67 | "widgetTitle": "Баптау", 68 | "appearanceSectionTitle": "Безендіру", 69 | "advancedSectionTitle": "Қосымша", 70 | "contributorsLabel": "Үлес қосушылар" 71 | }, 72 | "appInfoView": { 73 | "widgetTitle": "Қолданба ақпары", 74 | "installButton": "Орнату", 75 | "uninstallButton": "Алмау", 76 | "rootDialogTitle": "Қате" 77 | }, 78 | "contributorsView": { 79 | "widgetTitle": "Үлес қосушылар" 80 | }, 81 | "installErrorDialog": {} 82 | } -------------------------------------------------------------------------------- /assets/i18n/km_KH.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "okButton": "យល់ព្រម", 3 | "cancelButton": "បោះបង់", 4 | "dismissButton": "ទាត់ចោល", 5 | "quitButton": "ចេញ", 6 | "updateButton": "អាប់ដេត", 7 | "suggested": "បានណែនាំ៖ ${version}", 8 | "yesButton": "បាទ/ចាស", 9 | "noButton": "ទេ", 10 | "warning": "ការព្រមាន", 11 | "notice": "សម្គាល់", 12 | "noShowAgain": "កុំបង្ហាញដូច្នេះម្ដងទៀត", 13 | "add": "បន្ថែម", 14 | "remove": "ដកចេញ", 15 | "showChangelogButton": "បង្ហាញកំណត់ហេតុផ្លាស់ប្ដូរ", 16 | "showUpdateButton": "បង្ហាញបច្ចុប្បន្នភាព", 17 | "navigationView": { 18 | "dashboardTab": "ផ្ទាំងគ្រប់គ្រង", 19 | "patcherTab": "ផាត់ឆើ", 20 | "settingsTab": "ការកំណត់" 21 | }, 22 | "homeView": { 23 | "refreshSuccess": "បានរីហ្វ្រែសដោយជោគជ័យ", 24 | "widgetTitle": "ផ្ទាំងគ្រប់គ្រង", 25 | "updatesSubtitle": "អាប់ដេត", 26 | "changeLaterSubtitle": "អ្នកអាចផ្លាស់ប្តូរដូច្នេះនៅក្នុងការកំណត់នៅពេលក្រោយ។", 27 | "installUpdate": "បន្តដំឡើងបច្ចុប្បន្នភាពឬ?", 28 | "updateSheetTitle": "អាប់ដេត ReVanced Manager", 29 | "updateDialogTitle": "មានបច្ចុប្បន្នភាពថ្មិ", 30 | "updateChangelogTitle": "កំណត់ហេតុផ្លាស់ប្ដូរ" 31 | }, 32 | "applicationItem": {}, 33 | "latestCommitCard": {}, 34 | "patcherView": { 35 | "widgetTitle": "ផាត់ឆើ" 36 | }, 37 | "appSelectorCard": {}, 38 | "patchSelectorCard": {}, 39 | "socialMediaCard": {}, 40 | "appSelectorView": {}, 41 | "patchesSelectorView": {}, 42 | "patchOptionsView": {}, 43 | "patchItem": {}, 44 | "installerView": {}, 45 | "settingsView": { 46 | "widgetTitle": "ការកំណត់", 47 | "sourcesResetDialogTitle": "កំណត់ឡើងវិញ" 48 | }, 49 | "appInfoView": {}, 50 | "contributorsView": {}, 51 | "installErrorDialog": {} 52 | } -------------------------------------------------------------------------------- /assets/i18n/ms_MY.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "cancelButton": "Batal", 3 | "updateButton": "Kemas kini", 4 | "yesButton": "Ya", 5 | "noButton": "Tidak", 6 | "warning": "Amaran", 7 | "navigationView": { 8 | "dashboardTab": "Papan Pemuka", 9 | "patcherTab": "Pemodifikasi", 10 | "settingsTab": "Tetapan" 11 | }, 12 | "homeView": { 13 | "widgetTitle": "Papan Pemuka", 14 | "updatesSubtitle": "Kemas Kini", 15 | "updateChangelogTitle": "Log perubahan", 16 | "downloadingMessage": "Memuat turun pengemaskinian...", 17 | "downloadedMessage": "Kemaskini dimuat turun", 18 | "installingMessage": "Memasang pengemaskinian...", 19 | "errorDownloadMessage": "Tidak dapat memuat turun pengemaskinian", 20 | "errorInstallMessage": "Tidak dapat memasang pengemaskinian", 21 | "noConnection": "Tiada sambungan internet" 22 | }, 23 | "applicationItem": { 24 | "infoButton": "Maklumat" 25 | }, 26 | "latestCommitCard": { 27 | "loadingLabel": "Memuatkan..." 28 | }, 29 | "patcherView": { 30 | "widgetTitle": "Pemodifikasi", 31 | "patchButton": "Modifikasi" 32 | }, 33 | "appSelectorCard": { 34 | "noAppsLabel": "Tiada aplikasi ditemui" 35 | }, 36 | "patchSelectorCard": { 37 | "widgetTitle": "Pilih modifikasi", 38 | "widgetTitleSelected": "Modifikasi pilihan", 39 | "widgetSubtitle": "Pilih aplikasi dahulu", 40 | "widgetEmptySubtitle": "Tiada modifikasi terpilih" 41 | }, 42 | "socialMediaCard": { 43 | "widgetTitle": "Sosial", 44 | "widgetSubtitle": "Ikuti kami!" 45 | }, 46 | "appSelectorView": { 47 | "storageButton": "Storan", 48 | "errorMessage": "Tidak dapat menggunakan aplikasi yang dipilih" 49 | }, 50 | "patchesSelectorView": { 51 | "viewTitle": "Pilih modifikasi", 52 | "searchBarHint": "Cari modifikasi", 53 | "doneButton": "Selesai", 54 | "noneChip": "Tiada", 55 | "noPatchesFound": "Tiada modifikasi dijumpai untuk apl pilihan" 56 | }, 57 | "patchOptionsView": {}, 58 | "patchItem": { 59 | "unsupportedDialogText": "Memilih modifikasi mungkin menyebabkan ralat ketika modifikasi.\n\nVersi aplikasi: ${packageVersion}\nVersi disokong:\n${supportedVersions}" 60 | }, 61 | "installerView": { 62 | "installButton": "Pasang", 63 | "openButton": "Buka", 64 | "notificationTitle": "Revanced Manager sedang memodifikasi", 65 | "notificationText": "Tap untuk kembali ke pemasang", 66 | "noExit": "Pemasang masih dijalankan, jangan keluar..." 67 | }, 68 | "settingsView": { 69 | "widgetTitle": "Tetapan", 70 | "appearanceSectionTitle": "Penampilan", 71 | "teamSectionTitle": "Pasukan", 72 | "advancedSectionTitle": "Lanjutan", 73 | "exportSectionTitle": "Import & Eksport", 74 | "dynamicThemeHint": "Nikmati tema yang lebih serasi dengan anda", 75 | "languageLabel": "Bahasa", 76 | "sourcesResetDialogTitle": "Set semula", 77 | "orgPatchesLabel": "Pengarang Modifikasi", 78 | "sourcesPatchesLabel": "Sumber Modifikasi", 79 | "contributorsLabel": "Penyumbang", 80 | "contributorsHint": "Senarai penyokong ReVanced", 81 | "aboutLabel": "Tentang", 82 | "snackbarMessage": "Disalin ke papan klip", 83 | "restartAppForChanges": "Mulakan semula apl untuk menggunakan tetapan", 84 | "deleteTempDirLabel": "Buang fail sementara", 85 | "deleteTempDirHint": "Padam fail sementara yang tidak digunakan", 86 | "deletedTempDir": "Fail sementara dibuang", 87 | "deletedLogs": "Log telah dipadam", 88 | "jsonSelectorErrorMessage": "Tidak dapat menggunakan fail JSON yang dipilih" 89 | }, 90 | "appInfoView": { 91 | "widgetTitle": "Maklumat apl", 92 | "openButton": "Buka", 93 | "installButton": "Pasang", 94 | "uninstallButton": "Nyah pasang", 95 | "rootDialogTitle": "Ralat", 96 | "rootDialogText": "Aplikasi telah dipasang dengan kebenaran superuser, tetapi ReVanced Manager sekarang tidak ada kebeneran.\nMinta membenarkan kebenaran superuser dahulu.", 97 | "packageNameLabel": "Nama pakej", 98 | "installTypeLabel": "Jenis Pemasangan", 99 | "patchedDateLabel": "Tarikh Modifikasi", 100 | "appliedPatchesLabel": "Modifikasi Digunakan", 101 | "patchedDateHint": "${date} pada ${time}", 102 | "appliedPatchesHint": "${quantity} modifikasi digunakan", 103 | "updateNotImplemented": "Ciri ini masih belum dilaksanakan" 104 | }, 105 | "contributorsView": { 106 | "widgetTitle": "Penyumbang" 107 | }, 108 | "installErrorDialog": {} 109 | } -------------------------------------------------------------------------------- /assets/i18n/my_MM.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "okButton": "အိုကေ", 3 | "cancelButton": "ပယ်ဖျက်မည်", 4 | "dismissButton": "မလုပ်တော့ပါ", 5 | "quitButton": "ထွက်မည်", 6 | "updateButton": "အပ်ပဒိတ်", 7 | "navigationView": {}, 8 | "homeView": {}, 9 | "applicationItem": {}, 10 | "latestCommitCard": {}, 11 | "patcherView": {}, 12 | "appSelectorCard": {}, 13 | "patchSelectorCard": {}, 14 | "socialMediaCard": {}, 15 | "appSelectorView": {}, 16 | "patchesSelectorView": {}, 17 | "patchOptionsView": {}, 18 | "patchItem": {}, 19 | "installerView": {}, 20 | "settingsView": {}, 21 | "appInfoView": {}, 22 | "contributorsView": {}, 23 | "installErrorDialog": {} 24 | } -------------------------------------------------------------------------------- /assets/i18n/no_NO.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "cancelButton": "Avbryt", 3 | "updateButton": "Oppdater", 4 | "suggested": "Anbefalt: ${version}", 5 | "yesButton": "Ja", 6 | "noButton": "Nei", 7 | "warning": "Advarsel", 8 | "navigationView": { 9 | "dashboardTab": "Dashbord", 10 | "settingsTab": "Innstillinger" 11 | }, 12 | "homeView": { 13 | "refreshSuccess": "Oppdatering vellykket", 14 | "widgetTitle": "Dashbord", 15 | "updatesSubtitle": "Oppdateringer", 16 | "patchedSubtitle": "Patched applikasjoner", 17 | "noInstallations": "Patchet applikasjon er ikke installert", 18 | "installUpdate": "Fortsett til installasjon av oppdatering?", 19 | "updateChangelogTitle": "Endringslogg", 20 | "downloadingMessage": "Laster ned oppdatering...", 21 | "installingMessage": "Installerer oppdatering...", 22 | "errorDownloadMessage": "Nedlasting av oppdatering var misslykket", 23 | "errorInstallMessage": "Installasjon av oppdatering var misslykket", 24 | "noConnection": "Ingen nettverksforbindelse" 25 | }, 26 | "latestCommitCard": { 27 | "loadingLabel": "Laster...", 28 | "timeagoLabel": "${time} siden" 29 | }, 30 | "appSelectorCard": { 31 | "noAppsLabel": "Ingen applikasjoner ble funnet" 32 | }, 33 | "patchSelectorCard": { 34 | "widgetTitle": "Velg patcher", 35 | "widgetTitleSelected": "Valgte patcher", 36 | "widgetSubtitle": "Velg en applikasjon først", 37 | "widgetEmptySubtitle": "Ingen patcher valgt" 38 | }, 39 | "socialMediaCard": { 40 | "widgetTitle": "Sosiale Medier", 41 | "widgetSubtitle": "Vi er på nett!" 42 | }, 43 | "appSelectorView": { 44 | "storageButton": "Lager", 45 | "selectFromStorageButton": "Velg fra lager", 46 | "errorMessage": "Kan ikke bruke valgt applikasjon", 47 | "downloadToast": "Nedlastingsfunksjonen er for øyeblikket utilgjengelig", 48 | "featureNotAvailable": "Funksjonen er ikke implementert" 49 | }, 50 | "patchesSelectorView": { 51 | "viewTitle": "Velg patcher", 52 | "searchBarHint": "Søk etter patcher", 53 | "doneButton": "Fullført", 54 | "defaultTooltip": "Velg alle standard patcher" 55 | }, 56 | "settingsView": { 57 | "advancedSectionTitle": "Avansert", 58 | "darkThemeLabel": "Mørk modus", 59 | "dynamicThemeHint": "Nyt en erfaring nærmere din enhet", 60 | "languageLabel": "Språk", 61 | "sourcesResetDialogTitle": "Tilbakestill", 62 | "orgPatchesLabel": "Patches organisasjon", 63 | "sourcesPatchesLabel": "Patches kilde", 64 | "contributorsLabel": "Medvirkende", 65 | "contributorsHint": "En liste med bidragsytere til ReVanced" 66 | } 67 | } -------------------------------------------------------------------------------- /assets/i18n/nuke.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: avoid_print 2 | 3 | import 'dart:convert'; 4 | import 'dart:io'; 5 | 6 | T? removeBlankEntries(T? json) { 7 | // This function is protected by BSD 3-Clause License 8 | // Changes made to this section are allow removing of '' values from JSON 9 | 10 | /* 11 | https://pub.dev/documentation/swiss_knife/latest/swiss_knife/removeEmptyEntries.html 12 | 13 | Copyright 2014, the Dart project authors. All rights reserved. 14 | Redistribution and use in source and binary forms, with or without 15 | modification, are permitted provided that the following conditions are 16 | met: 17 | 18 | * Redistributions of source code must retain the above copyright 19 | notice, this list of conditions and the following disclaimer. 20 | * Redistributions in binary form must reproduce the above 21 | copyright notice, this list of conditions and the following 22 | disclaimer in the documentation and/or other materials provided 23 | with the distribution. 24 | * Neither the name of Google Inc. nor the names of its 25 | contributors may be used to endorse or promote products derived 26 | from this software without specific prior written permission. 27 | 28 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 | */ 40 | if (json == null) { 41 | return null; 42 | } 43 | if (json is List) { 44 | json.removeWhere((e) => e == null); 45 | json.forEach(removeBlankEntries); 46 | // If the list is empty after removing nulls, return null to remove it. 47 | return json.isEmpty ? null : json; 48 | } else if (json is Map) { 49 | json.removeWhere( 50 | (key, value) => key == null || value == null || value == '', 51 | ); 52 | json.values.forEach(removeBlankEntries); 53 | // If the map is empty after removing blank entries, return null to remove it. 54 | return json.isEmpty ? null : json; 55 | 56 | } 57 | return json; 58 | } 59 | 60 | Future processJsonFiles() async { 61 | final Directory directory = Directory.current; 62 | final List files = directory.listSync(); 63 | 64 | for (final file in files) { 65 | try { 66 | if (file is File && file.path.endsWith('.json')) { 67 | final String contents = await file.readAsString(); 68 | final dynamic json = jsonDecode(contents); 69 | final dynamic processedJson = removeBlankEntries(json); 70 | bool isEmpty = false; 71 | 72 | if (processedJson is Map) { 73 | isEmpty = processedJson.values.every((value) => value is Map && value.isEmpty); 74 | } 75 | 76 | if (processedJson == null || isEmpty) { 77 | await file.delete(); 78 | print('🗑️ File deleted: ${file.path}'); 79 | } else { 80 | await file.writeAsString( 81 | const JsonEncoder.withIndent(' ').convert(processedJson), 82 | ); 83 | print('🥞 Task successful on: ${file.path}'); 84 | } 85 | } 86 | } catch (e) { 87 | print('💥 Task failed on: ${file.path}: $e'); 88 | } 89 | } 90 | } 91 | 92 | void main() async { 93 | processJsonFiles(); 94 | } 95 | -------------------------------------------------------------------------------- /assets/i18n/or_IN.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "okButton": "ଠିକ୍ ଅଛି", 3 | "yesButton": "ହଁ", 4 | "noButton": "ନାହିଁ", 5 | "warning": "ଚେତାଵନୀ", 6 | "navigationView": { 7 | "patcherTab": "ରଫୁକାର", 8 | "settingsTab": "ସେଟିଂ" 9 | }, 10 | "homeView": { 11 | "updateChangelogTitle": "ପରିବର୍ତ୍ତନ ପୋଥି", 12 | "noConnection": "କୌଣସି ଇଣ୍ଟର୍‌ନେଟ୍ ସଂଯୋଗ ନାହିଁ" 13 | }, 14 | "applicationItem": { 15 | "infoButton": "ସୂଚନା" 16 | }, 17 | "latestCommitCard": { 18 | "timeagoLabel": "${time} ପୂର୍ବେ" 19 | }, 20 | "patcherView": { 21 | "widgetTitle": "ରଫୁକାର", 22 | "patchButton": "ରଫୁ" 23 | }, 24 | "appSelectorCard": {}, 25 | "patchSelectorCard": {}, 26 | "socialMediaCard": { 27 | "widgetSubtitle": "ଆମେ ଅନଲାଇନ୍ ଅଛୁ!" 28 | }, 29 | "appSelectorView": { 30 | "storageButton": "ଷ୍ଟୋରେଜ୍" 31 | }, 32 | "patchesSelectorView": { 33 | "doneButton": "ହେଲା", 34 | "defaultChip": "ଡିଫଲ୍ଟ", 35 | "defaultTooltip": "ସମସ୍ତ ଡିଫଲ୍ଟ ରଫୁ ଚୟନ କର" 36 | }, 37 | "patchOptionsView": {}, 38 | "patchItem": {}, 39 | "installerView": {}, 40 | "settingsView": { 41 | "widgetTitle": "ସେଟିଂ", 42 | "appearanceSectionTitle": "ରୂପ", 43 | "teamSectionTitle": "ଦଳ", 44 | "advancedSectionTitle": "ଵିକଶିତ", 45 | "exportSectionTitle": "ଆମଦାନୀ ଓ ରପ୍ତାନି", 46 | "themeModeLabel": "ଆପ୍ ଥିମ୍", 47 | "systemThemeLabel": "ସିଷ୍ଟମ୍", 48 | "lightThemeLabel": "ହାଲୁକା", 49 | "darkThemeLabel": "ଗାଢ଼", 50 | "languageLabel": "ଭାଷା", 51 | "languageUpdated": "ଭାଷା ଅଦ୍ୟତନ କରାଗଲା", 52 | "apiURLLabel": "APIର URL", 53 | "selectApiURL": "APIର URL", 54 | "aboutLabel": "ସମ୍ବନ୍ଧରେ", 55 | "snackbarMessage": "କ୍ଲିପବୋର୍ଡରେ କପି କରିନିଆଗଲା" 56 | }, 57 | "appInfoView": { 58 | "widgetTitle": "ଆପ୍ ସୂଚନା", 59 | "rootDialogTitle": "ତ୍ରୁଟି" 60 | }, 61 | "contributorsView": {}, 62 | "installErrorDialog": {} 63 | } -------------------------------------------------------------------------------- /assets/i18n/sw_KE.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationView": {}, 3 | "homeView": {}, 4 | "applicationItem": {}, 5 | "latestCommitCard": {}, 6 | "patcherView": {}, 7 | "appSelectorCard": {}, 8 | "patchSelectorCard": { 9 | "widgetSubtitle": "Chagua programu kwanza" 10 | }, 11 | "socialMediaCard": {}, 12 | "appSelectorView": {}, 13 | "patchesSelectorView": {}, 14 | "patchOptionsView": {}, 15 | "patchItem": {}, 16 | "installerView": {}, 17 | "settingsView": {}, 18 | "appInfoView": {}, 19 | "contributorsView": {}, 20 | "installErrorDialog": {} 21 | } -------------------------------------------------------------------------------- /assets/i18n/te_IN.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "okButton": "సరే", 3 | "cancelButton": "రద్దుచేయి", 4 | "dismissButton": "రద్దుచేయు", 5 | "quitButton": "నిష్క్రమించు", 6 | "updateButton": "అప్డేట్", 7 | "yesButton": "అవును", 8 | "noButton": "కాదు", 9 | "warning": "హెచ్చరిక", 10 | "notice": "నోటీసు", 11 | "noShowAgain": "దీనిని మళ్లీ చూపవద్దు", 12 | "add": "జోడించు", 13 | "remove": "తొలగించు", 14 | "showChangelogButton": "మార్పులను చూపించండి", 15 | "navigationView": { 16 | "dashboardTab": "డాష్‌బోర్డ్", 17 | "patcherTab": "ప్యాచర్", 18 | "settingsTab": "సెట్టింగులు" 19 | }, 20 | "homeView": { 21 | "refreshSuccess": "విజయవంతంగా రిఫ్రెష్ చేయబడింది", 22 | "widgetTitle": "డాష్‌బోర్డ్", 23 | "updatesSubtitle": "అప్డేట్లు", 24 | "patchedSubtitle": "ఇన్‌స్టాల్ చేయబడిన యాప్‌లు", 25 | "noInstallations": "ప్యాచ్ చేయబడిన అప్లికేషన్లు ఏమి లేవు", 26 | "updateDialogTitle": "కొత్త నవీకరణ అందుబాటులో ఉంది", 27 | "updateChangelogTitle": "మార్పుల సంచిక", 28 | "downloadingMessage": "అప్డేట్ డౌన్లోడ్ చేయబడుతోంది...", 29 | "downloadedMessage": "అప్‌డేట్ డౌన్‌లోడ్ అయింది", 30 | "installingMessage": "అప్డేట్ ఇన్స్టాల్ చేయబడుతోంది...", 31 | "errorDownloadMessage": "అప్డేట్ డౌన్లోడ్ చేయుట కుదరలేదు", 32 | "errorInstallMessage": "అప్డేట్ ఇన్స్టాల్ చేయుట కుదరలేదు", 33 | "noConnection": "ఇంటర్నెట్ కనెక్షన్ లేదు" 34 | }, 35 | "applicationItem": { 36 | "infoButton": "సమాచారం" 37 | }, 38 | "latestCommitCard": { 39 | "loadingLabel": "లోడ్ అవుతుంది..." 40 | }, 41 | "patcherView": { 42 | "widgetTitle": "పూడ్చేది", 43 | "patchButton": "అతుకు" 44 | }, 45 | "appSelectorCard": { 46 | "widgetTitle": "ఒక యాప్‌ని ఎంచుకోండి", 47 | "noAppsLabel": "ఏ అనువర్తనాలూ లేవు" 48 | }, 49 | "patchSelectorCard": { 50 | "widgetTitle": "అతుకులు ఎంచుకోండి", 51 | "widgetTitleSelected": "ఎంచుకున్న అతుకులు", 52 | "widgetSubtitle": "ముందు అనువర్తనాన్ని ఎంచుకోండి", 53 | "widgetEmptySubtitle": "అతుకులు ఏవీ ఎంచుకోబడలేదు" 54 | }, 55 | "socialMediaCard": { 56 | "widgetTitle": "సామాజికాలు", 57 | "widgetSubtitle": "మేము ఆన్లైన్లో ఉన్నాం!" 58 | }, 59 | "appSelectorView": { 60 | "viewTitle": "ఒక యాప్‌ని ఎంచుకోండి", 61 | "storageButton": "నిల్వ", 62 | "errorMessage": "ఎంచుకున్న అనువర్తనాన్ని వాడలేకపోయాం" 63 | }, 64 | "patchesSelectorView": { 65 | "viewTitle": "అతుకులు ఎంచుకోండి", 66 | "searchBarHint": "అతుకులు వెతకండి", 67 | "patches": "Patches", 68 | "doneButton": "అయింది", 69 | "noneChip": "ఏదీ కాదు" 70 | }, 71 | "patchOptionsView": { 72 | "saveOptions": "భద్రపరచు" 73 | }, 74 | "patchItem": {}, 75 | "installerView": { 76 | "installButton": "స్థాపించు", 77 | "openButton": "తెరువు", 78 | "notificationTitle": "రీవాన్సడ్ మేనేజర్ పాచ్ చేస్తుంది" 79 | }, 80 | "settingsView": { 81 | "widgetTitle": "అమరికలు", 82 | "appearanceSectionTitle": "స్వరూపం", 83 | "teamSectionTitle": "జట్టు", 84 | "advancedSectionTitle": "అధునాతన", 85 | "dynamicThemeLabel": "Material You", 86 | "dynamicThemeHint": "మీ పరికరానికి దగ్గరి అనుభవాన్ని ఆనందించండి", 87 | "languageLabel": "భాషలు", 88 | "contributorsLabel": "దోహదకారి", 89 | "aboutLabel": "గురించి", 90 | "snackbarMessage": "క్లిప్‌బోర్డ్‌కి కాపీ అయింది" 91 | }, 92 | "appInfoView": { 93 | "widgetTitle": "అనువర్తన సమాచారం", 94 | "openButton": "తెరువు", 95 | "installButton": "స్థాపించు", 96 | "uninstallButton": "తీసివేయు", 97 | "rootDialogTitle": "లోపం" 98 | }, 99 | "contributorsView": { 100 | "widgetTitle": "దోహదకారి" 101 | }, 102 | "installErrorDialog": { 103 | "install_failed_verification_failure": "ధృవీకరణ విఫలమైంది" 104 | } 105 | } -------------------------------------------------------------------------------- /assets/i18n/ur_PK.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "okButton": "ٹھیک ہے", 3 | "cancelButton": "منسوخ کریں۔", 4 | "quitButton": "چھوڑو", 5 | "updateButton": "اپڈیٹ", 6 | "suggested": "تجویز کردہ: ${version}", 7 | "yesButton": "ہاں", 8 | "noButton": "نہیں", 9 | "warning": "انتباہ", 10 | "notice": "اطلاع", 11 | "noShowAgain": "اسے دوبارہ مت دکھائیں۔", 12 | "add": "شامل کریں۔", 13 | "navigationView": { 14 | "dashboardTab": "ڈیش بورڈ", 15 | "patcherTab": "پیچر", 16 | "settingsTab": "ترتیبات" 17 | }, 18 | "homeView": { 19 | "refreshSuccess": "کامیابی کے ساتھ ریفریش کیا گیا", 20 | "widgetTitle": "ڈیش بورڈ", 21 | "updatesSubtitle": "اپڈیٹس", 22 | "patchedSubtitle": "پیچ شدہ ایپلی کیشنز", 23 | "noInstallations": "کوئی پیچ شدہ ایپلیکیشن انسٹالڈ نہیں", 24 | "installUpdate": "اپڈیٹس انسٹال کرنا جاری رکھیں؟", 25 | "updateChangelogTitle": "تبدیلیوں کے لاگز", 26 | "downloadingMessage": "اپ ڈیٹ ڈونلوڈ ہو رہی ہے...", 27 | "installingMessage": "اپ ڈیٹ انسٹال ہو رہی ہے...", 28 | "errorDownloadMessage": "اپ ڈیٹ ڈونلوڈ نہیں ہو سکی", 29 | "errorInstallMessage": "اپڈیٹ انسٹال نہیں ہو سکی", 30 | "noConnection": "انٹرنیٹ کنکشن میسر نہیں" 31 | }, 32 | "applicationItem": { 33 | "infoButton": "معلومات نامہ" 34 | }, 35 | "latestCommitCard": { 36 | "loadingLabel": "لوڈ ہو رہا ہے...", 37 | "timeagoLabel": "${time} پہلے" 38 | }, 39 | "patcherView": { 40 | "widgetTitle": "پیچر", 41 | "patchButton": "پیچ کریں" 42 | }, 43 | "appSelectorCard": { 44 | "noAppsLabel": "کوئی ایپلیکیشن نہیں ملی" 45 | } 46 | } -------------------------------------------------------------------------------- /assets/i18n/uz_UZ.i18n.json: -------------------------------------------------------------------------------- 1 | { 2 | "okButton": "OK", 3 | "cancelButton": "Bekor qilish", 4 | "dismissButton": "O'tkazib yuborish", 5 | "quitButton": "Chiqish", 6 | "updateButton": "Yangilash", 7 | "suggested": "Taklif etilgan versiya: ${version}", 8 | "yesButton": "Xa", 9 | "noButton": "Yo'q", 10 | "warning": "Ogohlantirish", 11 | "notice": "Eslatma", 12 | "noShowAgain": "Boshqa ko'rsatilmasin", 13 | "add": "Qo'shish", 14 | "remove": "Olib tashlash", 15 | "showChangelogButton": "O'zgarishlarni ko'rsatish", 16 | "showUpdateButton": "Yangilanishni ko'rish", 17 | "navigationView": { 18 | "dashboardTab": "Asboblar", 19 | "settingsTab": "Sozlamalar" 20 | }, 21 | "homeView": { 22 | "refreshSuccess": "Muvaffaqiyatli yangilandi", 23 | "widgetTitle": "Asboblar", 24 | "updatesSubtitle": "Yangilanishlar", 25 | "changeLaterSubtitle": "Keyinroq sozlamalardan o'zgartirishingiz mumkin.", 26 | "noInstallations": "Patchlangan dasturlar o'rnatilmagan", 27 | "installUpdate": "Yangilanish o'rnatilishi davom ettirilsinmi?", 28 | "updateSheetTitle": "ReVanced Managerni yangilash", 29 | "updateDialogTitle": "Yangilanish mavjud", 30 | "updatePatchesSheetTitle": "ReVanched Patchlarni yangilash", 31 | "updateChangelogTitle": "O'zgarishlar", 32 | "updateDialogText": "${file} uchun yangilanish mavjud.\n\nHozirgi o'rnatilgan versiya: ${version}.", 33 | "downloadConsentDialogTitle": "Ba'zi fayllarni yuklab olish?", 34 | "downloadConsentDialogText": "ReVanced Manager ishlashi uchun ba'zi fayllarni yuklab olish kerak.", 35 | "downloadingMessage": "Yangilanishlar otvotti...", 36 | "downloadedMessage": "Yangilanish otqizildi", 37 | "installingMessage": "Yangilanishlar ornatib olinvotti...", 38 | "errorDownloadMessage": "Yangilanishni otqizib bomadi", 39 | "errorInstallMessage": "Yangilanishni ornatib bolmadi", 40 | "noConnection": "Internet bog‘lanishingiz yoq" 41 | }, 42 | "applicationItem": { 43 | "infoButton": "Ma'lumot" 44 | }, 45 | "latestCommitCard": { 46 | "loadingLabel": "Yuklanmoqda..." 47 | }, 48 | "patcherView": { 49 | "patchButton": "Patch" 50 | }, 51 | "appSelectorCard": { 52 | "noAppsLabel": "Ilovalar topilmadi" 53 | }, 54 | "patchSelectorCard": { 55 | "widgetTitle": "Patchlarni tanlang", 56 | "widgetTitleSelected": "Tanlangan patchlar", 57 | "widgetSubtitle": "Ilovani birinchi tanlang" 58 | }, 59 | "socialMediaCard": {}, 60 | "appSelectorView": {}, 61 | "patchesSelectorView": { 62 | "viewTitle": "Patchlarni tanlang", 63 | "patches": "Patches" 64 | }, 65 | "patchOptionsView": {}, 66 | "patchItem": {}, 67 | "installerView": {}, 68 | "settingsView": { 69 | "widgetTitle": "Sozlamalar", 70 | "exportSectionTitle": "Import & eksport", 71 | "sourcesResetDialogTitle": "Oddiy holga qaytarish", 72 | "apiURLLabel": "API URL", 73 | "selectApiURL": "API URL", 74 | "sourcesPatchesLabel": "Patchlarni manbai", 75 | "contributorsLabel": "Yordamchilar", 76 | "contributorsHint": "ReVanced yordamchilani royxati", 77 | "aboutLabel": "Haqida", 78 | "snackbarMessage": "Vaqtinchalik xotiraga nusxalandi" 79 | }, 80 | "appInfoView": {}, 81 | "contributorsView": { 82 | "widgetTitle": "Yordamchilar" 83 | }, 84 | "installErrorDialog": {} 85 | } -------------------------------------------------------------------------------- /assets/revanced-logo/revanced-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | project_id_env: "CROWDIN_PROJECT_ID" 2 | api_token_env: "CROWDIN_PERSONAL_TOKEN" 3 | 4 | preserve_hierarchy: false 5 | files: 6 | - source: /assets/i18n/en.i18n.json 7 | translation: /assets/i18n/%locale_with_underscore%.i18n.json 8 | skip_untranslated_strings: true 9 | -------------------------------------------------------------------------------- /docs/0_prerequisites.md: -------------------------------------------------------------------------------- 1 | # 💼 Prerequisites 2 | 3 | To use ReVanced Manager, you need to fulfill certain requirements. 4 | 5 | ## 🤝 Requirements 6 | 7 | - Android device running Android 8.0 or higher 8 | - Device's CPU supporting at least `arm64-v8a`, `armeabi-v7a`, or `x86_64` architecture(s) 9 | 10 | ## ⏭️ What's next 11 | 12 | The next page will explain how to install ReVanced Manager. 13 | 14 | Continue: [⬇️ Installation](1_installation.md) 15 | -------------------------------------------------------------------------------- /docs/1_installation.md: -------------------------------------------------------------------------------- 1 | # ⬇️ Installation 2 | 3 | To use ReVanced on your Android device, ReVanced Manager must be first installed. 4 | 5 | ## ✅ Installation steps 6 | 7 | 1. Download the latest version of ReVanced Manager at [revanced.app/download](https://revanced.app/download) or from [GitHub releases](https://github.com/ReVanced/revanced-manager/releases/latest) 8 | 2. Install ReVanced Manager 9 | 10 | ## ⏭️ What's next 11 | 12 | The next page explain how to use ReVanced Manager to update ReVanced Manager and manage or patch apps. 13 | 14 | Continue: [🛠️ Usage](2_usage.md) 15 | -------------------------------------------------------------------------------- /docs/2_1_patching.md: -------------------------------------------------------------------------------- 1 | # 🧩 Patching apps 2 | 3 | Learn how to use ReVanced Manager to patch apps. 4 | 5 | ## ✅ Steps to patch apps 6 | 7 | 1. Navigate to the **Patcher** tab from the bottom navigation bar 8 | 2. Tap on the **Select an app** card 9 | 3. Choose an app to patch[^1] 10 | 11 | > ℹ️ Note 12 | > The suggested version is visible on each app's card. 13 | > You can tap on it to open a search query to obtain an APK file for the selected app with the suggested version 14 | 15 | > 💡 Tip 16 | > If you are prompted to select an APK file from storage because the selected app is a split APK, tap on the "Suggested version" label to open a search query to obtain said APK file 17 | 18 | 4. Tap on the **Select patches** card and select the patches you want to apply[^2]. 19 | 20 | > ℹ️ Note 21 | > Some patches have options that can or must be configured by tapping on ⚙️ icon next to the patch name. 22 | 23 | > ⚠️ Warning 24 | > If you see a warning, you can click on it for more information. 25 | 26 | 5. Tap on the **Done** then **Patch** button 27 | 28 | > ⚠️ Warning 29 | > The patching process may take ~5 minutes. Exiting the app may cancel patching or significantly increase the time it takes to patch. 30 | 31 | 6. Tap on the **Install** button 32 | 33 | > ℹ️ Note 34 | > If you are rooted, you can mount[^3] the patched app on top of the original app.[^4] 35 | > Optionally, you may export the patched app to storage using the option in the bottom left corner. 36 | 37 | [^1]: You can select installed apps from the list of installed apps or APK files from device storage. ReVanced does not provide any APK files, so you must source them yourself. 38 | [^2]: It is suggested to use the default set of patches by tapping on the **Default** button above the list of patches. 39 | [^3]: Mounting refers to using Linux's mounting mechanism to layer the patched app on top of the existing installed app. 40 | [^4]: Mounting the patched app on top of the original app may only work if the installed app version matches the version of the app selected in step 3. above. 41 | 42 | ## ⏭️ What's next 43 | 44 | The next page will explain how to view, open and uninstall patched apps. 45 | 46 | Continue: [🧰 Managing patched apps](2_2_managing.md) 47 | -------------------------------------------------------------------------------- /docs/2_2_managing.md: -------------------------------------------------------------------------------- 1 | # 🧰 Managing patched apps 2 | 3 | Learn how to view, open and uninstall patched apps. 4 | 5 | ## ✅ Steps to view, open and uninstall patched apps 6 | 7 | 1. Tap on the **Dashboard** tab in the bottom navigation bar 8 | 2. Tap on the **Info** button for the app you want to manage 9 | 3. Choose any of the options from the menu to view, open or uninstall the app 10 | 11 | ## ⏭️ What's next 12 | 13 | The next page will explain how to update ReVanced Manager. 14 | 15 | Continue: [🔄 Updating ReVanced Manager](2_3_updating.md) 16 | -------------------------------------------------------------------------------- /docs/2_3_updating.md: -------------------------------------------------------------------------------- 1 | # 🔄 Updating ReVanced Manager 2 | 3 | Learn how to update ReVanced Manager. 4 | 5 | ## ✅ Updating steps 6 | 7 | 1. Navigate to the **Dashboard** tab from the bottom navigation bar 8 | 2. Tap on the **Update** button in the **Updates** section 9 | 10 | ## ⏭️ What's next 11 | 12 | The next page will explain how to configure ReVanced Manager. 13 | 14 | Continue: [⚙️ Configuring ReVanced Manager](2_4_settings.md) 15 | -------------------------------------------------------------------------------- /docs/2_4_settings.md: -------------------------------------------------------------------------------- 1 | # ⚙️ Configuring ReVanced Manager 2 | 3 | Learn how to configure ReVanced Manager. 4 | 5 | ## 🎛️ Essential settings 6 | 7 | - ### 🪛 Allow changing patch selection 8 | 9 | By default, you can not change the patch selection and the default selection is used. Enabling this will allow you to change the patch selection. 10 | 11 | > ⚠️ Warning 12 | > Changing the selection may cause unexpected issues. Unless you know what you are doing, it is recommended to keep this disabled. 13 | 14 | - ### 📦 Require suggested app version 15 | 16 | By default, ReVanced Manager allows you to patch an app if the suggested version to patch matches the version of the app you selected. Disabling this will allow you to patch an app even if the suggested version does not match the version of the app you selected. 17 | 18 | > ⚠️ Warning 19 | > Patches are more likely to fail on versions that are not suggested by ReVanced Manager. Unless you know what you are doing, it is recommended to keep this enabled. 20 | 21 | - ### ✅ Version compatibility check 22 | 23 | By default, ReVanced Manager does not allow you to select patches that are not compatible with the version of the app you selected. Disabling this will allow you to select patches that are not compatible with the version of the app you selected. 24 | 25 | > ⚠️ Warning 26 | > Patches are more likely to fail on versions they are not compatible with. Unless you know what you are doing, it is recommended to keep this enabled. 27 | 28 | - ### 🧑‍🔬 Show universal patches 29 | 30 | By default, ReVanced Manager only shows patches that are compatible with specific apps. Enabling this will show patches that are intended to work on all apps. 31 | 32 | > ⚠️ Warning 33 | > Patches that are intended to may not work on all apps. Unless you know what you are doing, it is recommended to keep this disabled. 34 | 35 | - ### 🔗 API URL 36 | 37 | Configure the API URL to use. The API is used to download patches and updates. 38 | 39 | - ### 🧬 Use alternative source 40 | 41 | Use alternative sources for patches and integrations instead of the API. 42 | 43 | > ℹ️ Note 44 | > ReVanced Manager will still use the API for updates. 45 | 46 | - ### 💾 Import, export and reset options 47 | 48 | You can import, export or reset saved settings. This includes: 49 | 50 | - 🔑 Keystore used to sign patched apps 51 | - 📄 Remembered selection of patches for each app 52 | - ⚙️ Remembered patch options 53 | - 🛠️ Remembered settings 54 | 55 | > ℹ️ Note 56 | > These can be used to backup and restore or reset settings to default in case of issues. 57 | 58 | - ### ❓ About 59 | 60 | View information about your device and ReVanced Manager. This includes the version of ReVanced Manager and architectures your device supports. 61 | 62 | ## ⏭️ What's next 63 | 64 | The next page will explain how to troubleshoot issues with ReVanced Manager. 65 | 66 | Continue: [❔ Troubleshooting](3_troubleshooting.md) 67 | -------------------------------------------------------------------------------- /docs/2_usage.md: -------------------------------------------------------------------------------- 1 | # 🛠️ Usage 2 | 3 | Learn how to use ReVanced Manager to manage and patch apps or update ReVanced Manager. 4 | 5 | ## 📖 Table of contents 6 | 7 | 1. [🧩 Patching apps](2_1_patching.md) 8 | 2. [🧰 Managing patched apps](2_2_managing.md) 9 | 3. [🔄 Updating ReVanced Manager](2_3_updating.md) 10 | 4. [⚙️ Configuring ReVanced Manager](2_4_settings.md) 11 | 12 | ## ⏭️ What's next 13 | 14 | The next page will explain how to use ReVanced Manager to patch apps. 15 | 16 | Continue: [🧩 Patching apps](2_1_patching.md) 17 | -------------------------------------------------------------------------------- /docs/3_troubleshooting.md: -------------------------------------------------------------------------------- 1 | # ❔ Troubleshooting 2 | 3 | In case you encounter any issues while using ReVanced Manager, this page will help you troubleshoot them. 4 | 5 | - 💉 Common issues during or after patching 6 | 7 | - Make sure ReVanced Manager is up to date by following [🔄 Updating ReVanced Manager](2_3_updating.md) 8 | - You may have changed settings in ReVanced Manager that are not recommended to change. Please review the warnings that appear when adjusting these settings and reset them to their default configuration as explained in [⚙️ Configuring ReVanced Manager](2_4_settings.md) 9 | 10 | - 🚫 App not installed as package conflicts with an existing package 11 | 12 | An existing installation of the app you're trying to patch conflicts with the patched app (i.e., signature mismatch or downgrade). Uninstall the existing app before installing the patched app. 13 | 14 | > 💡 Tip 15 | > This may also be caused by changing settings in ReVanced Manager that are not recommended to change. Please review the warnings that appear when adjusting these settings and reset them to their default configuration as explained in [⚙️ Configuring ReVanced Manager](2_4_settings.md) 16 | 17 | - ❗️ Error code `135`, `139` or `1` when patching the app 18 | 19 | - You may be trying to patch a split APK[^1]. This can fail under certain circumstances. If that is the case, patch a full APK 20 | - Your device may otherwise be unsupported. Please look at the [Prerequisites](0_prerequisites.md) page to see if your device is supported. Alternatively, you can use [ReVanced CLI](https://github.com/revanced/revanced-cli) to patch the app. 21 | 22 | - 🚨 Patched app crashes on launch 23 | 24 | This may also be caused by changing settings in ReVanced Manager that are not recommended to change. Please review the warnings that appear when adjusting these settings and reset them to their default configuration as explained in [⚙️ Configuring ReVanced Manager](2_4_settings.md) 25 | 26 | ## ⏭️ What's next 27 | 28 | The next page will teach you how to build ReVanced Manager from source. 29 | 30 | Continue: [🔨 Building from source](4_building.md) 31 | 32 | [^1]: https://developer.android.com/guide/app-bundle/app-bundle-format 33 | -------------------------------------------------------------------------------- /docs/4_building.md: -------------------------------------------------------------------------------- 1 | # 🛠️ Building from source 2 | 3 | Learn how to build ReVanced Manager from source. 4 | 5 | 1. Setup the Flutter environment for your [platform](https://docs.flutter.dev/get-started/install) 6 | 7 | 2. Clone the repository 8 | 9 | ```sh 10 | git clone https://github.com/revanced/revanced-manager.git && cd revanced-manager 11 | ``` 12 | 13 | 3. Get dependencies 14 | 15 | ```sh 16 | flutter pub get 17 | ``` 18 | 19 | 4. Generate temporary files 20 | 21 | ```sh 22 | dart run slang 23 | dart run build_runner build -d 24 | ``` 25 | 26 | 5. Build the APK 27 | 28 | ```sh 29 | flutter build apk 30 | ``` 31 | 32 | > [!NOTE] 33 | > If the build fails due to authentication, you may need to authenticate to GitHub Packages. 34 | > Create a PAT with the scope `read:packages` [here](https://github.com/settings/tokens/new?scopes=read:packages&description=ReVanced) and add your token to ~/.gradle/gradle.properties. 35 | > 36 | > Example `gradle.properties` file: 37 | > 38 | > ```properties 39 | > gpr.user = user 40 | > gpr.key = key 41 | > ``` 42 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # 💊 ReVanced Manager 2 | 3 | This documentation explains how to use [ReVanced Manager](https://github.com/revanced/revanced-manager). 4 | 5 | ## 📖 Table of contents 6 | 7 | 0. [💼 Prerequisites](0_prerequisites.md) 8 | 1. [⬇️ Installation](1_installation.md) 9 | 2. [🛠️ Usage](2_usage.md) 10 | 1. [🧩 Patching apps](2_1_patching.md) 11 | 2. [🧰 Managing patched apps](2_2_managing.md) 12 | 3. [🔄 Updating ReVanced Manager](2_3_updating.md) 13 | 4. [⚙️ Configuring ReVanced Manager](2_4_settings.md) 14 | 3. [❔ Troubleshooting](3_troubleshooting.md) 15 | 4. [🔨 Building from source](4_building.md) 16 | 17 | ## ⏭️ Start here 18 | 19 | The next page will tell you about the prerequisites for using ReVanced Manager. 20 | 21 | Continue: [💼 Prerequisites](0_prerequisites.md) 22 | -------------------------------------------------------------------------------- /fonts/custom-icons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReVanced/revanced-manager/a8e192b85f433210bf7df7049d653119c8da1f16/fonts/custom-icons.ttf -------------------------------------------------------------------------------- /lib/app/app.dart: -------------------------------------------------------------------------------- 1 | import 'package:revanced_manager/services/download_manager.dart'; 2 | import 'package:revanced_manager/services/github_api.dart'; 3 | import 'package:revanced_manager/services/manager_api.dart'; 4 | import 'package:revanced_manager/services/patcher_api.dart'; 5 | import 'package:revanced_manager/services/revanced_api.dart'; 6 | import 'package:revanced_manager/services/toast.dart'; 7 | import 'package:revanced_manager/ui/views/app_selector/app_selector_view.dart'; 8 | import 'package:revanced_manager/ui/views/contributors/contributors_view.dart'; 9 | import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; 10 | import 'package:revanced_manager/ui/views/installer/installer_view.dart'; 11 | import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart'; 12 | import 'package:revanced_manager/ui/views/navigation/navigation_view.dart'; 13 | import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart'; 14 | import 'package:revanced_manager/ui/views/patch_options/patch_options_view.dart'; 15 | import 'package:revanced_manager/ui/views/patch_options/patch_options_viewmodel.dart'; 16 | import 'package:revanced_manager/ui/views/patcher/patcher_view.dart'; 17 | import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart'; 18 | import 'package:revanced_manager/ui/views/patches_selector/patches_selector_view.dart'; 19 | import 'package:revanced_manager/ui/views/settings/settings_view.dart'; 20 | import 'package:revanced_manager/ui/widgets/appInfoView/app_info_view.dart'; 21 | import 'package:stacked/stacked_annotations.dart'; 22 | import 'package:stacked_services/stacked_services.dart'; 23 | 24 | @StackedApp( 25 | routes: [ 26 | MaterialRoute(page: NavigationView), 27 | MaterialRoute(page: PatcherView), 28 | MaterialRoute(page: AppSelectorView), 29 | MaterialRoute(page: PatchesSelectorView), 30 | MaterialRoute(page: PatchOptionsView), 31 | MaterialRoute(page: InstallerView), 32 | MaterialRoute(page: SettingsView), 33 | MaterialRoute(page: ContributorsView), 34 | MaterialRoute(page: AppInfoView), 35 | ], 36 | dependencies: [ 37 | LazySingleton(classType: NavigationViewModel), 38 | LazySingleton(classType: HomeViewModel), 39 | LazySingleton(classType: PatcherViewModel), 40 | LazySingleton(classType: PatchOptionsViewModel), 41 | LazySingleton(classType: InstallerViewModel), 42 | LazySingleton(classType: NavigationService), 43 | LazySingleton(classType: ManagerAPI), 44 | LazySingleton(classType: PatcherAPI), 45 | LazySingleton(classType: RevancedAPI), 46 | LazySingleton(classType: GithubAPI), 47 | LazySingleton(classType: DownloadManager), 48 | LazySingleton(classType: Toast), 49 | ], 50 | ) 51 | class AppSetup {} 52 | -------------------------------------------------------------------------------- /lib/main.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:revanced_manager/app/app.locator.dart'; 3 | import 'package:revanced_manager/gen/strings.g.dart'; 4 | import 'package:revanced_manager/services/download_manager.dart'; 5 | import 'package:revanced_manager/services/github_api.dart'; 6 | import 'package:revanced_manager/services/manager_api.dart'; 7 | import 'package:revanced_manager/services/revanced_api.dart'; 8 | import 'package:revanced_manager/services/root_api.dart'; 9 | import 'package:revanced_manager/ui/theme/dynamic_theme_builder.dart'; 10 | import 'package:revanced_manager/ui/views/navigation/navigation_view.dart'; 11 | import 'package:shared_preferences/shared_preferences.dart'; 12 | import 'package:timezone/data/latest.dart' as tz; 13 | 14 | late SharedPreferences prefs; 15 | Future main() async { 16 | await setupLocator(); 17 | WidgetsFlutterBinding.ensureInitialized(); 18 | await locator().initialize(); 19 | 20 | await locator().initialize(); 21 | final String apiUrl = locator().getApiUrl(); 22 | await locator().initialize(apiUrl); 23 | final String repoUrl = locator().getRepoUrl(); 24 | locator().initialize(repoUrl); 25 | tz.initializeTimeZones(); 26 | 27 | // TODO(aAbed): remove in the future, keep it for now during migration. 28 | final rootAPI = RootAPI(); 29 | if (await rootAPI.hasRootPermissions()) { 30 | await rootAPI.removeOrphanedFiles(); 31 | } 32 | 33 | prefs = await SharedPreferences.getInstance(); 34 | 35 | final managerAPI = locator(); 36 | final locale = managerAPI.getLocale(); 37 | LocaleSettings.setLocaleRaw(locale); 38 | 39 | runApp(TranslationProvider(child: const MyApp())); 40 | } 41 | 42 | class MyApp extends StatelessWidget { 43 | const MyApp({super.key}); 44 | 45 | @override 46 | Widget build(BuildContext context) { 47 | return const DynamicThemeBuilder( 48 | title: 'ReVanced Manager', 49 | home: NavigationView(), 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/models/patch.dart: -------------------------------------------------------------------------------- 1 | import 'package:json_annotation/json_annotation.dart'; 2 | 3 | part 'patch.g.dart'; 4 | 5 | @JsonSerializable() 6 | class Patch { 7 | Patch({ 8 | required this.name, 9 | required this.description, 10 | required this.excluded, 11 | required this.compatiblePackages, 12 | required this.options, 13 | }); 14 | 15 | factory Patch.fromJson(Map json) { 16 | _migrateV16ToV17(json); 17 | 18 | return _$PatchFromJson(json); 19 | } 20 | 21 | static void _migrateV16ToV17(Map json) { 22 | if (json['options'] == null) { 23 | json['options'] = []; 24 | } 25 | } 26 | 27 | final String name; 28 | final String? description; 29 | final bool excluded; 30 | final List compatiblePackages; 31 | final List