Compare commits

..

92 Commits

Author SHA1 Message Date
a5d09b2bf5 Consolidate optional root device requirements in docs 2025-02-19 23:27:05 +07:00
8731e7267a Fix grammar in GitHub Registry section 2025-02-19 23:24:01 +07:00
c2a942b46c Update docs/2_4_settings.md
Co-authored-by: Ax333l <main@axelen.xyz>
2025-01-29 17:50:04 +07:00
b9401b5f89 Update docs/3_troubleshooting.md
Co-authored-by: Ax333l <main@axelen.xyz>
2025-01-29 17:49:08 +07:00
0eee869b99 Update docs/2_4_settings.md
Co-authored-by: Ax333l <main@axelen.xyz>
2025-01-29 17:48:43 +07:00
15cfeb6ba7 Update docs/0_prerequisites.md 2025-01-29 17:47:48 +07:00
d47819cae7 Update docs/developer/3_verifying.md
Co-authored-by: Ax333l <main@axelen.xyz>
2025-01-29 00:09:26 +07:00
351e00c380 format 2025-01-27 17:31:42 +07:00
046179db1b Remove copy-pasta 2025-01-27 17:30:13 +07:00
5993dc34cb Add manage app 2025-01-27 17:29:56 +07:00
91f6672711 Add linkj 2025-01-27 16:47:56 +07:00
d3748cf305 Easily distinguishness 2025-01-27 16:47:36 +07:00
db304a70c8 Merge suggestions from Copilot 2025-01-27 16:41:18 +07:00
8f9ea54790 Update ref 2025-01-27 15:43:16 +07:00
a53a0bd2d4 Comfortable docs edit viewing 2025-01-27 15:36:30 +07:00
1c6a9dbbbd Developer - Transparency 2025-01-27 15:34:59 +07:00
802330c062 Verification step 2025-01-27 15:34:47 +07:00
d1ef14a25a format 2025-01-27 15:34:37 +07:00
617481f26f End of section 2025-01-27 15:34:25 +07:00
6598db5078 Update Manager guide!! 2025-01-27 15:33:36 +07:00
5b790a86e2 Comfortable docs viewing 2025-01-19 19:53:32 +07:00
bec0d823dc grammartical corerct 2025-01-19 19:53:20 +07:00
2616576b3d grammartical corerct 2025-01-19 19:53:12 +07:00
44fc4551aa Add settings location 2025-01-19 19:49:00 +07:00
6dfb2a2de0 Try or report 2025-01-19 19:42:02 +07:00
03c91687ae Split to section 2025-01-19 19:41:36 +07:00
91e06cbce6 OOM error troubleshooting 2025-01-19 19:41:21 +07:00
b0624a3544 OOM error troubleshooting 2025-01-19 19:40:06 +07:00
04a2a78914 Change wording to remove redundancy 2025-01-19 19:24:38 +07:00
4364f2e4c2 Standardised download site 2025-01-19 19:24:13 +07:00
177b716fd0 🔮 Merge repository updated to latest snapshot!
Script Execution UTC Time: null

Signed-off-by: validcube <pun.butrach@gmail.com>
2025-01-19 18:45:06 +07:00
d987845bba docs: Actually link to documentation 2024-11-24 22:11:46 +07:00
50c46dc20d docs(readme): Merge building to contributing section 2024-11-24 22:09:45 +07:00
5125084279 docs: Merge valid suggestions from Copilot review
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2024-11-24 19:38:53 +07:00
911201ad9f Signed off to switch branch
Signed-off-by: validcube <pun.butrach@gmail.com>
2024-10-18 01:53:51 +07:00
8442bf2e14 🔮 Merge repository updated to latest snapshot!
Script Execution UTC Time: null

Signed-off-by: validcube <pun.butrach@gmail.com>
2024-10-01 17:08:55 +07:00
05bf940cdf nitpicking on style 2024-08-18 20:43:29 +07:00
3bbad156c4 part: 10 (1/?) 2024-08-18 20:41:45 +07:00
db4ce6bb77 docs: Use correct asset directory 2024-08-18 20:01:45 +07:00
a290369d8d docs: Pull change from ReVanced Manager Flutter 2024-08-18 20:00:44 +07:00
adf5f9f6e8 docs: Pull change from ReVanced Branding 2024-08-18 20:00:17 +07:00
ace6701aaf 🔮 Merge repository updated to latest snapshot!
Script Execution UTC Time: null

Signed-off-by: validcube <pun.butrach@gmail.com>
2024-08-18 18:56:57 +07:00
94de170490 docs: part 9.5
merge changes from `dev` (flutter)
2023-12-09 21:40:43 +07:00
3c56db4121 Merge branch 'compose-dev' into docs/readme 2023-12-09 21:35:37 +07:00
62bb0d34ce docs(accessibility): part 9.4
Heading 1 -> 2 -> 3 not 1 -> 3
2023-11-09 00:01:02 +07:00
1521d21e4e docs: part 9.3 2023-11-08 23:46:31 +07:00
35996b6c69 docs: part 9.2
Co-authored-by: Palm <palmpasuthorn@gmail.com>
2023-11-08 22:41:12 +07:00
d32a213457 docs: part 9.1 2023-11-08 22:31:19 +07:00
2a3395ce15 docs: part 9
This commit removes the developer version, preventing this PR from being locked up with additional developer experiences.
2023-11-08 22:25:33 +07:00
944b57c336 docs: part 8.7
Co-authored-by: KobeW50 <84587632+KobeW50@users.noreply.github.com>
2023-11-08 22:19:54 +07:00
bc09af9d0b docs: part 8.6.1 (test) 2023-10-23 15:28:56 +07:00
0419b2f86b docs: part 8.6 2023-10-23 15:16:34 +07:00
2f31fc7d6e docs: part 8.5
TODO: see PR #1411 suggestions

Co-authored-by: Palm <palmpasuthorn@gmail.com>
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-10-23 15:07:17 +07:00
dcf51c1777 docs: part 8.4-2 2023-10-23 00:52:19 +07:00
94eb893a01 docs: 8.4-1.1 2023-10-23 00:51:58 +07:00
af49457bfc docs: part 8.4-1 2023-10-23 00:50:38 +07:00
a8682d671d docs: part 8.3 2023-10-23 00:49:46 +07:00
10815c8f73 docs: part 7.2 2023-10-23 00:49:28 +07:00
891fb57531 docs: part 8.1 2023-10-22 12:41:45 +07:00
07ee005613 docs: part 8
Co-authored-by: Ushie <ushiekane@gmail.com>
2023-10-22 12:38:49 +07:00
a3c48d14ab docs: part 7.1 2023-10-21 22:45:41 +07:00
f14b697769 docs: part 7
Co-authored-by: Ushie <ushiekane@gmail.com>
2023-10-21 22:43:40 +07:00
d06fb08239 docs: part 6.9 2023-10-21 20:46:06 +07:00
cf9a14c762 docs: part 6.8 2023-10-21 20:35:25 +07:00
7b49af21d0 docs: part 6.7 2023-10-21 20:32:34 +07:00
18774084c9 docs: part 6.6 2023-10-21 20:30:53 +07:00
a70ad3d666 docs: part 6.5 2023-10-21 20:13:42 +07:00
0d2d879603 docs 6.4 2023-10-21 20:13:12 +07:00
8acdc17cc4 docs: part 6.3 2023-10-21 19:57:45 +07:00
1f5331dbfe docs: part 6.2 2023-10-21 19:57:00 +07:00
98747f4afb docs: part 6.1 2023-10-21 19:54:44 +07:00
2f782b4963 docs: part 6 2023-10-21 19:45:49 +07:00
3c083edfda docs: part 5.2 2023-10-21 19:45:00 +07:00
7bf1a5af65 docs: part 5.1 2023-10-21 19:44:05 +07:00
8a3d163266 docs: part 5 2023-10-21 19:39:20 +07:00
d58fd96bb0 docs: part 4.10 2023-10-21 18:29:51 +07:00
259f76379e docs: part 4.9 2023-10-21 17:50:59 +07:00
b8378fbb02 docs: part 4.8 2023-10-21 17:44:01 +07:00
2f0cdfff59 docs: part 4.7 2023-10-21 17:35:29 +07:00
cd5787a4f7 docs: part 4.6 2023-10-21 17:30:32 +07:00
a280fc2446 docs: part 4.5.1 (test) 2023-10-21 17:21:21 +07:00
a503f4830b docs: part 4.5 2023-10-21 17:15:39 +07:00
f732df1b9a docs: part 4.4 2023-10-21 17:11:43 +07:00
9b9525ece5 docs: part 4.3 2023-10-21 17:06:43 +07:00
e0dfbaf4a3 docs: part 4.2 2023-10-21 17:05:53 +07:00
949b1dad0e docs: part 4.1 2023-10-21 17:03:28 +07:00
830a666a58 docs: part 4 2023-10-21 16:58:45 +07:00
26b9652135 docs: part 3 2023-10-21 16:38:29 +07:00
85c6e7283d docs: add ReVanced assets 2023-10-21 16:21:19 +07:00
67603f64cd docs: part 2.1 2023-10-21 16:09:55 +07:00
676eb1e9e2 docs: part 2 2023-10-09 17:09:34 +07:00
e7b94868d6 docs: merge branding to readme (SEE TODO)
TODO:
2023-10-08 16:47:28 +07:00
51 changed files with 819 additions and 795 deletions

View File

@ -9,9 +9,6 @@ jobs:
build:
name: Build
runs-on: ubuntu-latest
permissions:
id-token: write
attestations: write
steps:
- uses: actions/checkout@v4
- name: Set env
@ -44,11 +41,6 @@ jobs:
- name: Add version to APK
run: mv ${{ steps.sign_apk.outputs.signedFile }} revanced-manager-${{ env.RELEASE_VERSION }}.apk
- name: Generate artifact attestation
uses: actions/attest-build-provenance@v1
with:
subject-path: revanced-manager-${{ env.RELEASE_VERSION }}.apk
- name: Publish release APK
uses: "marvinpinto/action-automatic-releases@latest"
with:

111
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,111 @@
<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
Welcome to contribution guidelines, this document contains
everything you'll need to contribute to ReVanced Manager (and might even possibly apply to our other project like ReVanced Patches!)
There are many ways to contribute like writing docs and code, opening issues,
helping people out in our community, translating or sponsoring our project, etc.
## 📖 Resources to help you get started
* The [documentation](/docs/developer/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-issue.yml&title=feat%3A+%3Ctitle%3E).
> [!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 the ReVanced Manager app, open an issue using the
[bug report issue template](https://github.com/ReVanced/revanced-manager/issues/new?assignees=&labels=bug&projects=&template=bug-issue.yml&title=bug%3A+%3Ctitle%3E).
## 🌐 Submitting translations
You can contribute translations at translate.revanced.app
> [!TIP]
> * Try to keep the translated text roughly the same length as the original.
> * Consider opting for gender-neutral words for language with variations of words based on gender.
## 🧑‍💻 Developing for ReVanced Manager
See the guidelines for developing for ReVanced Manager [here](/docs/developer/README.md)
## 🔒 Submitting a vulnerability
See the guideline for reporting security vulnerability [here](/SECURITY.md)
## 🤚 I don't want to do any of that but I want to contribute either way
You can still contribute by spreading positive word about us or if you'd like to sponsor us, checkout https://revanced.app/donate
to learn more about how you can sponsor via GitHub, Open Collective, and cryptocurrencies.
❤️ Thank you for considering contributing to ReVanced Manager,
ReVanced

119
README.md
View File

@ -1,55 +1,104 @@
# ReVanced Manager (Compose Rewrite)
<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>
[![GitHub license](https://img.shields.io/github/license/revanced/revanced-manager)](../../blob/main/LICENSE)
[![GitHub last commit](https://img.shields.io/github/last-commit/revanced/revanced-manager/compose-dev)](https://github.com/ReVanced/revanced-manager/commits/compose-dev)
[![GitHub commit activity](https://img.shields.io/github/commit-activity/w/revanced/revanced-manager/compose-dev)](https://github.com/ReVanced/revanced-manager/commits/compose-dev)
# 💊 ReVanced Manager
_(Yet another)_ rewrite of the ReVanced Manager using Kotlin and Jetpack Compose.
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/ReVanced/revanced-manager/release.yml)](https://github.com/ReVanced/revanced-manager/actions/workflows/release.yml)
[![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](#-license)
## Design system
Application to use ReVanced on Android
In this rewrite, we are adopting the latest Material Design principles and guidelines by using Material 3 and Material You.
## ❓ About
Material Design is a design system developed by Google that provides a unified visual language for building beautiful and consistent user interfaces across all platforms and devices. Material You is an extension of Material Design that provides even more customization options for users, making it possible for them to personalize their device and create a unique look and feel.
ReVanced Manager is an application that uses [ReVanced Patcher](https://github.com/revanced/revanced-patcher) to patch Android apps.
### Why Material 3?
## 💪 Features
* **Consistent design language**
* **Improved accessibility**
* **Better user experience**
Some of the features ReVanced Manager provides are:
By using Material 3 and Material You, we are ensuring that the app's user interface is consistent, customizable, accessible, and engaging for our users. This will help to improve the overall user experience and increase user satisfaction with the the manager.
## Technology stack
* Kotlin: Kotlin is a modern and concise programming language that is fully interoperable with Java and provides improved safety, readability, and maintainability compared to Java.
* Jetpack Compose: Jetpack Compose is a modern UI toolkit for Android development that allows developers to build beautiful and performant user interfaces using declarative programming. It provides a unified and efficient way of building UI that is well-integrated with the Android framework.
## Why Kotlin and Compose?
* **Improved safety:** Kotlin provides improved safety compared to Java, which reduces the likelihood of common programming mistakes that can cause security vulnerabilities or crashes.
* **Concise and readable code:** Kotlin's concise syntax and expressive type system make the code more readable, which makes it easier for developers to understand and maintain the codebase.
* **Better performance:** Jetpack Compose uses the power of the Android framework to provide smooth and fast performance, which enhances the user experience.
* **Modern and efficient UI development:** Jetpack Compose provides a modern and efficient way of building UI, which makes it easier for developers to create beautiful and performant user interfaces.
- 💉 **Patch apps**: Apply any patch of your choice to Android apps
- 📱 **Portable**: ReVanced Patcher that fits in your pocket
- 🤗 **Simple UI**: Quickly understand the ins and outs of ReVanced Manager
- 🛠️ **Customization**: Configurable API, custom sources, language, signing keystore, theme and more
## 🔽 Download
You can obtain ReVanced Manager by downloading it from either [revanced.app/download](https://revanced.app/download) or [GitHub Releases](https://github.com/ReVanced/revanced-manager/releases)
You can get the most recent version of ReVanced Manager by downloading from
the [ReVanced site](https://revanced.app/download).
## 📝 Prerequisites
Learn how to use ReVanced Manager by following the [documentation](/docs).
For a list of prerequisites, refer to [docs/0_prerequisites.md](docs/0_prerequisites.md)
## 📚 Everything else
## 🔴 Issues
### 📙 Contributing
For suggestions and bug reports, open an issue [here](https://github.com/revanced/revanced-manager/issues/new/choose).
Thank you for considering contributing to ReVanced Manager.
## 🌐 Translation
The [contribution guidelines](CONTRIBUTING.md) provides information you'll need to open an issue, develop for ReVanced Manager and translations.
[![Crowdin](https://badges.crowdin.net/revanced/localized.svg)](https://crowdin.com/project/revanced)
### 📄 Documentation
We're accepting translations on [Crowdin](https://translate.revanced.app)
You can find the documentation for ReVanced Manager [here](/docs).
## 🛠 Building Manager from source
## License
For instructions on how to build ReVanced Manager from source, refer to [docs/4_building.md](docs/4_building.md)
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.

View File

@ -64,14 +64,20 @@ This document describes how to report security vulnerabilities for ReVanced Mana
## 🚨 Reporting a Vulnerability
Please open an issue in our [advisory tracker](https://github.com/ReVanced/revanced-manager/security/advisories/new) or reach out privately to us on [Discord](https://discord.gg/revanced).
Please open an issue in our [advisory tracker](https://github.com/ReVanced/revanced-manager/security/advisories/new)
or reach out privately to us on [Discord](https://discord.gg/revanced).
If a vulnerability is confirmed and accepted, you can join our [Discord](https://discord.gg/revanced) server to receive a special contributor role.
If a vulnerability is confirmed and accepted, they will be published and
you can join our [Discord](https://discord.gg/revanced) server to receive a
special contributor role.
### ⏳ Supported Versions
| Version | Branch | Supported |
| --------------------------------------------------------------------------------------------------------------------------------------- | ----------- | ------------------ |
| ![Latest stable release](https://img.shields.io/github/v/release/ReVanced/revanced-manager?style=for-the-badge "Latest stable release") | main | :white_check_mark: |
| ![Latest version](https://img.shields.io/badge/version-latest-brightgreen?style=for-the-badge "Latest version") | dev | :white_check_mark: |
| ![Latest version](https://img.shields.io/badge/version-latest-brightgreen?style=for-the-badge "Latest version") | compose-dev | :white_check_mark: |
| Version | Branch | Supported |
|------------------------------------------|---------------|--------------------|
| ![Latest stable release][LatestRelBadge] | `main` | :white_check_mark: |
| ![Latest version][LatestVerBadge] | `dev` | :white_check_mark: |
| ![Latest version][LatestVerBadge] | `compose-dev` | :white_check_mark: |
[LatestRelBadge]: https://img.shields.io/github/v/release/ReVanced/revanced-manager?style=for-the-badge "Latest stable release"
[LatestVerBadge]: https://img.shields.io/badge/version-latest-brightgreen?style=for-the-badge "Latest version"

View File

@ -13,7 +13,7 @@ plugins {
android {
namespace = "app.revanced.manager"
compileSdk = 35
buildToolsVersion = "35.0.1"
buildToolsVersion = "35.0.0"
defaultConfig {
applicationId = "app.revanced.manager"
@ -28,7 +28,6 @@ android {
debug {
applicationIdSuffix = ".debug"
resValue("string", "app_name", "ReVanced Manager (dev)")
isPseudoLocalesEnabled = true
buildConfigField("long", "BUILD_ID", "${Random.nextLong()}L")
}
@ -44,8 +43,6 @@ android {
applicationIdSuffix = ".debug"
resValue("string", "app_name", "ReVanced Manager Debug")
signingConfig = signingConfigs.getByName("debug")
isPseudoLocalesEnabled = true
}
buildConfigField("long", "BUILD_ID", "0L")

View File

@ -9,8 +9,6 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
@ -25,32 +23,11 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation
import androidx.navigation.compose.rememberNavController
import androidx.navigation.toRoute
import app.revanced.manager.ui.model.navigation.AppSelector
import app.revanced.manager.ui.model.navigation.ComplexParameter
import app.revanced.manager.ui.model.navigation.Dashboard
import app.revanced.manager.ui.model.navigation.InstalledApplicationInfo
import app.revanced.manager.ui.model.navigation.Patcher
import app.revanced.manager.ui.model.navigation.SelectedApplicationInfo
import app.revanced.manager.ui.model.navigation.Settings
import app.revanced.manager.ui.model.navigation.Update
import app.revanced.manager.ui.screen.AppSelectorScreen
import app.revanced.manager.ui.screen.DashboardScreen
import app.revanced.manager.ui.screen.InstalledAppInfoScreen
import app.revanced.manager.ui.screen.PatcherScreen
import app.revanced.manager.ui.screen.PatchesSelectorScreen
import app.revanced.manager.ui.screen.RequiredOptionsScreen
import app.revanced.manager.ui.screen.SelectedAppInfoScreen
import app.revanced.manager.ui.screen.SettingsScreen
import app.revanced.manager.ui.screen.UpdateScreen
import app.revanced.manager.ui.screen.settings.AboutSettingsScreen
import app.revanced.manager.ui.screen.settings.AdvancedSettingsScreen
import app.revanced.manager.ui.screen.settings.BackupRestoreSettingsScreen
import app.revanced.manager.ui.screen.settings.ContributorScreen
import app.revanced.manager.ui.screen.settings.DeveloperOptionsScreen
import app.revanced.manager.ui.screen.settings.DownloadsSettingsScreen
import app.revanced.manager.ui.screen.settings.GeneralSettingsScreen
import app.revanced.manager.ui.screen.settings.LicensesScreen
import app.revanced.manager.ui.model.navigation.*
import app.revanced.manager.ui.screen.*
import app.revanced.manager.ui.screen.settings.*
import app.revanced.manager.ui.screen.settings.update.ChangelogsScreen
import app.revanced.manager.ui.screen.settings.update.UpdatesSettingsScreen
import app.revanced.manager.ui.theme.ReVancedManagerTheme
import app.revanced.manager.ui.theme.Theme
import app.revanced.manager.ui.viewmodel.MainViewModel
@ -112,10 +89,6 @@ private fun ReVancedManager(vm: MainViewModel) {
NavHost(
navController = navController,
startDestination = Dashboard,
enterTransition = { slideInHorizontally(initialOffsetX = { it }) },
exitTransition = { slideOutHorizontally(targetOffsetX = { -it / 3 }) },
popEnterTransition = { slideInHorizontally(initialOffsetX = { -it / 3 }) },
popExitTransition = { slideOutHorizontally(targetOffsetX = { it }) },
) {
composable<Dashboard> {
DashboardScreen(
@ -269,28 +242,32 @@ private fun ReVancedManager(vm: MainViewModel) {
}
composable<Settings.General> {
GeneralSettingsScreen(
onBackClick = navController::popBackStack,
onUpdateClick = { navController.navigate(Update()) }
)
GeneralSettingsScreen(onBackClick = navController::popBackStack)
}
composable<Settings.Advanced> {
AdvancedSettingsScreen(onBackClick = navController::popBackStack)
}
composable<Settings.Updates> {
UpdatesSettingsScreen(
onBackClick = navController::popBackStack,
onChangelogClick = { navController.navigate(Settings.Changelogs) },
onUpdateClick = { navController.navigate(Update()) }
)
}
composable<Settings.Downloads> {
DownloadsSettingsScreen(onBackClick = navController::popBackStack)
}
composable<Settings.ImportExport> {
BackupRestoreSettingsScreen(onBackClick = navController::popBackStack)
ImportExportSettingsScreen(onBackClick = navController::popBackStack)
}
composable<Settings.About> {
AboutSettingsScreen(
onBackClick = navController::popBackStack,
onChangelogClick = { navController.navigate(Settings.Changelogs) },
navigate = navController::navigate
)
}

View File

@ -4,20 +4,9 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@ -55,14 +44,9 @@ fun AppTopBar(
)
},
actions: @Composable (RowScope.() -> Unit) = {},
scrollBehavior: TopAppBarScrollBehavior? = null,
applyContainerColor: Boolean = false
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val containerColor = if (applyContainerColor) {
MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
} else {
Color.Unspecified
}
val containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(3.0.dp)
TopAppBar(
title = { Text(title) },

View File

@ -70,6 +70,9 @@ object Settings {
@Serializable
data object Advanced : Destination
@Serializable
data object Updates : Destination
@Serializable
data object Downloads : Destination

View File

@ -3,26 +3,12 @@ package app.revanced.manager.ui.screen
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Storage
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -31,7 +17,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@ -153,13 +138,10 @@ fun AppSelectorScreen(
}
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.select_app),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick,
actions = {
IconButton(onClick = { search = true }) {
@ -167,8 +149,7 @@ fun AppSelectorScreen(
}
}
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
LazyColumnWithScrollbar(
modifier = Modifier

View File

@ -7,46 +7,17 @@ import android.provider.Settings
import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.BatteryAlert
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.outlined.Apps
import androidx.compose.material.icons.outlined.BugReport
import androidx.compose.material.icons.outlined.DeleteOutline
import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.outlined.Source
import androidx.compose.material.icons.outlined.Update
import androidx.compose.material.icons.outlined.WarningAmber
import androidx.compose.material3.Badge
import androidx.compose.material3.BadgedBox
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TabRow
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
@ -62,9 +33,9 @@ import app.revanced.manager.ui.component.AutoUpdatesDialog
import app.revanced.manager.ui.component.AvailableUpdateDialog
import app.revanced.manager.ui.component.NotificationCard
import app.revanced.manager.ui.component.bundle.BundleTopBar
import app.revanced.manager.ui.component.bundle.ImportPatchBundleDialog
import app.revanced.manager.ui.component.haptics.HapticFloatingActionButton
import app.revanced.manager.ui.component.haptics.HapticTab
import app.revanced.manager.ui.component.bundle.ImportPatchBundleDialog
import app.revanced.manager.ui.viewmodel.DashboardViewModel
import app.revanced.manager.util.RequestInstallAppsContract
import app.revanced.manager.util.toast
@ -200,7 +171,11 @@ fun DashboardScreen(
) {
BadgedBox(
badge = {
Badge(modifier = Modifier.size(6.dp))
Badge(
// A size value above 6.dp forces the Badge icon to be closer to the center, fixing a clipping issue
modifier = Modifier.size(7.dp),
containerColor = MaterialTheme.colorScheme.primary,
)
}
) {
Icon(Icons.Outlined.Update, stringResource(R.string.update))
@ -210,8 +185,7 @@ fun DashboardScreen(
IconButton(onClick = onSettingsClick) {
Icon(Icons.Outlined.Settings, stringResource(R.string.settings))
}
},
applyContainerColor = true
}
)
}
},
@ -264,9 +238,7 @@ fun DashboardScreen(
}
}
val showBatteryOptimizationsWarning by vm.showBatteryOptimizationsWarningFlow.collectAsStateWithLifecycle(
false
)
val showBatteryOptimizationsWarning by vm.showBatteryOptimizationsWarningFlow.collectAsStateWithLifecycle(false)
Notifications(
if (!Aapt.supportsDevice()) {
{

View File

@ -21,8 +21,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.getValue
@ -31,7 +29,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
@ -67,17 +64,13 @@ fun InstalledAppInfoScreen(
onConfirm = { viewModel.uninstall() }
)
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.app_info),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
ColumnWithScrollbar(
modifier = Modifier

View File

@ -121,10 +121,9 @@ fun PatcherScreen(
}
AppScaffold(
topBar = { scrollBehavior ->
topBar = {
AppTopBar(
title = stringResource(R.string.patcher),
scrollBehavior = scrollBehavior,
onBackClick = ::leaveScreen
)
},

View File

@ -76,8 +76,8 @@ import app.revanced.manager.ui.component.haptics.HapticExtendedFloatingActionBut
import app.revanced.manager.ui.component.haptics.HapticTab
import app.revanced.manager.ui.component.patches.OptionItem
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_UNIVERSAL
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_UNSUPPORTED
import app.revanced.manager.ui.viewmodel.PatchesSelectorViewModel.Companion.SHOW_UNIVERSAL
import app.revanced.manager.util.Options
import app.revanced.manager.util.PatchSelection
import app.revanced.manager.util.isScrollingUp

View File

@ -15,8 +15,6 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScrollableTabRow
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
@ -24,7 +22,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@ -69,13 +66,10 @@ fun RequiredOptionsScreen(
}
val composableScope = rememberCoroutineScope()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.required_options_screen),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
@ -96,8 +90,7 @@ fun RequiredOptionsScreen(
onContinue(vm.getCustomSelection(), vm.getOptions())
}
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
Column(
Modifier

View File

@ -12,21 +12,12 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowRight
import androidx.compose.material.icons.filled.AutoFixHigh
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@ -84,14 +75,10 @@ fun SelectedAppInfoScreen(
val composableScope = rememberCoroutineScope()
val error by vm.errorFlow.collectAsStateWithLifecycle(null)
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.app_info),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
@ -127,8 +114,7 @@ fun SelectedAppInfoScreen(
}
}
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
val plugins by vm.plugins.collectAsStateWithLifecycle(emptyList())

View File

@ -4,14 +4,8 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Download
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.outlined.SwapVert
import androidx.compose.material.icons.outlined.Tune
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.Scaffold
import androidx.compose.material.icons.outlined.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@ -28,13 +22,18 @@ private val settingsSections = listOf(
Icons.Outlined.Settings
) to Settings.General,
Triple(
R.string.extensions,
R.string.extensions_description,
R.string.updates,
R.string.updates_description,
Icons.Outlined.Update
) to Settings.Updates,
Triple(
R.string.downloads,
R.string.downloads_description,
Icons.Outlined.Download
) to Settings.Downloads,
Triple(
R.string.backup_restore,
R.string.backup_restore_description,
R.string.import_export,
R.string.import_export_description,
Icons.Outlined.SwapVert
) to Settings.ImportExport,
Triple(

View File

@ -24,13 +24,10 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@ -55,17 +52,13 @@ fun UpdateScreen(
onBackClick: () -> Unit,
vm: UpdateViewModel = koinViewModel()
) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.update),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
AnimatedVisibility(visible = vm.showInternetCheckDialog) {
MeteredDownloadConfirmationDialog(

View File

@ -24,13 +24,10 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedCard
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@ -51,7 +48,6 @@ import org.koin.androidx.compose.koinViewModel
@Composable
fun AboutSettingsScreen(
onBackClick: () -> Unit,
onChangelogClick: () -> Unit,
navigate: (Settings.Destination) -> Unit,
viewModel: AboutViewModel = koinViewModel()
) {
@ -109,11 +105,6 @@ fun AboutSettingsScreen(
}
val listItems = listOfNotNull(
Triple(
stringResource(R.string.changelog),
stringResource(R.string.changelog_description),
third = { onChangelogClick }
),
Triple(stringResource(R.string.submit_feedback),
stringResource(R.string.submit_feedback_description),
third = {
@ -136,17 +127,13 @@ fun AboutSettingsScreen(
)
)
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.about),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
ColumnWithScrollbar(
modifier = Modifier

View File

@ -10,34 +10,14 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Api
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Restore
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@ -73,17 +53,14 @@ fun AdvancedSettingsScreen(
activityManager.largeMemoryClass
)
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.advanced),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
ColumnWithScrollbar(
modifier = Modifier
@ -101,10 +78,17 @@ fun AdvancedSettingsScreen(
defaultUrl = vm.prefs.api.default,
onSubmit = {
showApiUrlDialog = false
it?.let(vm::setApiSource)
it?.let(vm::setApiUrl)
}
)
}
SettingsListItem(
headlineContent = stringResource(R.string.api_url),
supportingContent = stringResource(R.string.api_url_description),
modifier = Modifier.clickable {
showApiUrlDialog = true
}
)
GroupHeader(stringResource(R.string.patcher))
BooleanItem(
@ -120,28 +104,13 @@ fun AdvancedSettingsScreen(
description = R.string.process_runtime_memory_limit_description,
)
GroupHeader(stringResource(R.string.manager))
SettingsListItem(
headlineContent = stringResource(R.string.api_url),
supportingContent = apiUrl,
modifier = Modifier.clickable {
showApiUrlDialog = true
},
trailingContent = {
IconButton(onClick = { showApiUrlDialog = true }) {
Icon(
Icons.Outlined.Edit,
contentDescription = stringResource(R.string.edit)
)
}
}
)
GroupHeader(stringResource(R.string.safeguards))
SafeguardBooleanItem(
preference = vm.prefs.disablePatchVersionCompatCheck,
coroutineScope = vm.viewModelScope,
headline = R.string.allow_compatibility_mixing,
description = R.string.allow_compatibility_mixing_description,
confirmationText = R.string.allow_compatibility_mixing_confirmation
headline = R.string.patch_compat_check,
description = R.string.patch_compat_check_description,
confirmationText = R.string.patch_compat_check_confirmation
)
SafeguardBooleanItem(
preference = vm.prefs.disableUniversalPatchWarning,
@ -150,6 +119,13 @@ fun AdvancedSettingsScreen(
description = R.string.universal_patches_safeguard_description,
confirmationText = R.string.universal_patches_safeguard_confirmation
)
SafeguardBooleanItem(
preference = vm.prefs.suggestedVersionSafeguard,
coroutineScope = vm.viewModelScope,
headline = R.string.suggested_version_safeguard,
description = R.string.suggested_version_safeguard_description,
confirmationText = R.string.suggested_version_safeguard_confirmation
)
SafeguardBooleanItem(
preference = vm.prefs.disableSelectionWarning,
coroutineScope = vm.viewModelScope,
@ -158,21 +134,6 @@ fun AdvancedSettingsScreen(
confirmationText = R.string.patch_selection_safeguard_confirmation
)
GroupHeader(stringResource(R.string.update))
BooleanItem(
preference = vm.prefs.showManagerUpdateDialogOnLaunch,
headline = R.string.show_manager_update_dialog_on_launch,
description = R.string.check_for_update_auto_description
)
GroupHeader(stringResource(R.string.experimental_features))
BooleanItem(
preference = vm.prefs.useProcessRuntime,
coroutineScope = vm.viewModelScope,
headline = R.string.process_runtime,
description = R.string.process_runtime_description,
)
GroupHeader(stringResource(R.string.debugging))
val exportDebugLogsLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("text/plain")) {

View File

@ -25,14 +25,11 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@ -56,17 +53,13 @@ fun ContributorScreen(
viewModel: ContributorViewModel = koinViewModel()
) {
val repositories = viewModel.repositories
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.contributors),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
) { paddingValues ->
LazyColumnWithScrollbar(
modifier = Modifier

View File

@ -5,11 +5,8 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
@ -24,17 +21,13 @@ fun DeveloperOptionsScreen(
onBackClick: () -> Unit,
vm: DeveloperOptionsViewModel = koinViewModel()
) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.developer_options),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
Column(modifier = Modifier.padding(paddingValues)) {
GroupHeader(stringResource(R.string.patch_bundles_section))
@ -44,13 +37,7 @@ fun DeveloperOptionsScreen(
)
SettingsListItem(
headlineContent = stringResource(R.string.patch_bundles_reset),
modifier = Modifier.clickable(onClick = vm::resetBundles)
)
GroupHeader(stringResource(R.string.testing))
SettingsListItem(
headlineContent = stringResource(R.string.disable_safeguard),
modifier = Modifier.clickable(onClick = vm::disableSafeguard)
modifier = Modifier.clickable(onClick = vm::redownloadBundles)
)
}
}

View File

@ -17,11 +17,9 @@ import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.pulltorefresh.PullToRefreshDefaults
import androidx.compose.material3.pulltorefresh.pullToRefresh
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -30,7 +28,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@ -58,13 +55,11 @@ fun DownloadsSettingsScreen(
val pullRefreshState = rememberPullToRefreshState()
val downloadedApps by viewModel.downloadedApps.collectAsStateWithLifecycle(emptyList())
val pluginStates by viewModel.downloaderPluginStates.collectAsStateWithLifecycle()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.extensions),
scrollBehavior = scrollBehavior,
title = stringResource(R.string.downloads),
onBackClick = onBackClick,
actions = {
if (viewModel.appSelection.isNotEmpty()) {
@ -74,8 +69,7 @@ fun DownloadsSettingsScreen(
}
}
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
Box(
contentAlignment = Alignment.TopCenter,

View File

@ -8,14 +8,11 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@ -23,7 +20,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewModelScope
import app.revanced.manager.R
@ -43,7 +39,6 @@ import org.koin.compose.koinInject
@Composable
fun GeneralSettingsScreen(
onBackClick: () -> Unit,
onUpdateClick: () -> Unit,
viewModel: GeneralSettingsViewModel = koinViewModel()
) {
val prefs = viewModel.prefs
@ -56,17 +51,14 @@ fun GeneralSettingsScreen(
onConfirm = { viewModel.setTheme(it) }
)
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.general),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
ColumnWithScrollbar(
modifier = Modifier
@ -78,10 +70,10 @@ fun GeneralSettingsScreen(
val theme by prefs.theme.getAsState()
SettingsListItem(
modifier = Modifier.clickable { showThemePicker = true },
headlineContent = stringResource(R.string.theme_mode),
supportingContent = stringResource(R.string.theme_mode_description),
headlineContent = stringResource(R.string.theme),
supportingContent = stringResource(R.string.theme_description),
trailingContent = {
Button(
FilledTonalButton(
onClick = {
showThemePicker = true
}
@ -94,24 +86,11 @@ fun GeneralSettingsScreen(
BooleanItem(
preference = prefs.dynamicColor,
coroutineScope = coroutineScope,
headline = R.string.personalized_color,
description = R.string.personalized_color_description
headline = R.string.dynamic_color,
description = R.string.dynamic_color_description
)
}
}
GroupHeader(stringResource(R.string.update))
BooleanItem(
preference = prefs.managerAutoUpdates,
headline = R.string.check_for_update,
description = R.string.check_for_update_auto_description
)
FilledTonalButton (
modifier = Modifier.padding(top = paddingValues.calculateTopPadding()),
onClick = onUpdateClick
) {
Text(stringResource(R.string.check_for_update))
}
}
}
@ -125,7 +104,7 @@ private fun ThemePicker(
AlertDialog(
onDismissRequest = onDismiss,
title = { Text(stringResource(R.string.theme_mode)) },
title = { Text(stringResource(R.string.theme)) },
text = {
Column {
Theme.entries.forEach {

View File

@ -13,17 +13,7 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Key
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
@ -32,7 +22,6 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
@ -48,82 +37,118 @@ import app.revanced.manager.ui.component.bundle.BundleSelector
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.ImportExportViewModel
import app.revanced.manager.util.toast
import app.revanced.manager.util.uiSafe
import kotlinx.coroutines.launch
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun BackupRestoreSettingsScreen(
fun ImportExportSettingsScreen(
onBackClick: () -> Unit,
viewModel: ImportExportViewModel = koinViewModel()
vm: ImportExportViewModel = koinViewModel()
) {
val context = LocalContext.current
val importKeystoreLauncher =
rememberLauncherForActivityResult(contract = ActivityResultContracts.GetContent()) {
it?.let { uri -> viewModel.startKeystoreImport(uri) }
it?.let { uri -> vm.startKeystoreImport(uri) }
}
val exportKeystoreLauncher =
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("*/*")) {
it?.let(viewModel::exportKeystore)
it?.let(vm::exportKeystore)
}
val patchBundles by viewModel.patchBundles.collectAsStateWithLifecycle(initialValue = emptyList())
val packagesWithOptions by viewModel.packagesWithOptions.collectAsStateWithLifecycle(initialValue = emptySet())
val patchBundles by vm.patchBundles.collectAsStateWithLifecycle(initialValue = emptyList())
val packagesWithOptions by vm.packagesWithOptions.collectAsStateWithLifecycle(initialValue = emptySet())
viewModel.selectionAction?.let { action ->
vm.selectionAction?.let { action ->
val launcher = rememberLauncherForActivityResult(action.activityContract) { uri ->
if (uri == null) {
viewModel.clearSelectionAction()
vm.clearSelectionAction()
} else {
viewModel.executeSelectionAction(uri)
vm.executeSelectionAction(uri)
}
}
if (viewModel.selectedBundle == null) {
if (vm.selectedBundle == null) {
BundleSelector(patchBundles) {
if (it == null) {
viewModel.clearSelectionAction()
vm.clearSelectionAction()
} else {
viewModel.selectBundle(it)
vm.selectBundle(it)
launcher.launch(action.activityArg)
}
}
}
}
if (viewModel.showCredentialsDialog) {
if (vm.showCredentialsDialog) {
KeystoreCredentialsDialog(
onDismissRequest = viewModel::cancelKeystoreImport,
onDismissRequest = vm::cancelKeystoreImport,
onSubmit = { cn, pass ->
viewModel.viewModelScope.launch {
uiSafe(context, R.string.failed_to_import_keystore, "Failed to import keystore") {
val result = viewModel.tryKeystoreImport(cn, pass)
if (!result) context.toast(context.getString(R.string.restore_keystore_wrong_credentials))
}
vm.viewModelScope.launch {
val result = vm.tryKeystoreImport(cn, pass)
if (!result) context.toast(context.getString(R.string.import_keystore_wrong_credentials))
}
}
)
}
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.backup_restore),
scrollBehavior = scrollBehavior,
title = stringResource(R.string.import_export),
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
GroupHeader(stringResource(R.string.signing))
GroupItem(
onClick = {
importKeystoreLauncher.launch("*/*")
},
headline = R.string.import_keystore,
description = R.string.import_keystore_description
)
GroupItem(
onClick = {
if (!vm.canExport()) {
context.toast(context.getString(R.string.export_keystore_unavailable))
return@GroupItem
}
exportKeystoreLauncher.launch("Manager.keystore")
},
headline = R.string.export_keystore,
description = R.string.export_keystore_description
)
GroupItem(
onClick = vm::regenerateKeystore,
headline = R.string.regenerate_keystore,
description = R.string.regenerate_keystore_description
)
GroupHeader(stringResource(R.string.patches))
GroupItem(
onClick = vm::importSelection,
headline = R.string.import_patch_selection,
description = R.string.import_patch_selection_description
)
GroupItem(
onClick = vm::exportSelection,
headline = R.string.export_patch_selection,
description = R.string.export_patch_selection_description
)
// TODO: allow resetting selection for specific bundle or package name.
GroupItem(
onClick = vm::resetSelection,
headline = R.string.reset_patch_selection,
description = R.string.reset_patch_selection_description
)
var showPackageSelector by rememberSaveable {
mutableStateOf(false)
}
@ -131,108 +156,37 @@ fun BackupRestoreSettingsScreen(
mutableStateOf(false)
}
if (showPackageSelector) {
if (showPackageSelector)
PackageSelector(packages = packagesWithOptions) { selected ->
selected?.let(viewModel::resetOptionsForPackage)
selected?.let(vm::resetOptionsForPackage)
showPackageSelector = false
}
}
if (showBundleSelector) {
if (showBundleSelector)
BundleSelector(bundles = patchBundles) { bundle ->
bundle?.let(viewModel::clearOptionsForBundle)
bundle?.let(vm::clearOptionsForBundle)
showBundleSelector = false
}
}
GroupHeader(stringResource(R.string.keystore))
GroupItem(
onClick = {
if (!viewModel.canExport()) {
context.toast(context.getString(R.string.backup_keystore_unavailable))
return@GroupItem
}
exportKeystoreLauncher.launch("Manager.keystore")
},
headline = R.string.backup,
description = R.string.backup_keystore_description
)
GroupItem(
onClick = {
importKeystoreLauncher.launch("*/*")
},
headline = R.string.restore,
description = R.string.restore_keystore_description
)
GroupItem(
onClick = viewModel::regenerateKeystore,
headline = {
Text(
stringResource(R.string.regenerate_keystore),
color = MaterialTheme.colorScheme.error
)
},
description = R.string.regenerate_keystore_description
)
GroupHeader(stringResource(R.string.patch_selection))
GroupItem(
onClick = viewModel::exportSelection,
headline = R.string.backup,
description = R.string.restore_patch_selection_description
)
GroupItem(
onClick = viewModel::importSelection,
headline = R.string.restore,
description = R.string.backup_patch_selection_description
)
GroupItem(
onClick = viewModel::resetSelection, // TODO: allow resetting selection for specific bundle or package name.
headline = {
Text(
stringResource(R.string.reset),
color = MaterialTheme.colorScheme.error
)
},
description = R.string.reset_patch_selection_description
)
GroupHeader(stringResource(R.string.patch_options))
// TODO: patch options import/export.
GroupItem(
onClick = viewModel::resetOptions,
headline = {
Text(
stringResource(R.string.reset),
color = MaterialTheme.colorScheme.error
)
},
onClick = vm::resetOptions,
headline = R.string.patch_options_reset_all,
description = R.string.patch_options_reset_all_description,
)
GroupItem(
onClick = { showPackageSelector = true },
headline = {
Text(
stringResource(R.string.patch_options_reset_package),
color = MaterialTheme.colorScheme.error
)
},
headline = R.string.patch_options_reset_package,
description = R.string.patch_options_reset_package_description
)
if (patchBundles.size > 1) {
if (patchBundles.size > 1)
GroupItem(
onClick = { showBundleSelector = true },
headline = {
Text(
stringResource(R.string.patch_options_reset_bundle),
color = MaterialTheme.colorScheme.error
)
},
headline = R.string.patch_options_reset_bundle,
description = R.string.patch_options_reset_bundle_description,
)
}
}
}
}
@ -308,19 +262,6 @@ private fun GroupItem(
)
}
@Composable
private fun GroupItem(
onClick: () -> Unit,
headline: @Composable () -> Unit,
@StringRes description: Int? = null
) {
SettingsListItem(
modifier = Modifier.clickable { onClick() },
headlineContent = headline,
supportingContent = description?.let { stringResource(it) }
)
}
@Composable
fun KeystoreCredentialsDialog(
onDismissRequest: () -> Unit,
@ -337,7 +278,7 @@ fun KeystoreCredentialsDialog(
onSubmit(cn, pass)
}
) {
Text(stringResource(R.string.restore_keystore_dialog_button))
Text(stringResource(R.string.import_keystore_dialog_button))
}
},
dismissButton = {
@ -350,7 +291,7 @@ fun KeystoreCredentialsDialog(
},
title = {
Text(
text = stringResource(R.string.restore_keystore_dialog_title),
text = stringResource(R.string.import_keystore_dialog_title),
style = MaterialTheme.typography.headlineSmall.copy(textAlign = TextAlign.Center),
color = MaterialTheme.colorScheme.onSurface,
)
@ -361,19 +302,19 @@ fun KeystoreCredentialsDialog(
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = stringResource(R.string.restore_keystore_dialog_description),
text = stringResource(R.string.import_keystore_dialog_description),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
OutlinedTextField(
value = cn,
onValueChange = { cn = it },
label = { Text(stringResource(R.string.restore_keystore_dialog_alias_field)) }
label = { Text(stringResource(R.string.import_keystore_dialog_alias_field)) }
)
PasswordField(
value = pass,
onValueChange = { pass = it },
label = { Text(stringResource(R.string.restore_keystore_dialog_password_field)) }
label = { Text(stringResource(R.string.import_keystore_dialog_password_field)) }
)
}
}

View File

@ -7,12 +7,9 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
@ -31,17 +28,13 @@ fun ChangelogsScreen(
onBackClick: () -> Unit,
vm: ChangelogsViewModel = koinViewModel()
) {
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.changelog),
scrollBehavior = scrollBehavior,
onBackClick = onBackClick
)
},
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
}
) { paddingValues ->
ColumnWithScrollbar(
modifier = Modifier

View File

@ -0,0 +1,75 @@
package app.revanced.manager.ui.screen.settings.update
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import app.revanced.manager.R
import app.revanced.manager.ui.component.AppTopBar
import app.revanced.manager.ui.component.ColumnWithScrollbar
import app.revanced.manager.ui.component.settings.BooleanItem
import app.revanced.manager.ui.component.settings.SettingsListItem
import app.revanced.manager.ui.viewmodel.UpdatesSettingsViewModel
import kotlinx.coroutines.launch
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun UpdatesSettingsScreen(
onBackClick: () -> Unit,
onChangelogClick: () -> Unit,
onUpdateClick: () -> Unit,
vm: UpdatesSettingsViewModel = koinViewModel(),
) {
val coroutineScope = rememberCoroutineScope()
Scaffold(
topBar = {
AppTopBar(
title = stringResource(R.string.updates),
onBackClick = onBackClick
)
}
) { paddingValues ->
ColumnWithScrollbar(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
) {
SettingsListItem(
modifier = Modifier.clickable {
coroutineScope.launch {
if (vm.checkForUpdates()) onUpdateClick()
}
},
headlineContent = stringResource(R.string.manual_update_check),
supportingContent = stringResource(R.string.manual_update_check_description)
)
SettingsListItem(
modifier = Modifier.clickable(onClick = onChangelogClick),
headlineContent = stringResource(R.string.changelog),
supportingContent = stringResource(
R.string.changelog_description
)
)
BooleanItem(
preference = vm.managerAutoUpdates,
headline = R.string.update_checking_manager,
description = R.string.update_checking_manager_description
)
BooleanItem(
preference = vm.showManagerUpdateDialogOnLaunch,
headline = R.string.show_manager_update_dialog_on_launch,
description = R.string.update_checking_manager_description
)
}
}
}

View File

@ -34,7 +34,7 @@ class AdvancedSettingsViewModel(
return "revanced-manager_logcat_$time"
}
fun setApiSource(value: String) = viewModelScope.launch(Dispatchers.Default) {
fun setApiUrl(value: String) = viewModelScope.launch(Dispatchers.Default) {
if (value == prefs.api.get()) return@launch
prefs.api.update(value)

View File

@ -24,10 +24,4 @@ class DeveloperOptionsViewModel(
fun resetBundles() = viewModelScope.launch {
patchBundleRepository.reset()
}
fun disableSafeguard() = viewModelScope.launch {
prefs.disablePatchVersionCompatCheck.update(true)
prefs.disableSelectionWarning.update(true)
prefs.disableUniversalPatchWarning.update(true)
}
}

View File

@ -69,27 +69,25 @@ class ImportExportViewModel(
}
fun startKeystoreImport(content: Uri) = viewModelScope.launch {
uiSafe(app, R.string.failed_to_import_keystore, "Failed to import keystore") {
val path = withContext(Dispatchers.IO) {
File.createTempFile("signing", "ks", app.cacheDir).toPath().also {
Files.copy(
contentResolver.openInputStream(content)!!,
it,
StandardCopyOption.REPLACE_EXISTING
)
}
val path = withContext(Dispatchers.IO) {
File.createTempFile("signing", "ks", app.cacheDir).toPath().also {
Files.copy(
contentResolver.openInputStream(content)!!,
it,
StandardCopyOption.REPLACE_EXISTING
)
}
aliases.forEach { alias ->
knownPasswords.forEach { pass ->
if (tryKeystoreImport(alias, pass, path)) {
return@launch
}
}
}
keystoreImportPath = path
}
aliases.forEach { alias ->
knownPasswords.forEach { pass ->
if (tryKeystoreImport(alias, pass, path)) {
return@launch
}
}
}
keystoreImportPath = path
}
fun cancelKeystoreImport() {
@ -103,7 +101,7 @@ class ImportExportViewModel(
private suspend fun tryKeystoreImport(cn: String, pass: String, path: Path): Boolean {
path.inputStream().use { stream ->
if (keystoreManager.import(cn, pass, stream)) {
app.toast(app.getString(R.string.restore_keystore_success))
app.toast(app.getString(R.string.import_keystore_success))
cancelKeystoreImport()
return true
}
@ -122,7 +120,7 @@ class ImportExportViewModel(
fun exportKeystore(target: Uri) = viewModelScope.launch {
keystoreManager.export(contentResolver.openOutputStream(target)!!)
app.toast(app.getString(R.string.backup_keystore_success))
app.toast(app.getString(R.string.export_keystore_success))
}
fun regenerateKeystore() = viewModelScope.launch {
@ -171,7 +169,7 @@ class ImportExportViewModel(
override val activityArg = JSON_MIMETYPE
override suspend fun execute(bundleUid: Int, location: Uri) = uiSafe(
app,
R.string.restore_patch_selection_fail,
R.string.import_patch_selection_fail,
"Failed to restore patch selection"
) {
val selection = withContext(Dispatchers.IO) {
@ -181,7 +179,7 @@ class ImportExportViewModel(
}
selectionRepository.import(bundleUid, selection)
app.toast(app.getString(R.string.restore_patch_selection_success))
app.toast(app.getString(R.string.import_patch_selection_success))
}
}
@ -190,7 +188,7 @@ class ImportExportViewModel(
override val activityArg = "selection.json"
override suspend fun execute(bundleUid: Int, location: Uri) = uiSafe(
app,
R.string.backup_patch_selection_fail,
R.string.export_patch_selection_fail,
"Failed to backup patch selection"
) {
val selection = selectionRepository.export(bundleUid)
@ -200,7 +198,7 @@ class ImportExportViewModel(
Json.Default.encodeToStream(selection, it)
}
}
app.toast(app.getString(R.string.backup_patch_selection_success))
app.toast(app.getString(R.string.export_patch_selection_success))
}
}

View File

@ -137,8 +137,8 @@ class MainViewModel(
updateCheck()
}
}
settings.patchesChangeEnabled?.let { allowChangingPatchSelection ->
prefs.allowChangingPatchSelection.update(allowChangingPatchSelection)
settings.patchesChangeEnabled?.let { disableSelectionWarning ->
prefs.disableSelectionWarning.update(disableSelectionWarning)
}
settings.keystore?.let { keystore ->
val keystoreBytes = Base64.decode(keystore, Base64.DEFAULT)

View File

@ -66,7 +66,7 @@ class PatchesSelectorViewModel(input: SelectedApplicationInfo.PatchesSelector.Vi
viewModelScope.launch {
universalPatchWarningEnabled = !prefs.disableUniversalPatchWarning.get()
if (prefs.allowChangingPatchSelection.get()) {
if (prefs.disableSelectionWarning.get()) {
selectionWarningEnabled = false
return@launch
}

View File

@ -152,7 +152,7 @@ class SelectedAppInfoViewModel(
// Try to get the previous selection if customization is enabled.
viewModelScope.launch {
if (!prefs.allowChangingPatchSelection.get()) return@launch
if (!prefs.disableSelectionWarning.get()) return@launch
val previous = selectionRepository.getSelection(packageName)
if (previous.values.sumOf { it.size } == 0) return@launch

View File

@ -108,19 +108,14 @@ class UpdateViewModel(
val extra =
intent.getStringExtra(InstallService.EXTRA_INSTALL_STATUS_MESSAGE)!!
when(pmStatus) {
PackageInstaller.STATUS_SUCCESS -> {
app.toast(app.getString(R.string.install_app_success))
state = State.SUCCESS
}
PackageInstaller.STATUS_FAILURE_ABORTED -> {
state = State.CAN_INSTALL
}
else -> {
app.toast(app.getString(R.string.install_app_fail, extra))
installError = extra
state = State.FAILED
}
if (pmStatus == PackageInstaller.STATUS_SUCCESS) {
app.toast(app.getString(R.string.install_app_success))
state = State.SUCCESS
} else {
state = State.FAILED
// TODO: handle install fail with a popup
installError = extra
app.toast(app.getString(R.string.install_app_fail, extra))
}
}
}

View File

@ -5,11 +5,8 @@
<string name="cli">CLI</string>
<string name="manager">Manager</string>
<string name="revanced_patcher">ReVanced Patcher</string>
<string name="plugin_host_permission_label">ReVanced Manager plugin host</string>
<string name="plugin_host_permission_description">Used to control access to ReVanced Manager
plugins. Only ReVanced Manager has this.</string>
<string name="plugin_host_permission_description">Used to control access to ReVanced Manager plugins. Only ReVanced Manager has this.</string>
<string name="toast_copied_to_clipboard">Copied!</string>
<string name="copy_to_clipboard">Copy to clipboard</string>
@ -19,10 +16,8 @@
<string name="select_app">Select an app</string>
<string name="patches_selected">%1$d/%2$d selected</string>
<string name="new_downloader_plugins_notification">New downloader plugins available. Click here
to configure them.</string>
<string name="unsupported_architecture_warning">Patching on this device architecture is
unsupported and will most likely fail.</string>
<string name="new_downloader_plugins_notification">New downloader plugins available. Click here to configure them.</string>
<string name="unsupported_architecture_warning">Patching on this device architecture is unsupported and will most likely fail.</string>
<string name="import_">Import</string>
<string name="import_bundle">Import patch bundle</string>
@ -41,20 +36,15 @@
<string name="bundle_name_fallback">Unnamed</string>
<string name="android_11_bug_dialog_title">Android 11 bug</string>
<string name="android_11_bug_dialog_description">The app installation permission must be granted
ahead of time to avoid a bug in the Android 11 system that will negatively affect the user
experience.</string>
<string name="android_11_bug_dialog_description">The app installation permission must be granted ahead of time to avoid a bug in the Android 11 system that will negatively affect the user experience.</string>
<string name="selected_app_meta_any_version">Any available version</string>
<string name="app_source_dialog_title">Select source</string>
<string name="app_source_dialog_option_auto">Auto</string>
<string name="app_source_dialog_option_auto_description">Use all installed downloaders to find a
suitable APK file</string>
<string name="app_source_dialog_option_auto_description">Use all installed downloaders to find a suitable APK file</string>
<string name="app_source_dialog_option_auto_unavailable">No plugins available</string>
<string name="app_source_dialog_option_installed_no_root">Mounted apps cannot be patched again
without root access</string>
<string name="app_source_dialog_option_installed_version_not_suggested">Version %s does not
match the suggested version</string>
<string name="app_source_dialog_option_installed_no_root">Mounted apps cannot be patched again without root access</string>
<string name="app_source_dialog_option_installed_version_not_suggested">Version %s does not match the suggested version</string>
<string name="patch_item_description">Start patching the application</string>
<string name="patch_selector_item">Patch selection and options</string>
@ -70,91 +60,77 @@
<string name="legacy_import_failed">Could not import legacy settings</string>
<string name="auto_updates_dialog_title">Configure updates</string>
<string name="auto_updates_dialog_description">Do you want ReVanced Manager to periodically
check for updates for the following components?</string>
<string name="auto_updates_dialog_description">Do you want ReVanced Manager to periodically check for updates for the following components?</string>
<string name="auto_updates_dialog_manager">ReVanced Manager</string>
<string name="auto_updates_dialog_patches">ReVanced Patches</string>
<string name="auto_updates_dialog_note">These settings can be changed later.</string>
<string name="general">General</string>
<string name="general_description">Appearances, Updates</string>
<string name="general_description">Theme, dynamic color</string>
<string name="updates">Updates</string>
<string name="updates_description">Check for updates and view changelogs</string>
<string name="extensions">Extensions</string>
<string name="extensions_description">Downloader plugins, downloaded apps</string>
<string name="backup_restore">Backup &amp; Restore</string>
<string name="backup_restore_description">Keystore, Patch selections, Patch options</string>
<string name="downloads">Downloads</string>
<string name="downloads_description">Downloader plugins and downloaded apps</string>
<string name="import_export">Import &amp; export</string>
<string name="import_export_description">Keystore, patch options and selection</string>
<string name="advanced">Advanced</string>
<string name="advanced_description">API Source, memory limits, debug logs</string>
<string name="experimental_features">Experimental features</string>
<string name="advanced_description">API URL, memory limit, debugging</string>
<string name="about">About</string>
<string name="opensource_licenses">Open source licenses</string>
<string name="opensource_licenses_description">View all the libraries used to make this
application</string>
<string name="opensource_licenses_description">View all the libraries used to make this application</string>
<string name="contributors">Contributors</string>
<string name="contributors_description">View the contributors of ReVanced</string>
<string name="personalized_color">Personalized color</string>
<string name="personalized_color_description">Use color provided by your device\'s palette</string>
<string name="theme_mode">Theme mode</string>
<string name="theme_mode_description">Choose between light, dark, and system provided mode</string>
<string name="dynamic_color">Dynamic color</string>
<string name="dynamic_color_description">Adapt colors to the wallpaper</string>
<string name="theme">Theme</string>
<string name="theme_description">Choose between light or dark theme</string>
<string name="safeguards">Safeguards</string>
<string name="allow_compatibility_mixing">Allow unsupported compatibility</string>
<string name="allow_compatibility_mixing_description">Permit apps and patches to be mixed in
unsupported state</string>
<string name="allow_compatibility_mixing_confirmation">Selecting incompatible patches can result
in a broken app.\n\nAllow anyways?</string>
<string name="patch_compat_check">Disable version compatibility check</string>
<string name="patch_compat_check_description">The check restricts patches to supported app versions</string>
<string name="patch_compat_check_confirmation">Selecting incompatible patches can result in a broken app.\n\nDo you want to proceed anyways?</string>
<string name="suggested_version_safeguard">Require suggested app version</string>
<string name="suggested_version_safeguard_description">Enforce selection of the suggested app version</string>
<string name="suggested_version_safeguard_confirmation">Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?</string>
<string name="patch_selection_safeguard">Allow changing patch selection</string>
<string name="patch_selection_safeguard_description">Permit selecting or deselecting patches
from default</string>
<string name="patch_selection_safeguard_confirmation">Changing the selection of patches may
cause unexpected issues.\n\nAllow anyways?</string>
<string name="universal_patches_safeguard">Allow universal patch</string>
<string name="universal_patches_safeguard_description">Permit selecting app\'s generic patch</string>
<string name="universal_patches_safeguard_confirmation">Universal patch are not as well tested
as those that target specific apps.\n\nAllow anyways?</string>
<string name="backup">Backup</string>
<string name="restore">Restore</string>
<string name="keystore">Keystore</string>
<string name="patch_selection">Patch selection</string>
<string name="patch_options">Patch options</string>
<string name="restore_keystore_description">Restore keystore from external source</string>
<string name="restore_keystore_dialog_title">Enter keystore credentials</string>
<string name="restore_keystore_dialog_description">You\'ll need enter the keystores credentials
to restore it.</string>
<string name="restore_keystore_dialog_alias_field">Username (Alias)</string>
<string name="restore_keystore_dialog_password_field">Password</string>
<string name="restore_keystore_dialog_button">Import</string>
<string name="restore_keystore_wrong_credentials">Wrong keystore credentials</string>
<string name="restore_keystore_success">Keystore successfully restored</string>
<string name="backup_keystore_description">Export apps keystore into usable file</string>
<string name="backup_keystore_unavailable">No keystore to backup</string>
<string name="backup_keystore_success">Keystore successfully backed up</string>
<string name="regenerate_keystore">Regeneration</string>
<string name="regenerate_keystore_description">Replace current keystore with new one</string>
<string name="patch_selection_safeguard_description">Do not prevent selecting or deselecting patches</string>
<string name="patch_selection_safeguard_confirmation">Changing the selection of patches may cause unexpected issues.\n\nEnable anyways?</string>
<string name="universal_patches_safeguard">Disable universal patch warning</string>
<string name="universal_patches_safeguard_description">Disables the warning that appears when you try to select universal patches</string>
<string name="universal_patches_safeguard_confirmation">Universal patches are not as well tested as those that target specific apps.\n\nEnable anyways?</string>
<string name="import_keystore">Import keystore</string>
<string name="import_keystore_description">Import a custom keystore</string>
<string name="import_keystore_dialog_title">Enter keystore credentials</string>
<string name="import_keystore_dialog_description">You\'ll need enter the keystores credentials to import it.</string>
<string name="import_keystore_dialog_alias_field">Username (Alias)</string>
<string name="import_keystore_dialog_password_field">Password</string>
<string name="import_keystore_dialog_button">Import</string>
<string name="import_keystore_wrong_credentials">Wrong keystore credentials</string>
<string name="import_keystore_success">Imported keystore</string>
<string name="export_keystore">Export keystore</string>
<string name="export_keystore_description">Export the current keystore</string>
<string name="export_keystore_unavailable">No keystore to export</string>
<string name="export_keystore_success">Exported keystore</string>
<string name="regenerate_keystore">Regenerate keystore</string>
<string name="regenerate_keystore_description">Generate a new keystore</string>
<string name="regenerate_keystore_success">The keystore has been successfully replaced</string>
<string name="restore_patch_selection_description">Export apps patch selections into usable
file</string>
<string name="restore_patch_selection_fail">Could not import patch selection: %s</string>
<string name="restore_patch_selection_success">Patch selection successfully restored</string>
<string name="backup_patch_selection_description">Import apps patch selections from external
source</string>
<string name="backup_patch_selection_fail">Could not backup patch selection: %s</string>
<string name="backup_patch_selection_success">Patch selection successfully restored</string>
<string name="import_patch_selection">Import patch selection</string>
<string name="import_patch_selection_description">Import patch selection from a JSON file</string>
<string name="import_patch_selection_fail">Could not import patch selection: %s</string>
<string name="import_patch_selection_success">Imported patch selection</string>
<string name="export_patch_selection">Export patch selection</string>
<string name="export_patch_selection_description">Export patch selection to a JSON file</string>
<string name="export_patch_selection_fail">Could not export patch selection: %s</string>
<string name="export_patch_selection_success">Exported patch selection</string>
<string name="reset_patch_selection">Reset patch selection</string>
<string name="reset_patch_selection_description">Reset the stored patch selection</string>
<string name="reset_patch_selection_success">Patch selection successfully reset</string>
<string name="patch_options_reset_package">Reset for app</string>
<string name="patch_options_reset_package_description">Use the default patch options
configuration for a single app</string>
<string name="patch_options_reset_bundle">Reset for bundle</string>
<string name="patch_options_reset_bundle_description">Use the default patch options
configuration for all patches in a bundle</string>
<string name="patch_options_reset_all_description">Use the default patch options configuration</string>
<string name="reset_patch_selection_success">Patch selection has been reset</string>
<string name="patch_options_reset_package">Reset patch options for app</string>
<string name="patch_options_reset_package_description">Resets patch options for a single app</string>
<string name="patch_options_reset_bundle">Resets patch options for bundle</string>
<string name="patch_options_reset_bundle_description">Resets patch options for all patches in a bundle</string>
<string name="patch_options_reset_all">Reset patch options</string>
<string name="patch_options_reset_all_description">Resets all patch options</string>
<string name="downloader_plugins">Plugins</string>
<string name="downloader_plugin_state_trusted">Trusted</string>
<string name="downloader_plugin_state_failed">Failed to load. Click for more details</string>
@ -194,25 +170,21 @@
<string name="dark">Dark</string>
<string name="appearance">Appearance</string>
<string name="downloaded_apps">Downloaded apps</string>
<string name="process_runtime">Run patcher in another process</string>
<string name="process_runtime_description">Faster and allows patcher to use more memory</string>
<string name="process_runtime">Run Patcher in another process (experimental)</string>
<string name="process_runtime_description">This is faster and allows Patcher to use more memory.</string>
<string name="process_runtime_memory_limit">Patcher process memory limit</string>
<string name="process_runtime_memory_limit_description">The max amount of memory that the
patcher process can use (in megabytes)</string>
<string name="process_runtime_memory_limit_description">The max amount of memory that the Patcher process can use (in megabytes)</string>
<string name="debug_logs_export">Export debug logs</string>
<string name="debug_logs_export_read_failed">Failed to read logs (exit code %d)</string>
<string name="debug_logs_export_failed">Failed to export logs</string>
<string name="debug_logs_export_success">Exported logs</string>
<string name="api_url">API Source</string>
<string name="api_url_dialog_title">Set custom API Source</string>
<string name="api_url_dialog_description">Set the API Source of ReVanced Manager. ReVanced
Manager uses the API to download patches and updates.</string>
<string name="api_url_dialog_warning">ReVanced Manager connects to the API to download patches
and updates. Make sure that you trust it.</string>
<string name="api_url">API URL</string>
<string name="api_url_description">The API used to download necessary files.</string>
<string name="api_url_dialog_title">Set custom API URL</string>
<string name="api_url_dialog_description">Set the API URL of ReVanced Manager. ReVanced Manager uses the API to download patches and updates.</string>
<string name="api_url_dialog_warning">ReVanced Manager connects to the API to download patches and updates. Make sure that you trust it.</string>
<string name="api_url_dialog_save">Set</string>
<string name="api_url_dialog_reset">Reset API Source</string>
<string name="testing">Testing</string>
<string name="disable_safeguard">Disable all safeguards</string>
<string name="api_url_dialog_reset">Reset API URL</string>
<string name="device">Device</string>
<string name="device_android_version">Android version</string>
<string name="device_model">Model</string>
@ -241,32 +213,22 @@
<string name="bundles_selected">%s selected</string>
<string name="unsupported_patches">Incompatible patches</string>
<string name="universal_patches">Universal patches</string>
<string name="patch_selection_reset_toast">Patch selection and options has been reset to
recommended defaults</string>
<string name="patch_selection_reset_toast">Patch selection and options has been reset to recommended defaults</string>
<string name="patch_options_reset_toast">Patch options have been reset</string>
<string name="non_suggested_version_warning_title">Non suggested version</string>
<string name="non_suggested_version_warning_description">The version of the app you have
selected does not match the suggested version.\nPlease use the suggested version: %s\n\nTo
continue anyway, disable \"Require suggested app version\" in the advanced settings.</string>
<string name="non_suggested_version_warning_description">The version of the app you have selected does not match the suggested version.\nPlease use the suggested version: %s\n\nTo continue anyway, disable \"Require suggested app version\" in the advanced settings.</string>
<string name="selection_warning_title">Stop using defaults?</string>
<string name="selection_warning_description">It is recommended to use the default patch
selection and options. Changing them may result in unexpected issues.\n\nYou need to turn on
\"Allow changing patch selection\" in the advanced settings before toggling patches.</string>
<string name="universal_patch_warning_description">Universal patches have a more generalized use
and do not work as reliably as patches that target specific apps. You may encounter issues
while using them.\n\nThis warning can be disabled in the advanced settings.</string>
<string name="selection_warning_description">It is recommended to use the default patch selection and options. Changing them may result in unexpected issues.\n\nYou need to turn on \"Allow changing patch selection\" in the advanced settings before toggling patches.</string>
<string name="universal_patch_warning_description">Universal patches have a more generalized use and do not work as reliably as patches that target specific apps. You may encounter issues while using them.\n\nThis warning can be disabled in the advanced settings.</string>
<string name="supported">This version</string>
<string name="universal">Any app</string>
<string name="unsupported">Unsupported</string>
<string name="search_patches">Search patches</string>
<string name="app_not_supported">This patch is not compatible with the selected app version
(%1$s).\n\nIt only supports the following version(s): %2$s.</string>
<string name="app_not_supported">This patch is not compatible with the selected app version (%1$s).\n\nIt only supports the following version(s): %2$s.</string>
<string name="continue_with_version">Continue with this version?</string>
<string name="version_not_supported">Not all patches support this version (%s). Do you want to
continue anyway?</string>
<string name="version_not_supported">Not all patches support this version (%s). Do you want to continue anyway?</string>
<string name="download_application">Download application?</string>
<string name="app_not_installed">The app you selected isn\'t installed. Do you want to download
it?</string>
<string name="app_not_installed">The app you selected isn\'t installed. Do you want to download it?</string>
<string name="failed_to_load_apk">Failed to load APK</string>
<string name="loading">Loading…</string>
<string name="not_installed">Not installed</string>
@ -296,8 +258,7 @@
<string name="downloader_app_not_found">Downloader did not find the app</string>
<string name="downloader_error">Downloader error: %s</string>
<string name="downloader_no_plugins_installed">No plugins installed.</string>
<string name="downloader_no_plugins_available">No trusted plugins available for use. Check your
settings.</string>
<string name="downloader_no_plugins_available">No trusted plugins available for use. Check your settings.</string>
<string name="already_patched">Already patched</string>
<string name="patch_selector_sheet_filter_title">Filter</string>
@ -325,8 +286,7 @@
<string name="save_apk_success">APK Saved</string>
<string name="sign_fail">Failed to sign APK: %s</string>
<string name="save_logs">Save logs</string>
<string name="plugin_activity_dialog_body">User interaction is required in order to proceed with
this plugin.</string>
<string name="plugin_activity_dialog_body">User interaction is required in order to proceed with this plugin.</string>
<string name="select_install_type">Select installation type</string>
<string name="patcher_step_group_preparing">Preparing</string>
@ -368,33 +328,28 @@
<string name="bundle_update_success">Successfully updated %s</string>
<string name="bundle_update_unavailable">No update available for %s</string>
<string name="bundle_auto_update">Auto update</string>
<string name="bundle_auto_update_description">Automatically update this bundle when ReVanced
starts</string>
<string name="bundle_auto_update_description">Automatically update this bundle when ReVanced starts</string>
<string name="bundle_view_patches">View patches</string>
<string name="bundle_view_patches_any_version">Any version</string>
<string name="bundle_view_patches_any_package">Any package</string>
<string name="about_revanced_manager">About ReVanced Manager</string>
<string name="revanced_manager_description">ReVanced Manager is an application designed to work
with ReVanced Patcher, which allows for long-lasting patches to be created for Android apps.
The patching system is designed to automatically work with new versions of apps with minimal
maintenance.</string>
<string name="revanced_manager_description">ReVanced Manager is an application designed to work with ReVanced Patcher, which allows for long-lasting patches to be created for Android apps. The patching system is designed to automatically work with new versions of apps with minimal maintenance.</string>
<string name="update_available">An update is available</string>
<string name="current_version">Current version: %s</string>
<string name="new_version">New version: %s</string>
<string name="ready_to_install_update">Ready to install update</string>
<string name="update_completed">Update installed</string>
<string name="install_update_manager_failed">Failed to install update</string>
<string name="check_for_update">Check for update</string>
<string name="check_for_update_auto_description">Automatically check for new version when the
app launched</string>
<string name="manual_update_check">Check for updates</string>
<string name="manual_update_check_description">Manually check for updates</string>
<string name="update_checking_manager">Auto check for updates</string>
<string name="update_checking_manager_description">Check for new versions of ReVanced Manager when the application starts</string>
<string name="changelog">View changelogs</string>
<string name="changelog_loading">Loading changelog</string>
<string name="changelog_download_fail">Failed to download changelog: %s</string>
<string name="changelog_description">Check out the latest changes in this update</string>
<string name="battery_optimization_notification">Battery optimizations must be turned off in
order for ReVanced Manager to work correctly in the background. Click here to turn off
optimizations.</string>
<string name="battery_optimization_notification">Battery optimizations must be turned off in order for ReVanced Manager to work correctly in the background. Click here to turn off optimizations.</string>
<string name="installing_manager_update">Installing update…</string>
<string name="downloading_manager_update">Downloading update…</string>
<string name="download_manager_failed">Failed to download update: %s</string>
@ -403,8 +358,7 @@
<string name="save_with_count">Save (%1$s)</string>
<string name="update">Update</string>
<string name="empty">Empty</string>
<string name="installing_message">Tap on <b>Update</b> when prompted. \n ReVanced Manager will
close when updating.</string>
<string name="installing_message">Tap on <b>Update</b> when prompted. \n ReVanced Manager will close when updating.</string>
<string name="no_changelogs_found">No changelogs found</string>
<string name="just_now">Just now</string>
<string name="minutes_ago">%sm ago</string>
@ -420,22 +374,18 @@
<string name="no_update_available">No update available</string>
<string name="update_check">Checking for updates…</string>
<string name="dismiss_temporary">Not now</string>
<string name="update_available_dialog_description">A new version of ReVanced Manager (%s) is
available.</string>
<string name="update_available_dialog_description">A new version of ReVanced Manager (%s) is available.</string>
<string name="failed_to_download_update">Failed to download update: %s</string>
<string name="download">Download</string>
<string name="download_confirmation_metered">You are currently on a metered connection, and data
charges from your service provider may apply.\n\nDo you still want to continue?</string>
<string name="download_confirmation_metered">You are currently on a metered connection, and data charges from your service provider may apply.\n\nDo you still want to continue?</string>
<string name="download_update_confirmation">Download update?</string>
<string name="no_contributors_found">No contributors found</string>
<string name="select">Select</string>
<string name="select_deselect_all">Select or deselect all</string>
<string name="select_bundle_type_dialog_title">Add new bundle</string>
<string name="select_bundle_type_dialog_description">Add a new bundle from a URL or storage</string>
<string name="local_bundle_description">Import local files from your storage, does not
automatically update</string>
<string name="remote_bundle_description">Import remote files from a URL, can automatically
update</string>
<string name="local_bundle_description">Import local files from your storage, does not automatically update</string>
<string name="remote_bundle_description">Import remote files from a URL, can automatically update</string>
<string name="recommended">Recommended</string>
<string name="installation_failed_dialog_title">Installation failed</string>
@ -446,20 +396,13 @@
<string name="installation_invalid_dialog_title">Installation invalid</string>
<string name="installation_storage_issue_dialog_title">Not enough storage</string>
<string name="installation_timeout_dialog_title">Installation timed out</string>
<string name="installation_failed_description">The installation failed due to an unknown reason.
Try again?</string>
<string name="installation_aborted_description">The installation was cancelled manually. Try
again?</string>
<string name="installation_blocked_description">The installation was blocked. Review your device
security settings and try again.</string>
<string name="installation_conflict_description">The installation was prevented by an existing
installation of the app. Uninstall the installed app and try again?</string>
<string name="installation_incompatible_description">The app is incompatible with this device.
Use an APK that is supported by this device and try again.</string>
<string name="installation_invalid_description">The app is invalid. Uninstall the app and try
again?</string>
<string name="installation_storage_issue_description">The app could not be installed due to
insufficient storage. Free up some space and try again.</string>
<string name="installation_failed_description">The installation failed due to an unknown reason. Try again?</string>
<string name="installation_aborted_description">The installation was cancelled manually. Try again?</string>
<string name="installation_blocked_description">The installation was blocked. Review your device security settings and try again.</string>
<string name="installation_conflict_description">The installation was prevented by an existing installation of the app. Uninstall the installed app and try again?</string>
<string name="installation_incompatible_description">The app is incompatible with this device. Use an APK that is supported by this device and try again.</string>
<string name="installation_invalid_description">The app is invalid. Uninstall the app and try again?</string>
<string name="installation_storage_issue_description">The app could not be installed due to insufficient storage. Free up some space and try again.</string>
<string name="installation_timeout_description">The installation took too long. Try again?</string>
<string name="reinstall">Reinstall</string>
<string name="show">Show</string>
@ -470,14 +413,10 @@
<string name="add_patch_bundle">Add patch bundle</string>
<string name="bundle_url">Bundle URL</string>
<string name="auto_update">Auto update</string>
<string name="unsupported_patches_dialog">These patches are not compatible with the selected app
version (%1$s).\n\nClick on the patches to see more details.</string>
<string name="unsupported_patches_dialog">These patches are not compatible with the selected app version (%1$s).\n\nClick on the patches to see more details.</string>
<string name="unsupported_patch">Unsupported patch</string>
<string name="any_version">Any</string>
<string name="never_show_again">Never show again</string>
<string name="show_manager_update_dialog_on_launch">Show update message on launch</string>
<string name="show_manager_update_dialog_on_launch_description">Shows a popup notification
whenever there is a new update available on launch.</string>
<string name="failed_to_import_keystore">Failed to import keystore</string>
<string name="export">Export</string>
</resources>
<string name="show_manager_update_dialog_on_launch_description">Shows a popup notification whenever there is a new update available on launch.</string>
</resources>

View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -1,10 +1,11 @@
# 💼 Prerequisites
In order to use ReVanced Manager, certain requirements must be met.
To use ReVanced Manager, certain requirements have to be met.
## 🤝 Requirements
- An Android device running Android 8 or higher
- Android device running Android 8.0 or higher
- **Optionally** Rooted Android device with latest version of [KernelSU](https://github.com/tiann/KernelSU) or [Magisk](https://github.com/topjohnwu/Magisk)
## ⏭️ What's next

View File

@ -1,14 +1,26 @@
# ⬇️ Installation
In order to use ReVanced on your Android device, ReVanced Manager must be installed.
To use ReVanced on your Android device, ReVanced Manager have to be install,
refer to the [Prerequisites](0_prerequisites.md) if haven't already.
## Installation steps
## 🪜 Installation steps
1. Download the latest version of ReVanced Manager from [here](https://github.com/revanced/revanced-manager/releases/latest)
1. Get the latest version of ReVanced Manager from the [ReVanced site][Official ReVanced Download].
2. Install ReVanced Manager
### ✒️ Verifying authenticity of ReVanced Manager
> [!NOTE]
> It's always advisable that you download from trusted sources like the [ReVanced site][Official ReVanced Download]
> or GitHub releases as it's the safest way to download ReVanced without potential risk of malware.
To verify if your ReVanced Manager is provided without sign of tampering,
we have signed the APK with hashes corresponding to `b6362c6ea7888efd15c0800f480786ad0f5b133b4f84e12d46afba5f9eac1223` *unless otherwise stated*.
## ⏭️ What's next
The next page will guide you through using ReVanced Manager.
Continue: [🛠️ Usage](2_usage.md)
[Official ReVanced Download]: https://revanced.app/download

View File

@ -8,16 +8,26 @@ The following pages will guide you through using ReVanced Manager to patch apps.
2. Tap the + button in the bottom right corner
3. Choose an app to patch[^1]
4. Tap on the version of the app you want to patch[^2]
5. Select the patches you want to apply
6. Tap the Patch button
7. Tap on the **Install** button
> **Note**: If you are rooted, you can mount the patched app on top of the original app.[^3]
> Optionally, you may export the patched app to storage using the options in the top right corner.
5. Tap the 🪄 **Patch** button
6. Tap on the 📲 **Install** button
> [!Note]
> If the **Install** Button isn't there, it could be that something went wrong. Refer to [3. ❔ Troubleshooting](3_troubleshooting.md)
> [!Tip]
> If you are rooted, you can mount the patched app on top of the original app.[^3]
> Optionally, you may export the patched app to storage using the options in the bottom left corner.
[^1]: Non-root users may be prompted to select an APK from storage, in which case you have to source the APK file yourself. ReVanced does not provide any APK files.
[^1]: You need to select an APK from storage, in which case you have to source the APK file yourself. ReVanced does not provide any APK files.
[^2]: It is suggested to use the version with the most patches to get the most out of ReVanced.
[^3]: Mounting the patched app on top of the original app will only work if the installed app version matches the version of the app selected in step 4. above.
### Change patch selection and options
Before you can change the selection of patches, follow the step below to allow changing the selection of patches.
1. Tap ⚙️ Settings button in the top right corner
2. Go to Advanced Settings
3. Toggle "Allow changing patch selection" on
## ⏭️ What's next
The next page will bring you back to the usage page.

View File

@ -6,10 +6,13 @@ After patching an app, you may want to manage it. This page will guide you throu
1. Navigate to the Apps tab from the top navigation bar
2. Select the app you want to manage
3.
Inside you will be able to open, and uninstall the app within the manager,
additionally you will be able to repatch the app by patching the app again, see [🧩 Patching apps](2_1_patching.md),
and view all patches applied to the patched app.
## ⏭️ What's next
The next page will bring you back to the usage page.
Continue: [🛠️ Usage](2_usage.md)

View File

@ -4,7 +4,25 @@ In order to keep up with the latest features and bug fixes, it is recommended to
## ✅ Updating steps
> Currently not implemented
1. Tap the ↻ Update button in the top right corner right next to the ⚙️ Settings icon
2. Tap the **Update** button in the bottom right corner
3. Wait for the update to be downloaded
4. Tap the **Install** button to install[^1]
> [!Note]
> If you see a prompt regarding your device is unable to install application for security reason
> you may need to allow ReVanced Manager to install APK file on your device.
> 1. Tap on Settings
> 2. Toggle "Allow from this source" on
5. Wait for installation prompt to show then tap **Install** again
6. Open ReVanced Manager again to see the new version
## 🔎 Check for update
Usually ReVanced Manager always check update on first startup, so it's not need to manually check for update yourself.
To trigger the check for update function follow the step bellow:
1. Go to ⚙️ Settings menu and ↻ Update section
2. Tap on "Check for updates"
## ⏭️ What's next

View File

@ -8,30 +8,44 @@ ReVanced Manager has settings that can be configured to your liking.
Specify the URL of the API to use. This is used to fetch ReVanced Patches and update ReVanced Manager.
Location: `⚙️ Settings -> Advanced -> API URL`
- ### 🧬 Sources
Override the API and change the source of ReVanced Patches.
- ### 🧪 Experimental ReVanced Patches support
Location: `Patch bundles -> + Button`
- ### 🧪 Experimental patches
Lift app version constraints from ReVanced Patches. This allows you to patch any version of an app, even if the patch is not explicitly compatible with it.
Location: `⚙️ Settings -> Advanced -> Safeguards`
- ### 🧑‍🔬 Experimental universal support
This will show or hide ReVanced Patches, which are not meant for any app in particular but rather for all apps but may not work on all apps.
Location: `⚙️ Settings -> Advanced -> Safeguards`
- ### 🔑 Export, import or delete keystore
Manage the keystore used to sign patched apps.
- ### 📄 Export, import or reset ReVanced Patches selection
Location: `⚙️ Settings -> Import & export -> Signing`
Manage the ReVanced Patches selection. This is useful if you want to share your ReVanced Patches selection with others or reset it to the default selection.
- ### 📄 Export, import or reset patch selection
Manage the ReVanced Patches selection. This is useful if you want to share your patch selection with others or reset it to the default selection.
Location: `⚙️ Settings -> Import & export -> Patches`
- ### About
View information about your device and ReVanced Manager. This includes the version of ReVanced Manager and supported architectures of your device.
Location: `⚙️ Settings -> About`
## ⏭️ What's next
The next page will bring you back to the usage page.

View File

@ -10,11 +10,19 @@ In case you encounter any issues while using ReVanced Manager, please refer to t
An existing installation of the app you're trying to patch is conflicting with the patched app. Uninstall the existing app before installing the patched app.
- 🥛 Out Of Memory error
This indicates that your device is not giving ReVanced Manager enough memory to patch the app.
Turning on `⚙️ Settings -> Advanced -> toggle "Run Patcher in another process (experimental)"` may solve the issue.
- ❗️ Error code `135`, `139` or `1` when patching the app
Your device is not supported. Refer to the [Prerequisites](0_prerequisites.md) page for supported devices.
Alternatively, you can use [ReVanced CLI](https://github.com/revanced/revanced-cli) to patch the app.
Alternatively, you can use [ReVanced CLI][ReVanced CLI GitHub]) to patch the app.
[ReVanced CLI GitHub]: https://github.com/revanced/revanced-cli
- 🚫 Non-root install is not possible with the current patches selection
@ -22,10 +30,14 @@ In case you encounter any issues while using ReVanced Manager, please refer to t
- 🚨 Patched app crashes on launch
Select the **Default** button when choosing patches.
Try selecting the **Default** button when choosing patches, if the patched app still failed, file an issue at [ReVanced Patches][ReVanced Patches GitHub].
[ReVanced Patches GitHub]: https://github.com/revanced/revanced-patches
## ⏭️ What's next
The next page will teach you how to build ReVanced Manager from source.
You have successfully finished the guide for on how to use ReVanced Manager.
Continue: [🔨 Building from source](4_building.md)
If you wish to review the Table of Content for how to use ReVanced Manager, feel free to do so.
Continue: [💊 ReVanced Manager](/docs/README.md)

View File

@ -1,38 +0,0 @@
# 🛠️ Building from source
This page will guide you through building ReVanced Manager from source.
1. Download Java SDK 17 ([Azul JDK](https://www.azul.com/downloads/?version=java-17-lts&package=jdk#zulu) or [OpenJDK](https://jdk.java.net/java-se-ri/17)) and add it to path
2. Clone the repository
```sh
git clone https://github.com/revanced/revanced-manager.git && cd revanced-manager
```
3. Create a GitHub personal access token with the `read:packages` scope [here](https://github.com/settings/tokens/new?scopes=read:packages&description=ReVanced)
4. Add your GitHub username and the token to `~/.gradle/gradle.properties`
```properties
gpr.user = YourUsername
gpr.key = ghp_longrandomkey
```
5. Set the `sdk.dir` property in `local.properties` to your Android SDK location
```properties
sdk.dir = /path/to/android/sdk
```
6. Build the APK
Debug:
```sh
./gradlew assembleDebug
```
Release:
```sh
./gradlew assembleRelease -Psign
```

View File

@ -1,6 +1,6 @@
# 💊 ReVanced Manager
This documentation explains how to use [ReVanced Manager](https://github.com/revanced/revanced-manager).
This documentation explains how to use [ReVanced Manager](https://github.com/ReVanced/revanced-manager).
## 📖 Table of contents
@ -12,7 +12,10 @@ This documentation explains how to use [ReVanced Manager](https://github.com/rev
3. [🔄 Updating ReVanced Manager](2_3_updating.md)
4. [⚙️ Configuring ReVanced Manager](2_4_settings.md)
3. [❔ Troubleshooting](3_troubleshooting.md)
4. [🔨 Building from source](4_building.md)
## 🧑‍💻 Developing for ReVanced Manager
Checkout the documentation for developer [here](developer/README.md).
## ⏭️ Start here

View File

@ -0,0 +1,28 @@
# 💼 Prerequisites
Here's everything you'll need to develop on ReVanced Manager
## 🤝 Recommended environment
- Any environment that is capable of running the latest Android Studio, latest Android SDK, and JDK 17 with at least 4 GB of memory for coding
- Any devices with preferably the latest Android version or at least higher than the [`minSdk`](/app/build.gradle.kts) for testing
- **Optionally** A device with root capabilities using the latest version of [KernelSU](https://github.com/tiann/KernelSU) or [Magisk](https://github.com/topjohnwu/Magisk)
## ⚙️ Setting up
### Authenticating to GitHub Registry
ReVanced Manager use dependency from the GitHub Registry (i.e., [ReVanced Patcher](https://github.com/ReVanced/revanced-patcher/packages)) and so your build may fail without authenticating to the service,
to authenticate you must create a personal access token with the scope `read:packages` [here](https://github.com/settings/tokens/new?scopes=read:packages&description=ReVanced)
and add your token to `~/.gradle/gradle.properties`, create the file if it does not exist.
```properties
gpr.user = username
gpr.key = ghp_******************************
```
## ⏭️ What's next
The next page will guide you through developing for ReVanced Manager.
Continue: [🧑‍💻 Developing for ReVanced Manager](1_develop.md)

View File

@ -0,0 +1,25 @@
# 🧑‍💻 Developing for ReVanced Manager
ReVanced Manager is developed on Kotlin using [Jetpack Compose](https://developer.android.com/compose), here are some tips to help you get started.
## Code style
The styling is based on https://kotlinlang.org/docs/coding-conventions.html
## Commit
At ReVanced, we adopt a naming convention for commit called [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) so for example when you're adding a new feature you must add `feat: ` before the description of your commit.
## Building
To build ReVanced Manager, simply hit build button on your IDE or run:
```sh
./gradlew assembleDebug
```
## ⏭️ What's next
The next page will guide you through developing for ReVanced Manager.
Continue: [🎉 Submitting your Pull Request](2_submitting.md)

View File

@ -0,0 +1,21 @@
# 🎉 Submitting your Pull Request
> [!TIP]
> We recommend that you discuss your changes with
> the maintainers of ReVanced Manager before contributing.
> This will help you determine whether your change is acceptable.
1. Fork the repository and create your branch from `dev`
2. Commit your changes in [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) style
3. 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
4. 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
## ⏭️ What's next
You have successfully finished the guide for developing for ReVanced Manager.
This next section will be verifying the authenticity of ReVanced Manager
which may be relevant for store provider or those who's looking to verify prebuilt librar(ies).
Continue: [✒️ Verification and Authenticity of ReVanced Manager](3_verifying.md)

View File

@ -0,0 +1,19 @@
# ✒️ Verification and Authenticity of ReVanced Manager
> [!NOTE]
> This information is more relevant to alternative store providers
To distribute ReVanced Manager safely and recommended way is to provide the users with a link to
[1. ⬇️ Installation, ✒️ Verifying authenticity of ReVanced Manager (user-side)][installation authenticity].
The certificate SHA-256 of the APK will always be `b6362c6ea7888efd15c0800f480786ad0f5b133b4f84e12d46afba5f9eac1223` unless otherwise noted.
[installation authenticity]: /docs/1_installation.md#%EF%B8%8F-verifying-authenticity-of-revanced-manager
## `libaapt2.so`
ReVanced Manager includes prebuilt binaries of [`libaapt2.so`][location of libaapt2.so] from https://github.com/ReVanced/aapt2
which fixes issues on ARM32-based systems. Attestation is provided here: https://github.com/ReVanced/aapt2/attestations
[location of libaapt2.so]: /app/src/main/jniLibs/

25
docs/developer/README.md Normal file
View File

@ -0,0 +1,25 @@
# 💊 ReVanced Manager
> [!WARNING]
> This guide is for people who want to develop for ReVanced Manager, may feature technical words or jargons.
> For regular user you may want to view this [documentation](/docs/README.md) instead.
This documentation explains how to develop for [ReVanced Manager](https://github.com/ReVanced/revanced-manager).
## 📖 Table of contents
## Developing
0. [💼 Prerequisites](0_prerequisites.md)
1. [🧑‍💻 Developing for ReVanced Manager](1_developing.md)
2. [🎉 Submitting your Pull Request](2_submitting.md)
## Transparency
1. [✒️ Verification and Authenticity of ReVanced Manager](3_verifying.md)
## ⏭️ Start here
The next page will tell you about the prerequisites for developing for ReVanced Manager.
Continue: [💼 Prerequisites](0_prerequisites.md)

View File

@ -1,41 +1,41 @@
[versions]
ktx = "1.15.0"
material3 = "1.3.1"
ui-tooling = "1.7.7"
ui-tooling = "1.7.6"
viewmodel-lifecycle = "2.8.7"
splash-screen = "1.0.1"
activity = "1.10.0"
activity = "1.9.3"
appcompat = "1.7.0"
preferences-datastore = "1.1.2"
preferences-datastore = "1.1.1"
work-runtime = "2.10.0"
compose-bom = "2025.01.01"
navigation = "2.8.6"
accompanist = "0.37.0"
compose-bom = "2024.12.01"
navigation = "2.8.5"
accompanist = "0.34.0"
placeholder = "1.1.2"
reorderable = "2.4.3"
serialization = "1.8.0"
reorderable = "1.5.2"
serialization = "1.7.3"
collection = "0.3.8"
datetime = "0.6.1"
datetime = "0.6.0"
room-version = "2.6.1"
revanced-patcher = "21.0.0"
revanced-library = "3.0.2"
koin = "3.5.3"
ktor = "2.3.9"
markdown-renderer = "0.30.0"
markdown-renderer = "0.22.0"
fading-edges = "1.0.4"
kotlin = "2.1.10"
kotlin = "2.1.0"
android-gradle-plugin = "8.8.0"
dev-tools-gradle-plugin = "2.1.10-1.0.29"
about-libraries-gradle-plugin = "11.5.0"
dev-tools-gradle-plugin = "2.1.0-1.0.29"
about-libraries-gradle-plugin = "11.1.1"
binary-compatibility-validator = "0.17.0"
coil = "2.7.0"
coil = "2.6.0"
app-icon-loader-coil = "1.5.0"
skrapeit = "1.2.2"
libsu = "6.0.0"
libsu = "5.2.2"
scrollbars = "1.0.4"
enumutil = "1.1.1"
enumutil = "1.1.0"
compose-icons = "1.2.4"
kotlin-process = "1.5.1"
kotlin-process = "1.4.1"
hidden-api-stub = "4.3.3"
[libraries]

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=8d97a97984f6cbd2b85fe4c60a743440a347544bf18818048e611f5288d46c94
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
distributionSha256Sum=7a00d51fb93147819aab76024feece20b6b84e420694101f276be952e08bef03
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME