Compare commits

..

4 Commits

Author SHA1 Message Date
semantic-release-bot
1997e474f2 chore(release): 1.0.0-dev.1 [skip ci]
# [1.0.0-dev.1](https://github.com/revanced/revanced-manager/compare/v0.0.57...v1.0.0-dev.1) (2023-04-29)

### Bug Fixes

* fix broken manager update implmentation ([6492507](6492507d0e))
* **i18n:** update translation for `refreshSucess` ([b286444](b286444ad9))
* open contributor links externally ([#791](https://github.com/revanced/revanced-manager/issues/791)) ([f0b0282](f0b028279c))
* resized monochrome icon to match the original ([#789](https://github.com/revanced/revanced-manager/issues/789)) ([ac830cb](ac830cbe7f))
* update pubspec version ([65da6af](65da6af3f9))

* chore!: merge `dev` to `main` (#830) ([782c012](782c0127b1)), closes [#830](https://github.com/revanced/revanced-manager/issues/830)

### Features

* add continue anyway button to select from storage dialog ([#810](https://github.com/revanced/revanced-manager/issues/810)) ([affba66](affba669ce))
* add option to import/export keystore ([#776](https://github.com/revanced/revanced-manager/issues/776)) ([dca2d4f](dca2d4fe12))
* appreciation message for new contributors ([0a1f2da](0a1f2da33d))
* auto select default patches ([4c9cb56](4c9cb560e3))
* change `continue anyways` to `cancel` ([cfc866b](cfc866bef2))
* **ci:** update crowdin workflow to use new main branch ([ded59d2](ded59d2da0))
* confirmation dialog for deleting keystore ([#764](https://github.com/revanced/revanced-manager/issues/764)) ([054afbb](054afbbedd))
* disable selecting installed apps for nonroot ([bb681e3](bb681e31c9))
* improve suggested app version text ([#822](https://github.com/revanced/revanced-manager/issues/822)) ([ad17995](ad17995f28))
* improve ux ([#752](https://github.com/revanced/revanced-manager/issues/752)) ([3b677f8](3b677f8ae3)), closes [#782](https://github.com/revanced/revanced-manager/issues/782)
* progress bar for manager updates ([f5aafdb](f5aafdb7d6))
* remove notice about stale development [skip ci] ([62f7a82](62f7a820d8))
* resetting source to default dismiss the sources pop-up ([#797](https://github.com/revanced/revanced-manager/issues/797)) ([62ef1c8](62ef1c88fe))
* trim extra space when setting custom source ([#771](https://github.com/revanced/revanced-manager/issues/771)) ([37b583f](37b583f560))
* warning for armv7 devices ([cdfb09f](cdfb09fbfa))

### BREAKING CHANGES

* this is to release as 1.0.0
2023-04-29 19:19:25 +00:00
Aunali321
6492507d0e fix: fix broken manager update implmentation 2023-04-30 00:39:42 +05:30
semantic-release-bot
3091f441ea chore(release): 1.0.0 [skip ci]
# [1.0.0](https://github.com/revanced/revanced-manager/compare/v0.0.57...v1.0.0) (2023-04-29)

### Bug Fixes

* **i18n:** update translation for `refreshSucess` ([b286444](b286444ad9))
* open contributor links externally ([#791](https://github.com/revanced/revanced-manager/issues/791)) ([f0b0282](f0b028279c))
* resized monochrome icon to match the original ([#789](https://github.com/revanced/revanced-manager/issues/789)) ([ac830cb](ac830cbe7f))
* update pubspec version ([65da6af](65da6af3f9))

* chore!: merge `dev` to `main` (#830) ([782c012](782c0127b1)), closes [#830](https://github.com/revanced/revanced-manager/issues/830)

### Features

* add continue anyway button to select from storage dialog ([#810](https://github.com/revanced/revanced-manager/issues/810)) ([affba66](affba669ce))
* add option to import/export keystore ([#776](https://github.com/revanced/revanced-manager/issues/776)) ([dca2d4f](dca2d4fe12))
* appreciation message for new contributors ([0a1f2da](0a1f2da33d))
* auto select default patches ([4c9cb56](4c9cb560e3))
* change `continue anyways` to `cancel` ([cfc866b](cfc866bef2))
* **ci:** update crowdin workflow to use new main branch ([ded59d2](ded59d2da0))
* confirmation dialog for deleting keystore ([#764](https://github.com/revanced/revanced-manager/issues/764)) ([054afbb](054afbbedd))
* disable selecting installed apps for nonroot ([bb681e3](bb681e31c9))
* improve suggested app version text ([#822](https://github.com/revanced/revanced-manager/issues/822)) ([ad17995](ad17995f28))
* improve ux ([#752](https://github.com/revanced/revanced-manager/issues/752)) ([3b677f8](3b677f8ae3)), closes [#782](https://github.com/revanced/revanced-manager/issues/782)
* progress bar for manager updates ([f5aafdb](f5aafdb7d6))
* remove notice about stale development [skip ci] ([62f7a82](62f7a820d8))
* resetting source to default dismiss the sources pop-up ([#797](https://github.com/revanced/revanced-manager/issues/797)) ([62ef1c8](62ef1c88fe))
* trim extra space when setting custom source ([#771](https://github.com/revanced/revanced-manager/issues/771)) ([37b583f](37b583f560))
* warning for armv7 devices ([cdfb09f](cdfb09fbfa))

### BREAKING CHANGES

* this is to release as 1.0.0
2023-04-29 18:16:26 +00:00
Palm
782c0127b1 chore!: merge dev to main (#830)
BREAKING CHANGE: this is to release as 1.0.0
2023-04-30 01:06:26 +07:00
441 changed files with 24564 additions and 30942 deletions

120
.github/ISSUE_TEMPLATE/bug-issue.yml vendored Normal file
View File

@@ -0,0 +1,120 @@
name: 🐞 Bug report
description: Report a very clearly broken issue.
title: 'bug: <title>'
labels: [bug]
body:
- type: markdown
attributes:
value: |
# ReVanced Manager bug report
Important to note that your issue may have already been reported before. Please check for existing issues [here](https://github.com/revanced/revanced-manager/labels/bug).
- type: dropdown
attributes:
label: Type
options:
- Error while running the manager
- Error at runtime
- Cosmetic
- Other
validations:
required: true
- type: textarea
attributes:
label: Bug description
description: How did you find the bug? Any additional details that might help?
validations:
required: true
- type: textarea
attributes:
label: Steps to reproduce
description: Add the steps to reproduce this bug including your environment.
placeholder: Step 1. Download some files. Step 2. ...
validations:
required: true
- type: textarea
attributes:
label: Android version
description: Android version used.
validations:
required: true
- type: textarea
attributes:
label: Manager version
description: Manager version used.
validations:
required: true
- type: textarea
attributes:
label: Target package name
description: App you tried to patch.
validations:
required: true
- type: textarea
attributes:
label: Target package version.
description: Version of the app you tried to patch.
validations:
required: true
- type: dropdown
attributes:
label: Installation type
options:
- Non-root
- Root
validations:
required: true
- type: textarea
attributes:
label: Patches selected.
description: Patches you selected for the app.
validations:
required: true
- type: textarea
attributes:
label: Device logs (exported using Manager settings).
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: true
- type: textarea
attributes:
label: Installer logs (exported using Installer menu option) [unneeded if issue is not during patching].
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: false
- type: textarea
attributes:
label: Screenshots or videos
description: Add screenshots or videos that show the bug here.
placeholder: Drag and drop the screenshots/videos into this box.
validations:
required: false
- type: textarea
attributes:
label: Solution
description: If applicable, add a possible solution.
validations:
required: false
- type: textarea
attributes:
label: Additional context
description: Add additional context here.
validations:
required: false
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Your issue will be closed if you haven't done these steps.
options:
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
required: true
- label: I have written a short but informative title.
required: true
- label: I filled out all of the requested information in this issue properly.
required: true
- label: The issue is related solely to the ReVanced Manager and not related to patching errors or patches
required: true

View File

@@ -1,109 +0,0 @@
name: 🐞 Bug report
description: Report a bug or an issue.
title: 'bug: '
labels: ['Bug report']
body:
- type: markdown
attributes:
value: |
<p align="center">
<picture>
<source
width="256px"
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-headline/revanced-headline-vertical-dark.svg"
>
<img
width="256px"
src="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-headline/revanced-headline-vertical-light.svg"
>
</picture>
<br>
<a href="https://revanced.app/">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-logo/revanced-logo.svg" />
<img height="24px" src="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-logo/revanced-logo.svg" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://github.com/ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="http://revanced.app/discord">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://reddit.com/r/revancedapp">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://t.me/app_revanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://x.com/revancedapp">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://www.youtube.com/@ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
</picture>
</a>
<br>
<br>
Continuing the legacy of Vanced
</p>
# ReVanced Manager bug report
Before creating a new bug report, please keep the following in mind:
- **Do not submit a duplicate bug report**: Search for existing bug reports [here](https://github.com/ReVanced/revanced-manager/issues?q=label%3A%22Bug+report%22).
- **Review the contribution guidelines**: Make sure your bug report adheres to it. You can find the guidelines [here](https://github.com/ReVanced/revanced-manager/blob/main/CONTRIBUTING.md).
- **Do not use the issue page for support**: If you need help or have questions, check out other platforms on [revanced.app](https://revanced.app).
- type: textarea
attributes:
label: Bug description
description: |
- Describe your bug in detail
- Add steps to reproduce the bug if possible (Step 1. ... Step 2. ...)
- Add images and videos if possible
- List used patches, downloader and settings if applicable
validations:
required: true
- type: textarea
attributes:
label: Patch logs
description: Patch logs can be exported by clicking on the "Logs" button in the "Patcher" screen, when patching finishes.
render: shell
- type: textarea
attributes:
label: Debug logs
description: Debug logs can be exported by clicking on "Export debug logs" in "Settings" > "Advanced".
validations:
required: true
- type: checkboxes
attributes:
label: Acknowledgements
description: Your bug report will be closed if you don't follow the checklist below.
options:
- label: I have checked all open and closed bug reports and this is not a duplicate.
required: true
- label: I have chosen an appropriate title.
required: true
- label: All requested information has been provided properly.
required: true
- label: The bug is only related to ReVanced Manager.
required: true

View File

@@ -1,5 +1 @@
blank_issues_enabled: false
contact_links:
- name: 🗨 Discussions
url: https://github.com/revanced/revanced-suggestions/discussions
about: Have something unspecific to ReVanced Manager in mind? Search for or start a new discussion!
blank_issues_enabled: false

View File

@@ -0,0 +1,52 @@
name: ⭐ Feature request
description: Create a detailed feature request.
title: 'feat: <title>'
labels: [feature-request]
body:
- type: dropdown
attributes:
label: Type
options:
- Functionality
- Cosmetic
- Other
validations:
required: true
- type: textarea
attributes:
label: Issue
description: What is the current problem. Why does it require a feature request?
validations:
required: true
- type: textarea
attributes:
label: Feature
description: Describe your feature in detail. How does it solve the issue?
validations:
required: true
- type: textarea
attributes:
label: Motivation
description: Why should your feature should be considered?
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: Add additional context here.
validations:
required: false
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Your issue will be closed if you haven't done these steps.
options:
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
required: true
- label: I have written a short but informative title.
required: true
- label: I filled out all of the requested information in this issue properly.
required: true
- label: The issue is related solely to the ReVanced Manager
required: true

View File

@@ -1,107 +0,0 @@
name: ⭐ Feature request
description: Create a detailed request for a new feature.
title: 'feat: '
labels: ['Feature request']
body:
- type: markdown
attributes:
value: |
<p align="center">
<picture>
<source
width="256px"
media="(prefers-color-scheme: dark)"
srcset="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-headline/revanced-headline-vertical-dark.svg"
>
<img
width="256px"
src="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-headline/revanced-headline-vertical-light.svg"
>
</picture>
<br>
<a href="https://revanced.app/">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-logo/revanced-logo.svg" />
<img height="24px" src="https://raw.githubusercontent.com/revanced/revanced-manager/main/assets/revanced-logo/revanced-logo.svg" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://github.com/ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="http://revanced.app/discord">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://reddit.com/r/revancedapp">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://t.me/app_revanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://x.com/revancedapp">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://www.youtube.com/@ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
</picture>
</a>
<br>
<br>
Continuing the legacy of Vanced
</p>
# ReVanced Manager feature request
Before creating a new feature request, please keep the following in mind:
- **Do not submit a duplicate feature request**: Search for existing feature requests [here](https://github.com/ReVanced/revanced-manager/issues?q=label%3A%22Feature+request%22).
- **Review the contribution guidelines**: Make sure your feature request adheres to it. You can find the guidelines [here](https://github.com/ReVanced/revanced-manager/blob/main/CONTRIBUTING.md).
- **Do not use the issue page for support**: If you need help or have questions, check out other platforms on [revanced.app](https://revanced.app).
- type: textarea
attributes:
label: Feature description
description: |
- Describe your feature in detail
- Add images, videos, links, examples, references, etc. if possible
- type: textarea
attributes:
label: Motivation
description: |
A strong motivation is necessary for a feature request to be considered.
- Why should this feature be implemented?
- What is the explicit use case?
- What are the benefits?
- What makes this feature important?
validations:
required: true
- type: checkboxes
id: acknowledgements
attributes:
label: Acknowledgements
description: Your feature request will be closed if you don't follow the checklist below.
options:
- label: I have checked all open and closed feature requests and this is not a duplicate
required: true
- label: I have chosen an appropriate title.
required: true
- label: All requested information has been provided properly.
required: true
- label: The feature request is only related to ReVanced Manager.
required: true

2
.github/config.yaml vendored
View File

@@ -1,2 +1,2 @@
firstPRMergeComment: >
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) to receive a role for your contribution.
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) if you want to receive a contributor role.

32
.github/workflows/analyze.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: Analyze Code
on:
push:
branches: [ "main", "dev" ]
paths:
- "**.dart"
- ".github/workflows/analyze.yml"
pull_request:
branches: [ "main", "dev" ]
paths:
- "**.dart"
- ".github/workflows/analyze.yml"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
cache: true
- name: Install Flutter dependencies
run: flutter pub get
- name: Generate files with Builder
run: flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Analyze code
uses: ValentinVignal/action-dart-analyze@v0.15
with:
fail-on: warning

View File

@@ -1,31 +0,0 @@
name: Build pull request
on:
workflow_dispatch:
pull_request:
branches:
- dev
jobs:
release:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Cache Gradle
uses: burrunan/gradle-cache-action@v1
- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew assembleRelease --no-daemon
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: revanced-manager
path: |
app/build/outputs/apk/release/revanced-manager*.apk
app/build/outputs/apk/release/revanced-manager*.apk.asc

46
.github/workflows/crowdin.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: Sync Crowdin translations
on:
push:
branches:
- "dev"
paths:
- "assets/i18n/en_US.json"
- ".github/workflows/crowdin.yml"
schedule:
- cron: "0 0 * * *" # daily
workflow_dispatch:
jobs:
sync-crowdin:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Crowdin
uses: crowdin/github-action@v1
with:
config: crowdin.yml
upload_sources: true
upload_translations: false
download_translations: true
push_translations: true
create_pull_request: false
localization_branch_name: i18n_flutter
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
# commented due to Manager not being ready for the translated files to be in the main branch
# - name: GitHub is so dumb i just cant
# run: |
# sudo chmod -R ugo+rwX .
# - name: Merge
# run: |
# git checkout flutter
# git add *
# git merge i18n_flutter
# git push

View File

@@ -1,26 +0,0 @@
name: Open a PR to main
on:
push:
branches:
- dev
workflow_dispatch:
env:
MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main`
jobs:
pull-request:
name: Open pull request
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Open pull request
uses: repo-sync/pull-request@v2
with:
destination_branch: 'main'
pr_title: 'chore: ${{ env.MESSAGE }}'
pr_body: 'This pull request will ${{ env.MESSAGE }}.'
pr_draft: true

View File

@@ -0,0 +1,41 @@
name: PR Build
on:
workflow_dispatch:
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
# Make sure the release step uses its own credentials:
# https://github.com/cycjimmy/semantic-release-action#private-packages
persist-credentials: false
fetch-depth: 0
- name: Setup JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'zulu'
cache: 'gradle'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
cache: true
- name: Install Flutter dependencies
run: flutter pub get
- name: Generate files with Builder
run: flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Build with Flutter
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: flutter build apk
- name: Upload build
uses: actions/upload-artifact@v3
with:
name: revanced-manager
path: build/app/outputs/flutter-apk/app-release.apk

View File

@@ -1,80 +1,68 @@
name: Release
on:
workflow_dispatch:
push:
branches:
- main
- dev
jobs:
release:
name: Release
permissions:
contents: write
packages: write
id-token: write
attestations: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Cache Gradle
uses: burrunan/gradle-cache-action@v3
- name: Build
env:
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew assembleRelease
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "lts/*"
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Import GPG key
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
fingerprint: ${{ vars.GPG_FINGERPRINT }}
- name: Setup keystore
run: |
echo "${{ secrets.KEYSTORE }}" | base64 --decode > "app/keystore.jks"
- name: Release API
run: npx multi-semantic-release --tag-format 'api@${version}' --ignore-packages app
env:
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release
id: release
run: |
echo "NEW_TAG=$(npx multi-semantic-release --tag-format 'v${version}' --ignore-packages api | tee | grep 'Created tag ' | sed -E 's/.*Created tag ([^ ]+).*/\1/')" >> $GITHUB_OUTPUT
env:
GITHUB_ACTOR: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
KEYSTORE_ENTRY_ALIAS: ${{ secrets.KEYSTORE_ENTRY_ALIAS }}
KEYSTORE_ENTRY_PASSWORD: ${{ secrets.KEYSTORE_ENTRY_PASSWORD }}
- name: Attest
if: steps.release.outputs.NEW_TAG != ''
uses: actions/attest-build-provenance@v2
with:
subject-name: 'ReVanced Manager ${{ steps.release.outputs.NEW_TAG }}'
subject-path: app/build/outputs/apk/release/revanced-manager*.apk
name: Release
on:
workflow_dispatch:
push:
branches:
- main
- dev
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
# Make sure the release step uses its own credentials:
# https://github.com/cycjimmy/semantic-release-action#private-packages
persist-credentials: false
fetch-depth: 0
- name: Setup JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'zulu'
cache: 'gradle'
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
cache: true
- name: Install Flutter dependencies
run: flutter pub get
- name: Generate files with Builder
run: flutter packages pub run build_runner build --delete-conflicting-outputs
- name: Build with Flutter
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: flutter build apk
- name: Sign APK
id: sign_apk
uses: ilharp/sign-android-release@v1
with:
releaseDir: build/app/outputs/apk/release
signingKey: ${{ secrets.SIGNING_KEYSTORE }}
keyStorePassword: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }}
keyAlias: ${{ secrets.SIGNING_KEY_ALIAS }}
keyPassword: ${{ secrets.SIGNING_KEY_PASSWORD }}
- name: Setup semantic-release
run: npm ci
- name: Get release version
run: npm exec -- semantic-release --dry-run
id: get-next-version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Add version to APK
run: mv $SIGNED_FILE_PATH $(dirname $SIGNED_FILE_PATH)/revanced-manager-${{ steps.get-next-version.outputs.new-release-version }}.apk
env:
SIGNED_FILE_PATH: ${{steps.sign_apk.outputs.signedFile}}
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
run: npm exec semantic-release

View File

@@ -1,19 +0,0 @@
name: Update documentation
on:
push:
paths:
- docs/**
jobs:
trigger:
runs-on: ubuntu-latest
name: Dispatch event to documentation repository
if: github.ref == 'refs/heads/main'
steps:
- uses: peter-evans/repository-dispatch@v3
with:
token: ${{ secrets.DOCUMENTATION_REPO_ACCESS_TOKEN }}
repository: revanced/revanced-documentation
event-type: update-documentation
client-payload: '{"repo": "${{ github.event.repository.name }}", "ref": "${{ github.ref }}"}'

253
.gitignore vendored
View File

@@ -1,132 +1,141 @@
### Java template
# Compiled class file
# Miscellaneous
*.class
# Log file
*.lock
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
.idea/artifacts
.idea/compiler.xml
.idea/jarRepositories.xml
.idea/modules.xml
.idea/*.iml
.idea/modules
# IntelliJ related
*.iml
*.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Gradle template
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Cache of project
.gradletasknamecache
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
# Potentially copyrighted test APK
*.apk
# Ignore vscode config
.vscode/
# Dependency directories
node_modules/
# Ignore IDEA files
.idea/
.kotlin/
# Visual Studio Code related
.classpath
.project
.settings/
local.properties
# Flutter repo-specific
/bin/cache/
/bin/mingit/
/dev/benchmarks/mega_gallery/
/dev/bots/.recipe_deps
/dev/bots/android_tools/
/dev/docs/doc/
/dev/docs/flutter.docs.zip
/dev/docs/lib/
/dev/docs/pubspec.yaml
/dev/integration_tests/**/xcuserdata
/dev/integration_tests/**/Pods
/packages/flutter/coverage/
version
.cxx
# packages file containing multi-root paths
.packages.generated
# Flutter/Dart/Pub related
**/doc/api/
**/*.g.dart
**/*.locator.dart
**/*.router.dart
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
**/generated_plugin_registrant.dart
.packages
.pub-cache/
.pub/
build/
flutter_*.png
linked_*.ds
unlinked.ds
unlinked_spec.ds
# Android related
**/android/**/gradle-wrapper.jar
**/android/.gradle
**/android/captures/
**/android/gradlew
**/android/gradlew.bat
**/android/local.properties
**/android/**/GeneratedPluginRegistrant.java
**/android/key.properties
*.jks
# iOS/XCode related
**/ios/**/*.mode1v3
**/ios/**/*.mode2v3
**/ios/**/*.moved-aside
**/ios/**/*.pbxuser
**/ios/**/*.perspectivev3
**/ios/**/*sync/
**/ios/**/.sconsign.dblite
**/ios/**/.tags*
**/ios/**/.vagrant/
**/ios/**/DerivedData/
**/ios/**/Icon?
**/ios/**/Pods/
**/ios/**/.symlinks/
**/ios/**/profile
**/ios/**/xcuserdata
**/ios/.generated/
**/ios/Flutter/.last_build_id
**/ios/Flutter/App.framework
**/ios/Flutter/Flutter.framework
**/ios/Flutter/Flutter.podspec
**/ios/Flutter/Generated.xcconfig
**/ios/Flutter/app.flx
**/ios/Flutter/app.zip
**/ios/Flutter/flutter_assets/
**/ios/Flutter/flutter_export_environment.sh
**/ios/ServiceDefinitions.json
**/ios/Runner/GeneratedPluginRegistrant.*
# macOS related
**/macos/Flutter/GeneratedPluginRegistrant.swift
**/macos/Flutter/Flutter-Debug.xcconfig
**/macos/Flutter/Flutter-Release.xcconfig
**/macos/Flutter/Flutter-Profile.xcconfig
# Windows related
**/windows/flutter/ephemeral/
**/windows/**/*.suo
**/windows/**/*.user
**/windows/**/*.userosscache
**/windows/**/*.sln.docstates
**/windows/x64/
**/windows/x86/
**/windows/**/*.[Cc]ache
**/windows/**/!*.[Cc]ache/
# Web related
lib/generated_plugin_registrant.dart
# Coverage
coverage/
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# Exceptions to above rules.
!**/ios/**/default.mode1v3
!**/ios/**/default.mode2v3
!**/ios/**/default.pbxuser
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock
# Firebase related
.firebase
# Dependency directories
node_modules/

45
.metadata Normal file
View File

@@ -0,0 +1,45 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled.
version:
revision: 85684f9300908116a78138ea4c6036c35c9a1236
channel: stable
project_type: app
# Tracks metadata for the flutter migrate command
migration:
platforms:
- platform: root
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
- platform: android
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
- platform: ios
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
- platform: linux
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
- platform: macos
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
- platform: web
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
- platform: windows
create_revision: 85684f9300908116a78138ea4c6036c35c9a1236
base_revision: 85684f9300908116a78138ea4c6036c35c9a1236
# User provided section
# List of Local paths (relative to this file) that should be
# ignored by the migrate tool.
#
# Files that are not part of the templates will be ignored by default.
unmanaged_files:
- 'lib/main.dart'
- 'ios/Runner.xcodeproj/project.pbxproj'

75
.releaserc Normal file
View File

@@ -0,0 +1,75 @@
{
"branches": [
"main",
{
"name": "dev",
"prerelease": true
}
],
"plugins": [
"semantic-release-export-data",
"@semantic-release/commit-analyzer",
[
"@semantic-release/release-notes-generator",
{
"presetConfig": {
"types": [
{
"type": "build",
"section": "Dependency Updates"
},
{
"type": "chore",
"section": "Other Changes",
"hidden": false
},
{
"type": "perf",
"section": "Performance Improvements",
"hidden": false
},
{
"type": "refactor",
"section": "Code Improvements",
"hidden": false
}
]
}
}
],
"@semantic-release/changelog",
"semantic-release-flutter-plugin",
[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md",
"pubspec.yaml"
]
}
],
[
"@semantic-release/github",
{
"assets": [
{
"path": "build/app/outputs/apk/release/revanced-manager-*.apk"
}
],
"successComment": false
}
],
[
"@saithodev/semantic-release-backmerge",
{
"backmergeBranches": [
{
"from": "main",
"to": "dev"
}
],
"clearWorkspace": true
}
]
]
}

6
.run/main.dart.run.xml Normal file
View File

@@ -0,0 +1,6 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="main.dart" type="FlutterRunConfigurationType" factoryName="Flutter">
<option name="filePath" value="$PROJECT_DIR$/lib/main.dart" />
<method v="2" />
</configuration>
</component>

91
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,91 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Generate (Builder)",
"type": "shell",
"command": "flutter packages pub run build_runner build --delete-conflicting-outputs",
"problemMatcher": []
},
{
"label": "Build (Android)",
"type": "shell",
"command": "flutter build apk",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Install (Android)",
"type": "shell",
"command": "adb install build\\app\\outputs\\flutter-apk\\app-release.apk",
"problemMatcher": []
},
{
"label": "Clean (Flutter)",
"type": "shell",
"command": "flutter clean && flutter pub get",
"problemMatcher": []
},
{
"label": "Clean (Builder)",
"type": "shell",
"command": "flutter packages pub run build_runner clean",
"problemMatcher": []
},
{
"label": "Build all (Android)",
"dependsOrder": "sequence",
"dependsOn": [
"Generate (Builder)",
"Build (Android)"
],
"problemMatcher": []
},
{
"label": "Clean all",
"dependsOrder": "sequence",
"dependsOn": [
"Clean (Flutter)",
"Clean (Builder)"
],
"problemMatcher": []
},
{
"label": "Clean all & Build all (Android)",
"dependsOrder": "sequence",
"dependsOn": [
"Clean all",
"Build all (Android)"
],
"problemMatcher": []
},
{
"label": "Clean all & Install (Android)",
"dependsOrder": "sequence",
"dependsOn": [
"Clean all",
"Build all (Android)",
"Install (Android)",
],
"problemMatcher": []
},
{
"label": "Build & Install (Android)",
"dependsOrder": "sequence",
"dependsOn": [
"Build (Android)",
"Install (Android)"
],
"problemMatcher": []
},
{
"label": "Validate translations",
"type": "shell",
"command": "flutter pub run flutter_i18n diff en.json pt.json",
"problemMatcher": []
}
]
}

74
CHANGELOG.md Normal file
View File

@@ -0,0 +1,74 @@
# [1.0.0-dev.1](https://github.com/revanced/revanced-manager/compare/v0.0.57...v1.0.0-dev.1) (2023-04-29)
### Bug Fixes
* fix broken manager update implmentation ([6492507](https://github.com/revanced/revanced-manager/commit/6492507d0e0015b594f7d9e97bbadee9501b29d6))
* **i18n:** update translation for `refreshSucess` ([b286444](https://github.com/revanced/revanced-manager/commit/b286444ad93fc6009412ac14b996ff6268069811))
* open contributor links externally ([#791](https://github.com/revanced/revanced-manager/issues/791)) ([f0b0282](https://github.com/revanced/revanced-manager/commit/f0b028279c69f97817952063d84809d3e486ad6e))
* resized monochrome icon to match the original ([#789](https://github.com/revanced/revanced-manager/issues/789)) ([ac830cb](https://github.com/revanced/revanced-manager/commit/ac830cbe7f3b1ebd7849e586b829d3c077436a0d))
* update pubspec version ([65da6af](https://github.com/revanced/revanced-manager/commit/65da6af3f96550b138dcaf61832a5de23f529b32))
* chore!: merge `dev` to `main` (#830) ([782c012](https://github.com/revanced/revanced-manager/commit/782c0127b1f6f5380bd8ca23c8c2f280e2bfc432)), closes [#830](https://github.com/revanced/revanced-manager/issues/830)
### Features
* add continue anyway button to select from storage dialog ([#810](https://github.com/revanced/revanced-manager/issues/810)) ([affba66](https://github.com/revanced/revanced-manager/commit/affba669ce1ca6866a1dd1bd801e3f33e4bfe051))
* add option to import/export keystore ([#776](https://github.com/revanced/revanced-manager/issues/776)) ([dca2d4f](https://github.com/revanced/revanced-manager/commit/dca2d4fe126a6966a094d335e0f27bb62d76c5e8))
* appreciation message for new contributors ([0a1f2da](https://github.com/revanced/revanced-manager/commit/0a1f2da33da7d44f0613b19f3e6b2b7b50240548))
* auto select default patches ([4c9cb56](https://github.com/revanced/revanced-manager/commit/4c9cb560e3e38295a5140419f2565b478cb6c497))
* change `continue anyways` to `cancel` ([cfc866b](https://github.com/revanced/revanced-manager/commit/cfc866bef2497bc1675bf5dea834cea59d9cc969))
* **ci:** update crowdin workflow to use new main branch ([ded59d2](https://github.com/revanced/revanced-manager/commit/ded59d2da0d193b2dea4a5a7f2fc8eefaceecc0a))
* confirmation dialog for deleting keystore ([#764](https://github.com/revanced/revanced-manager/issues/764)) ([054afbb](https://github.com/revanced/revanced-manager/commit/054afbbedd70a1933d8241ff5b63a772f90b555f))
* disable selecting installed apps for nonroot ([bb681e3](https://github.com/revanced/revanced-manager/commit/bb681e31c9c4e8a5b7b0c883edd1bc5c28505627))
* improve suggested app version text ([#822](https://github.com/revanced/revanced-manager/issues/822)) ([ad17995](https://github.com/revanced/revanced-manager/commit/ad17995f2883682f67eb42b1f82ca865fba86ef9))
* improve ux ([#752](https://github.com/revanced/revanced-manager/issues/752)) ([3b677f8](https://github.com/revanced/revanced-manager/commit/3b677f8ae3739c079e2116417fef6ed395c2ff06)), closes [#782](https://github.com/revanced/revanced-manager/issues/782)
* progress bar for manager updates ([f5aafdb](https://github.com/revanced/revanced-manager/commit/f5aafdb7d6f51386b667abbccf7f2521ef664ba5))
* remove notice about stale development [skip ci] ([62f7a82](https://github.com/revanced/revanced-manager/commit/62f7a820d8ee2506376306e119698d427de745ef))
* resetting source to default dismiss the sources pop-up ([#797](https://github.com/revanced/revanced-manager/issues/797)) ([62ef1c8](https://github.com/revanced/revanced-manager/commit/62ef1c88fe0352d3962f8c73edff4b99ea347c0f))
* trim extra space when setting custom source ([#771](https://github.com/revanced/revanced-manager/issues/771)) ([37b583f](https://github.com/revanced/revanced-manager/commit/37b583f560910c0b5da2a8e64de9b53f5a26bb56))
* warning for armv7 devices ([cdfb09f](https://github.com/revanced/revanced-manager/commit/cdfb09fbfa8e74d84ddcc91565489c3c5b61dfa2))
### BREAKING CHANGES
* this is to release as 1.0.0
# [1.0.0](https://github.com/revanced/revanced-manager/compare/v0.0.57...v1.0.0) (2023-04-29)
### Bug Fixes
* **i18n:** update translation for `refreshSucess` ([b286444](https://github.com/revanced/revanced-manager/commit/b286444ad93fc6009412ac14b996ff6268069811))
* open contributor links externally ([#791](https://github.com/revanced/revanced-manager/issues/791)) ([f0b0282](https://github.com/revanced/revanced-manager/commit/f0b028279c69f97817952063d84809d3e486ad6e))
* resized monochrome icon to match the original ([#789](https://github.com/revanced/revanced-manager/issues/789)) ([ac830cb](https://github.com/revanced/revanced-manager/commit/ac830cbe7f3b1ebd7849e586b829d3c077436a0d))
* update pubspec version ([65da6af](https://github.com/revanced/revanced-manager/commit/65da6af3f96550b138dcaf61832a5de23f529b32))
* chore!: merge `dev` to `main` (#830) ([782c012](https://github.com/revanced/revanced-manager/commit/782c0127b1f6f5380bd8ca23c8c2f280e2bfc432)), closes [#830](https://github.com/revanced/revanced-manager/issues/830)
### Features
* add continue anyway button to select from storage dialog ([#810](https://github.com/revanced/revanced-manager/issues/810)) ([affba66](https://github.com/revanced/revanced-manager/commit/affba669ce1ca6866a1dd1bd801e3f33e4bfe051))
* add option to import/export keystore ([#776](https://github.com/revanced/revanced-manager/issues/776)) ([dca2d4f](https://github.com/revanced/revanced-manager/commit/dca2d4fe126a6966a094d335e0f27bb62d76c5e8))
* appreciation message for new contributors ([0a1f2da](https://github.com/revanced/revanced-manager/commit/0a1f2da33da7d44f0613b19f3e6b2b7b50240548))
* auto select default patches ([4c9cb56](https://github.com/revanced/revanced-manager/commit/4c9cb560e3e38295a5140419f2565b478cb6c497))
* change `continue anyways` to `cancel` ([cfc866b](https://github.com/revanced/revanced-manager/commit/cfc866bef2497bc1675bf5dea834cea59d9cc969))
* **ci:** update crowdin workflow to use new main branch ([ded59d2](https://github.com/revanced/revanced-manager/commit/ded59d2da0d193b2dea4a5a7f2fc8eefaceecc0a))
* confirmation dialog for deleting keystore ([#764](https://github.com/revanced/revanced-manager/issues/764)) ([054afbb](https://github.com/revanced/revanced-manager/commit/054afbbedd70a1933d8241ff5b63a772f90b555f))
* disable selecting installed apps for nonroot ([bb681e3](https://github.com/revanced/revanced-manager/commit/bb681e31c9c4e8a5b7b0c883edd1bc5c28505627))
* improve suggested app version text ([#822](https://github.com/revanced/revanced-manager/issues/822)) ([ad17995](https://github.com/revanced/revanced-manager/commit/ad17995f2883682f67eb42b1f82ca865fba86ef9))
* improve ux ([#752](https://github.com/revanced/revanced-manager/issues/752)) ([3b677f8](https://github.com/revanced/revanced-manager/commit/3b677f8ae3739c079e2116417fef6ed395c2ff06)), closes [#782](https://github.com/revanced/revanced-manager/issues/782)
* progress bar for manager updates ([f5aafdb](https://github.com/revanced/revanced-manager/commit/f5aafdb7d6f51386b667abbccf7f2521ef664ba5))
* remove notice about stale development [skip ci] ([62f7a82](https://github.com/revanced/revanced-manager/commit/62f7a820d8ee2506376306e119698d427de745ef))
* resetting source to default dismiss the sources pop-up ([#797](https://github.com/revanced/revanced-manager/issues/797)) ([62ef1c8](https://github.com/revanced/revanced-manager/commit/62ef1c88fe0352d3962f8c73edff4b99ea347c0f))
* trim extra space when setting custom source ([#771](https://github.com/revanced/revanced-manager/issues/771)) ([37b583f](https://github.com/revanced/revanced-manager/commit/37b583f560910c0b5da2a8e64de9b53f5a26bb56))
* warning for armv7 devices ([cdfb09f](https://github.com/revanced/revanced-manager/commit/cdfb09fbfa8e74d84ddcc91565489c3c5b61dfa2))
### BREAKING CHANGES
* this is to release as 1.0.0

View File

@@ -1,103 +0,0 @@
<p align="center">
<picture>
<source
width="256px"
media="(prefers-color-scheme: dark)"
srcset="assets/revanced-headline/revanced-headline-vertical-dark.svg"
>
<img
width="256px"
src="assets/revanced-headline/revanced-headline-vertical-light.svg"
>
</picture>
<br>
<a href="https://revanced.app/">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="assets/revanced-logo/revanced-logo.svg" />
<img height="24px" src="assets/revanced-logo/revanced-logo.svg" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://github.com/ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="http://revanced.app/discord">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://reddit.com/r/revancedapp">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://t.me/app_revanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://x.com/revancedapp">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://www.youtube.com/@ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
</picture>
</a>
<br>
<br>
Continuing the legacy of Vanced
</p>
# 👋 Contribution guidelines
This document describes how to contribute to ReVanced Manager.
## 📖 Resources to help you get started
* The [documentation](/docs/README.md) provides steps to build ReVanced Manager from source
* Our [backlog](https://github.com/orgs/ReVanced/projects/12) is where we keep track of what we're working on
* [Issues](https://github.com/ReVanced/revanced-manager/issues) are where we keep track of bugs and feature requests
## 🙏 Submitting a feature request
Features can be requested by opening an issue using the
[Feature request issue template](https://github.com/ReVanced/revanced-manager/issues/new?assignees=&labels=Feature+request&projects=&template=feature_request.yml&title=feat%3A+).
> **Note**
> Requests can be accepted or rejected at the discretion of maintainers of ReVanced Manager.
> Good motivation has to be provided for a request to be accepted.
## 🐞 Submitting a bug report
If you encounter a bug while using ReVanced Manager, open an issue using the
[Bug report issue template](https://github.com/ReVanced/revanced-manager/issues/new?assignees=&labels=Bug+report&projects=&template=bug_report.yml&title=bug%3A+).
## 📝 How to contribute
1. Before contributing, it is recommended to open an issue to discuss your change
with the maintainers of ReVanced Manager. This will help you determine whether your change is acceptable
and whether it is worth your time to implement it
2. Development happens on the `dev` branch. Fork the repository and create your branch from `dev`
3. Commit your changes
4. Submit a pull request to the `dev` branch of the repository and reference issues
that your pull request closes in the description of your pull request
5. Our team will review your pull request and provide feedback. Once your pull request is approved,
it will be merged into the `dev` branch and will be included in the next release of ReVanced Manager
## 🤚 I want to contribute but don't know how to code
Even if you don't know how to code, you can still contribute by
translating ReVanced Manager on [Crowdin](https://translate.revanced.app/).
❤️ Thank you for considering contributing to ReVanced Manager,
ReVanced

113
README.md
View File

@@ -1,104 +1,31 @@
<p align="center">
<picture>
<source
width="256px"
media="(prefers-color-scheme: dark)"
srcset="assets/revanced-headline/revanced-headline-vertical-dark.svg"
>
<img
width="256px"
src="assets/revanced-headline/revanced-headline-vertical-light.svg"
>
</picture>
<br>
<a href="https://revanced.app/">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="assets/revanced-logo/revanced-logo.svg" />
<img height="24px" src="assets/revanced-logo/revanced-logo.svg" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://github.com/ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="http://revanced.app/discord">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://reddit.com/r/revancedapp">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://t.me/app_revanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://x.com/revancedapp">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
</picture>
</a>&nbsp;&nbsp;&nbsp;
<a href="https://www.youtube.com/@ReVanced">
<picture>
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
</picture>
</a>
<br>
<br>
Continuing the legacy of Vanced
</p>
# 💊 ReVanced Manager
![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/ReVanced/revanced-manager/release.yml)
![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)
Application to use ReVanced on Android
## ❓ About
ReVanced Manager is an application that uses [ReVanced Patcher](https://github.com/revanced/revanced-patcher) to patch Android apps.
## 💪 Features
Some of the features ReVanced Manager provides are:
- ⬇️ **Download**: Automatically download apps using the ReVanced Manager downloader plugin system
- 💉 **Patch**: Select and apply patches to any Android app
- 🛠️ **Customize**: Manage patches, apps, signing, themes, updates, and many more settings
The official ReVanced Manager based on Flutter.
## 🔽 Download
To download latest Manager, go [here](https://github.com/revanced/revanced-manager/releases/latest) and install the provided APK file.
You can download the most recent version of ReVanced Manager at [revanced.app/download](https://revanced.app/download) or from [GitHub releases](https://github.com/ReVanced/revanced-manager/releases/latest).
Learn how to use ReVanced Manager by following the [documentation](/docs).
## 📝 Prerequisites
1. Android 8 or higher
2. Does not work on some armv7 devices
## 📚 Everything else
## 🔴 Issues
For suggestions and bug reports, open an issue [here](https://github.com/revanced/revanced-manager/issues/new/choose).
### 📙 Contributing
## 💭 Discussion
If you wish to discuss the Manager, a thread has been made under the [#development](https://discord.com/channels/952946952348270622/1002922226443632761) channel in the Discord server, please note that this thread may be temporary and may be removed in the future.
Thank you for considering contributing to ReVanced Manager.
You can find the contribution guidelines [here](CONTRIBUTING.md).
### 🛠️ Building
## 🌐 Translation
[![Crowdin](https://badges.crowdin.net/revanced/localized.svg)](https://crowdin.com/project/revanced)
To build a ReVanced Manager, you can follow the [documentation](/docs).
If you wish to translate ReVanced Manager, we're accepting translations on [Crowdin](https://translate.revanced.app)
### 📄 Documentation
You can find the documentation for ReVanced Manager [here](/docs).
## ⚖️ License
ReVanced Manager is licensed under the GPLv3 license. Please see the [license file](LICENSE) for more information.
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced Manager as long as you track changes/dates in source files.
Any modifications to ReVanced Manager must also be made available under the GPL, along with build & install instructions.
## 🛠️ Building Manager from source
1. Setup flutter environment for your [platform](https://docs.flutter.dev/get-started/install)
2. Clone the repository locally
3. Add your github token in gradle.properties like [this](https://github.com/revanced/revanced-manager/blob/docs/docs/5_building-from-source.md)
4. Open the project in terminal
5. Run `flutter pub get` in terminal
6. Then `flutter packages pub run build_runner build --delete-conflicting-outputs` (Must be done on each git pull)
7. To build release apk run `flutter build apk`

View File

@@ -1,8 +0,0 @@
{
"info": "This is verification file for ads.fund project",
"project": {
"name": "ReVanced Manager",
"walletAddress": "0x7ab4091e00363654bf84B34151225742cd92FCE5",
"tokenAddress": "0xadf954bc6f509b3a32fb5e97ed4ba6c000e37155"
}
}

165
analysis_options.yaml Normal file
View File

@@ -0,0 +1,165 @@
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.
# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- lib/app/app.locator.dart
- lib/app/app.router.dart
- lib/models/patch.g.dart
- lib/models/patched_application.g.dart
linter:
rules:
- always_declare_return_types
- require_trailing_commas
- always_put_control_body_on_new_line
- always_require_non_null_named_parameters
- always_use_package_imports # we do this commonly
- annotate_overrides
- avoid_bool_literals_in_conditional_expressions
- avoid_double_and_int_checks
- avoid_empty_else
- avoid_equals_and_hash_code_on_mutable_classes
- avoid_escaping_inner_quotes
- avoid_field_initializers_in_const_classes
- avoid_function_literals_in_foreach_calls
- avoid_implementing_value_types
- avoid_init_to_null
- avoid_js_rounded_ints
- avoid_null_checks_in_equality_operators
- avoid_print
- avoid_redundant_argument_values
- avoid_relative_lib_imports
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
- avoid_returning_null
- avoid_returning_null_for_future
- avoid_returning_null_for_void
- avoid_setters_without_getters
- avoid_shadowing_type_parameters
- avoid_single_cascade_in_expression_statements
- avoid_type_to_string
- avoid_types_as_parameter_names
- avoid_unnecessary_containers
- avoid_void_async
- avoid_web_libraries_in_flutter # we use web libraries in web-specific code, and our tests prevent us from using them elsewhere
- await_only_futures
- camel_case_extensions
- camel_case_types
- cancel_subscriptions
- cast_nullable_to_non_nullable
- close_sinks # not reliable enough
- control_flow_in_finally
- curly_braces_in_flow_control_structures
- depend_on_referenced_packages
- deprecated_consistency
- directives_ordering
- empty_catches
- empty_constructor_bodies
- empty_statements
- eol_at_end_of_file
- exhaustive_cases
- file_names
- flutter_style_todos
- hash_and_equals
- implementation_imports
- iterable_contains_unrelated_type
- leading_newlines_in_multiline_strings
- library_names
- library_prefixes
- library_private_types_in_public_api
- list_remove_unrelated_type
- missing_whitespace_between_adjacent_strings
- no_adjacent_strings_in_list
- no_duplicate_case_values
- no_logic_in_create_state
- non_constant_identifier_names
- noop_primitive_operations
- null_check_on_nullable_type_parameter
- null_closures
- overridden_fields
- package_api_docs
- package_names
- package_prefixed_library_names
- prefer_adjacent_string_concatenation
- prefer_asserts_in_initializer_lists
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_const_constructors
- prefer_const_constructors_in_immutables
- prefer_const_declarations
- prefer_const_literals_to_create_immutables
- prefer_contains
- prefer_equal_for_default_values
- prefer_final_fields
- prefer_final_in_for_each
- prefer_final_locals
- prefer_for_elements_to_map_fromIterable
- prefer_foreach
- prefer_function_declarations_over_variables
- prefer_generic_function_type_aliases
- prefer_if_elements_to_conditional_expressions
- prefer_if_null_operators
- prefer_initializing_formals
- prefer_inlined_adds
- prefer_interpolation_to_compose_strings
- prefer_is_empty
- prefer_is_not_empty
- prefer_is_not_operator
- prefer_iterable_whereType
- prefer_mixin # Has false positives, see https://github.com/dart-lang/linter/issues/3018
- prefer_null_aware_method_calls # "call()" is confusing to people new to the language since it's not documented anywhere
- prefer_null_aware_operators
- prefer_single_quotes
- prefer_spread_collections
- prefer_typing_uninitialized_variables
- prefer_void_to_null
- provide_deprecation_message
- recursive_getters
- sized_box_for_whitespace
- slash_for_doc_comments
- sort_child_properties_last
- sort_constructors_first
- sort_unnamed_constructors_first
- test_types_in_equals
- throw_in_finally
- tighten_type_of_initializing_formals
- type_init_formals
- unnecessary_brace_in_string_interps
- unnecessary_const
- unnecessary_getters_setters
- unnecessary_new
- unnecessary_null_aware_assignments
- unnecessary_null_checks
- unnecessary_null_in_if_null_operators
- unnecessary_nullable_for_final_variable_declarations
- unnecessary_overrides
- unnecessary_parenthesis
- unnecessary_statements
- unnecessary_string_escapes
- unnecessary_string_interpolations
- unnecessary_this
- unrelated_type_equality_checks
- unsafe_html
- use_build_context_synchronously
- use_full_hex_values_for_flutter_colors
- use_function_type_syntax_for_parameters
- use_if_null_to_convert_nulls_to_bools
- use_is_even_rather_than_modulo
- use_key_in_widget_constructors
- use_late_for_private_fields_and_variables
- use_named_constants
- use_raw_strings
- use_rethrow_when_possible
- use_setters_to_change_properties
- use_test_throws_matchers
- valid_regexps
- void_checks

13
android/.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
**/*.keystore
**/*.jks

93
android/app/build.gradle Normal file
View File

@@ -0,0 +1,93 @@
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
compileSdkVersion 33
ndkVersion flutter.ndkVersion
compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
kotlinOptions {
jvmTarget = '11'
}
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
defaultConfig {
applicationId "app.revanced.manager.flutter"
minSdkVersion 26
targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
multiDexEnabled true
}
buildTypes {
release {
shrinkResources false
minifyEnabled false
signingConfig signingConfigs.debug
}
}
packagingOptions {
exclude '/prebuilt/**'
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// ReVanced
implementation "app.revanced:revanced-patcher:7.0.0"
// Signing & aligning
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
implementation("com.android.tools.build:apksig:7.2.2")
// MicroG cronet
implementation("org.microg:cronet-common:$cronetVersion")
implementation("org.microg:cronet-native:$cronetVersion")
// Core libraries
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
// Window
implementation 'androidx.window:window:1.0.0'
implementation 'androidx.window:window-java:1.0.0'
}

View File

@@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.revanced.manager.flutter">
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

View File

@@ -0,0 +1,51 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.revanced.manager.flutter">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:label="ReVanced Manager"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:largeHeap="true"
android:extractNativeLibs="true"
android:enableOnBackInvokedCallback="true">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
</application>
</manifest>

View File

@@ -0,0 +1,316 @@
package app.revanced.manager.flutter
import android.os.Build
import android.os.Handler
import android.os.Looper
import androidx.annotation.NonNull
import app.revanced.manager.flutter.utils.Aapt
import app.revanced.manager.flutter.utils.aligning.ZipAligner
import app.revanced.manager.flutter.utils.signing.Signer
import app.revanced.manager.flutter.utils.zip.ZipFile
import app.revanced.manager.flutter.utils.zip.structures.ZipEntry
import app.revanced.patcher.Patcher
import app.revanced.patcher.PatcherOptions
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.logging.Logger
import app.revanced.patcher.util.patch.PatchBundle
import dalvik.system.DexClassLoader
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.io.File
private const val PATCHER_CHANNEL = "app.revanced.manager.flutter/patcher"
private const val INSTALLER_CHANNEL = "app.revanced.manager.flutter/installer"
class MainActivity : FlutterActivity() {
private val handler = Handler(Looper.getMainLooper())
private lateinit var installerChannel: MethodChannel
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
super.configureFlutterEngine(flutterEngine)
val mainChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, PATCHER_CHANNEL)
installerChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, INSTALLER_CHANNEL)
mainChannel.setMethodCallHandler { call, result ->
when (call.method) {
"runPatcher" -> {
val patchBundleFilePath = call.argument<String>("patchBundleFilePath")
val originalFilePath = call.argument<String>("originalFilePath")
val inputFilePath = call.argument<String>("inputFilePath")
val patchedFilePath = call.argument<String>("patchedFilePath")
val outFilePath = call.argument<String>("outFilePath")
val integrationsPath = call.argument<String>("integrationsPath")
val selectedPatches = call.argument<List<String>>("selectedPatches")
val cacheDirPath = call.argument<String>("cacheDirPath")
val keyStoreFilePath = call.argument<String>("keyStoreFilePath")
val keystorePassword = call.argument<String>("keystorePassword")
if (patchBundleFilePath != null &&
originalFilePath != null &&
inputFilePath != null &&
patchedFilePath != null &&
outFilePath != null &&
integrationsPath != null &&
selectedPatches != null &&
cacheDirPath != null &&
keyStoreFilePath != null &&
keystorePassword != null
) {
runPatcher(
result,
patchBundleFilePath,
originalFilePath,
inputFilePath,
patchedFilePath,
outFilePath,
integrationsPath,
selectedPatches,
cacheDirPath,
keyStoreFilePath,
keystorePassword
)
} else {
result.notImplemented()
}
}
else -> result.notImplemented()
}
}
}
private fun runPatcher(
result: MethodChannel.Result,
patchBundleFilePath: String,
originalFilePath: String,
inputFilePath: String,
patchedFilePath: String,
outFilePath: String,
integrationsPath: String,
selectedPatches: List<String>,
cacheDirPath: String,
keyStoreFilePath: String,
keystorePassword: String
) {
val originalFile = File(originalFilePath)
val inputFile = File(inputFilePath)
val patchedFile = File(patchedFilePath)
val outFile = File(outFilePath)
val integrations = File(integrationsPath)
val keyStoreFile = File(keyStoreFilePath)
Thread {
try {
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.1,
"header" to "",
"log" to "Copying original apk"
)
)
}
originalFile.copyTo(inputFile, true)
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.2,
"header" to "Unpacking apk...",
"log" to "Unpacking input apk"
)
)
}
val patcher =
Patcher(
PatcherOptions(
inputFile,
cacheDirPath,
Aapt.binary(applicationContext).absolutePath,
cacheDirPath,
logger = ManagerLogger()
)
)
handler.post {
installerChannel.invokeMethod(
"update",
mapOf("progress" to 0.3, "header" to "", "log" to "")
)
}
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.4,
"header" to "Merging integrations...",
"log" to "Merging integrations"
)
)
}
patcher.addIntegrations(listOf(integrations)) {}
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.5,
"header" to "Applying patches...",
"log" to ""
)
)
}
val patches = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
PatchBundle.Dex(
patchBundleFilePath,
DexClassLoader(
patchBundleFilePath,
cacheDirPath,
null,
javaClass.classLoader
)
).loadPatches().filter { patch ->
(patch.compatiblePackages?.any { it.name == patcher.context.packageMetadata.packageName } == true || patch.compatiblePackages.isNullOrEmpty()) &&
selectedPatches.any { it == patch.patchName }
}
} else {
TODO("VERSION.SDK_INT < CUPCAKE")
}
patcher.addPatches(patches)
patcher.executePatches().forEach { (patch, res) ->
if (res.isSuccess) {
val msg = "Applied $patch"
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.5,
"header" to "",
"log" to msg
)
)
}
return@forEach
}
val msg = "Failed to apply $patch: " + "${res.exceptionOrNull()!!.message ?: res.exceptionOrNull()!!.cause!!::class.simpleName}"
handler.post {
installerChannel.invokeMethod(
"update",
mapOf("progress" to 0.5, "header" to "", "log" to msg)
)
}
}
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.7,
"header" to "Repacking apk...",
"log" to "Repacking patched apk"
)
)
}
val res = patcher.save()
ZipFile(patchedFile).use { file ->
res.dexFiles.forEach {
file.addEntryCompressData(
ZipEntry.createWithName(it.name),
it.stream.readBytes()
)
}
res.resourceFile?.let {
file.copyEntriesFromFileAligned(
ZipFile(it),
ZipAligner::getEntryAlignment
)
}
file.copyEntriesFromFileAligned(
ZipFile(inputFile),
ZipAligner::getEntryAlignment
)
}
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 0.9,
"header" to "Signing apk...",
"log" to ""
)
)
}
// Signer("ReVanced", "s3cur3p@ssw0rd").signApk(patchedFile, outFile, keyStoreFile)
try {
Signer("ReVanced", keystorePassword).signApk(patchedFile, outFile, keyStoreFile)
} catch (e: Exception) {
//log to console
print("Error signing apk: ${e.message}")
e.printStackTrace()
}
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to 1.0,
"header" to "Finished!",
"log" to "Finished!"
)
)
}
} catch (ex: Throwable) {
val stack = ex.stackTraceToString()
handler.post {
installerChannel.invokeMethod(
"update",
mapOf(
"progress" to -100.0,
"header" to "Aborting...",
"log" to "An error occurred! Aborting\nError:\n$stack"
)
)
}
}
handler.post { result.success(null) }
}.start()
}
inner class ManagerLogger : Logger {
override fun error(msg: String) {
handler.post {
installerChannel
.invokeMethod(
"update",
mapOf("progress" to -1.0, "header" to "", "log" to msg)
)
}
}
override fun warn(msg: String) {
handler.post {
installerChannel.invokeMethod(
"update",
mapOf("progress" to -1.0, "header" to "", "log" to msg)
)
}
}
override fun info(msg: String) {
handler.post {
installerChannel.invokeMethod(
"update",
mapOf("progress" to -1.0, "header" to "", "log" to msg)
)
}
}
override fun trace(_msg: String) { /* unused */
}
}
}

View File

@@ -0,0 +1,12 @@
package app.revanced.manager.flutter.utils
import android.content.Context
import java.io.File
object Aapt {
fun binary(context: Context): File {
return File(context.applicationInfo.nativeLibraryDir).resolveAapt()
}
}
private fun File.resolveAapt() = resolve(list { _, f -> !File(f).isDirectory && f.contains("aapt") }!!.first())

View File

@@ -0,0 +1,11 @@
package app.revanced.manager.flutter.utils.aligning
import app.revanced.manager.flutter.utils.zip.structures.ZipEntry
internal object ZipAligner {
private const val DEFAULT_ALIGNMENT = 4
private const val LIBRARY_ALIGNMENT = 4096
fun getEntryAlignment(entry: ZipEntry): Int? =
if (entry.compression.toUInt() != 0u) null else if (entry.fileName.endsWith(".so")) LIBRARY_ALIGNMENT else DEFAULT_ALIGNMENT
}

View File

@@ -0,0 +1,74 @@
package app.revanced.manager.flutter.utils.signing
import com.android.apksig.ApkSigner
import org.bouncycastle.asn1.x500.X500Name
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
import org.bouncycastle.cert.X509v3CertificateBuilder
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.operator.ContentSigner
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.math.BigInteger
import java.security.*
import java.security.cert.X509Certificate
import java.util.*
internal class Signer(
private val cn: String, password: String
) {
private val passwordCharArray = password.toCharArray()
private fun newKeystore(out: File) {
val (publicKey, privateKey) = createKey()
val privateKS = KeyStore.getInstance("BKS", "BC")
privateKS.load(null, passwordCharArray)
privateKS.setKeyEntry("alias", privateKey, passwordCharArray, arrayOf(publicKey))
privateKS.store(FileOutputStream(out), passwordCharArray)
}
private fun createKey(): Pair<X509Certificate, PrivateKey> {
val gen = KeyPairGenerator.getInstance("RSA")
gen.initialize(2048)
val pair = gen.generateKeyPair()
var serialNumber: BigInteger
do serialNumber =
BigInteger.valueOf(SecureRandom().nextLong()) while (serialNumber < BigInteger.ZERO)
val x500Name = X500Name("CN=$cn")
val builder = X509v3CertificateBuilder(
x500Name,
serialNumber,
Date(System.currentTimeMillis() - 1000L * 60L * 60L * 24L * 30L),
Date(System.currentTimeMillis() + 1000L * 60L * 60L * 24L * 366L * 30L),
Locale.ENGLISH,
x500Name,
SubjectPublicKeyInfo.getInstance(pair.public.encoded)
)
val signer: ContentSigner = JcaContentSignerBuilder("SHA256withRSA").build(pair.private)
return JcaX509CertificateConverter().getCertificate(builder.build(signer)) to pair.private
}
fun signApk(input: File, output: File, ks: File) {
Security.addProvider(BouncyCastleProvider())
if (!ks.exists()) newKeystore(ks)
val keyStore = KeyStore.getInstance("BKS", "BC")
FileInputStream(ks).use { fis -> keyStore.load(fis, null) }
val alias = keyStore.aliases().nextElement()
val config = ApkSigner.SignerConfig.Builder(
cn,
keyStore.getKey(alias, passwordCharArray) as PrivateKey,
listOf(keyStore.getCertificate(alias) as X509Certificate)
).build()
val signer = ApkSigner.Builder(listOf(config))
signer.setCreatedBy(cn)
signer.setInputApk(input)
signer.setOutputApk(output)
signer.build().sign()
}
}

View File

@@ -0,0 +1,35 @@
@file:Suppress("unused")
package app.revanced.manager.flutter.utils.zip
import java.io.DataInput
import java.io.DataOutput
import java.nio.ByteBuffer
fun UInt.toLittleEndian() =
(((this.toInt() and 0xff000000.toInt()) shr 24) or ((this.toInt() and 0x00ff0000) shr 8) or ((this.toInt() and 0x0000ff00) shl 8) or (this.toInt() shl 24)).toUInt()
fun UShort.toLittleEndian() = (this.toUInt() shl 16).toLittleEndian().toUShort()
fun UInt.toBigEndian() = (((this.toInt() and 0xff) shl 24) or ((this.toInt() and 0xff00) shl 8)
or ((this.toInt() and 0x00ff0000) ushr 8) or (this.toInt() ushr 24)).toUInt()
fun UShort.toBigEndian() = (this.toUInt() shl 16).toBigEndian().toUShort()
fun ByteBuffer.getUShort() = this.short.toUShort()
fun ByteBuffer.getUInt() = this.int.toUInt()
fun ByteBuffer.putUShort(ushort: UShort): ByteBuffer = this.putShort(ushort.toShort())
fun ByteBuffer.putUInt(uint: UInt): ByteBuffer = this.putInt(uint.toInt())
fun DataInput.readUShort() = this.readShort().toUShort()
fun DataInput.readUInt() = this.readInt().toUInt()
fun DataOutput.writeUShort(ushort: UShort) = this.writeShort(ushort.toInt())
fun DataOutput.writeUInt(uint: UInt) = this.writeInt(uint.toInt())
fun DataInput.readUShortLE() = this.readUShort().toBigEndian()
fun DataInput.readUIntLE() = this.readUInt().toBigEndian()
fun DataOutput.writeUShortLE(ushort: UShort) = this.writeUShort(ushort.toLittleEndian())
fun DataOutput.writeUIntLE(uint: UInt) = this.writeUInt(uint.toLittleEndian())

View File

@@ -0,0 +1,176 @@
package app.revanced.manager.flutter.utils.zip
import app.revanced.manager.flutter.utils.zip.structures.ZipEndRecord
import app.revanced.manager.flutter.utils.zip.structures.ZipEntry
import java.io.Closeable
import java.io.File
import java.io.RandomAccessFile
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import java.util.zip.CRC32
import java.util.zip.Deflater
class ZipFile(file: File) : Closeable {
var entries: MutableList<ZipEntry> = mutableListOf()
private val filePointer: RandomAccessFile = RandomAccessFile(file, "rw")
private var CDNeedsRewrite = false
private val compressionLevel = 5
init {
//if file isn't empty try to load entries
if (file.length() > 0) {
val endRecord = findEndRecord()
if (endRecord.diskNumber > 0u || endRecord.totalEntries != endRecord.diskEntries)
throw IllegalArgumentException("Multi-file archives are not supported")
entries = readEntries(endRecord).toMutableList()
}
//seek back to start for writing
filePointer.seek(0)
}
private fun findEndRecord(): ZipEndRecord {
//look from end to start since end record is at the end
for (i in filePointer.length() - 1 downTo 0) {
filePointer.seek(i)
//possible beginning of signature
if (filePointer.readByte() == 0x50.toByte()) {
//seek back to get the full int
filePointer.seek(i)
val possibleSignature = filePointer.readUIntLE()
if (possibleSignature == ZipEndRecord.ECD_SIGNATURE) {
filePointer.seek(i)
return ZipEndRecord.fromECD(filePointer)
}
}
}
throw Exception("Couldn't find end record")
}
private fun readEntries(endRecord: ZipEndRecord): List<ZipEntry> {
filePointer.seek(endRecord.centralDirectoryStartOffset.toLong())
val numberOfEntries = endRecord.diskEntries.toInt()
return buildList(numberOfEntries) {
for (i in 1..numberOfEntries) {
add(
ZipEntry.fromCDE(filePointer).also
{
//for some reason the local extra field can be different from the central one
it.readLocalExtra(
filePointer.channel.map(
FileChannel.MapMode.READ_ONLY,
it.localHeaderOffset.toLong() + 28,
2
)
)
})
}
}
}
private fun writeCD() {
val CDStart = filePointer.channel.position().toUInt()
entries.forEach {
filePointer.channel.write(it.toCDE())
}
val entriesCount = entries.size.toUShort()
val endRecord = ZipEndRecord(
0u,
0u,
entriesCount,
entriesCount,
filePointer.channel.position().toUInt() - CDStart,
CDStart,
""
)
filePointer.channel.write(endRecord.toECD())
}
private fun addEntry(entry: ZipEntry, data: ByteBuffer) {
CDNeedsRewrite = true
entry.localHeaderOffset = filePointer.channel.position().toUInt()
filePointer.channel.write(entry.toLFH())
filePointer.channel.write(data)
entries.add(entry)
}
fun addEntryCompressData(entry: ZipEntry, data: ByteArray) {
val compressor = Deflater(compressionLevel, true)
compressor.setInput(data)
compressor.finish()
val uncompressedSize = data.size
val compressedData =
ByteArray(uncompressedSize) //i'm guessing compression won't make the data bigger
val compressedDataLength = compressor.deflate(compressedData)
val compressedBuffer =
ByteBuffer.wrap(compressedData.take(compressedDataLength).toByteArray())
compressor.end()
val crc = CRC32()
crc.update(data)
entry.compression = 8u //deflate compression
entry.uncompressedSize = uncompressedSize.toUInt()
entry.compressedSize = compressedDataLength.toUInt()
entry.crc32 = crc.value.toUInt()
addEntry(entry, compressedBuffer)
}
private fun addEntryCopyData(entry: ZipEntry, data: ByteBuffer, alignment: Int? = null) {
alignment?.let {
//calculate where data would end up
val dataOffset = filePointer.filePointer + entry.LFHSize
val mod = dataOffset % alignment
//wrong alignment
if (mod != 0L) {
//add padding at end of extra field
entry.localExtraField =
entry.localExtraField.copyOf((entry.localExtraField.size + (alignment - mod)).toInt())
}
}
addEntry(entry, data)
}
fun getDataForEntry(entry: ZipEntry): ByteBuffer {
return filePointer.channel.map(
FileChannel.MapMode.READ_ONLY,
entry.dataOffset.toLong(),
entry.compressedSize.toLong()
)
}
fun copyEntriesFromFileAligned(file: ZipFile, entryAlignment: (entry: ZipEntry) -> Int?) {
for (entry in file.entries) {
if (entries.any { it.fileName == entry.fileName }) continue //don't add duplicates
val data = file.getDataForEntry(entry)
addEntryCopyData(entry, data, entryAlignment(entry))
}
}
override fun close() {
if (CDNeedsRewrite) writeCD()
filePointer.close()
}
}

View File

@@ -0,0 +1,78 @@
package app.revanced.manager.flutter.utils.zip.structures
import app.revanced.manager.flutter.utils.zip.putUInt
import app.revanced.manager.flutter.utils.zip.putUShort
import app.revanced.manager.flutter.utils.zip.readUIntLE
import app.revanced.manager.flutter.utils.zip.readUShortLE
import java.io.DataInput
import java.nio.ByteBuffer
import java.nio.ByteOrder
data class ZipEndRecord(
val diskNumber: UShort,
val startingDiskNumber: UShort,
val diskEntries: UShort,
val totalEntries: UShort,
val centralDirectorySize: UInt,
val centralDirectoryStartOffset: UInt,
val fileComment: String,
) {
companion object {
const val ECD_HEADER_SIZE = 22
const val ECD_SIGNATURE = 0x06054b50u
fun fromECD(input: DataInput): ZipEndRecord {
val signature = input.readUIntLE()
if (signature != ECD_SIGNATURE)
throw IllegalArgumentException("Input doesn't start with end record signature")
val diskNumber = input.readUShortLE()
val startingDiskNumber = input.readUShortLE()
val diskEntries = input.readUShortLE()
val totalEntries = input.readUShortLE()
val centralDirectorySize = input.readUIntLE()
val centralDirectoryStartOffset = input.readUIntLE()
val fileCommentLength = input.readUShortLE()
var fileComment = ""
if (fileCommentLength > 0u) {
val fileCommentBytes = ByteArray(fileCommentLength.toInt())
input.readFully(fileCommentBytes)
fileComment = fileCommentBytes.toString(Charsets.UTF_8)
}
return ZipEndRecord(
diskNumber,
startingDiskNumber,
diskEntries,
totalEntries,
centralDirectorySize,
centralDirectoryStartOffset,
fileComment
)
}
}
fun toECD(): ByteBuffer {
val commentBytes = fileComment.toByteArray(Charsets.UTF_8)
val buffer = ByteBuffer.allocate(ECD_HEADER_SIZE + commentBytes.size)
.also { it.order(ByteOrder.LITTLE_ENDIAN) }
buffer.putUInt(ECD_SIGNATURE)
buffer.putUShort(diskNumber)
buffer.putUShort(startingDiskNumber)
buffer.putUShort(diskEntries)
buffer.putUShort(totalEntries)
buffer.putUInt(centralDirectorySize)
buffer.putUInt(centralDirectoryStartOffset)
buffer.putUShort(commentBytes.size.toUShort())
buffer.put(commentBytes)
buffer.flip()
return buffer
}
}

View File

@@ -0,0 +1,190 @@
package app.revanced.manager.flutter.utils.zip.structures
import app.revanced.manager.flutter.utils.zip.*
import java.io.DataInput
import java.nio.ByteBuffer
import java.nio.ByteOrder
data class ZipEntry(
val version: UShort,
val versionNeeded: UShort,
val flags: UShort,
var compression: UShort,
val modificationTime: UShort,
val modificationDate: UShort,
var crc32: UInt,
var compressedSize: UInt,
var uncompressedSize: UInt,
val diskNumber: UShort,
val internalAttributes: UShort,
val externalAttributes: UInt,
var localHeaderOffset: UInt,
val fileName: String,
val extraField: ByteArray,
val fileComment: String,
var localExtraField: ByteArray = ByteArray(0), //separate for alignment
) {
val LFHSize: Int
get() = LFH_HEADER_SIZE + fileName.toByteArray(Charsets.UTF_8).size + localExtraField.size
val dataOffset: UInt
get() = localHeaderOffset + LFHSize.toUInt()
companion object {
const val CDE_HEADER_SIZE = 46
const val CDE_SIGNATURE = 0x02014b50u
const val LFH_HEADER_SIZE = 30
const val LFH_SIGNATURE = 0x04034b50u
fun createWithName(fileName: String): ZipEntry {
return ZipEntry(
0x1403u, //made by unix, version 20
0u,
0u,
0u,
0x0821u, //seems to be static time google uses, no idea
0x0221u, //same as above
0u,
0u,
0u,
0u,
0u,
0u,
0u,
fileName,
ByteArray(0),
""
)
}
fun fromCDE(input: DataInput): ZipEntry {
val signature = input.readUIntLE()
if (signature != CDE_SIGNATURE)
throw IllegalArgumentException("Input doesn't start with central directory entry signature")
val version = input.readUShortLE()
val versionNeeded = input.readUShortLE()
var flags = input.readUShortLE()
val compression = input.readUShortLE()
val modificationTime = input.readUShortLE()
val modificationDate = input.readUShortLE()
val crc32 = input.readUIntLE()
val compressedSize = input.readUIntLE()
val uncompressedSize = input.readUIntLE()
val fileNameLength = input.readUShortLE()
var fileName = ""
val extraFieldLength = input.readUShortLE()
val extraField = ByteArray(extraFieldLength.toInt())
val fileCommentLength = input.readUShortLE()
var fileComment = ""
val diskNumber = input.readUShortLE()
val internalAttributes = input.readUShortLE()
val externalAttributes = input.readUIntLE()
val localHeaderOffset = input.readUIntLE()
val variableFieldsLength =
fileNameLength.toInt() + extraFieldLength.toInt() + fileCommentLength.toInt()
if (variableFieldsLength > 0) {
val fileNameBytes = ByteArray(fileNameLength.toInt())
input.readFully(fileNameBytes)
fileName = fileNameBytes.toString(Charsets.UTF_8)
input.readFully(extraField)
val fileCommentBytes = ByteArray(fileCommentLength.toInt())
input.readFully(fileCommentBytes)
fileComment = fileCommentBytes.toString(Charsets.UTF_8)
}
flags = (flags and 0b1000u.inv()
.toUShort()) //disable data descriptor flag as they are not used
return ZipEntry(
version,
versionNeeded,
flags,
compression,
modificationTime,
modificationDate,
crc32,
compressedSize,
uncompressedSize,
diskNumber,
internalAttributes,
externalAttributes,
localHeaderOffset,
fileName,
extraField,
fileComment,
)
}
}
fun readLocalExtra(buffer: ByteBuffer) {
buffer.order(ByteOrder.LITTLE_ENDIAN)
localExtraField = ByteArray(buffer.getUShort().toInt())
}
fun toLFH(): ByteBuffer {
val nameBytes = fileName.toByteArray(Charsets.UTF_8)
val buffer = ByteBuffer.allocate(LFH_HEADER_SIZE + nameBytes.size + localExtraField.size)
.also { it.order(ByteOrder.LITTLE_ENDIAN) }
buffer.putUInt(LFH_SIGNATURE)
buffer.putUShort(versionNeeded)
buffer.putUShort(flags)
buffer.putUShort(compression)
buffer.putUShort(modificationTime)
buffer.putUShort(modificationDate)
buffer.putUInt(crc32)
buffer.putUInt(compressedSize)
buffer.putUInt(uncompressedSize)
buffer.putUShort(nameBytes.size.toUShort())
buffer.putUShort(localExtraField.size.toUShort())
buffer.put(nameBytes)
buffer.put(localExtraField)
buffer.flip()
return buffer
}
fun toCDE(): ByteBuffer {
val nameBytes = fileName.toByteArray(Charsets.UTF_8)
val commentBytes = fileComment.toByteArray(Charsets.UTF_8)
val buffer =
ByteBuffer.allocate(CDE_HEADER_SIZE + nameBytes.size + extraField.size + commentBytes.size)
.also { it.order(ByteOrder.LITTLE_ENDIAN) }
buffer.putUInt(CDE_SIGNATURE)
buffer.putUShort(version)
buffer.putUShort(versionNeeded)
buffer.putUShort(flags)
buffer.putUShort(compression)
buffer.putUShort(modificationTime)
buffer.putUShort(modificationDate)
buffer.putUInt(crc32)
buffer.putUInt(compressedSize)
buffer.putUInt(uncompressedSize)
buffer.putUShort(nameBytes.size.toUShort())
buffer.putUShort(extraField.size.toUShort())
buffer.putUShort(commentBytes.size.toUShort())
buffer.putUShort(diskNumber)
buffer.putUShort(internalAttributes)
buffer.putUInt(externalAttributes)
buffer.putUInt(localHeaderOffset)
buffer.put(nameBytes)
buffer.put(extraField)
buffer.put(commentBytes)
buffer.flip()
return buffer
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<!-- <item>
<bitmap
android:gravity="center"
android:src="@mipmap/launch_image" />
</item> -->
</layer-list>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_launcher_round</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_launcher_round</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="." />
</paths>

View File

@@ -0,0 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.revanced.manager.flutter">
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>

37
android/build.gradle Normal file
View File

@@ -0,0 +1,37 @@
buildscript {
ext.cronetVersion = '102.5005.125'
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects {
repositories {
google()
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher")
credentials {
username = (project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")) as String
password = (project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")) as String
}
}
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@@ -0,0 +1,3 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true

View File

@@ -1,8 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=61ad310d3c7d3e5da131b76bbf22b5a4c0786e9d892dae8c1658d4b484de3caa
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

11
android/settings.gradle Normal file
View File

@@ -0,0 +1,11 @@
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"

View File

@@ -1,39 +0,0 @@
{
"branches": [
"main",
{
"name": "dev",
"prerelease": true
}
],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"releaseRules": [
{ "type": "build", "scope": "Needs bump", "release": "patch" }
]
}
],
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"gradle-semantic-release-plugin",
[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md",
"gradle.properties"
],
"message": "chore: Release API v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
[
"@saithodev/semantic-release-backmerge",
{
"backmergeBranches": [{"from": "main", "to": "dev"}],
"clearWorkspace": true
}
]
]
}

View File

@@ -1,182 +0,0 @@
public abstract interface class app/revanced/manager/plugin/downloader/BaseDownloadScope : app/revanced/manager/plugin/downloader/Scope {
}
public final class app/revanced/manager/plugin/downloader/ConstantsKt {
public static final field PLUGIN_HOST_PERMISSION Ljava/lang/String;
}
public final class app/revanced/manager/plugin/downloader/DownloadUrl : android/os/Parcelable {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Ljava/util/Map;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Map;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/util/Map;
public final fun copy (Ljava/lang/String;Ljava/util/Map;)Lapp/revanced/manager/plugin/downloader/DownloadUrl;
public static synthetic fun copy$default (Lapp/revanced/manager/plugin/downloader/DownloadUrl;Ljava/lang/String;Ljava/util/Map;ILjava/lang/Object;)Lapp/revanced/manager/plugin/downloader/DownloadUrl;
public final fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getHeaders ()Ljava/util/Map;
public final fun getUrl ()Ljava/lang/String;
public fun hashCode ()I
public final fun toDownloadResult ()Lkotlin/Pair;
public fun toString ()Ljava/lang/String;
public final fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class app/revanced/manager/plugin/downloader/DownloadUrl$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/DownloadUrl;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/DownloadUrl;
public synthetic fun newArray (I)[Ljava/lang/Object;
}
public final class app/revanced/manager/plugin/downloader/Downloader {
public static final field $stable I
}
public final class app/revanced/manager/plugin/downloader/DownloaderBuilder {
public static final field $stable I
}
public final class app/revanced/manager/plugin/downloader/DownloaderKt {
public static final fun Downloader (Lkotlin/jvm/functions/Function1;)Lapp/revanced/manager/plugin/downloader/DownloaderBuilder;
}
public final class app/revanced/manager/plugin/downloader/DownloaderScope : app/revanced/manager/plugin/downloader/Scope {
public static final field $stable I
public final fun download (Lkotlin/jvm/functions/Function3;)V
public final fun get (Lkotlin/jvm/functions/Function4;)V
public fun getHostPackageName ()Ljava/lang/String;
public fun getPluginPackageName ()Ljava/lang/String;
public final fun useService (Landroid/content/Intent;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class app/revanced/manager/plugin/downloader/ExtensionsKt {
public static final fun download (Lapp/revanced/manager/plugin/downloader/DownloaderScope;Lkotlin/jvm/functions/Function4;)V
}
public abstract interface class app/revanced/manager/plugin/downloader/GetScope : app/revanced/manager/plugin/downloader/Scope {
public abstract fun requestStartActivity (Landroid/content/Intent;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public abstract interface class app/revanced/manager/plugin/downloader/InputDownloadScope : app/revanced/manager/plugin/downloader/BaseDownloadScope {
}
public abstract interface class app/revanced/manager/plugin/downloader/OutputDownloadScope : app/revanced/manager/plugin/downloader/BaseDownloadScope {
public abstract fun reportSize (JLkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class app/revanced/manager/plugin/downloader/Package : android/os/Parcelable {
public static final field $stable I
public static final field CREATOR Landroid/os/Parcelable$Creator;
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;Ljava/lang/String;)Lapp/revanced/manager/plugin/downloader/Package;
public static synthetic fun copy$default (Lapp/revanced/manager/plugin/downloader/Package;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lapp/revanced/manager/plugin/downloader/Package;
public final fun describeContents ()I
public fun equals (Ljava/lang/Object;)Z
public final fun getName ()Ljava/lang/String;
public final fun getVersion ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public final fun writeToParcel (Landroid/os/Parcel;I)V
}
public final class app/revanced/manager/plugin/downloader/Package$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/Package;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/Package;
public synthetic fun newArray (I)[Ljava/lang/Object;
}
public abstract interface annotation class app/revanced/manager/plugin/downloader/PluginHostApi : java/lang/annotation/Annotation {
}
public abstract interface class app/revanced/manager/plugin/downloader/Scope {
public abstract fun getHostPackageName ()Ljava/lang/String;
public abstract fun getPluginPackageName ()Ljava/lang/String;
}
public abstract class app/revanced/manager/plugin/downloader/UserInteractionException : java/lang/Exception {
public static final field $stable I
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public abstract class app/revanced/manager/plugin/downloader/UserInteractionException$Activity : app/revanced/manager/plugin/downloader/UserInteractionException {
public static final field $stable I
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/manager/plugin/downloader/UserInteractionException$Activity$Cancelled : app/revanced/manager/plugin/downloader/UserInteractionException$Activity {
public static final field $stable I
}
public final class app/revanced/manager/plugin/downloader/UserInteractionException$Activity$NotCompleted : app/revanced/manager/plugin/downloader/UserInteractionException$Activity {
public static final field $stable I
public final fun getIntent ()Landroid/content/Intent;
public final fun getResultCode ()I
}
public final class app/revanced/manager/plugin/downloader/UserInteractionException$RequestDenied : app/revanced/manager/plugin/downloader/UserInteractionException {
public static final field $stable I
}
public final class app/revanced/manager/plugin/downloader/webview/APIKt {
public static final fun WebViewDownloader (Lkotlin/jvm/functions/Function4;)Lapp/revanced/manager/plugin/downloader/DownloaderBuilder;
public static final fun runWebView (Lapp/revanced/manager/plugin/downloader/GetScope;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public class app/revanced/manager/plugin/downloader/webview/IWebView$Default : app/revanced/manager/plugin/downloader/webview/IWebView {
public fun <init> ()V
public fun asBinder ()Landroid/os/IBinder;
public fun finish ()V
public fun load (Ljava/lang/String;)V
}
public abstract class app/revanced/manager/plugin/downloader/webview/IWebView$Stub : android/os/Binder, app/revanced/manager/plugin/downloader/webview/IWebView {
public fun <init> ()V
public fun asBinder ()Landroid/os/IBinder;
public static fun asInterface (Landroid/os/IBinder;)Lapp/revanced/manager/plugin/downloader/webview/IWebView;
public fun onTransact (ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
}
public class app/revanced/manager/plugin/downloader/webview/IWebViewEvents$Default : app/revanced/manager/plugin/downloader/webview/IWebViewEvents {
public fun <init> ()V
public fun asBinder ()Landroid/os/IBinder;
public fun download (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
public fun pageLoad (Ljava/lang/String;)V
public fun ready (Lapp/revanced/manager/plugin/downloader/webview/IWebView;)V
}
public abstract class app/revanced/manager/plugin/downloader/webview/IWebViewEvents$Stub : android/os/Binder, app/revanced/manager/plugin/downloader/webview/IWebViewEvents {
public fun <init> ()V
public fun asBinder ()Landroid/os/IBinder;
public static fun asInterface (Landroid/os/IBinder;)Lapp/revanced/manager/plugin/downloader/webview/IWebViewEvents;
public fun onTransact (ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
}
public final class app/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters$Creator : android/os/Parcelable$Creator {
public fun <init> ()V
public final fun createFromParcel (Landroid/os/Parcel;)Lapp/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters;
public synthetic fun createFromParcel (Landroid/os/Parcel;)Ljava/lang/Object;
public final fun newArray (I)[Lapp/revanced/manager/plugin/downloader/webview/WebViewActivity$Parameters;
public synthetic fun newArray (I)[Ljava/lang/Object;
}
public abstract interface class app/revanced/manager/plugin/downloader/webview/WebViewCallbackScope : app/revanced/manager/plugin/downloader/Scope {
public abstract fun finish (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun load (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
}
public final class app/revanced/manager/plugin/downloader/webview/WebViewScope : app/revanced/manager/plugin/downloader/Scope {
public static final field $stable I
public final fun download (Lkotlin/jvm/functions/Function5;)V
public fun getHostPackageName ()Ljava/lang/String;
public fun getPluginPackageName ()Ljava/lang/String;
public final fun pageLoad (Lkotlin/jvm/functions/Function3;)V
}

View File

@@ -1,111 +0,0 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.binary.compatibility.validator)
`maven-publish`
signing
}
group = "app.revanced"
dependencies {
implementation(libs.androidx.ktx)
implementation(libs.runtime.ktx)
implementation(libs.activity.compose)
implementation(libs.appcompat)
}
android {
namespace = "app.revanced.manager.plugin.downloader"
compileSdk = 35
defaultConfig {
minSdk = 26
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
aidl = true
}
}
apiValidation {
nonPublicMarkers += "app.revanced.manager.plugin.downloader.PluginHostApi"
}
publishing {
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/revanced/revanced-manager")
credentials {
username = System.getenv("GITHUB_ACTOR") ?: extra["gpr.user"] as String?
password = System.getenv("GITHUB_TOKEN") ?: extra["gpr.key"] as String?
}
}
}
publications {
create<MavenPublication>("Api") {
afterEvaluate {
from(components["release"])
}
groupId = "app.revanced"
artifactId = "revanced-manager-api"
version = project.version.toString()
pom {
name = "ReVanced Manager API"
description = "API for ReVanced Manager."
url = "https://revanced.app"
licenses {
license {
name = "GNU General Public License v3.0"
url = "https://www.gnu.org/licenses/gpl-3.0.en.html"
}
}
developers {
developer {
id = "ReVanced"
name = "ReVanced"
email = "contact@revanced.app"
}
}
scm {
connection = "scm:git:git://github.com/revanced/revanced-manager.git"
developerConnection = "scm:git:git@github.com:revanced/revanced-manager.git"
url = "https://github.com/revanced/revanced-manager"
}
}
}
}
}
signing {
useGpgCmd()
sign(publishing.publications["Api"])
}

1
api/gradlew vendored
View File

@@ -1 +0,0 @@
../gradlew

View File

@@ -1,11 +0,0 @@
{
"name": "api",
"private": false,
"devDependencies": {
"@anolilab/multi-semantic-release": "^1.1.10",
"@saithodev/semantic-release-backmerge": "^4.0.1",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.10.1"
}
}

View File

@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -1,8 +0,0 @@
// IWebView.aidl
package app.revanced.manager.plugin.downloader.webview;
@JavaPassthrough(annotation="@app.revanced.manager.plugin.downloader.PluginHostApi")
oneway interface IWebView {
void load(String url);
void finish();
}

View File

@@ -1,11 +0,0 @@
// IWebViewEvents.aidl
package app.revanced.manager.plugin.downloader.webview;
import app.revanced.manager.plugin.downloader.webview.IWebView;
@JavaPassthrough(annotation="@app.revanced.manager.plugin.downloader.PluginHostApi")
oneway interface IWebViewEvents {
void ready(IWebView iface);
void pageLoad(String url);
void download(String url, String mimetype, String userAgent);
}

View File

@@ -1,7 +0,0 @@
package app.revanced.manager.plugin.downloader
/**
* The permission ID of the special plugin host permission. Only ReVanced Manager will have this permission.
* Plugin UI activities and internal services can be protected using this permission.
*/
const val PLUGIN_HOST_PERMISSION = "app.revanced.manager.permission.PLUGIN_HOST"

View File

@@ -1,165 +0,0 @@
package app.revanced.manager.plugin.downloader
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.app.Activity
import android.os.Parcelable
import kotlinx.coroutines.withTimeout
import java.io.InputStream
import java.io.OutputStream
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
@RequiresOptIn(
level = RequiresOptIn.Level.ERROR,
message = "This API is only intended for plugin hosts, don't use it in a plugin.",
)
@Retention(AnnotationRetention.BINARY)
annotation class PluginHostApi
/**
* The base interface for all DSL scopes.
*/
interface Scope {
/**
* The package name of ReVanced Manager.
*/
val hostPackageName: String
/**
* The package name of the plugin.
*/
val pluginPackageName: String
}
/**
* The scope of [DownloaderScope.get].
*/
interface GetScope : Scope {
/**
* Ask the user to perform some required interaction in the activity specified by the provided [Intent].
* This function returns normally with the resulting [Intent] when the activity finishes with code [Activity.RESULT_OK].
*
* @throws UserInteractionException.RequestDenied User decided to skip this plugin.
* @throws UserInteractionException.Activity.Cancelled The activity was cancelled.
* @throws UserInteractionException.Activity.NotCompleted The activity finished with an unknown result code.
*/
suspend fun requestStartActivity(intent: Intent): Intent?
}
interface BaseDownloadScope : Scope
/**
* The scope for [DownloaderScope.download].
*/
interface InputDownloadScope : BaseDownloadScope
typealias Size = Long
typealias DownloadResult = Pair<InputStream, Size?>
typealias Version = String
typealias GetResult<T> = Pair<T, Version?>
class DownloaderScope<T : Parcelable> internal constructor(
private val scopeImpl: Scope,
internal val context: Context
) : Scope by scopeImpl {
// Returning an InputStream is the primary way for plugins to implement the download function, but we also want to offer an OutputStream API since using InputStream might not be convenient in all cases.
// It is much easier to implement the main InputStream API on top of OutputStreams compared to doing it the other way around, which is why we are using OutputStream here. This detail is not visible to plugins.
internal var download: (suspend OutputDownloadScope.(T, OutputStream) -> Unit)? = null
internal var get: (suspend GetScope.(String, String?) -> GetResult<T>?)? = null
private val inputDownloadScopeImpl = object : InputDownloadScope, Scope by scopeImpl {}
/**
* Define the download block of the plugin.
*/
fun download(block: suspend InputDownloadScope.(data: T) -> DownloadResult) {
download = { app, outputStream ->
val (inputStream, size) = inputDownloadScopeImpl.block(app)
inputStream.use {
if (size != null) reportSize(size)
it.copyTo(outputStream)
}
}
}
/**
* Define the get block of the plugin.
* The block should return null if the app cannot be found. The version in the result must match the version argument unless it is null.
*/
fun get(block: suspend GetScope.(packageName: String, version: String?) -> GetResult<T>?) {
get = block
}
/**
* Utilize the service specified by the provided [Intent]. The service will be unbound when the scope ends.
*/
suspend fun <R : Any?> useService(intent: Intent, block: suspend (IBinder) -> R): R {
var onBind: ((IBinder) -> Unit)? = null
val serviceConn = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) =
onBind!!(service!!)
override fun onServiceDisconnected(name: ComponentName?) {}
}
return try {
val binder = withTimeout(10000L) {
suspendCoroutine { continuation ->
onBind = continuation::resume
context.bindService(intent, serviceConn, Context.BIND_AUTO_CREATE)
}
}
block(binder)
} finally {
onBind = null
context.unbindService(serviceConn)
}
}
}
class DownloaderBuilder<T : Parcelable> internal constructor(private val block: DownloaderScope<T>.() -> Unit) {
@PluginHostApi
fun build(scopeImpl: Scope, context: Context) =
with(DownloaderScope<T>(scopeImpl, context)) {
block()
Downloader(
download = download!!,
get = get!!
)
}
}
class Downloader<T : Parcelable> internal constructor(
@property:PluginHostApi val get: suspend GetScope.(packageName: String, version: String?) -> GetResult<T>?,
@property:PluginHostApi val download: suspend OutputDownloadScope.(data: T, outputStream: OutputStream) -> Unit
)
/**
* Define a downloader plugin.
*/
fun <T : Parcelable> Downloader(block: DownloaderScope<T>.() -> Unit) = DownloaderBuilder(block)
/**
* @see GetScope.requestStartActivity
*/
sealed class UserInteractionException(message: String) : Exception(message) {
class RequestDenied @PluginHostApi constructor() :
UserInteractionException("Request denied by user")
sealed class Activity(message: String) : UserInteractionException(message) {
class Cancelled @PluginHostApi constructor() : Activity("Interaction cancelled")
/**
* @param resultCode The result code of the activity.
* @param intent The [Intent] of the activity.
*/
class NotCompleted @PluginHostApi constructor(val resultCode: Int, val intent: Intent?) :
Activity("Unexpected activity result code: $resultCode")
}
}

View File

@@ -1,42 +0,0 @@
package app.revanced.manager.plugin.downloader
import android.app.Activity
import android.app.Service
import android.content.Intent
import android.os.IBinder
import android.os.Parcelable
import java.io.OutputStream
/**
* The scope of the [OutputStream] version of [DownloaderScope.download].
*/
interface OutputDownloadScope : BaseDownloadScope {
suspend fun reportSize(size: Long)
}
/**
* A replacement for [DownloaderScope.download] that uses [OutputStream].
* The provided [OutputStream] does not need to be closed manually.
*/
fun <T : Parcelable> DownloaderScope<T>.download(block: suspend OutputDownloadScope.(T, OutputStream) -> Unit) {
download = block
}
/**
* Performs [GetScope.requestStartActivity] with an [Intent] created using the type information of [ACTIVITY].
* @see [GetScope.requestStartActivity]
*/
suspend inline fun <reified ACTIVITY : Activity> GetScope.requestStartActivity() =
requestStartActivity(
Intent().apply { setClassName(pluginPackageName, ACTIVITY::class.qualifiedName!!) }
)
/**
* Performs [DownloaderScope.useService] with an [Intent] created using the type information of [SERVICE].
* @see [DownloaderScope.useService]
*/
suspend inline fun <reified SERVICE : Service, R : Any?> DownloaderScope<*>.useService(
noinline block: suspend (IBinder) -> R
) = useService(
Intent().apply { setClassName(pluginPackageName, SERVICE::class.qualifiedName!!) }, block
)

View File

@@ -1,39 +0,0 @@
package app.revanced.manager.plugin.downloader
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import java.net.HttpURLConnection
import java.net.URI
/**
* A simple parcelable data class for storing a package name and version.
* This can be used as the data type for plugins that only need a name and version to implement their [DownloaderScope.download] function.
*
* @param name The package name.
* @param version The version.
*/
@Parcelize
data class Package(val name: String, val version: String) : Parcelable
/**
* A data class for storing a download URL.
*
* @param url The download URL.
* @param headers The headers to use for the request.
*/
@Parcelize
data class DownloadUrl(val url: String, val headers: Map<String, String> = emptyMap()) : Parcelable {
/**
* Converts this into a [DownloadResult].
*/
fun toDownloadResult(): DownloadResult = with(URI.create(url).toURL().openConnection() as HttpURLConnection) {
useCaches = false
allowUserInteraction = false
headers.forEach(::setRequestProperty)
connectTimeout = 10_000
connect()
inputStream to getHeaderField("Content-Length").toLong()
}
}

View File

@@ -1,176 +0,0 @@
package app.revanced.manager.plugin.downloader.webview
import android.content.Intent
import app.revanced.manager.plugin.downloader.DownloadUrl
import app.revanced.manager.plugin.downloader.DownloaderScope
import app.revanced.manager.plugin.downloader.GetScope
import app.revanced.manager.plugin.downloader.Scope
import app.revanced.manager.plugin.downloader.Downloader
import app.revanced.manager.plugin.downloader.PluginHostApi
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.withContext
import kotlin.properties.Delegates
typealias InitialUrl = String
typealias PageLoadCallback<T> = suspend WebViewCallbackScope<T>.(url: String) -> Unit
typealias DownloadCallback<T> = suspend WebViewCallbackScope<T>.(url: String, mimeType: String, userAgent: String) -> Unit
interface WebViewCallbackScope<T> : Scope {
/**
* Finishes the activity and returns the [result].
*/
suspend fun finish(result: T)
/**
* Tells the WebView to load the specified [url].
*/
suspend fun load(url: String)
}
@OptIn(PluginHostApi::class)
class WebViewScope<T> internal constructor(
coroutineScope: CoroutineScope,
private val scopeImpl: Scope,
setResult: (T) -> Unit
) : Scope by scopeImpl {
private var onPageLoadCallback: PageLoadCallback<T> = {}
private var onDownloadCallback: DownloadCallback<T> = { _, _, _ -> }
@OptIn(ExperimentalCoroutinesApi::class)
private val dispatcher = Dispatchers.Default.limitedParallelism(1)
private lateinit var webView: IWebView
internal lateinit var initialUrl: String
internal val binder = object : IWebViewEvents.Stub() {
override fun ready(iface: IWebView?) {
coroutineScope.launch(dispatcher) {
webView = iface!!.also {
it.load(initialUrl)
}
}
}
override fun pageLoad(url: String?) {
coroutineScope.launch(dispatcher) { onPageLoadCallback(callbackScope, url!!) }
}
override fun download(url: String?, mimetype: String?, userAgent: String?) {
coroutineScope.launch(dispatcher) {
onDownloadCallback(
callbackScope,
url!!,
mimetype!!,
userAgent!!
)
}
}
}
private val callbackScope = object : WebViewCallbackScope<T>, Scope by scopeImpl {
override suspend fun finish(result: T) {
setResult(result)
// Tell the WebViewActivity to finish
webView.let { withContext(Dispatchers.IO) { it.finish() } }
}
override suspend fun load(url: String) {
webView.let { withContext(Dispatchers.IO) { it.load(url) } }
}
}
/**
* Called when the WebView attempts to download a file to disk.
*/
fun download(block: DownloadCallback<T>) {
onDownloadCallback = block
}
/**
* Called when the WebView finishes loading a page.
*/
fun pageLoad(block: PageLoadCallback<T>) {
onPageLoadCallback = block
}
}
@JvmInline
private value class Container<U>(val value: U)
/**
* Run a [android.webkit.WebView] Activity controlled by the provided code block.
* The activity will keep running until it is cancelled or an event handler calls [WebViewCallbackScope.finish].
* The [block] defines the event handlers and returns the initial URL.
*
* @param title The string displayed in the action bar.
* @param block The control block.
*/
@OptIn(PluginHostApi::class)
suspend fun <T> GetScope.runWebView(
title: String,
block: suspend WebViewScope<T>.() -> InitialUrl
) = supervisorScope {
var result by Delegates.notNull<Container<T>>()
val scope = WebViewScope<T>(this@supervisorScope, this@runWebView) { result = Container(it) }
scope.initialUrl = scope.block()
// Start the webview activity and wait until it finishes.
requestStartActivity(Intent().apply {
putExtra(
WebViewActivity.KEY,
WebViewActivity.Parameters(title, scope.binder)
)
setClassName(
hostPackageName,
WebViewActivity::class.qualifiedName!!
)
})
// Return the result and cancel any leftover coroutines.
coroutineContext.cancelChildren()
result.value
}
/**
* Implement a downloader using [runWebView] and [DownloadUrl]. This function will automatically define a handler for download events unlike [runWebView].
* Returning null inside the [block] is equivalent to returning null inside [DownloaderScope.get].
*
* @see runWebView
*/
fun WebViewDownloader(block: suspend WebViewScope<DownloadUrl>.(packageName: String, version: String?) -> InitialUrl?) =
Downloader<DownloadUrl> {
val label = context.applicationInfo.loadLabel(
context.packageManager
).toString()
get { packageName, version ->
class ReturnNull : Exception()
try {
runWebView(label) {
download { url, _, userAgent ->
finish(
DownloadUrl(
url,
mapOf("User-Agent" to userAgent)
)
)
}
block(this@runWebView, packageName, version) ?: throw ReturnNull()
} to version
} catch (_: ReturnNull) {
null
}
}
download {
it.toDownloadResult()
}
}

View File

@@ -1,161 +0,0 @@
package app.revanced.manager.plugin.downloader.webview
import android.annotation.SuppressLint
import android.os.Bundle
import android.os.IBinder
import android.os.Parcelable
import android.view.MenuItem
import android.webkit.CookieManager
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.ComponentActivity
import androidx.activity.addCallback
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.viewModelScope
import app.revanced.manager.plugin.downloader.PluginHostApi
import app.revanced.manager.plugin.downloader.R
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
@OptIn(PluginHostApi::class)
@PluginHostApi
class WebViewActivity : ComponentActivity() {
@SuppressLint("SetJavaScriptEnabled")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val vm by viewModels<WebViewModel>()
enableEdgeToEdge()
setContentView(R.layout.activity_webview)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val webView = findViewById<WebView>(R.id.webview)
onBackPressedDispatcher.addCallback {
if (webView.canGoBack()) webView.goBack()
else cancelActivity()
}
val params = intent.getParcelableExtra<Parameters>(KEY)!!
actionBar?.apply {
title = params.title
setHomeAsUpIndicator(android.R.drawable.ic_menu_close_clear_cancel)
setDisplayHomeAsUpEnabled(true)
}
val events = IWebViewEvents.Stub.asInterface(params.events)!!
vm.setup(events)
webView.apply {
settings.apply {
cacheMode = WebSettings.LOAD_NO_CACHE
allowContentAccess = false
domStorageEnabled = true
javaScriptEnabled = true
}
webViewClient = vm.webViewClient
setDownloadListener { url, userAgent, _, mimetype, _ ->
vm.onDownload(url, mimetype, userAgent)
}
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
vm.commands.collect {
when (it) {
is WebViewModel.Command.Finish -> {
setResult(RESULT_OK)
finish()
}
is WebViewModel.Command.Load -> webView.loadUrl(it.url)
}
}
}
}
}
private fun cancelActivity() {
setResult(RESULT_CANCELED)
finish()
}
override fun onOptionsItemSelected(item: MenuItem) = if (item.itemId == android.R.id.home) {
cancelActivity()
true
} else super.onOptionsItemSelected(item)
@Parcelize
internal class Parameters(
val title: String, val events: IBinder
) : Parcelable
internal companion object {
const val KEY = "params"
}
}
@OptIn(PluginHostApi::class)
internal class WebViewModel : ViewModel() {
init {
CookieManager.getInstance().apply {
removeAllCookies(null)
setAcceptCookie(true)
}
}
private val commandChannel = Channel<Command>()
val commands = commandChannel.receiveAsFlow()
private var eventBinder: IWebViewEvents? = null
private val ctrlBinder = object : IWebView.Stub() {
override fun load(url: String?) {
viewModelScope.launch {
commandChannel.send(Command.Load(url!!))
}
}
override fun finish() {
viewModelScope.launch {
commandChannel.send(Command.Finish)
}
}
}
val webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
eventBinder!!.pageLoad(url)
}
}
fun onDownload(url: String, mimeType: String, userAgent: String) {
eventBinder!!.download(url, mimeType, userAgent)
}
fun setup(binder: IWebViewEvents) {
if (eventBinder != null) return
eventBinder = binder
binder.ready(ctrlBinder)
}
sealed interface Command {
data class Load(val url: String) : Command
data object Finish : Command
}
}

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/main">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@@ -1 +0,0 @@
<resources></resources>

View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.WebViewActivity" parent="Theme.AppCompat.DayNight">
<item name="android:windowActionBar">true</item>
<item name="android:windowNoTitle">false</item>
</style>
</resources>

1
app/.gitignore vendored
View File

@@ -1 +0,0 @@
/build

View File

@@ -1,50 +0,0 @@
{
"branches": [
"main",
{
"name": "dev",
"prerelease": true
}
],
"plugins": [
[
"@semantic-release/commit-analyzer",
{
"releaseRules": [
{ "type": "build", "scope": "Needs bump", "release": "patch" }
]
}
],
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"gradle-semantic-release-plugin",
[
"@semantic-release/git",
{
"assets": [
"CHANGELOG.md",
"gradle.properties"
],
"message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
[
"@semantic-release/github",
{
"assets": [
{
"path": "build/outputs/apk/release/revanced-manager*.apk?(.asc)"
}
],
"successComment": false
}
],
[
"@saithodev/semantic-release-backmerge",
{
"backmergeBranches": [{"from": "main", "to": "dev"}],
"clearWorkspace": true
}
]
]
}

View File

@@ -1,380 +0,0 @@
# app [1.26.0-dev.16](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.15...v1.26.0-dev.16) (2025-12-30)
### Features
* Show patches as individual steps in patcher screen ([#2889](https://github.com/ReVanced/revanced-manager/issues/2889)) ([11dd6e4](https://github.com/ReVanced/revanced-manager/commit/11dd6e4064099427a8c9bc6f225a19412e5c70e2))
# app [1.26.0-dev.15](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.14...v1.26.0-dev.15) (2025-12-29)
### Bug Fixes
* install dialog getting stuck ([#2900](https://github.com/ReVanced/revanced-manager/issues/2900)) ([18a4df9](https://github.com/ReVanced/revanced-manager/commit/18a4df9af9cac120fdb8e4ff7aadd2e2a8d5c1a6))
# app [1.26.0-dev.14](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.13...v1.26.0-dev.14) (2025-12-28)
### Bug Fixes
* Update selected patch count when SelectionState changes ([#2896](https://github.com/ReVanced/revanced-manager/issues/2896)) ([0d26df0](https://github.com/ReVanced/revanced-manager/commit/0d26df03f463195dae550240c7f652680763079c))
# app [1.26.0-dev.13](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.12...v1.26.0-dev.13) (2025-12-17)
### Features
* Make patcher screen design more consistent with inspiration ([#2805](https://github.com/ReVanced/revanced-manager/issues/2805)) ([dbb6c01](https://github.com/ReVanced/revanced-manager/commit/dbb6c01e89a5e710185ff4304de0ac9e19bed053))
# app [1.26.0-dev.12](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.11...v1.26.0-dev.12) (2025-12-17)
### Features
* Improve trust plugin dialog design ([#2420](https://github.com/ReVanced/revanced-manager/issues/2420)) ([0300da9](https://github.com/ReVanced/revanced-manager/commit/0300da9eac6c0fc29dbbb66622c0d52f4cf68934))
# app [1.26.0-dev.11](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.10...v1.26.0-dev.11) (2025-10-25)
### Features
* Add pure black theme ([#2824](https://github.com/ReVanced/revanced-manager/issues/2824)) ([3d75ffe](https://github.com/ReVanced/revanced-manager/commit/3d75ffe6a7a39efdebe13dbd07c937c1de409ead))
# app [1.26.0-dev.10](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.9...v1.26.0-dev.10) (2025-10-06)
### Bug Fixes
* prevent back presses during installation ([2ff7072](https://github.com/ReVanced/revanced-manager/commit/2ff70728b490b92f212a82dcf599bc0c23f589e7))
# app [1.26.0-dev.9](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.8...v1.26.0-dev.9) (2025-10-06)
### Bug Fixes
* Instantly re-fetch patch bundle on pre-release preference update ([d5671db](https://github.com/ReVanced/revanced-manager/commit/d5671db3a77541c07bbbb4c3baca02f3ba0703f2)), closes [#2784](https://github.com/ReVanced/revanced-manager/issues/2784)
# app [1.26.0-dev.8](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.7...v1.26.0-dev.8) (2025-10-06)
### Bug Fixes
* Offcenter loading indicator in AppSelector ([12d92ba](https://github.com/ReVanced/revanced-manager/commit/12d92ba8110f5d1ac78aeecfa575444b5c53f561))
# app [1.26.0-dev.7](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.6...v1.26.0-dev.7) (2025-10-03)
### Bug Fixes
* Improve consistency between pre-release toggles ([e1b768c](https://github.com/ReVanced/revanced-manager/commit/e1b768c4679ecae8bff8007bdab56ff6544b12b6))
# app [1.26.0-dev.6](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.5...v1.26.0-dev.6) (2025-10-03)
### Bug Fixes
* Broken version comparison ([c327857](https://github.com/ReVanced/revanced-manager/commit/c3278578237dcddd9e7ab79ee80a02fdeef9604d))
### Features
* Open contributor's GitHub profile when clicked ([#2775](https://github.com/ReVanced/revanced-manager/issues/2775)) ([2571cb8](https://github.com/ReVanced/revanced-manager/commit/2571cb8c1108e9c1ed84950f17692c09d66e0556))
# app [1.26.0-dev.5](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.4...v1.26.0-dev.5) (2025-10-03)
### Features
* Toggle to use pre-release versions of ReVanced Patches ([08cec67](https://github.com/ReVanced/revanced-manager/commit/08cec674bbbe5297090ac5ee6039569975fbe9e7))
# app [1.26.0-dev.4](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.3...v1.26.0-dev.4) (2025-10-03)
### Bug Fixes
* add newlines to debug logs ([4753873](https://github.com/ReVanced/revanced-manager/commit/4753873866b575e2dcb160020df63f63862c8f33))
# app [1.26.0-dev.3](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.2...v1.26.0-dev.3) (2025-10-03)
### Features
* Toggle to use pre-release versions of ReVanced Manager ([#2773](https://github.com/ReVanced/revanced-manager/issues/2773)) ([d758964](https://github.com/ReVanced/revanced-manager/commit/d7589647426b3d3438161a2f0b59bf4f154ac34b))
# app [1.26.0-dev.2](https://github.com/ReVanced/revanced-manager/compare/v1.26.0-dev.1...v1.26.0-dev.2) (2025-10-03)
### Bug Fixes
* Migration of keystore, by fixing mislabeling of alias as cn ([#2769](https://github.com/ReVanced/revanced-manager/issues/2769)) ([aeab639](https://github.com/ReVanced/revanced-manager/commit/aeab639b2b09e8bbd2478cfbf5a518586405c0f7))
# app [1.26.0-dev.1](https://github.com/ReVanced/revanced-manager/compare/v1.25.1...v1.26.0-dev.1) (2025-10-02)
### Bug Fixes
* `ExtendedFloatingActionButton` not accessible by screen readers ([#2080](https://github.com/ReVanced/revanced-manager/issues/2080)) ([e4f19b0](https://github.com/ReVanced/revanced-manager/commit/e4f19b0c251e818cce59e11362a29dc8f657e065))
* add bounds checks in patch selector ([483be5d](https://github.com/ReVanced/revanced-manager/commit/483be5d722db2be2595f6f6dd0c537a6c8487daf))
* Add missing header for "Updates" settings ([#2642](https://github.com/ReVanced/revanced-manager/issues/2642)) ([d4d2056](https://github.com/ReVanced/revanced-manager/commit/d4d2056585ccd4a0456318448dc822c0f40c9c50))
* Allow different app version when downloading via plugin if setting is off ([#2579](https://github.com/ReVanced/revanced-manager/issues/2579)) ([59d233e](https://github.com/ReVanced/revanced-manager/commit/59d233e15c885104900c7d4129fb4839c4da81e0))
* always use default patch selection if customization is disabled ([cc77181](https://github.com/ReVanced/revanced-manager/commit/cc771817cba3dfd8f704cb7ecc9089ad7911c6ce))
* android icon not loading in app selector ([deea682](https://github.com/ReVanced/revanced-manager/commit/deea68265157da65ef98986d751e2551797522e0))
* automatically focus search views ([d23d673](https://github.com/ReVanced/revanced-manager/commit/d23d673c4703cdfa3be3a292873bbb37bea30ac7))
* available updates dialog list item color ([1a54313](https://github.com/ReVanced/revanced-manager/commit/1a54313c1dc4efbb8b274201a79e28661a7ecf64))
* Broken header padding in `AlertDialogExtended` when using an Icon ([8d939a6](https://github.com/ReVanced/revanced-manager/commit/8d939a6669909a44382fc7404276f2eeefcf728d))
* broken logo in about page on release builds ([ad775f3](https://github.com/ReVanced/revanced-manager/commit/ad775f3059345dd93ff2baf6d018c2beecc413df))
* buildfile syntax ([#66](https://github.com/ReVanced/revanced-manager/issues/66)) ([5c17a78](https://github.com/ReVanced/revanced-manager/commit/5c17a78e46db586642d53362267472fbbd47ae8c))
* bundles not loading on Android 14 ([56896d6](https://github.com/ReVanced/revanced-manager/commit/56896d6197baa836bcd4a499ea2cee487e3d07c8))
* Change the title in the Update screen from "Updates" to "Update" ([5f23769](https://github.com/ReVanced/revanced-manager/commit/5f2376919bd036987eba8188e3a1a2ff53ef6793)), closes [#1960](https://github.com/ReVanced/revanced-manager/issues/1960)
* cleanup advanced settings screen ([02ea5c6](https://github.com/ReVanced/revanced-manager/commit/02ea5c6d4a2e6baa7c034b614deb6e4232cf6d0b))
* **Compose:** Adjusted universal patches safeguard and warnings ([#2550](https://github.com/ReVanced/revanced-manager/issues/2550)) ([663cf2d](https://github.com/ReVanced/revanced-manager/commit/663cf2d6b86c276c6bb236af8e05a4f69df9eba0))
* contributors screen fix ([#1256](https://github.com/ReVanced/revanced-manager/issues/1256)) ([dc73462](https://github.com/ReVanced/revanced-manager/commit/dc73462ac41bd5f1813358eb5e2265a3e2e7c0f9))
* contributors screen repository name ([426b289](https://github.com/ReVanced/revanced-manager/commit/426b28932fe37a6d7412685819ffc8e26b69d31c))
* Correct preference description ([#2619](https://github.com/ReVanced/revanced-manager/issues/2619)) ([0096169](https://github.com/ReVanced/revanced-manager/commit/0096169af8f9e2db6c22b8e88f0dfe1cab1260be))
* Correctly display universal patches warning ([#2570](https://github.com/ReVanced/revanced-manager/issues/2570)) ([24c4cd3](https://github.com/ReVanced/revanced-manager/commit/24c4cd3f991953dd00b5bf5e7c3ec965315a9528))
* correctly patch apk files ([c5cb18a](https://github.com/ReVanced/revanced-manager/commit/c5cb18a7eab838ea096577780335a29b9771b43d))
* crash caused by compose inlining bug ([05fe058](https://github.com/ReVanced/revanced-manager/commit/05fe0581516a373cc26dd559d3fc7f21fcf16f3f))
* crash when removing used bundles ([189c993](https://github.com/ReVanced/revanced-manager/commit/189c993ada6406db6f8c48c4051c5bd9fac98e2b))
* delete temporary files ([#1341](https://github.com/ReVanced/revanced-manager/issues/1341)) ([b03f7b1](https://github.com/ReVanced/revanced-manager/commit/b03f7b18a029465142d08fe1ed68e92c81586a5f))
* disable `WebView` history ([#1278](https://github.com/ReVanced/revanced-manager/issues/1278)) ([a811df9](https://github.com/ReVanced/revanced-manager/commit/a811df9547da33fc61397cb33ba5fd35ee470ff9))
* display version from manifest ([#2634](https://github.com/ReVanced/revanced-manager/issues/2634)) ([1fb94b7](https://github.com/ReVanced/revanced-manager/commit/1fb94b711fdbbbca7d9baaa90c53faf208fc4d0d))
* Do not poll battery optimization status ([#2491](https://github.com/ReVanced/revanced-manager/issues/2491)) ([26778f5](https://github.com/ReVanced/revanced-manager/commit/26778f57e6dd185d9aed1086aa03659a2e91d1a9))
* don't store app list in parcel ([e7802ed](https://github.com/ReVanced/revanced-manager/commit/e7802ed3d714cbe6e29409d27989c65d4d7ce6a5))
* dont crash when the bundle cannot be downloaded ([4d201f1](https://github.com/ReVanced/revanced-manager/commit/4d201f17f2ce01aad6adb456a49c3f03526c5ad3))
* **downloader:** versions not loading correctly ([16c4290](https://github.com/ReVanced/revanced-manager/commit/16c4290f05d94cbe53e68cb98307d7be1bfce7af))
* handle edge-to-edge properly in fullscreen dialogs ([eba92e2](https://github.com/ReVanced/revanced-manager/commit/eba92e2644663b10e7e17f2cf955afefe260d769))
* handle exceptions when checking for bundle updates ([1dd6738](https://github.com/ReVanced/revanced-manager/commit/1dd673896454710094e83789abb585c106ee6bcb))
* Handle open source licenses page crash ([#2569](https://github.com/ReVanced/revanced-manager/issues/2569)) ([f2ea007](https://github.com/ReVanced/revanced-manager/commit/f2ea00757a76ed8758bc0d4df54843c89483c986))
* hide patch button ([#1284](https://github.com/ReVanced/revanced-manager/issues/1284)) ([dadc546](https://github.com/ReVanced/revanced-manager/commit/dadc5462e352e91cf971395def91d693677701bc))
* Ignore long click when already in delete mode ([6f6296b](https://github.com/ReVanced/revanced-manager/commit/6f6296b8cde56d5fc73e00ef671ca7ab431455f4)), closes [#2503](https://github.com/ReVanced/revanced-manager/issues/2503)
* import bundles on another thread ([0383bd7](https://github.com/ReVanced/revanced-manager/commit/0383bd74f73a3523d539c44cdf38b0e857c16bdc))
* import export screen UX ([69c119d](https://github.com/ReVanced/revanced-manager/commit/69c119d545ac811c605124173e5cbc97a9064c79))
* Improve background running notification ([#2614](https://github.com/ReVanced/revanced-manager/issues/2614)) ([05444d8](https://github.com/ReVanced/revanced-manager/commit/05444d8824a429c7e554d0597f8997e670936a63))
* improve bundle page strings ([2a63a61](https://github.com/ReVanced/revanced-manager/commit/2a63a6163a8d2e6ee649cb22099b426ed605de8f))
* improve keystore import error handling and show toast ([cd142a7](https://github.com/ReVanced/revanced-manager/commit/cd142a70d3f210161d3c1f20d2cb82a70432469f))
* Inconsistent padding for battery optimisation warning ([6c3a99a](https://github.com/ReVanced/revanced-manager/commit/6c3a99a4921ab4438a038ad4c4bccd0326fdd565))
* **installer:** make the correct column scrollable ([64496bf](https://github.com/ReVanced/revanced-manager/commit/64496bfbe77a9a44f5535fd5f12eee803ac7c26a))
* **installer:** progress tracking ([f547bb7](https://github.com/ReVanced/revanced-manager/commit/f547bb7ab1b7149d7290729527714168a2561b23))
* **installer:** properly track worker state ([#32](https://github.com/ReVanced/revanced-manager/issues/32)) ([de1ef23](https://github.com/ReVanced/revanced-manager/commit/de1ef23824227796c8583242e624f83d9dae5af3))
* **installer:** save step incorrectly being marked as completed ([0264308](https://github.com/ReVanced/revanced-manager/commit/0264308b6dad051db80da6f130e8d28d86b38f04))
* **installer:** sign and install on threads ([3d59ee5](https://github.com/ReVanced/revanced-manager/commit/3d59ee51acc5a6ebb17f68c0462d17d7ecb0f07c))
* jvm signature clash error ([ee0f342](https://github.com/ReVanced/revanced-manager/commit/ee0f34245636027d55bd5bdfce4d6a5e6c3b3dcd))
* library info not being embedded ([8c9fe69](https://github.com/ReVanced/revanced-manager/commit/8c9fe6989fc6d05afd53baa877f1e6dffc067b50))
* load patch bundles earlier ([a2f9e2f](https://github.com/ReVanced/revanced-manager/commit/a2f9e2f1da961a13b2b20e2812593031c9339b88))
* Match "Installation incompatible" dialog message with Flutter Manager ([#2231](https://github.com/ReVanced/revanced-manager/issues/2231)) ([fedaedf](https://github.com/ReVanced/revanced-manager/commit/fedaedfda112260144b0b9b0776509ddb3438046))
* minify crash on building release ([#1245](https://github.com/ReVanced/revanced-manager/issues/1245)) ([6561e4c](https://github.com/ReVanced/revanced-manager/commit/6561e4c97c19134b22b72e19fad3884f99327b9a))
* more android 34 fixes ([7fb1e27](https://github.com/ReVanced/revanced-manager/commit/7fb1e27617b69803b3d4463993b2290877502545))
* move battery warning to dashboard ([3a05150](https://github.com/ReVanced/revanced-manager/commit/3a05150fa33f119ecdf436f8508862ef81c327a0))
* Move temporary files outside of the cache directory ([#2122](https://github.com/ReVanced/revanced-manager/issues/2122)) ([b93ecc0](https://github.com/ReVanced/revanced-manager/commit/b93ecc0db20339393e1296c44ce4b1dbd837b577))
* Offset badge ([c73fdfd](https://github.com/ReVanced/revanced-manager/commit/c73fdfdd2d3a1b8552d9c26df575b3019346596d))
* only perform haptics on events ([e55566d](https://github.com/ReVanced/revanced-manager/commit/e55566d3df25480260922f0418b4bbee5d7b7a07))
* option state crash ([#1456](https://github.com/ReVanced/revanced-manager/issues/1456)) ([f183b6d](https://github.com/ReVanced/revanced-manager/commit/f183b6d8a6b139fe3e84d5ea3a9658ef900453bc))
* parcel error for nullable types ([336eed3](https://github.com/ReVanced/revanced-manager/commit/336eed3a95111ebbe456321f5986e6875ded354e))
* pass worker inputs without serialization ([#44](https://github.com/ReVanced/revanced-manager/issues/44)) ([059a72b](https://github.com/ReVanced/revanced-manager/commit/059a72b9dd9103d2b3704daa7dbb13ad83971460))
* patch count remaining at zero when using process runtime ([#2542](https://github.com/ReVanced/revanced-manager/issues/2542)) ([f5e1e0b](https://github.com/ReVanced/revanced-manager/commit/f5e1e0b0659e5775dd460b8dfc15427eb0175139))
* patch options reset button being broken ([e1647fd](https://github.com/ReVanced/revanced-manager/commit/e1647fdef0c9f68e171a2d15e2b6e744da6bbaf5))
* Patch process cancelation dialog conditions ([#2554](https://github.com/ReVanced/revanced-manager/issues/2554)) ([e97b19d](https://github.com/ReVanced/revanced-manager/commit/e97b19d2b65dbfc49ed062b123c363e412b9bf8e))
* Patch selection screen padding ([#2533](https://github.com/ReVanced/revanced-manager/issues/2533)) ([cd2dbcc](https://github.com/ReVanced/revanced-manager/commit/cd2dbcc841e56dac99230ea6501af87c43e9c572))
* **patcher:** add notification and wakelock to worker; chore: add app icon ([8b6d32d](https://github.com/ReVanced/revanced-manager/commit/8b6d32dd7b3ca4c694414a55a1b6202b62636530))
* patches not being reloaded ([dccf861](https://github.com/ReVanced/revanced-manager/commit/dccf86163af34341e3e451df9f24356c7294ae1e))
* **patches selector:** copy the selected patches list ([70e49aa](https://github.com/ReVanced/revanced-manager/commit/70e49aaaa3a42510cb9ced2209c90cd1da98391d))
* perform selected app operations in the correct order ([34cf848](https://github.com/ReVanced/revanced-manager/commit/34cf848baaaa2504d162c515a95240d45bd7092a))
* permission error when using installed app ([8767f0e](https://github.com/ReVanced/revanced-manager/commit/8767f0e99c6de5bbb0a690ced40f6e9a486f0828))
* Playback Switch's Haptic Feedback ([#2639](https://github.com/ReVanced/revanced-manager/issues/2639)) ([9fdca5a](https://github.com/ReVanced/revanced-manager/commit/9fdca5a0afd6be8a24e2ec09eec0000b0b9cd179))
* process death resilience and account for android 11 bug ([#2355](https://github.com/ReVanced/revanced-manager/issues/2355)) ([83eeeae](https://github.com/ReVanced/revanced-manager/commit/83eeeae801827800a0787e9e753c72d2a24d7970))
* progress bar not updating ([dcaa38c](https://github.com/ReVanced/revanced-manager/commit/dcaa38c8824f54da7a833c354b247f309d1c9871))
* release builds not working properly ([6f6476e](https://github.com/ReVanced/revanced-manager/commit/6f6476e85158cad4e2497e9f72b73c4dc948f0bc))
* remove battery optimization notification if user grants the permission ([9863c51](https://github.com/ReVanced/revanced-manager/commit/9863c5161a1bc16941a323e654f80f8cb0122f9f))
* remove the unique constraint for patch bundle names ([ea29d0f](https://github.com/ReVanced/revanced-manager/commit/ea29d0f00c3b3b2c137c4849e6c445a6bf9a180f))
* Remove unnecessary screen padding ([8419f75](https://github.com/ReVanced/revanced-manager/commit/8419f75d597dd198aa1029fae2109646c5874078)), closes [#2062](https://github.com/ReVanced/revanced-manager/issues/2062)
* remove unused function preventing compilation ([2297e94](https://github.com/ReVanced/revanced-manager/commit/2297e94cb81a9a22ea032d8e247769774ca85087))
* Reset cached theme on theme change to avoid broken colors ([#2527](https://github.com/ReVanced/revanced-manager/issues/2527)) ([9a82b78](https://github.com/ReVanced/revanced-manager/commit/9a82b785280954973cafc5e6dccb3c90fdb5ef49))
* run blocking IO operations in the correct context ([969ddb7](https://github.com/ReVanced/revanced-manager/commit/969ddb7bef321d7aa2a682b8128b1f755f35c28b))
* run props flow on correct dispatcher ([#2035](https://github.com/ReVanced/revanced-manager/issues/2035)) ([d3d4c27](https://github.com/ReVanced/revanced-manager/commit/d3d4c27f6d7affceef233a0138ee6c985c7f56bc))
* Screen turns off while patching due to wrong WakeLock ([#2147](https://github.com/ReVanced/revanced-manager/issues/2147)) ([4de5340](https://github.com/ReVanced/revanced-manager/commit/4de534094adc0665021d3ba129a648d896718568))
* scrolling in patch selector ([154f036](https://github.com/ReVanced/revanced-manager/commit/154f036fe956096bca983fe9d6654ccca38fd8ac))
* Selected patch count ([#2559](https://github.com/ReVanced/revanced-manager/issues/2559)) ([a91ff60](https://github.com/ReVanced/revanced-manager/commit/a91ff60533b44629ea60e8cd6acceeb80b0253b7))
* serialization not working ([4d04ae0](https://github.com/ReVanced/revanced-manager/commit/4d04ae088c406d84936120cb753cd1f11fb8a8c2))
* show available and selected patches in patch selector screen ([61f1ee0](https://github.com/ReVanced/revanced-manager/commit/61f1ee0627d6cbb6b9a4d226eb6c2f9e0b8c6453))
* show install button when installation has been cancelled ([93f4a5b](https://github.com/ReVanced/revanced-manager/commit/93f4a5bb7c912ca77bb04e414432922c89d3e2c0))
* Show selection warning also on patch option ([#2643](https://github.com/ReVanced/revanced-manager/issues/2643)) ([3b82767](https://github.com/ReVanced/revanced-manager/commit/3b82767a897eeca1dda1d8343f1db4207050e960))
* sources screen being misaligned during transitions ([2ac3d5c](https://github.com/ReVanced/revanced-manager/commit/2ac3d5c483d5cc4776681ed3f900550a4e45f616))
* specify `multithreadingDexFileWriter` in `PatcherOptions` ([#1402](https://github.com/ReVanced/revanced-manager/issues/1402)) ([3f362b6](https://github.com/ReVanced/revanced-manager/commit/3f362b605fbce3ea72e7c95b7e0bc614443c7d44))
* Support patching on ARMv7 by updating AAPT2 ([#2084](https://github.com/ReVanced/revanced-manager/issues/2084)) ([15b47f9](https://github.com/ReVanced/revanced-manager/commit/15b47f9bb6cd6bb0360fda6ac641cd4c75542287))
* Transparent status on fullscreen dialog ([#2654](https://github.com/ReVanced/revanced-manager/issues/2654)) ([a8820a4](https://github.com/ReVanced/revanced-manager/commit/a8820a4daf71704f6945b8f794495fe8a8d7589e))
* Turn off filters by default ([#2079](https://github.com/ReVanced/revanced-manager/issues/2079)) ([44f8b1f](https://github.com/ReVanced/revanced-manager/commit/44f8b1fb6bffed5866ada356910119465320a9a8))
* typo in string name `import_keystore_description` ([#1273](https://github.com/ReVanced/revanced-manager/issues/1273)) ([933e69e](https://github.com/ReVanced/revanced-manager/commit/933e69e21e97fede2183a26dd1645a6eb96c4509))
* **ui:** make entire patches view button selectable ([#1271](https://github.com/ReVanced/revanced-manager/issues/1271)) ([83cdaae](https://github.com/ReVanced/revanced-manager/commit/83cdaaee183ff1b6d905977df38fe4e47f7d5973))
* Updates popup shows incorrect names ([#1283](https://github.com/ReVanced/revanced-manager/issues/1283)) ([c879faf](https://github.com/ReVanced/revanced-manager/commit/c879faf2eb338476c6abd9f104922b0d49f95cd6))
* Use `compatible` rather than `support` when referring to patch compatibility ([#2422](https://github.com/ReVanced/revanced-manager/issues/2422)) ([8b3c4eb](https://github.com/ReVanced/revanced-manager/commit/8b3c4eb91c491a0971e2ccf7d46012437eca5c25))
* use correct `getViewModel` ([5b6ae80](https://github.com/ReVanced/revanced-manager/commit/5b6ae800fdfc93ef5058b21b3e48daac2a4e1358))
* use correct classes to determine option type ([e833bf4](https://github.com/ReVanced/revanced-manager/commit/e833bf4ad14811bb6880ae2d97055e4ce0de222f))
* use correct directory ([9e1ebb3](https://github.com/ReVanced/revanced-manager/commit/9e1ebb390244dcb9af03a9164a32386481ec5691))
* Use FAB instead of ListItem to patch in App Overview ([6ace71b](https://github.com/ReVanced/revanced-manager/commit/6ace71b739302466274ce9b46f5f7dd6ab9da05d)), closes [#1995](https://github.com/ReVanced/revanced-manager/issues/1995)
* use proper update icon ([b59a161](https://github.com/ReVanced/revanced-manager/commit/b59a16191a61c64275137c4a6145fd30d68aa480))
* use ReVanced ring logo in about section ([#1302](https://github.com/ReVanced/revanced-manager/issues/1302)) ([933a4a3](https://github.com/ReVanced/revanced-manager/commit/933a4a32203425e745e05615217a8d0975c2e959))
* Use the correct icon in API URL dialog ([c22e5b4](https://github.com/ReVanced/revanced-manager/commit/c22e5b4051515e0f02828a2b30f6af19b48ba55f)), closes [#1972](https://github.com/ReVanced/revanced-manager/issues/1972)
* use upsert when modifying installed apps ([90edf1d](https://github.com/ReVanced/revanced-manager/commit/90edf1ddd0de29b299855810402a31828d989d04))
* **VersionSelector:** use correct LazyColumn item key ([413fe98](https://github.com/ReVanced/revanced-manager/commit/413fe980a8c0b45e3924c98b2fbd1a3e9b579528))
### Features
* **about screen:** complete about screen ([1d6b34a](https://github.com/ReVanced/revanced-manager/commit/1d6b34a39f76e8e733649f7fcfeb20eb1009a39a))
* Add `isScrollingUp` support for ScrollState ([bf049c3](https://github.com/ReVanced/revanced-manager/commit/bf049c3c1ac12a60c5c6226b5c3fec7f72caa7db))
* add ability to share debug logs ([feb0ca4](https://github.com/ReVanced/revanced-manager/commit/feb0ca4cf315e5d332f36039fbb989b3cfb9cf58))
* add checkboxes to the downloaded apps page ([ca93524](https://github.com/ReVanced/revanced-manager/commit/ca93524be0b37f38b860d8512c81d2898b2860af))
* Add confirm dialogs when toggling dangerous settings ([#2072](https://github.com/ReVanced/revanced-manager/issues/2072)) ([6643276](https://github.com/ReVanced/revanced-manager/commit/66432764cfe8192f4cf8e599a592f27c675f25ec))
* Add confirmation dialog to "Reset" options ([#2576](https://github.com/ReVanced/revanced-manager/issues/2576)) ([f32ffbb](https://github.com/ReVanced/revanced-manager/commit/f32ffbb6f2224f886af14205721fb2372f396de2))
* Add downloader plugin system ([#2041](https://github.com/ReVanced/revanced-manager/issues/2041)) ([ca38737](https://github.com/ReVanced/revanced-manager/commit/ca3873778307612b93af3273ffe4821c6a5e398d))
* add external process runtime ([#1799](https://github.com/ReVanced/revanced-manager/issues/1799)) ([0d73e0c](https://github.com/ReVanced/revanced-manager/commit/0d73e0cd32b6af3526c226ce4695c7e905f65b15))
* Add haptic feedback ([#1457](https://github.com/ReVanced/revanced-manager/issues/1457)) ([76e0c95](https://github.com/ReVanced/revanced-manager/commit/76e0c9518746620cd2723a99c310f92f5b3fd996))
* Add installer status dialog ([#1473](https://github.com/ReVanced/revanced-manager/issues/1473)) ([43b3743](https://github.com/ReVanced/revanced-manager/commit/43b37432138d7cd8a507efad80827d6f3bdcdf08))
* add network checks for features that require it ([f3f8bc4](https://github.com/ReVanced/revanced-manager/commit/f3f8bc4ec2f593ade91324d78f9ce83f60ef65cc))
* add patch bundle info screen ([#55](https://github.com/ReVanced/revanced-manager/issues/55)) ([8ae4e85](https://github.com/ReVanced/revanced-manager/commit/8ae4e850dae9cf4df14afe90048ca0b0a48389ac))
* add patches selector bottom sheet ([#1360](https://github.com/ReVanced/revanced-manager/issues/1360)) ([f6fb534](https://github.com/ReVanced/revanced-manager/commit/f6fb534e04777b4f0ec2ff2b13768c724c68c028))
* add required options screen ([#2378](https://github.com/ReVanced/revanced-manager/issues/2378)) ([3a63e42](https://github.com/ReVanced/revanced-manager/commit/3a63e42df9ce50069a573d98cf44a8abec03b639))
* Add reset button to custom API ([#2076](https://github.com/ReVanced/revanced-manager/issues/2076)) ([df52a7b](https://github.com/ReVanced/revanced-manager/commit/df52a7bdef05e1c9f034ae067c3dd183fb8fdffd)), closes [#2051](https://github.com/ReVanced/revanced-manager/issues/2051)
* Add sensitivity to `isScrollingUp` ([f6ca4e9](https://github.com/ReVanced/revanced-manager/commit/f6ca4e95551193c8d21afd09872d9bbe6c80c0e8))
* add social links ([#1294](https://github.com/ReVanced/revanced-manager/issues/1294)) ([7df3350](https://github.com/ReVanced/revanced-manager/commit/7df3350acb4aae957e2a7c0d2f30faf6cae6ab85))
* add toast feedback to the bundle update button ([ea50e65](https://github.com/ReVanced/revanced-manager/commit/ea50e65ab1d626152bdd40c1893cd408b7271472))
* add user agent ([#1382](https://github.com/ReVanced/revanced-manager/issues/1382)) ([3aea6cb](https://github.com/ReVanced/revanced-manager/commit/3aea6cbaecc9db103e9a3925b3c4a531de6c5f0e))
* advanced settings page with device info ([#51](https://github.com/ReVanced/revanced-manager/issues/51)) ([86e4244](https://github.com/ReVanced/revanced-manager/commit/86e42449eb553417726b95f79f6edd7f526f6d44))
* allow bundles to use classes from other bundles ([#1951](https://github.com/ReVanced/revanced-manager/issues/1951)) ([af8e2b4](https://github.com/ReVanced/revanced-manager/commit/af8e2b44c027d978046a0e7926f1425f0348b098))
* allow user to save logs ([a008cf5](https://github.com/ReVanced/revanced-manager/commit/a008cf5dd143fafb1f642cd037db29393716f7d5))
* animate the arrow button ([db070b1](https://github.com/ReVanced/revanced-manager/commit/db070b125bf08ff251450259045755e6469c2d5e))
* app downloader ([#43](https://github.com/ReVanced/revanced-manager/issues/43)) ([1f1a480](https://github.com/ReVanced/revanced-manager/commit/1f1a480d51edb310934523024c52e0c19b066662))
* app selector screen ([373cc4b](https://github.com/ReVanced/revanced-manager/commit/373cc4bbb1a8194bf9475d0a13e1c154cd87480b))
* **app-selector:** show patchable installed apps first ([#1496](https://github.com/ReVanced/revanced-manager/issues/1496)) ([afb0f80](https://github.com/ReVanced/revanced-manager/commit/afb0f80de5a73c213f77bfde761ea1ea0886abef))
* armv7 warning ([2ffcaec](https://github.com/ReVanced/revanced-manager/commit/2ffcaec724d5a13b816e04813d45cde75681eb69))
* Automatic language detection ([#2032](https://github.com/ReVanced/revanced-manager/issues/2032)) ([36a1c3f](https://github.com/ReVanced/revanced-manager/commit/36a1c3f36807500fbe820bf4142fef159b138c7d))
* backend ([45a54d1](https://github.com/ReVanced/revanced-manager/commit/45a54d1608a77547e06748867d63a452224727b6))
* better installer ui ([#29](https://github.com/ReVanced/revanced-manager/issues/29)) ([14888f9](https://github.com/ReVanced/revanced-manager/commit/14888f9da71ecf1c50d770123d1e8dd09aa6c8b1))
* **bundles tab:** add BackHandler ([a9171e1](https://github.com/ReVanced/revanced-manager/commit/a9171e17bd628601f1e074a7fcdf74c15cb73709))
* Change "Update" to "Show" in Update Available notification ([5c43413](https://github.com/ReVanced/revanced-manager/commit/5c434137d332aabaaca236b6f9616d7727d0b3d2)), closes [#1959](https://github.com/ReVanced/revanced-manager/issues/1959)
* change appID and name of debug builds ([5b3e9e5](https://github.com/ReVanced/revanced-manager/commit/5b3e9e595cded277c051cc669d9f29bcb6ce5d18))
* **Changelogs:** overall improvement ([#1429](https://github.com/ReVanced/revanced-manager/issues/1429)) ([2a3590d](https://github.com/ReVanced/revanced-manager/commit/2a3590ddd2cc74b746a3f632a93970bfa23cf384))
* check for updates on startup ([#1462](https://github.com/ReVanced/revanced-manager/issues/1462)) ([bb2164e](https://github.com/ReVanced/revanced-manager/commit/bb2164e1a95a698b1b0f69e725af5e0e1e45b868))
* check if the version being used is the recommended version ([#1675](https://github.com/ReVanced/revanced-manager/issues/1675)) ([9d961f6](https://github.com/ReVanced/revanced-manager/commit/9d961f6a52d15ed6116afc78c7008460347da69a))
* Collapse ExtendedFAB on scroll ([#1630](https://github.com/ReVanced/revanced-manager/issues/1630)) ([b5c1f6d](https://github.com/ReVanced/revanced-manager/commit/b5c1f6d732b65c1c9becb7962c51a70a840dea73))
* **Compose:** Add confirmation dialog on multiple operations ([#2529](https://github.com/ReVanced/revanced-manager/issues/2529)) ([2671e68](https://github.com/ReVanced/revanced-manager/commit/2671e68004269deebdedaee38a6692b2302ca732))
* **Compose:** hide developer settings ([#2551](https://github.com/ReVanced/revanced-manager/issues/2551)) ([0030c7a](https://github.com/ReVanced/revanced-manager/commit/0030c7a7885feee0578ee1423ee2aefc6a0e2c2c))
* **Compose:** Improve patches selector tab by adding the bundle version ([#2545](https://github.com/ReVanced/revanced-manager/issues/2545)) ([3710675](https://github.com/ReVanced/revanced-manager/commit/3710675ac0ca77cecfb172b4cf148f41a762bf06))
* **Compose:** Move developer options to top level ([#2528](https://github.com/ReVanced/revanced-manager/issues/2528)) ([cedc6ad](https://github.com/ReVanced/revanced-manager/commit/cedc6ad49f23d778a52a8846f9e384fd2106e074))
* contributors screen ([#42](https://github.com/ReVanced/revanced-manager/issues/42)) ([3f54381](https://github.com/ReVanced/revanced-manager/commit/3f54381d307fd71296be18e97a1ab870f1cdc297))
* **Contributors Screen:** implement design from Figma ([#1465](https://github.com/ReVanced/revanced-manager/issues/1465)) ([d5bdc29](https://github.com/ReVanced/revanced-manager/commit/d5bdc293f308e2a283d744afdc1aed6a165f7166))
* Dashboard Screen ([#18](https://github.com/ReVanced/revanced-manager/issues/18)) ([a127b95](https://github.com/ReVanced/revanced-manager/commit/a127b959ead5a9c83a0c4f7e7840aeeb68362c0d))
* disable filter chips when there are no patches ([fd520bb](https://github.com/ReVanced/revanced-manager/commit/fd520bba700bae9d8eae745ce23a95b07b7f7d34))
* dont ask for root on launch ([9562d80](https://github.com/ReVanced/revanced-manager/commit/9562d80bfdc785fe5ed512a15cfd7c0e09091acc))
* download apps in patcher screen ([#73](https://github.com/ReVanced/revanced-manager/issues/73)) ([a854221](https://github.com/ReVanced/revanced-manager/commit/a854221969c363712a0b3de84607092709db291f))
* experimental patches setting ([b07fd23](https://github.com/ReVanced/revanced-manager/commit/b07fd2321dd0aecce556f341e2b18f930baa58fd))
* filter options for patches ([62bccd1](https://github.com/ReVanced/revanced-manager/commit/62bccd150441747e5cd6de71de304e416922bdda))
* finish implementing the sources system ([#70](https://github.com/ReVanced/revanced-manager/issues/70)) ([858b0ec](https://github.com/ReVanced/revanced-manager/commit/858b0ec5b456043fa61b681bbbd195fd9c30a6f0))
* get bundle information from jar manifest ([#2027](https://github.com/ReVanced/revanced-manager/issues/2027)) ([60fdec9](https://github.com/ReVanced/revanced-manager/commit/60fdec9804c763ef9308a7a56d245401dbd35d7c))
* hide tabs when 1 bundle is used ([41268ca](https://github.com/ReVanced/revanced-manager/commit/41268ca80b71f68dbf9523fa7bac34feeec7d011))
* hide unfinished pages in release mode ([c199801](https://github.com/ReVanced/revanced-manager/commit/c199801fb7f91306538391177d240cf1121964d2))
* Highlight links in Markdown ([7bf8988](https://github.com/ReVanced/revanced-manager/commit/7bf89887e420a402b30da4796ba3648147f00394)), closes [#1962](https://github.com/ReVanced/revanced-manager/issues/1962)
* implement DI ([7fa7b9d](https://github.com/ReVanced/revanced-manager/commit/7fa7b9d53a3217c7e1e4c70a524fd68ae170c832))
* implement more patch option types ([#2015](https://github.com/ReVanced/revanced-manager/issues/2015)) ([b18c678](https://github.com/ReVanced/revanced-manager/commit/b18c6783547e910fa2dbd3d7edcc5fe329e6d921))
* implement navigation ([7fc6ec5](https://github.com/ReVanced/revanced-manager/commit/7fc6ec5c2cf8eb9ebfc3dda01cdfd80962be1f8f))
* implement Submit Issue button ([#1276](https://github.com/ReVanced/revanced-manager/issues/1276)) ([a269a39](https://github.com/ReVanced/revanced-manager/commit/a269a39aa4a34b94aef4e1e85126c571e96be575))
* improve accessibility ([#64](https://github.com/ReVanced/revanced-manager/issues/64)) ([39b08e5](https://github.com/ReVanced/revanced-manager/commit/39b08e5201d2cec6bdb67f9386120a7a40c9ccc6))
* Improve APK file name formatting on save ([#2421](https://github.com/ReVanced/revanced-manager/issues/2421)) ([a53a8ba](https://github.com/ReVanced/revanced-manager/commit/a53a8ba62734daf9bd80ab79265241a4a22f489c))
* improve bundle dialog UI ([409c888](https://github.com/ReVanced/revanced-manager/commit/409c888d523f398505daaaff9d2490dc5a863680))
* Improve bundle info screen design ([#2548](https://github.com/ReVanced/revanced-manager/issues/2548)) ([55524f7](https://github.com/ReVanced/revanced-manager/commit/55524f7284a44bbf8e8c782eedd7fc06d54944cf))
* Improve custom API URL dialog ([#2033](https://github.com/ReVanced/revanced-manager/issues/2033)) ([7dae562](https://github.com/ReVanced/revanced-manager/commit/7dae56281994942577bac7bf50c59e805672d0e1))
* Improve device information in debugging section ([d889677](https://github.com/ReVanced/revanced-manager/commit/d889677b29aeb4a49a025da98060265e88876ddf)), closes [#1977](https://github.com/ReVanced/revanced-manager/issues/1977)
* Improve initial update popup wording ([5901372](https://github.com/ReVanced/revanced-manager/commit/5901372523643eef5a605256662c8e1f0a9f2263)), closes [#1956](https://github.com/ReVanced/revanced-manager/issues/1956)
* improve keystore UI and UX ([#52](https://github.com/ReVanced/revanced-manager/issues/52)) ([49b4bbb](https://github.com/ReVanced/revanced-manager/commit/49b4bbbf0ba84b006a1694ca95662cf224a84b0f))
* Improve patch bundle screen ([#2070](https://github.com/ReVanced/revanced-manager/issues/2070)) ([a907528](https://github.com/ReVanced/revanced-manager/commit/a907528a2096d8de9778efa8f85e0cdc1d7c2b80))
* improve patcher screen labels ([f4d6c60](https://github.com/ReVanced/revanced-manager/commit/f4d6c60b9ec4c76e8e3fa233f79e062b802860e5))
* improve patcher UI ([#1494](https://github.com/ReVanced/revanced-manager/issues/1494)) ([429b428](https://github.com/ReVanced/revanced-manager/commit/429b428f673dd949289baaf27ed2e08970db83ae))
* Improve Settings order ([#2060](https://github.com/ReVanced/revanced-manager/issues/2060)) ([fa86c1a](https://github.com/ReVanced/revanced-manager/commit/fa86c1a0bb039a86e0649eae30c7b33620f98dbe))
* improve the safeguards ([#2038](https://github.com/ReVanced/revanced-manager/issues/2038)) ([e5b414e](https://github.com/ReVanced/revanced-manager/commit/e5b414e277341967c7b5a5f071ddac1fdfdb8e63))
* Improve unsupported patch warnings ([#2066](https://github.com/ReVanced/revanced-manager/issues/2066)) ([3c23d57](https://github.com/ReVanced/revanced-manager/commit/3c23d573bf3998304cad4485016004a871cf1636)), closes [#2052](https://github.com/ReVanced/revanced-manager/issues/2052)
* Improve update screen design ([#2487](https://github.com/ReVanced/revanced-manager/issues/2487)) ([7007010](https://github.com/ReVanced/revanced-manager/commit/7007010f14239452e565736fe7cee7666a682ffb))
* Improve update setting tile titles ([e2623d6](https://github.com/ReVanced/revanced-manager/commit/e2623d6d79b3b87e9ba29016e42f1d645b2f9e19)), closes [#1968](https://github.com/ReVanced/revanced-manager/issues/1968)
* improve UX for failed or missing bundles ([49f8510](https://github.com/ReVanced/revanced-manager/commit/49f851022db72b110c8597aa1c711461c1b01882))
* improved compose stability ([8c40119](https://github.com/ReVanced/revanced-manager/commit/8c40119609c650d1f012d810a4117e84fbe2da52))
* improved dashboard screen ([5c2f9d9](https://github.com/ReVanced/revanced-manager/commit/5c2f9d91a6e803d9b3705e2b3aa84176353ba963))
* in-app updater ([#25](https://github.com/ReVanced/revanced-manager/issues/25)) ([d71a4bf](https://github.com/ReVanced/revanced-manager/commit/d71a4bf3c3457a02578bb8ad3c7615b074f6e3f1))
* **installer:** adjust arrow icon size ([e997255](https://github.com/ReVanced/revanced-manager/commit/e997255cf3c3c5ba777da07752217f99e01dd789))
* **installer:** adjust step icon size and alignment ([cfcabf6](https://github.com/ReVanced/revanced-manager/commit/cfcabf6ef1c212f2627d5d02f4d59981bdc276ca))
* **installer:** apk signing and installation ([da32ff9](https://github.com/ReVanced/revanced-manager/commit/da32ff954a84cf8ff321bbbf71cc5b544d6e6be9))
* **installer:** sign apk in patcher worker ([c003c3c](https://github.com/ReVanced/revanced-manager/commit/c003c3c3245f5a663a0371d4e9df71777ba728b9))
* **Installer:** use BottomAppBar ([#1428](https://github.com/ReVanced/revanced-manager/issues/1428)) ([ceb7623](https://github.com/ReVanced/revanced-manager/commit/ceb762379461443e7e62c37511df1c84a6068bb4))
* integrate revanced patcher ([#22](https://github.com/ReVanced/revanced-manager/issues/22)) ([caeabfc](https://github.com/ReVanced/revanced-manager/commit/caeabfc91b2aa7e3de9e6a31859049d4b2d37388))
* keystore import/export ([#30](https://github.com/ReVanced/revanced-manager/issues/30)) ([fd0ec6c](https://github.com/ReVanced/revanced-manager/commit/fd0ec6c6a7fc8488db859056a95ebe0455e2843b))
* **koin:** use the android logger ([f30333e](https://github.com/ReVanced/revanced-manager/commit/f30333e75338dd2c1ef891723ecb834fc1eb10f7))
* licenses screen ([#47](https://github.com/ReVanced/revanced-manager/issues/47)) ([e3cb056](https://github.com/ReVanced/revanced-manager/commit/e3cb056858ea8917162c1a421a7a8d03ddaa08e2))
* make bundles selectable ([#1237](https://github.com/ReVanced/revanced-manager/issues/1237)) ([a246863](https://github.com/ReVanced/revanced-manager/commit/a246863a89fe8781feaf2a45fcb7ea991d26028f))
* Make patch bundles list scrollable ([#2322](https://github.com/ReVanced/revanced-manager/issues/2322)) ([a5c8a23](https://github.com/ReVanced/revanced-manager/commit/a5c8a23f9ffb36543d45b46bb5f01c5dea56bf90))
* more info for the select from application screen ([#81](https://github.com/ReVanced/revanced-manager/issues/81)) ([3f446f8](https://github.com/ReVanced/revanced-manager/commit/3f446f8236101755a9d51a2aa759f70a0bd429da))
* move plugin api to another repository ([55e7ebf](https://github.com/ReVanced/revanced-manager/commit/55e7ebf4fc5adf8800430ad4aa2579cb6210290d))
* Move safeguards above patcher preference group ([9f7eaa2](https://github.com/ReVanced/revanced-manager/commit/9f7eaa212339f2093050087dc7ab0b8237356939))
* move update to notification card ([#1917](https://github.com/ReVanced/revanced-manager/issues/1917)) ([b80f94b](https://github.com/ReVanced/revanced-manager/commit/b80f94b77bba89e31608cdb302dab0619bf7c5cc))
* **NotificationCard:** rewrite & consistent usage ([#1426](https://github.com/ReVanced/revanced-manager/issues/1426)) ([f8aafa0](https://github.com/ReVanced/revanced-manager/commit/f8aafa050328423b3168a7943f566fce58100cb0))
* Open the app-specific manage all files permission dialog ([#2148](https://github.com/ReVanced/revanced-manager/issues/2148)) ([a3f31ea](https://github.com/ReVanced/revanced-manager/commit/a3f31ea65788a43ce57d548e8240e5b1fe3005d0))
* Order bundles by number of patches ([bb5d414](https://github.com/ReVanced/revanced-manager/commit/bb5d414abb4f294aa88d795486836a99ade2b388))
* patch bundle sources system ([#24](https://github.com/ReVanced/revanced-manager/issues/24)) ([9675a27](https://github.com/ReVanced/revanced-manager/commit/9675a2777b364e5ede0d44b92eb7e551d4f7b3d6))
* patch options ([#45](https://github.com/ReVanced/revanced-manager/issues/45)) ([8540d30](https://github.com/ReVanced/revanced-manager/commit/8540d301962669e3d79ca345c852f5b01df641a4))
* patch options UI ([#80](https://github.com/ReVanced/revanced-manager/issues/80)) ([0a1acd2](https://github.com/ReVanced/revanced-manager/commit/0a1acd24e3f0d06fde412b8eeecd923d92ee64a9))
* **patch-selector:** default patches selection ([#1272](https://github.com/ReVanced/revanced-manager/issues/1272)) ([a17c2de](https://github.com/ReVanced/revanced-manager/commit/a17c2de228cccb4a0bb0ca7497720011bec131fc))
* **patch-selector:** remove TODO about an unplanned feature ([4924eae](https://github.com/ReVanced/revanced-manager/commit/4924eaef800c429f2a59b8a15fd48fae0292810c))
* **patcher:** Improve installation ([#2185](https://github.com/ReVanced/revanced-manager/issues/2185)) ([3bd4f0d](https://github.com/ReVanced/revanced-manager/commit/3bd4f0d8f3f60d079d4647d42592b10a15f0dae8))
* patches selector screen ([55e871a](https://github.com/ReVanced/revanced-manager/commit/55e871aa7d27885e44ef33faab1bb4ae33e7a460))
* Progressive AlertDialog for adding bundles ([9a01273](https://github.com/ReVanced/revanced-manager/commit/9a01273c43bd6bcdb0cdfd26c5a467cd3193e5d7)), closes [#1992](https://github.com/ReVanced/revanced-manager/issues/1992)
* ProGuard ([d84e6a3](https://github.com/ReVanced/revanced-manager/commit/d84e6a3ffc20d018b2edeb505de20a920785ba5c))
* Purple default theme ([#1601](https://github.com/ReVanced/revanced-manager/issues/1601)) ([0616666](https://github.com/ReVanced/revanced-manager/commit/0616666d5ef9b53bef5fd630b1b1a47088097d37))
* Redesign the patches screen ([#2381](https://github.com/ReVanced/revanced-manager/issues/2381)) ([8dc4e5b](https://github.com/ReVanced/revanced-manager/commit/8dc4e5b89ee4d36263c8b4187650691b68484688))
* remember patch options ([#1449](https://github.com/ReVanced/revanced-manager/issues/1449)) ([90db765](https://github.com/ReVanced/revanced-manager/commit/90db765c9aa014495775a34927904dedf5fef1e3))
* remove dead help icons ([3bb071d](https://github.com/ReVanced/revanced-manager/commit/3bb071d80d319d4943b0d4c3048f232f3eb9f5cf))
* Remove tag from changelog ([d2119d3](https://github.com/ReVanced/revanced-manager/commit/d2119d36430198151140b469192f76f781df6dd3))
* Rename "Patch bundle" to "Patches" ([#2541](https://github.com/ReVanced/revanced-manager/issues/2541)) ([2cdd6d1](https://github.com/ReVanced/revanced-manager/commit/2cdd6d1843f1e49c7c720f8859e11d6a30c0eea6))
* rename debug build to `ReVanced Manager (dev)` ([d3417ad](https://github.com/ReVanced/revanced-manager/commit/d3417adbeba0a8e06d3494a2fd108f735f73632c))
* rename main bundle to `Default` ([e44d3fd](https://github.com/ReVanced/revanced-manager/commit/e44d3fdee444d915e3e8b8143e55f1353980aad2))
* rename package to `app.revanced.manager` ([5ec97f4](https://github.com/ReVanced/revanced-manager/commit/5ec97f4a852a07d0e554bbe1eacc379179ac089e))
* Rename strings ([e127845](https://github.com/ReVanced/revanced-manager/commit/e1278452b9c73479cdfb0eb0703db1552b158633))
* rename ViewModels for consistency ([064a54e](https://github.com/ReVanced/revanced-manager/commit/064a54eaf0675a1cc9d21f3e1071160deb25c201))
* Reorder Import & Export settings ([#2403](https://github.com/ReVanced/revanced-manager/issues/2403)) ([2697077](https://github.com/ReVanced/revanced-manager/commit/2697077fc88bb795027303558c9d52448a4daded))
* ReVanced theme colors ([59b894d](https://github.com/ReVanced/revanced-manager/commit/59b894dce4b99c51151a4cccd03a998ceec31778))
* revert to blue theme colors ([5f4c958](https://github.com/ReVanced/revanced-manager/commit/5f4c9584a94a1edd1eeaa0b9ecfcd9b281b7cccc))
* root installation ([#1243](https://github.com/ReVanced/revanced-manager/issues/1243)) ([62e934c](https://github.com/ReVanced/revanced-manager/commit/62e934c4032096bed36201510fc55304ba48de68))
* save patch options and selected patches in bundle ([#50](https://github.com/ReVanced/revanced-manager/issues/50)) ([23162f6](https://github.com/ReVanced/revanced-manager/commit/23162f6233fa6a176514b35feff731f8f28b4d4b))
* save patch selection using room db ([#38](https://github.com/ReVanced/revanced-manager/issues/38)) ([1efccda](https://github.com/ReVanced/revanced-manager/commit/1efccda3f55d964fae3bee9ee1f0bd260bb1cc74))
* Screen slide transition ([#2396](https://github.com/ReVanced/revanced-manager/issues/2396)) ([2de16e1](https://github.com/ReVanced/revanced-manager/commit/2de16e18e8ba5e84149b377f225693ea35fa2385))
* Scrollbars ([#1479](https://github.com/ReVanced/revanced-manager/issues/1479)) ([b5558ea](https://github.com/ReVanced/revanced-manager/commit/b5558ea3ffef40f96b271f8dfe3a5cf95328781e))
* Select bundle type before adding bundle ([#1490](https://github.com/ReVanced/revanced-manager/issues/1490)) ([88e860c](https://github.com/ReVanced/revanced-manager/commit/88e860cf0132aed23a3cfd3d9d12e472aa895718))
* selected app info page ([#1395](https://github.com/ReVanced/revanced-manager/issues/1395)) ([b69a369](https://github.com/ReVanced/revanced-manager/commit/b69a369d4e304c8a4c8a8db052309b485171e353))
* Set app ownership when installing apps ([#2558](https://github.com/ReVanced/revanced-manager/issues/2558)) ([7c410fe](https://github.com/ReVanced/revanced-manager/commit/7c410fef4512087657e3978d5be049c422b25456))
* settings migration (compose) ([#1309](https://github.com/ReVanced/revanced-manager/issues/1309)) ([bf1d628](https://github.com/ReVanced/revanced-manager/commit/bf1d628944cb5a439d0bda7c49d820a5fa7576b3))
* settings screen ([b7d53cf](https://github.com/ReVanced/revanced-manager/commit/b7d53cfca84d7239bed9189e265a03fd44dc2e45))
* **settings screen:** add battery optimization notification ([5754864](https://github.com/ReVanced/revanced-manager/commit/57548641e7ecd06decfc926cb860674ce7443d7a))
* **settings screen:** match typography from figma ([948a6d1](https://github.com/ReVanced/revanced-manager/commit/948a6d14404e067907c9e84576cfeba76134aaf6))
* **settings:** move experimental patches option to advanced ([805d440](https://github.com/ReVanced/revanced-manager/commit/805d440450d821a26d3ef90a4f97cd796635057d))
* **Settings:** use SettingsListItem consistently and overall improvements ([#1427](https://github.com/ReVanced/revanced-manager/issues/1427)) ([5e35893](https://github.com/ReVanced/revanced-manager/commit/5e35893883fa109d74b028478e60b51f97a2e12d))
* show installed app in version selector ([1ab1e46](https://github.com/ReVanced/revanced-manager/commit/1ab1e4682ffbfe16c02c438ad833adbfdec58b33))
* Show manager update dialog ([#2069](https://github.com/ReVanced/revanced-manager/issues/2069)) ([113a74d](https://github.com/ReVanced/revanced-manager/commit/113a74d270c1c222d4d06049b4edda8f27724a20)), closes [#1963](https://github.com/ReVanced/revanced-manager/issues/1963) [#1958](https://github.com/ReVanced/revanced-manager/issues/1958)
* show stacktrace in installer ui ([#36](https://github.com/ReVanced/revanced-manager/issues/36)) ([8d53180](https://github.com/ReVanced/revanced-manager/commit/8d53180d86e6e9d9c8a4056a5fde0603f17e3157))
* show toast when no patches are selected ([8aa70d3](https://github.com/ReVanced/revanced-manager/commit/8aa70d350e07aae8b4a22b6bc6fb90c0f6227acd))
* splash screen ([60a5a11](https://github.com/ReVanced/revanced-manager/commit/60a5a11c71634aeda414c2ed85f7706ba3deefe1))
* store patched apps ([#79](https://github.com/ReVanced/revanced-manager/issues/79)) ([b14285b](https://github.com/ReVanced/revanced-manager/commit/b14285b2c83e60376ad42fa6ea508257cd04d47d))
* switch to androidx.navigation ([#2362](https://github.com/ReVanced/revanced-manager/issues/2362)) ([7438f45](https://github.com/ReVanced/revanced-manager/commit/7438f45903ec6ed3436a895d4c32d34d41b00010))
* switch to Preferences DataStore ([#60](https://github.com/ReVanced/revanced-manager/issues/60)) ([1852799](https://github.com/ReVanced/revanced-manager/commit/18527999b5f8752faf36c145276d51e2e095c8ee))
* switch to revanced api v4 ([7e858a2](https://github.com/ReVanced/revanced-manager/commit/7e858a244cc4038bdb029c4418278700f6a6490f))
* switch to the new api ([#75](https://github.com/ReVanced/revanced-manager/issues/75)) ([a55160e](https://github.com/ReVanced/revanced-manager/commit/a55160e7c619ec5541de72fa80f079c9bc94d2d5))
* TopAppBar scroll behavior ([#2397](https://github.com/ReVanced/revanced-manager/issues/2397)) ([dc51d61](https://github.com/ReVanced/revanced-manager/commit/dc51d6134dae0fdc415f66e2716c6bffa35dfdb5))
* **Update Screen:** changelogs & handle states ([#1464](https://github.com/ReVanced/revanced-manager/issues/1464)) ([3af26e7](https://github.com/ReVanced/revanced-manager/commit/3af26e706571339a3c69688098a51616549c58a8))
* **update screen:** complete main update screen ([553af83](https://github.com/ReVanced/revanced-manager/commit/553af831393d7276088ceb0b0a854ec654f72def))
* updater changelogs ([#48](https://github.com/ReVanced/revanced-manager/issues/48)) ([6dbcd62](https://github.com/ReVanced/revanced-manager/commit/6dbcd6293e94d8d20cccc401b0edeb1d7047553e))
* updater UI and code improvements ([#1597](https://github.com/ReVanced/revanced-manager/issues/1597)) ([a12cae7](https://github.com/ReVanced/revanced-manager/commit/a12cae72998d85138dcf29c0e5d430359e338d5e))
* Use "Debug" and "Debug signed" for build names respectively ([5133f02](https://github.com/ReVanced/revanced-manager/commit/5133f02ad61b85af28608c7180b7a2accb4811ab))
* Use correct casing in module description ([59b4c0b](https://github.com/ReVanced/revanced-manager/commit/59b4c0b2d2e426dfe66b5a01d219b57bb0df5b8b))
* use revanced api for changelogs ([686eb40](https://github.com/ReVanced/revanced-manager/commit/686eb40cb0f8b8d785732dd2bc82d17b5a4fd042))
* Use simpler strings ([83d33e8](https://github.com/ReVanced/revanced-manager/commit/83d33e87e3f89cb3efce63dcabcde6478f69b8e7))
* View bundle patches ([#2065](https://github.com/ReVanced/revanced-manager/issues/2065)) ([089f200](https://github.com/ReVanced/revanced-manager/commit/089f200fe6ff59020a87883a47ef20a0c4c08565))
### Reverts
* downgrade Kotlin to 1.8.21 ([fc90bbc](https://github.com/ReVanced/revanced-manager/commit/fc90bbc27ce765e0b55bb5ac9132e58f46aee9aa))

View File

@@ -1,274 +0,0 @@
import io.github.z4kn4fein.semver.toVersion
import kotlin.random.Random
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.serialization)
alias(libs.plugins.kotlin.parcelize)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.devtools)
alias(libs.plugins.about.libraries)
signing
}
val outputApkFileName = "${rootProject.name}-$version.apk"
dependencies {
// AndroidX Core
implementation(libs.androidx.ktx)
implementation(libs.runtime.ktx)
implementation(libs.runtime.compose)
implementation(libs.splash.screen)
implementation(libs.activity.compose)
implementation(libs.work.runtime.ktx)
implementation(libs.preferences.datastore)
implementation(libs.appcompat)
// Compose
implementation(platform(libs.compose.bom))
implementation(libs.compose.ui)
implementation(libs.compose.ui.preview)
implementation(libs.compose.ui.tooling)
implementation(libs.compose.livedata)
implementation(libs.compose.material.icons.extended)
implementation(libs.compose.material3)
implementation(libs.navigation.compose)
// Accompanist
implementation(libs.accompanist.drawablepainter)
// Placeholder
implementation(libs.placeholder.material3)
// Coil (async image loading, network image)
implementation(libs.coil.compose)
implementation(libs.coil.appiconloader)
// KotlinX
implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.collection.immutable)
implementation(libs.kotlinx.datetime)
// Room
implementation(libs.room.runtime)
implementation(libs.room.ktx)
annotationProcessor(libs.room.compiler)
ksp(libs.room.compiler)
// ReVanced
implementation(libs.revanced.patcher)
implementation(libs.revanced.library)
// Downloader plugins
implementation(project(":api"))
// Native processes
implementation(libs.kotlin.process)
// HiddenAPI
compileOnly(libs.hidden.api.stub)
// LibSU
implementation(libs.libsu.core)
implementation(libs.libsu.service)
implementation(libs.libsu.nio)
// Koin
implementation(libs.koin.android)
implementation(libs.koin.compose)
implementation(libs.koin.compose.navigation)
implementation(libs.koin.workmanager)
// Licenses
implementation(libs.about.libraries)
// Ktor
implementation(libs.ktor.core)
implementation(libs.ktor.logging)
implementation(libs.ktor.okhttp)
implementation(libs.ktor.content.negotiation)
implementation(libs.ktor.serialization)
// Markdown
implementation(libs.markdown.renderer)
// Fading Edges
implementation(libs.fading.edges)
// Scrollbars
implementation(libs.scrollbars)
// EnumUtil
implementation(libs.enumutil)
ksp(libs.enumutil.ksp)
// Reorderable lists
implementation(libs.reorderable)
// Compose Icons
implementation(libs.compose.icons.fontawesome)
// Ackpine
implementation(libs.ackpine.core)
implementation(libs.ackpine.ktx)
}
buildscript {
repositories {
mavenCentral()
}
dependencies {
// Semantic versioning string parser
classpath(libs.semver.parser)
}
}
android {
namespace = "app.revanced.manager"
compileSdk = 35
buildToolsVersion = "35.0.1"
defaultConfig {
applicationId = "app.revanced.manager"
minSdk = 26
targetSdk = 35
val versionStr = if (version == "unspecified") "1.0.0" else version.toString()
versionName = versionStr
versionCode = with(versionStr.toVersion()) {
major * 10_000_000 +
minor * 10_000 +
patch * 100 +
(preRelease?.substringAfterLast('.')?.toInt() ?: 99)
}
vectorDrawables.useSupportLibrary = true
}
buildTypes {
debug {
applicationIdSuffix = ".debug"
resValue("string", "app_name", "ReVanced Manager (Debug)")
isPseudoLocalesEnabled = true
buildConfigField("long", "BUILD_ID", "${Random.nextLong()}L")
}
release {
if (!project.hasProperty("noProguard")) {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
val keystoreFile = file("keystore.jks")
if (project.hasProperty("signAsDebug") || !keystoreFile.exists()) {
applicationIdSuffix = ".debug_signed"
resValue("string", "app_name", "ReVanced Manager (Debug signed)")
signingConfig = signingConfigs.getByName("debug")
isPseudoLocalesEnabled = true
} else {
signingConfig = signingConfigs.create("release") {
storeFile = keystoreFile
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEYSTORE_ENTRY_ALIAS")
keyPassword = System.getenv("KEYSTORE_ENTRY_PASSWORD")
}
}
buildConfigField("long", "BUILD_ID", "0L")
}
}
applicationVariants.all {
outputs.all {
this as com.android.build.gradle.internal.api.ApkVariantOutputImpl
outputFileName = outputApkFileName
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependenciesInfo {
includeInApk = false
includeInBundle = false
}
packaging {
resources.excludes.addAll(
listOf(
"/prebuilt/**",
"META-INF/DEPENDENCIES",
"META-INF/**.version",
"DebugProbesKt.bin",
"kotlin-tooling-metadata.json",
"org/bouncycastle/pqc/**.properties",
"org/bouncycastle/x509/**.properties",
)
)
jniLibs {
useLegacyPackaging = true
}
}
ksp {
arg("room.schemaLocation", "$projectDir/schemas")
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
compose = true
aidl = true
buildConfig = true
}
android {
androidResources {
generateLocaleConfig = true
}
}
externalNativeBuild {
cmake {
path = file("src/main/cpp/CMakeLists.txt")
version = "3.22.1"
}
}
}
kotlin {
jvmToolchain(17)
}
tasks {
// Needed by gradle-semantic-release-plugin.
// Tracking: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435.
val publish by registering {
group = "publishing"
description = "Build the release APK"
dependsOn("assembleRelease")
val apk = project.layout.buildDirectory.file("outputs/apk/release/${outputApkFileName}")
val ascFile = apk.map { it.asFile.resolveSibling("${it.asFile.name}.asc") }
inputs.file(apk).withPropertyName("inputApk")
outputs.file(ascFile).withPropertyName("outputAsc")
doLast {
signing {
useGpgCmd()
sign(apk.get().asFile)
}
}
}
}

View File

@@ -1 +0,0 @@
version = 1.26.0-dev.16

1
app/gradlew vendored
View File

@@ -1 +0,0 @@
../gradlew

View File

@@ -1,11 +0,0 @@
{
"name": "app",
"private": false,
"devDependencies": {
"@anolilab/multi-semantic-release": "^1.1.10",
"@saithodev/semantic-release-backmerge": "^4.0.1",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.10.1"
}
}

View File

@@ -1,14 +0,0 @@
-dontobfuscate
-keep class app.revanced.manager.patcher.runtime.process.* { *; }
-keep class app.revanced.manager.plugin.** { *; }
-keep class app.revanced.patcher.** { *; }
-keep class com.android.tools.smali.** { *; }
-keep class kotlin.** { *; }
-keepnames class com.android.apksig.internal.** { *; }
-keepnames class org.xmlpull.** { *; }
-dontwarn com.google.j2objc.annotations.*
-dontwarn java.awt.**
-dontwarn javax.**
-dontwarn org.slf4j.**

View File

@@ -1,429 +0,0 @@
{
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "d0119047505da435972c5247181de675",
"entities": [
{
"tableName": "patch_bundles",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `name` TEXT NOT NULL, `version` TEXT, `source` TEXT NOT NULL, `auto_update` INTEGER NOT NULL, PRIMARY KEY(`uid`))",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "name",
"columnName": "name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "source",
"columnName": "source",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "autoUpdate",
"columnName": "auto_update",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"uid"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "patch_selections",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `patch_bundle` INTEGER NOT NULL, `package_name` TEXT NOT NULL, PRIMARY KEY(`uid`), FOREIGN KEY(`patch_bundle`) REFERENCES `patch_bundles`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchBundle",
"columnName": "patch_bundle",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"uid"
]
},
"indices": [
{
"name": "index_patch_selections_patch_bundle_package_name",
"unique": true,
"columnNames": [
"patch_bundle",
"package_name"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_patch_selections_patch_bundle_package_name` ON `${TABLE_NAME}` (`patch_bundle`, `package_name`)"
}
],
"foreignKeys": [
{
"table": "patch_bundles",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"patch_bundle"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "selected_patches",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`selection` INTEGER NOT NULL, `patch_name` TEXT NOT NULL, PRIMARY KEY(`selection`, `patch_name`), FOREIGN KEY(`selection`) REFERENCES `patch_selections`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "selection",
"columnName": "selection",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchName",
"columnName": "patch_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"selection",
"patch_name"
]
},
"indices": [],
"foreignKeys": [
{
"table": "patch_selections",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"selection"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "downloaded_app",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `version` TEXT NOT NULL, `directory` TEXT NOT NULL, `last_used` INTEGER NOT NULL, PRIMARY KEY(`package_name`, `version`))",
"fields": [
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "directory",
"columnName": "directory",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "lastUsed",
"columnName": "last_used",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"package_name",
"version"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "installed_app",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`current_package_name` TEXT NOT NULL, `original_package_name` TEXT NOT NULL, `version` TEXT NOT NULL, `install_type` TEXT NOT NULL, PRIMARY KEY(`current_package_name`))",
"fields": [
{
"fieldPath": "currentPackageName",
"columnName": "current_package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "originalPackageName",
"columnName": "original_package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "version",
"columnName": "version",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "installType",
"columnName": "install_type",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"current_package_name"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "applied_patch",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `bundle` INTEGER NOT NULL, `patch_name` TEXT NOT NULL, PRIMARY KEY(`package_name`, `bundle`, `patch_name`), FOREIGN KEY(`package_name`) REFERENCES `installed_app`(`current_package_name`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`bundle`) REFERENCES `patch_bundles`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "bundle",
"columnName": "bundle",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchName",
"columnName": "patch_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"package_name",
"bundle",
"patch_name"
]
},
"indices": [
{
"name": "index_applied_patch_bundle",
"unique": false,
"columnNames": [
"bundle"
],
"orders": [],
"createSql": "CREATE INDEX IF NOT EXISTS `index_applied_patch_bundle` ON `${TABLE_NAME}` (`bundle`)"
}
],
"foreignKeys": [
{
"table": "installed_app",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"package_name"
],
"referencedColumns": [
"current_package_name"
]
},
{
"table": "patch_bundles",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"bundle"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "option_groups",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`uid` INTEGER NOT NULL, `patch_bundle` INTEGER NOT NULL, `package_name` TEXT NOT NULL, PRIMARY KEY(`uid`), FOREIGN KEY(`patch_bundle`) REFERENCES `patch_bundles`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "uid",
"columnName": "uid",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchBundle",
"columnName": "patch_bundle",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"uid"
]
},
"indices": [
{
"name": "index_option_groups_patch_bundle_package_name",
"unique": true,
"columnNames": [
"patch_bundle",
"package_name"
],
"orders": [],
"createSql": "CREATE UNIQUE INDEX IF NOT EXISTS `index_option_groups_patch_bundle_package_name` ON `${TABLE_NAME}` (`patch_bundle`, `package_name`)"
}
],
"foreignKeys": [
{
"table": "patch_bundles",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"patch_bundle"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "options",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`group` INTEGER NOT NULL, `patch_name` TEXT NOT NULL, `key` TEXT NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY(`group`, `patch_name`, `key`), FOREIGN KEY(`group`) REFERENCES `option_groups`(`uid`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "group",
"columnName": "group",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "patchName",
"columnName": "patch_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"group",
"patch_name",
"key"
]
},
"indices": [],
"foreignKeys": [
{
"table": "option_groups",
"onDelete": "CASCADE",
"onUpdate": "NO ACTION",
"columns": [
"group"
],
"referencedColumns": [
"uid"
]
}
]
},
{
"tableName": "trusted_downloader_plugins",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`package_name` TEXT NOT NULL, `signature` BLOB NOT NULL, PRIMARY KEY(`package_name`))",
"fields": [
{
"fieldPath": "packageName",
"columnName": "package_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "signature",
"columnName": "signature",
"affinity": "BLOB",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"package_name"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'd0119047505da435972c5247181de675')"
]
}
}

View File

@@ -1,86 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<permission
android:name="app.revanced.manager.permission.PLUGIN_HOST"
android:protectionLevel="signature"
android:label="@string/plugin_host_permission_label"
android:description="@string/plugin_host_permission_description"
/>
<uses-permission android:name="app.revanced.manager.permission.PLUGIN_HOST" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="QueryAllPackagesPermission" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.ENFORCE_UPDATE_OWNERSHIP" />
<application
android:name=".ManagerApplication"
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:largeHeap="true"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.ReVancedManager"
android:enableOnBackInvokedCallback="true"
tools:targetApi="34">
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/Theme.ReVancedManager">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".plugin.downloader.webview.WebViewActivity" android:exported="false" android:theme="@style/Theme.WebViewActivity" />
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="specialUse"
android:exported="false"
tools:node="merge">
<property
android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
android:value="patching"
/>
</service>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="ru.solrudev.ackpine.AckpineInitializer"
tools:node="remove" />
</provider>
</application>
</manifest>

View File

@@ -1,8 +0,0 @@
// IRootService.aidl
package app.revanced.manager;
// Declare any non-default types here with import statements
interface IRootSystemService {
IBinder getFileSystemService();
}

View File

@@ -1,4 +0,0 @@
// ProgressEventParcel.aidl
package app.revanced.manager.patcher;
parcelable ProgressEventParcel;

View File

@@ -1,12 +0,0 @@
// IPatcherEvents.aidl
package app.revanced.manager.patcher.runtime.process;
import app.revanced.manager.patcher.ProgressEventParcel;
// Interface for sending events back to the main app process.
oneway interface IPatcherEvents {
void log(String level, String msg);
void event(in ProgressEventParcel event);
// The patching process has ended. The exceptionStackTrace is null if it finished successfully.
void finished(String exceptionStackTrace);
}

Some files were not shown because too many files have changed in this diff Show More