diff --git a/.github/ISSUE_TEMPLATE/feature-issue.yml b/.github/ISSUE_TEMPLATE/feature-issue.yml index fda70e87..3e50be3a 100644 --- a/.github/ISSUE_TEMPLATE/feature-issue.yml +++ b/.github/ISSUE_TEMPLATE/feature-issue.yml @@ -1,7 +1,7 @@ name: ⭐ Feature request description: Create a new feature request. title: 'feat: ' -labels: [feature-request] +labels: 'feature request' body: - type: markdown attributes: diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml index 8424eff4..993298dc 100644 --- a/.github/workflows/pr-build.yml +++ b/.github/workflows/pr-build.yml @@ -1,45 +1,121 @@ name: PR Build on: - pull_request: - paths: - - ".github/workflows/pr-build.yml" - - "android/**" - - "assets/**" - - "lib/**" - + workflow_dispatch: + inputs: + # Flutter + flutter-branch: + description: Flutter branch + type: choice + default: 'stable' + options: + - stable + - beta + - dev + - master + flutter-cache: + description: Cache + type: boolean + default: true + # Application configuration + app-flavour: + description: App flavour + default: 'release' + type: choice + options: + - release + - debug + - profile + # Pull Request + pr-number: + description: PR number (No hashtag) + required: true + +run-name: "Build PR ${{ inputs.pr-number }}" + jobs: build: - name: Build + name: Build the application runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write steps: + - name: Setup + env: + GH_TOKEN: ${{ github.token }} + run: | + gh repo clone ${{ github.repository }} + cd revanced-manager + gh repo set-default ${{ github.repository }} + gh pr checkout ${{ inputs.pr-number }} + + echo "DATETIME=$( TZ='UTC+0' date --rfc-email )" >> $GITHUB_ENV + echo "COMMIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + - name: Checkout uses: actions/checkout@v4 with: - # Make sure the release step uses its own credentials: - # https://github.com/cycjimmy/semantic-release-action#private-packages persist-credentials: false - fetch-depth: 0 + - name: Setup JDK uses: actions/setup-java@v3 with: java-version: '17' distribution: 'zulu' + cache: gradle + - name: Setup Flutter uses: subosito/flutter-action@v2 with: - channel: 'stable' - cache: true + channel: ${{ inputs.flutter-branch }} + cache: ${{ inputs.flutter-cache }} + - name: Install Flutter dependencies run: flutter pub get + - name: Generate files with Builder - run: flutter packages pub run build_runner build --delete-conflicting-outputs + run: dart run build_runner build --delete-conflicting-outputs + - name: Build with Flutter - env: + continue-on-error: true + id: flutter-build + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: flutter build apk --debug + run: | + flutter build apk --${{ inputs.app-flavour }}; + + - name: Prepare to comment + run: | + if [[ "${{ steps.flutter-build.outcome }}" == "success" ]]; then + echo "MESSAGE=✅ ReVanced Manager ${{ env.COMMIT_HASH }} build succeeded." >> $GITHUB_ENV + else + echo "MESSAGE=🚫 ReVanced Manager ${{ env.COMMIT_HASH }} build failed." >> $GITHUB_ENV + fi + + - name: "Comment to Pull Request #${{ inputs.pr-number }}" + uses: thollander/actions-comment-pull-request@v2 + with: + GITHUB_TOKEN: ${{ github.token }} + pr_number: ${{ inputs.pr-number }} + mode: recreate + message: | + ## ⚒️ ReVanced PR Build workflow + + ${{ env.MESSAGE }} + + You can see more details in run [${{ github.run_id }}](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})! + + ### ⚙️ Overview + - App flavor: ${{ inputs.app-flavour }} + - Branch: ${{ inputs.flutter-branch }} + - Start time: ${{ env.DATETIME }} + - name: Upload build uses: actions/upload-artifact@v3 with: - name: revanced-manager - path: build/app/outputs/flutter-apk/app-debug.apk + if-no-files-found: error + name: revanced-manager-(${{ env.COMMIT_HASH }}-${{ inputs.pr-number }}-${{ inputs.app-flavour }})-${{ inputs.flutter-branch }} + path: | + build/app/outputs/flutter-apk/app-${{ inputs.app-flavour }}.apk + build/app/outputs/flutter-apk/app-${{ inputs.app-flavour }}.apk.sha1 diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 94f2921d..d8f3d745 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -23,7 +23,7 @@ jobs: - name: Set up Flutter run: flutter pub get - name: Generate files with Builder - run: flutter packages pub run build_runner build --delete-conflicting-outputs + run: dart run build_runner build --delete-conflicting-outputs - name: Build with Flutter env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.run/main.dart.run.xml b/.run/main.dart.run.xml deleted file mode 100644 index 4767aff8..00000000 --- a/.run/main.dart.run.xml +++ /dev/null @@ -1,6 +0,0 @@ -<component name="ProjectRunConfigurationManager"> - <configuration default="false" name="main.dart" type="FlutterRunConfigurationType" factoryName="Flutter"> - <option name="filePath" value="$PROJECT_DIR$/lib/main.dart" /> - <method v="2" /> - </configuration> -</component> \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..d261a86a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,88 @@ +<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/"> + <img height="24px" src="assets/revanced-logo/revanced-logo-round.svg" /> + </a>    + <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>    + <a href="http://revanced.app/discord"> + <img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" /> + </a>    + <a href="https://reddit.com/r/revancedapp"> + <img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" /> + </a>    + <a href="https://t.me/app_revanced"> + <img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" /> + </a>    + <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>    + <a href="https://www.youtube.com/@ReVanced"> + <img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" /> + </a> + <br> + <br> + Continuing the legacy of Vanced +</p> + +# 👋 Contribution guidelines + +This document describes how to contribute to ReVanced Manager. + +## 📖 Resources to help you get started + +* The [documentation](/docs/README.md) provides steps to build ReVanced Manager from source +* Our [backlog](https://github.com/orgs/ReVanced/projects/12) is where we keep track of what we're working on +* [Issues](https://github.com/ReVanced/revanced-manager/issues) are where we keep track of bugs and feature requests + +## 🙏 Submitting a feature request + +Features can be requested by opening an issue using the +[feature request issue template](https://github.com/ReVanced/revanced-manager/issues/new?assignees=&labels=feature-request&projects=&template=feature-issue.yml&title=feat%3A+%3Ctitle%3E). + +> [!NOTE] +> We may reject your request at the discretion of ReVanced Manager's maintainers, +> please provide good motivation 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). + +## 📝 How to contribute + +> [!NOTE] +> 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 a new branch based off the `dev` branch +2. Commit your changes +3. Open a pull request to the `dev` branch and reference issues that your pull request closes +4. The maintainers of ReVanced Manager will review and provide suggestions. + Once your pull request is approved and merged, it will be included in the next release of ReVanced Manager + +## 🤚 I want to contribute but don't know how to code + +Even if you don't know how to code, you can still contribute by +translating ReVanced Manager on [Crowdin](https://translate.revanced.app/). + +❤️ Thank you for considering contributing to ReVanced Manager. diff --git a/README.md b/README.md index 89f41ea6..6db2ff9b 100644 --- a/README.md +++ b/README.md @@ -1,35 +1,97 @@ +<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-round.svg" /> + <img height="24px" src="assets/revanced-logo/revanced-logo-round.svg" /> + </picture> + </a>    + <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>    + <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>    + <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>    + <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>    + <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>    + <a href="https://www.youtube.com/@ReVanced"> + <picture> + <source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" /> + <img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" /> + </picture> + </a> + <br> + <br> + Continuing the legacy of Vanced +</p> + # 💊 ReVanced Manager -The official ReVanced Manager based on Flutter. +[![GitHub last commit](https://img.shields.io/github/last-commit/ReVanced/revanced-manager)](https://github.com/ReVanced/revanced-manager/commits "") +[![GitHub commit activity](https://img.shields.io/github/commit-activity/w/ReVanced/revanced-manager)](https://github.com/ReVanced/revanced-manager/commits "") + +ReVanced Manager is an Android application that uses ReVanced Patcher to add, remove, and modify existing functionalities in Android applications. + +## 💪 Features + +We provide the some of the features are: + +* 📱 **Portable**: ReVanced Patcher that fit in your pocket; +* 🤗 **Intuitive UI**: Help you manage your patched applications with easy-to-use interface; +* 🛠️ **Customization**: Patch with third-party sources; +* ✨ And a **lot 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 ReVanced Manager by downloading from [ReVanced site](https://revanced.app/download) or [GitHub releases](https://github.com/ReVanced/revanced-manager/releases). -## 📝 Prerequisites +## 📚 Everything else -1. Android 8 or higher -2. Incompatible with certain ARMv7 devices +### 📄 Documentation -## 📃 Documentation -The documentation can be found [here](https://github.com/revanced/revanced-manager/tree/main/docs). +Documentation on how to use the application is available [here](/docs/README.md). -## 🔴 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, you can find the contribution guidelines [here](/CONTRIBUTING.md). -## 🌐 Translation +### 🔴 Issues -[![Crowdin](https://badges.crowdin.net/revanced/localized.svg)](https://crowdin.com/project/revanced) +For suggestions and bug reports, open an issue [here](https://github.com/ReVanced/revanced-manager/issues/choose). -We're accepting translations on [Crowdin](https://translate.revanced.app). +## ⚖️ License -## 🛠️ Building Manager from source - -1. Setup flutter environment for your [platform](https://docs.flutter.dev/get-started/install) -2. Clone the repository locally -3. Add your GitHub token in gradle.properties like [this](/docs/4_building.md) -4. Open the project in terminal -5. Run `flutter pub get` in terminal -6. Then `flutter packages pub run build_runner build --delete-conflicting-outputs` (Must be done on each git pull) -7. To build release APK run `flutter build apk` +ReVanced Manager adopts the [GNU General Public License 3.0](/LICENSE), [tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3): You may copy, distribute and modify the software as long as you track changes/dates in source files. Any modifications to or software including (via compiler) GPL-licensed code must also be made available under the GPL along with build & install instructions. diff --git a/android/app/build.gradle b/android/app/build.gradle index ecf4135c..0b83c0af 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,3 +1,9 @@ +plugins { + id "com.android.application" + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -6,11 +12,6 @@ if (localPropertiesFile.exists()) { } } -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' @@ -21,10 +22,6 @@ if (flutterVersionName == null) { flutterVersionName = '1.0' } -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - android { compileSdk 34 ndkVersion flutter.ndkVersion @@ -66,6 +63,16 @@ android { abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64' } } + profile { + shrinkResources false + minifyEnabled false + resValue "string", "app_name", "ReVanced Manager Profile" + applicationIdSuffix ".profile" + signingConfig signingConfigs.debug + ndk { + abiFilters 'arm64-v8a', 'armeabi-v7a', 'x86_64' + } + } } packagingOptions { jniLibs { diff --git a/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt b/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt index a250ff1c..10ff238e 100644 --- a/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt +++ b/android/app/src/main/kotlin/app/revanced/manager/flutter/MainActivity.kt @@ -1,5 +1,7 @@ package app.revanced.manager.flutter +import android.app.SearchManager +import android.content.Intent import android.os.Handler import android.os.Looper import app.revanced.manager.flutter.utils.Aapt @@ -41,6 +43,17 @@ class MainActivity : FlutterActivity() { val patcherChannel = "app.revanced.manager.flutter/patcher" val installerChannel = "app.revanced.manager.flutter/installer" + val openBrowserChannel = "app.revanced.manager.flutter/browser" + + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, openBrowserChannel).setMethodCallHandler { call, result -> + if (call.method == "openBrowser") { + val searchQuery = call.argument<String>("query") + openBrowser(searchQuery) + result.success(null) + } else { + result.notImplemented() + } + } val mainChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, patcherChannel) @@ -176,6 +189,15 @@ class MainActivity : FlutterActivity() { } } + fun openBrowser(query: String?) { + val intent = Intent(Intent.ACTION_WEB_SEARCH).apply { + putExtra(SearchManager.QUERY, query) + } + if (intent.resolveActivity(packageManager) != null) { + startActivity(intent) + } + } + @OptIn(InternalCoroutinesApi::class) private fun runPatcher( result: MethodChannel.Result, diff --git a/android/build.gradle b/android/build.gradle index 0a04adab..29e96801 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -22,13 +22,14 @@ allprojects { } } -layout.buildDirectory.set(file("../build")) -var root = layout.buildDirectory.get().asFile.absolutePath +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} subprojects { - project.layout.buildDirectory.set(file("$root/${project.name}")) project.evaluationDependsOn(':app') } tasks.register("clean", Delete) { - delete layout.buildDirectory + delete rootProject.buildDir } diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 8bc9958a..744c64d1 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index 44e62bcf..55c4ca8b 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,11 +1,20 @@ -include ':app' +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() + includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle") -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + plugins { + id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false + } +} -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" +include ":app" + +apply from: "${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/assets/i18n/en_US.json b/assets/i18n/en_US.json index 86b27131..511cd9c4 100644 --- a/assets/i18n/en_US.json +++ b/assets/i18n/en_US.json @@ -111,6 +111,8 @@ "downloadToast": "Download function is not available yet", + "requireSuggestedAppVersionDialogText": "The version of the app you have selected does not match the suggested version. Please select the app that matches the suggested version.\n\nSelected version: v{selected}\nSuggested version: v{suggested}\n\nTo proceed anyway, disable \"Require suggested app version\" in the settings.", + "featureNotAvailable": "Feature not implemented", "featureNotAvailableText": "This application is a split APK and cannot be selected. Unfortunately, this feature is only available for rooted users at the moment. However, you can still install the application by selecting its APK files from your device's storage instead" }, @@ -234,8 +236,12 @@ "autoUpdatePatchesHint": "Automatically update patches to the latest version", "universalPatchesLabel": "Show universal patches", "universalPatchesHint": "Display all apps and universal patches (may slow down the app list)", + "versionCompatibilityCheckLabel": "Version compatibility check", "versionCompatibilityCheckHint": "Restricts patches to supported app versions", + "requireSuggestedAppVersionLabel": "Require suggested app version", + "requireSuggestedAppVersionHint": "Enforce selection of suggested app version", + "requireSuggestedAppVersionDialogText": "Selecting an app that is not the suggested version may cause unexpected issues.\n\nDo you want to proceed anyways?", "aboutLabel": "About", "snackbarMessage": "Copied to clipboard", diff --git a/assets/revanced-headline/revanced-headline-vertical-dark.svg b/assets/revanced-headline/revanced-headline-vertical-dark.svg new file mode 100644 index 00000000..a59bfb50 --- /dev/null +++ b/assets/revanced-headline/revanced-headline-vertical-dark.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 9600 7249" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><clipPath id="_clip1"><rect id="Wordmark" x="614.902" y="5329.15" width="8370.2" height="1304.34"/></clipPath><g clip-path="url(#_clip1)"><path id="Wordmark1" serif:id="Wordmark" d="M614.902,6604.05l-0,-1274.9l538.293,0c12.394,0 29.069,0.443 50.022,1.328c20.953,0.885 39.693,2.804 56.22,5.755c76.14,11.805 138.557,36.889 187.251,75.255c48.694,38.365 84.551,86.616 107.57,144.754c23.019,58.138 34.529,122.916 34.529,194.335c-0,106.832 -26.561,198.171 -79.682,274.016c-53.121,75.845 -136.344,122.621 -249.668,140.328l-106.242,7.082l-297.478,0l-0,432.051l-240.815,0Zm718.904,0l-251.439,-518.815l247.898,-47.809l276.229,566.624l-272.688,0Zm-478.089,-656.93l286.853,0c12.395,0 25.971,-0.59 40.726,-1.77c14.756,-1.181 28.332,-3.542 40.727,-7.083c32.462,-8.854 57.547,-23.757 75.254,-44.71c17.707,-20.954 29.955,-44.268 36.742,-69.943c6.788,-25.675 10.182,-50.022 10.182,-73.041c-0,-23.019 -3.394,-47.367 -10.182,-73.042c-6.787,-25.675 -19.035,-48.989 -36.742,-69.942c-17.707,-20.954 -42.792,-35.857 -75.254,-44.711c-12.395,-3.541 -25.971,-5.902 -40.727,-7.082c-14.755,-1.181 -28.331,-1.771 -40.726,-1.771l-286.853,-0l-0,393.095Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M2245.72,6630.61c-97.979,-0 -184.301,-21.101 -258.965,-63.303c-74.665,-42.202 -133.098,-100.34 -175.3,-174.414c-42.201,-74.074 -63.302,-158.92 -63.302,-254.538c-0,-104.471 20.658,-195.367 61.974,-272.688c41.317,-77.32 98.274,-137.377 170.873,-180.169c72.599,-42.791 156.117,-64.187 250.554,-64.187c100.34,-0 185.628,23.609 255.866,70.828c70.238,47.218 122.178,113.62 155.822,199.203c33.643,85.584 45.448,186.219 35.414,301.905l-238.159,-0l-0,-88.535c-0,-97.389 -15.494,-167.479 -46.481,-210.271c-30.988,-42.792 -81.6,-64.188 -151.838,-64.188c-82.042,0 -142.394,24.938 -181.054,74.812c-38.66,49.875 -57.99,123.507 -57.99,220.895c-0,89.125 19.33,158.035 57.99,206.729c38.66,48.695 95.47,73.042 170.43,73.042c47.219,-0 87.65,-10.329 121.293,-30.988c33.643,-20.658 59.318,-50.464 77.025,-89.42l240.816,69.057c-36.005,87.355 -92.815,155.232 -170.43,203.631c-77.616,48.399 -162.462,72.599 -254.538,72.599Zm-316.956,-437.363l0,-178.841l633.911,0l-0,178.841l-633.911,-0Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M3099.19,6604.05l-389.554,-1274.9l247.898,0l318.726,1048.26l324.038,-1048.26l247.898,0l-389.554,1274.9l-359.452,0Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M4166.93,6630.61c-68.467,-0 -126.457,-13.133 -173.971,-39.398c-47.514,-26.266 -83.518,-61.385 -108.013,-105.357c-24.495,-43.972 -36.742,-92.519 -36.742,-145.64c0,-44.268 6.788,-84.699 20.363,-121.293c13.576,-36.595 35.562,-68.91 65.959,-96.946c30.397,-28.036 71.27,-51.498 122.621,-70.385c35.414,-12.985 77.615,-24.495 126.605,-34.529c48.989,-10.034 104.471,-19.625 166.446,-28.774c61.974,-9.148 130.146,-19.33 204.515,-30.544l-86.764,47.809c0,-56.663 -13.575,-98.274 -40.726,-124.835c-27.151,-26.56 -72.599,-39.841 -136.344,-39.841c-35.414,0 -72.303,8.559 -110.669,25.676c-38.365,17.116 -65.22,47.513 -80.566,91.191l-217.797,-69.058c24.2,-79.091 69.648,-143.426 136.344,-193.006c66.697,-49.58 157.593,-74.369 272.688,-74.369c84.404,-0 159.363,12.985 224.879,38.955c65.516,25.97 115.096,70.828 148.739,134.573c18.887,35.414 30.102,70.828 33.643,106.242c3.542,35.414 5.312,74.96 5.312,118.637l0,584.331l-210.713,0l-0,-196.548l30.102,40.727c-46.629,64.335 -96.946,110.816 -150.952,139.442c-54.007,28.626 -122.326,42.94 -204.959,42.94Zm51.35,-189.465c44.268,-0 81.6,-7.821 111.997,-23.462c30.397,-15.641 54.597,-33.496 72.599,-53.564c18.002,-20.068 30.249,-36.889 36.742,-50.465c12.395,-25.97 19.625,-56.219 21.691,-90.748c2.066,-34.529 3.099,-63.303 3.099,-86.322l70.828,17.707c-71.418,11.805 -129.261,21.691 -173.529,29.66c-44.267,7.968 -79.976,15.198 -107.127,21.691c-27.151,6.492 -51.055,13.575 -71.714,21.248c-23.609,9.444 -42.644,19.625 -57.105,30.545c-14.46,10.919 -25.085,22.871 -31.872,35.856c-6.788,12.985 -10.182,27.446 -10.182,43.382c0,21.839 5.46,40.579 16.379,56.22c10.92,15.641 26.413,27.594 46.481,35.857c20.068,8.263 43.972,12.395 71.713,12.395Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M5585.26,6604.05l-0,-451.528c-0,-21.839 -1.181,-49.728 -3.541,-83.666c-2.361,-33.938 -9.739,-68.024 -22.134,-102.258c-12.395,-34.233 -32.611,-62.86 -60.647,-85.879c-28.036,-23.019 -67.729,-34.529 -119.079,-34.529c-20.658,0 -42.792,3.247 -66.402,9.739c-23.609,6.493 -45.743,19.035 -66.401,37.628c-20.658,18.592 -37.627,45.89 -50.907,81.895c-13.281,36.004 -19.921,83.813 -19.921,143.426l-138.114,-65.516c-0,-75.549 15.346,-146.377 46.038,-212.484c30.692,-66.106 76.878,-119.522 138.557,-160.248c61.679,-40.726 139.443,-61.089 233.29,-61.089c74.959,-0 136.049,12.69 183.267,38.07c47.219,25.38 83.961,57.548 110.226,96.503c26.266,38.955 45.006,79.534 56.22,121.736c11.215,42.201 18.002,80.714 20.363,115.538c2.361,34.824 3.542,60.204 3.542,76.14l-0,536.522l-244.357,0Zm-653.388,0l-0,-956.178l214.254,0l0,316.955l30.102,0l0,639.223l-244.356,0Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M6463.52,6630.61c-99.159,-0 -184.153,-22.134 -254.981,-66.402c-70.828,-44.267 -125.129,-104.471 -162.904,-180.611c-37.775,-76.14 -56.662,-162.019 -56.662,-257.637c-0,-96.798 19.625,-183.267 58.875,-259.407c39.251,-76.141 94.585,-136.049 166.003,-179.727c71.419,-43.677 155.822,-65.515 253.211,-65.515c112.734,-0 207.319,28.478 283.754,85.436c76.436,56.957 125.277,134.721 146.526,233.29l-240.815,63.745c-14.166,-49.58 -38.808,-88.24 -73.927,-115.981c-35.119,-27.741 -74.812,-41.612 -119.08,-41.612c-50.76,0 -92.371,12.248 -124.834,36.743c-32.463,24.494 -56.367,57.842 -71.714,100.044c-15.346,42.202 -23.019,89.863 -23.019,142.984c0,83.223 18.445,150.657 55.335,202.303c36.889,51.645 91.634,77.468 164.232,77.468c54.302,-0 95.618,-12.395 123.949,-37.185c28.331,-24.79 49.58,-60.204 63.745,-106.242l246.128,51.35c-27.151,101.52 -78.501,179.726 -154.051,234.618c-75.55,54.892 -168.807,82.338 -279.771,82.338Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M7492.3,6630.61c-97.979,-0 -184.3,-21.101 -258.965,-63.303c-74.664,-42.202 -133.098,-100.34 -175.299,-174.414c-42.202,-74.074 -63.303,-158.92 -63.303,-254.538c0,-104.471 20.658,-195.367 61.975,-272.688c41.316,-77.32 98.274,-137.377 170.872,-180.169c72.599,-42.791 156.117,-64.187 250.554,-64.187c100.34,-0 185.629,23.609 255.867,70.828c70.237,47.218 122.178,113.62 155.821,199.203c33.643,85.584 45.448,186.219 35.414,301.905l-238.159,-0l-0,-88.535c-0,-97.389 -15.494,-167.479 -46.481,-210.271c-30.987,-42.792 -81.6,-64.188 -151.837,-64.188c-82.043,0 -142.394,24.938 -181.055,74.812c-38.66,49.875 -57.99,123.507 -57.99,220.895c0,89.125 19.33,158.035 57.99,206.729c38.661,48.695 95.471,73.042 170.43,73.042c47.219,-0 87.65,-10.329 121.293,-30.988c33.644,-20.658 59.319,-50.464 77.026,-89.42l240.815,69.057c-36.004,87.355 -92.814,155.232 -170.43,203.631c-77.616,48.399 -162.462,72.599 -254.538,72.599Zm-316.955,-437.363l-0,-178.841l633.91,0l0,178.841l-633.91,-0Z" style="fill:#fff;fill-rule:nonzero;"/><path d="M8512.22,6630.61c-87.945,-0 -164.97,-22.134 -231.076,-66.402c-66.106,-44.267 -117.604,-104.471 -154.494,-180.611c-36.889,-76.14 -55.334,-162.019 -55.334,-257.637c-0,-97.388 18.74,-184.005 56.22,-259.85c37.479,-75.845 90.158,-135.606 158.035,-179.284c67.876,-43.677 147.558,-65.515 239.044,-65.515c90.896,-0 167.331,22.133 229.306,66.401c61.974,44.267 108.898,104.471 140.77,180.611c31.873,76.14 47.809,162.019 47.809,257.637c0,95.618 -16.083,181.497 -48.251,257.637c-32.168,76.14 -80.124,136.344 -143.87,180.611c-63.745,44.268 -143.131,66.402 -238.159,66.402Zm38.956,-214.255c53.711,-0 96.65,-12.1 128.818,-36.299c32.168,-24.2 55.334,-58.138 69.5,-101.816c14.166,-43.677 21.248,-94.437 21.248,-152.28c0,-57.843 -7.082,-108.603 -21.248,-152.28c-14.166,-43.677 -36.742,-77.616 -67.729,-101.815c-30.987,-24.2 -71.566,-36.3 -121.736,-36.3c-53.711,0 -97.831,13.133 -132.36,39.398c-34.528,26.266 -60.056,61.385 -76.582,105.357c-16.527,43.972 -24.79,92.519 -24.79,145.64c-0,53.711 7.968,102.553 23.904,146.526c15.936,43.972 40.431,78.943 73.484,104.914c33.053,25.97 75.55,38.955 127.491,38.955Zm219.566,187.694l0,-655.159l-30.101,0l-0,-619.745l242.585,0l0,1274.9l-212.484,0Z" style="fill:#fff;fill-rule:nonzero;"/></g><g id="Logo"><g id="Ring"><circle id="Ring-Background" serif:id="Ring Background" cx="4800" cy="2664.57" r="2049.67" style="fill:#1b1b1b;"/><path id="Ring1" serif:id="Ring" d="M4800,614.902c1131.25,-0 2049.67,918.427 2049.67,2049.67c0,1131.25 -918.427,2049.67 -2049.67,2049.67c-1131.25,0 -2049.67,-918.427 -2049.67,-2049.67c-0,-1131.25 918.427,-2049.67 2049.67,-2049.67Zm-0,184.47c1029.43,0 1865.2,835.769 1865.2,1865.2c-0,1029.43 -835.769,1865.2 -1865.2,1865.2c-1029.43,-0 -1865.2,-835.769 -1865.2,-1865.2c0,-1029.43 835.769,-1865.2 1865.2,-1865.2Z" style="fill:url(#_Linear2);"/></g><g id="Shape"><path id="V-Shape" serif:id="V Shape" d="M5510.93,1997.78c7.593,-17.329 5.93,-37.319 -4.422,-53.156c-10.351,-15.836 -27.994,-25.381 -46.913,-25.381c-26.379,-0 -53.47,-0 -72.584,-0c-15.886,-0 -30.269,9.393 -36.655,23.938c-63.887,145.508 -401.084,913.501 -513.699,1169.99c-6.387,14.546 -20.77,23.939 -36.656,23.939c-15.886,-0 -30.269,-9.393 -36.655,-23.939c-112.615,-256.491 -449.812,-1024.49 -513.699,-1169.99c-6.387,-14.545 -20.769,-23.938 -36.655,-23.938c-19.114,-0 -46.202,-0 -72.58,-0c-18.919,-0 -36.561,9.545 -46.913,25.381c-10.351,15.837 -12.014,35.826 -4.421,53.155c120.706,275.509 522.01,1191.47 603.987,1378.58c8.931,20.385 29.079,33.554 51.335,33.554c32.246,0 78.957,0 111.203,0c22.256,0 42.403,-13.169 51.335,-33.554c81.978,-187.11 483.285,-1103.07 603.992,-1378.58Z" style="fill:#fff;"/><path id="Diamond" d="M4841.6,2640.55c-8.581,14.864 -24.44,24.02 -41.603,24.02c-17.163,0 -33.022,-9.156 -41.603,-24.02c-87.097,-150.856 -287.752,-498.4 -374.849,-649.256c-8.581,-14.864 -8.581,-33.176 0,-48.04c8.582,-14.863 24.441,-24.019 41.603,-24.019c174.194,-0 575.504,-0 749.698,-0c17.162,-0 33.021,9.156 41.603,24.019c8.581,14.864 8.581,33.176 -0,48.04c-87.097,150.856 -287.752,498.4 -374.849,649.256Z" style="fill:url(#_Linear3);"/></g></g><defs><linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.51012e-13,4099.34,-4099.34,2.51012e-13,4800,614.902)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient><linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(9.07776e-14,1482.51,-1447.76,8.86499e-14,4800,1919.24)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient></defs></svg> \ No newline at end of file diff --git a/assets/revanced-headline/revanced-headline-vertical-light.svg b/assets/revanced-headline/revanced-headline-vertical-light.svg new file mode 100644 index 00000000..3c5eeccc --- /dev/null +++ b/assets/revanced-headline/revanced-headline-vertical-light.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 9600 7249" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><clipPath id="_clip1"><rect id="Wordmark" x="614.902" y="5329.15" width="8370.2" height="1304.34"/></clipPath><g clip-path="url(#_clip1)"><path id="Wordmark1" serif:id="Wordmark" d="M614.902,6604.05l-0,-1274.9l538.293,0c12.394,0 29.069,0.443 50.022,1.328c20.953,0.885 39.693,2.804 56.22,5.755c76.14,11.805 138.557,36.889 187.251,75.255c48.694,38.365 84.551,86.616 107.57,144.754c23.019,58.138 34.529,122.916 34.529,194.335c-0,106.832 -26.561,198.171 -79.682,274.016c-53.121,75.845 -136.344,122.621 -249.668,140.328l-106.242,7.082l-297.478,0l-0,432.051l-240.815,0Zm718.904,0l-251.439,-518.815l247.898,-47.809l276.229,566.624l-272.688,0Zm-478.089,-656.93l286.853,0c12.395,0 25.971,-0.59 40.726,-1.77c14.756,-1.181 28.332,-3.542 40.727,-7.083c32.462,-8.854 57.547,-23.757 75.254,-44.71c17.707,-20.954 29.955,-44.268 36.742,-69.943c6.788,-25.675 10.182,-50.022 10.182,-73.041c-0,-23.019 -3.394,-47.367 -10.182,-73.042c-6.787,-25.675 -19.035,-48.989 -36.742,-69.942c-17.707,-20.954 -42.792,-35.857 -75.254,-44.711c-12.395,-3.541 -25.971,-5.902 -40.727,-7.082c-14.755,-1.181 -28.331,-1.771 -40.726,-1.771l-286.853,-0l-0,393.095Z" style="fill-rule:nonzero;"/><path d="M2245.72,6630.61c-97.979,-0 -184.301,-21.101 -258.965,-63.303c-74.665,-42.202 -133.098,-100.34 -175.3,-174.414c-42.201,-74.074 -63.302,-158.92 -63.302,-254.538c-0,-104.471 20.658,-195.367 61.974,-272.688c41.317,-77.32 98.274,-137.377 170.873,-180.169c72.599,-42.791 156.117,-64.187 250.554,-64.187c100.34,-0 185.628,23.609 255.866,70.828c70.238,47.218 122.178,113.62 155.822,199.203c33.643,85.584 45.448,186.219 35.414,301.905l-238.159,-0l-0,-88.535c-0,-97.389 -15.494,-167.479 -46.481,-210.271c-30.988,-42.792 -81.6,-64.188 -151.838,-64.188c-82.042,0 -142.394,24.938 -181.054,74.812c-38.66,49.875 -57.99,123.507 -57.99,220.895c-0,89.125 19.33,158.035 57.99,206.729c38.66,48.695 95.47,73.042 170.43,73.042c47.219,-0 87.65,-10.329 121.293,-30.988c33.643,-20.658 59.318,-50.464 77.025,-89.42l240.816,69.057c-36.005,87.355 -92.815,155.232 -170.43,203.631c-77.616,48.399 -162.462,72.599 -254.538,72.599Zm-316.956,-437.363l0,-178.841l633.911,0l-0,178.841l-633.911,-0Z" style="fill-rule:nonzero;"/><path d="M3099.19,6604.05l-389.554,-1274.9l247.898,0l318.726,1048.26l324.038,-1048.26l247.898,0l-389.554,1274.9l-359.452,0Z" style="fill-rule:nonzero;"/><path d="M4166.93,6630.61c-68.467,-0 -126.457,-13.133 -173.971,-39.398c-47.514,-26.266 -83.518,-61.385 -108.013,-105.357c-24.495,-43.972 -36.742,-92.519 -36.742,-145.64c0,-44.268 6.788,-84.699 20.363,-121.293c13.576,-36.595 35.562,-68.91 65.959,-96.946c30.397,-28.036 71.27,-51.498 122.621,-70.385c35.414,-12.985 77.615,-24.495 126.605,-34.529c48.989,-10.034 104.471,-19.625 166.446,-28.774c61.974,-9.148 130.146,-19.33 204.515,-30.544l-86.764,47.809c0,-56.663 -13.575,-98.274 -40.726,-124.835c-27.151,-26.56 -72.599,-39.841 -136.344,-39.841c-35.414,0 -72.303,8.559 -110.669,25.676c-38.365,17.116 -65.22,47.513 -80.566,91.191l-217.797,-69.058c24.2,-79.091 69.648,-143.426 136.344,-193.006c66.697,-49.58 157.593,-74.369 272.688,-74.369c84.404,-0 159.363,12.985 224.879,38.955c65.516,25.97 115.096,70.828 148.739,134.573c18.887,35.414 30.102,70.828 33.643,106.242c3.542,35.414 5.312,74.96 5.312,118.637l0,584.331l-210.713,0l-0,-196.548l30.102,40.727c-46.629,64.335 -96.946,110.816 -150.952,139.442c-54.007,28.626 -122.326,42.94 -204.959,42.94Zm51.35,-189.465c44.268,-0 81.6,-7.821 111.997,-23.462c30.397,-15.641 54.597,-33.496 72.599,-53.564c18.002,-20.068 30.249,-36.889 36.742,-50.465c12.395,-25.97 19.625,-56.219 21.691,-90.748c2.066,-34.529 3.099,-63.303 3.099,-86.322l70.828,17.707c-71.418,11.805 -129.261,21.691 -173.529,29.66c-44.267,7.968 -79.976,15.198 -107.127,21.691c-27.151,6.492 -51.055,13.575 -71.714,21.248c-23.609,9.444 -42.644,19.625 -57.105,30.545c-14.46,10.919 -25.085,22.871 -31.872,35.856c-6.788,12.985 -10.182,27.446 -10.182,43.382c0,21.839 5.46,40.579 16.379,56.22c10.92,15.641 26.413,27.594 46.481,35.857c20.068,8.263 43.972,12.395 71.713,12.395Z" style="fill-rule:nonzero;"/><path d="M5585.26,6604.05l-0,-451.528c-0,-21.839 -1.181,-49.728 -3.541,-83.666c-2.361,-33.938 -9.739,-68.024 -22.134,-102.258c-12.395,-34.233 -32.611,-62.86 -60.647,-85.879c-28.036,-23.019 -67.729,-34.529 -119.079,-34.529c-20.658,0 -42.792,3.247 -66.402,9.739c-23.609,6.493 -45.743,19.035 -66.401,37.628c-20.658,18.592 -37.627,45.89 -50.907,81.895c-13.281,36.004 -19.921,83.813 -19.921,143.426l-138.114,-65.516c-0,-75.549 15.346,-146.377 46.038,-212.484c30.692,-66.106 76.878,-119.522 138.557,-160.248c61.679,-40.726 139.443,-61.089 233.29,-61.089c74.959,-0 136.049,12.69 183.267,38.07c47.219,25.38 83.961,57.548 110.226,96.503c26.266,38.955 45.006,79.534 56.22,121.736c11.215,42.201 18.002,80.714 20.363,115.538c2.361,34.824 3.542,60.204 3.542,76.14l-0,536.522l-244.357,0Zm-653.388,0l-0,-956.178l214.254,0l0,316.955l30.102,0l0,639.223l-244.356,0Z" style="fill-rule:nonzero;"/><path d="M6463.52,6630.61c-99.159,-0 -184.153,-22.134 -254.981,-66.402c-70.828,-44.267 -125.129,-104.471 -162.904,-180.611c-37.775,-76.14 -56.662,-162.019 -56.662,-257.637c-0,-96.798 19.625,-183.267 58.875,-259.407c39.251,-76.141 94.585,-136.049 166.003,-179.727c71.419,-43.677 155.822,-65.515 253.211,-65.515c112.734,-0 207.319,28.478 283.754,85.436c76.436,56.957 125.277,134.721 146.526,233.29l-240.815,63.745c-14.166,-49.58 -38.808,-88.24 -73.927,-115.981c-35.119,-27.741 -74.812,-41.612 -119.08,-41.612c-50.76,0 -92.371,12.248 -124.834,36.743c-32.463,24.494 -56.367,57.842 -71.714,100.044c-15.346,42.202 -23.019,89.863 -23.019,142.984c0,83.223 18.445,150.657 55.335,202.303c36.889,51.645 91.634,77.468 164.232,77.468c54.302,-0 95.618,-12.395 123.949,-37.185c28.331,-24.79 49.58,-60.204 63.745,-106.242l246.128,51.35c-27.151,101.52 -78.501,179.726 -154.051,234.618c-75.55,54.892 -168.807,82.338 -279.771,82.338Z" style="fill-rule:nonzero;"/><path d="M7492.3,6630.61c-97.979,-0 -184.3,-21.101 -258.965,-63.303c-74.664,-42.202 -133.098,-100.34 -175.299,-174.414c-42.202,-74.074 -63.303,-158.92 -63.303,-254.538c0,-104.471 20.658,-195.367 61.975,-272.688c41.316,-77.32 98.274,-137.377 170.872,-180.169c72.599,-42.791 156.117,-64.187 250.554,-64.187c100.34,-0 185.629,23.609 255.867,70.828c70.237,47.218 122.178,113.62 155.821,199.203c33.643,85.584 45.448,186.219 35.414,301.905l-238.159,-0l-0,-88.535c-0,-97.389 -15.494,-167.479 -46.481,-210.271c-30.987,-42.792 -81.6,-64.188 -151.837,-64.188c-82.043,0 -142.394,24.938 -181.055,74.812c-38.66,49.875 -57.99,123.507 -57.99,220.895c0,89.125 19.33,158.035 57.99,206.729c38.661,48.695 95.471,73.042 170.43,73.042c47.219,-0 87.65,-10.329 121.293,-30.988c33.644,-20.658 59.319,-50.464 77.026,-89.42l240.815,69.057c-36.004,87.355 -92.814,155.232 -170.43,203.631c-77.616,48.399 -162.462,72.599 -254.538,72.599Zm-316.955,-437.363l-0,-178.841l633.91,0l0,178.841l-633.91,-0Z" style="fill-rule:nonzero;"/><path d="M8512.22,6630.61c-87.945,-0 -164.97,-22.134 -231.076,-66.402c-66.106,-44.267 -117.604,-104.471 -154.494,-180.611c-36.889,-76.14 -55.334,-162.019 -55.334,-257.637c-0,-97.388 18.74,-184.005 56.22,-259.85c37.479,-75.845 90.158,-135.606 158.035,-179.284c67.876,-43.677 147.558,-65.515 239.044,-65.515c90.896,-0 167.331,22.133 229.306,66.401c61.974,44.267 108.898,104.471 140.77,180.611c31.873,76.14 47.809,162.019 47.809,257.637c0,95.618 -16.083,181.497 -48.251,257.637c-32.168,76.14 -80.124,136.344 -143.87,180.611c-63.745,44.268 -143.131,66.402 -238.159,66.402Zm38.956,-214.255c53.711,-0 96.65,-12.1 128.818,-36.299c32.168,-24.2 55.334,-58.138 69.5,-101.816c14.166,-43.677 21.248,-94.437 21.248,-152.28c0,-57.843 -7.082,-108.603 -21.248,-152.28c-14.166,-43.677 -36.742,-77.616 -67.729,-101.815c-30.987,-24.2 -71.566,-36.3 -121.736,-36.3c-53.711,0 -97.831,13.133 -132.36,39.398c-34.528,26.266 -60.056,61.385 -76.582,105.357c-16.527,43.972 -24.79,92.519 -24.79,145.64c-0,53.711 7.968,102.553 23.904,146.526c15.936,43.972 40.431,78.943 73.484,104.914c33.053,25.97 75.55,38.955 127.491,38.955Zm219.566,187.694l0,-655.159l-30.101,0l-0,-619.745l242.585,0l0,1274.9l-212.484,0Z" style="fill-rule:nonzero;"/></g><g id="Logo"><g id="Ring"><circle id="Ring-Background" serif:id="Ring Background" cx="4800" cy="2664.57" r="2049.67" style="fill:#1b1b1b;"/><path id="Ring1" serif:id="Ring" d="M4800,614.902c1131.25,-0 2049.67,918.427 2049.67,2049.67c0,1131.25 -918.427,2049.67 -2049.67,2049.67c-1131.25,0 -2049.67,-918.427 -2049.67,-2049.67c-0,-1131.25 918.427,-2049.67 2049.67,-2049.67Zm-0,184.47c1029.43,0 1865.2,835.769 1865.2,1865.2c-0,1029.43 -835.769,1865.2 -1865.2,1865.2c-1029.43,-0 -1865.2,-835.769 -1865.2,-1865.2c0,-1029.43 835.769,-1865.2 1865.2,-1865.2Z" style="fill:url(#_Linear2);"/></g><g id="Shape"><path id="V-Shape" serif:id="V Shape" d="M5510.93,1997.78c7.593,-17.329 5.93,-37.319 -4.422,-53.156c-10.351,-15.836 -27.994,-25.381 -46.913,-25.381c-26.379,-0 -53.47,-0 -72.584,-0c-15.886,-0 -30.269,9.393 -36.655,23.938c-63.887,145.508 -401.084,913.501 -513.699,1169.99c-6.387,14.546 -20.77,23.939 -36.656,23.939c-15.886,-0 -30.269,-9.393 -36.655,-23.939c-112.615,-256.491 -449.812,-1024.49 -513.699,-1169.99c-6.387,-14.545 -20.769,-23.938 -36.655,-23.938c-19.114,-0 -46.202,-0 -72.58,-0c-18.919,-0 -36.561,9.545 -46.913,25.381c-10.351,15.837 -12.014,35.826 -4.421,53.155c120.706,275.509 522.01,1191.47 603.987,1378.58c8.931,20.385 29.079,33.554 51.335,33.554c32.246,0 78.957,0 111.203,0c22.256,0 42.403,-13.169 51.335,-33.554c81.978,-187.11 483.285,-1103.07 603.992,-1378.58Z" style="fill:#fff;"/><path id="Diamond" d="M4841.6,2640.55c-8.581,14.864 -24.44,24.02 -41.603,24.02c-17.163,0 -33.022,-9.156 -41.603,-24.02c-87.097,-150.856 -287.752,-498.4 -374.849,-649.256c-8.581,-14.864 -8.581,-33.176 0,-48.04c8.582,-14.863 24.441,-24.019 41.603,-24.019c174.194,-0 575.504,-0 749.698,-0c17.162,-0 33.021,9.156 41.603,24.019c8.581,14.864 8.581,33.176 -0,48.04c-87.097,150.856 -287.752,498.4 -374.849,649.256Z" style="fill:url(#_Linear3);"/></g></g><defs><linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(2.51012e-13,4099.34,-4099.34,2.51012e-13,4800,614.902)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient><linearGradient id="_Linear3" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(9.07776e-14,1482.51,-1447.76,8.86499e-14,4800,1919.24)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient></defs></svg> \ No newline at end of file diff --git a/assets/revanced-logo/revanced-logo-round.svg b/assets/revanced-logo/revanced-logo-round.svg new file mode 100644 index 00000000..901e1914 --- /dev/null +++ b/assets/revanced-logo/revanced-logo-round.svg @@ -0,0 +1 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 800 800" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><g id="Logo"><g id="Ring"><circle id="Ring-Background" serif:id="Ring Background" cx="400" cy="400" r="400" style="fill:#1b1b1b;"/><path id="Ring1" serif:id="Ring" d="M400,0c220.766,0 400,179.234 400,400c-0,220.766 -179.234,400 -400,400c-220.766,-0 -400,-179.234 -400,-400c0,-220.766 179.234,-400 400,-400Zm-0,36c200.897,-0 364,163.103 364,364c0,200.897 -163.103,364 -364,364c-200.897,0 -364,-163.103 -364,-364c-0,-200.897 163.103,-364 364,-364Z" style="fill:url(#_Linear1);"/></g><g id="Shape"><path id="V-Shape" serif:id="V Shape" d="M538.74,269.872c1.481,-3.382 1.157,-7.283 -0.863,-10.373c-2.021,-3.091 -5.464,-4.954 -9.156,-4.954c-5.148,0 -10.435,0 -14.165,0c-3.1,0 -5.907,1.834 -7.153,4.672c-12.468,28.396 -78.273,178.273 -100.25,228.328c-1.246,2.838 -4.053,4.671 -7.154,4.671c-3.1,0 -5.907,-1.833 -7.153,-4.671c-21.977,-50.055 -87.782,-199.932 -100.25,-228.328c-1.246,-2.838 -4.053,-4.672 -7.153,-4.672c-3.73,0 -9.017,0 -14.164,0c-3.693,0 -7.135,1.863 -9.156,4.954c-2.02,3.09 -2.344,6.991 -0.863,10.373c23.557,53.766 101.872,232.519 117.871,269.034c1.743,3.979 5.674,6.549 10.018,6.549c6.293,-0 15.408,-0 21.701,-0c4.344,-0 8.275,-2.57 10.018,-6.549c15.999,-36.515 94.315,-215.268 117.872,-269.034Z" style="fill:#fff;"/><path id="Diamond" d="M408.119,395.312c-1.675,2.901 -4.77,4.688 -8.119,4.688c-3.349,-0 -6.444,-1.787 -8.119,-4.688c-16.997,-29.44 -56.156,-97.264 -73.153,-126.704c-1.675,-2.901 -1.675,-6.474 0,-9.375c1.675,-2.901 4.77,-4.688 8.119,-4.688c33.995,0 112.311,0 146.306,0c3.349,0 6.444,1.787 8.119,4.688c1.675,2.901 1.675,6.474 -0,9.375c-16.997,29.44 -56.156,97.264 -73.153,126.704Z" style="fill:url(#_Linear2);"/></g></g><defs><linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.89859e-14,800,-800,4.89859e-14,400.001,3.31681e-10)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient><linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.77155e-14,289.317,-282.535,1.73003e-14,400,254.545)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient></defs></svg> \ No newline at end of file diff --git a/docs/4_building.md b/docs/4_building.md index b3904c50..fec5b7e9 100644 --- a/docs/4_building.md +++ b/docs/4_building.md @@ -18,7 +18,7 @@ This page will guide you through building ReVanced Manager from source. 4. Delete conflicting outputs ```sh - flutter packages pub run build_runner build --delete-conflicting-outputs + dart run build_runner build --delete-conflicting-outputs ``` > [!Note] diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7f93135c..00000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 3fa8f862..00000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100644 index 1aa94a42..00000000 --- a/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 93e3f59f..00000000 --- a/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/lib/main.dart b/lib/main.dart index c81701ba..b38cb4c7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -30,7 +30,7 @@ Future main() async { } class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); + const MyApp({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/services/manager_api.dart b/lib/services/manager_api.dart index 17a36446..85306873 100644 --- a/lib/services/manager_api.dart +++ b/lib/services/manager_api.dart @@ -34,6 +34,7 @@ class ManagerAPI { Patch? selectedPatch; BuildContext? ctx; bool isRooted = false; + bool suggestedAppVersionSelected = true; bool isDynamicThemeAvailable = false; String storedPatchesFile = '/selected-patches.json'; String keystoreFile = @@ -259,6 +260,14 @@ class ManagerAPI { await _prefs.setBool('versionCompatibilityCheckEnabled', value); } + bool isRequireSuggestedAppVersionEnabled() { + return _prefs.getBool('requireSuggestedAppVersionEnabled') ?? true; + } + + Future<void> enableRequireSuggestedAppVersionStatus(bool value) async { + await _prefs.setBool('requireSuggestedAppVersionEnabled', value); + } + Future<void> setKeystorePassword(String password) async { await _prefs.setString('keystorePassword', password); } @@ -573,8 +582,8 @@ class ManagerAPI { return showDialog( barrierDismissible: false, context: context, - builder: (context) => WillPopScope( - onWillPop: () async => false, + builder: (context) => PopScope( + canPop: false, child: AlertDialog( backgroundColor: Theme.of(context).colorScheme.secondaryContainer, title: I18nText('warning'), diff --git a/lib/theme.dart b/lib/theme.dart index 89c93d52..99883b4a 100644 --- a/lib/theme.dart +++ b/lib/theme.dart @@ -2,8 +2,8 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; var lightCustomColorScheme = ColorScheme.fromSeed( - seedColor: Colors.blue, - primary: const Color(0xff1B73E8), + seedColor: Colors.purple, + primary: const Color(0xFF4C51C0), ); var lightCustomTheme = ThemeData( @@ -21,10 +21,10 @@ var lightCustomTheme = ThemeData( ); var darkCustomColorScheme = ColorScheme.fromSeed( - seedColor: Colors.blue, + seedColor: Colors.purple, brightness: Brightness.dark, - primary: const Color(0xffA5CAFF), - surface: const Color(0xff1B1A1D), + primary: const Color(0xFFBFC1FF), + surface: const Color(0xFF131316), ); var darkCustomTheme = ThemeData( @@ -38,7 +38,7 @@ var darkCustomTheme = ThemeData( ), ), ), - canvasColor: const Color(0xff1B1A1D), - scaffoldBackgroundColor: const Color(0xff1B1A1D), + canvasColor: const Color(0xFF131316), + scaffoldBackgroundColor: const Color(0xFF131316), textTheme: GoogleFonts.robotoTextTheme(ThemeData.dark().textTheme), ); diff --git a/lib/ui/theme/dynamic_theme_builder.dart b/lib/ui/theme/dynamic_theme_builder.dart index 233c78b5..8f9fc98b 100644 --- a/lib/ui/theme/dynamic_theme_builder.dart +++ b/lib/ui/theme/dynamic_theme_builder.dart @@ -12,11 +12,11 @@ import 'package:stacked_services/stacked_services.dart'; class DynamicThemeBuilder extends StatefulWidget { const DynamicThemeBuilder({ - Key? key, + super.key, required this.title, required this.home, required this.localizationsDelegates, - }) : super(key: key); + }); final String title; final Widget home; final Iterable<LocalizationsDelegate> localizationsDelegates; diff --git a/lib/ui/views/app_selector/app_selector_view.dart b/lib/ui/views/app_selector/app_selector_view.dart index bca6df76..09f6dacc 100644 --- a/lib/ui/views/app_selector/app_selector_view.dart +++ b/lib/ui/views/app_selector/app_selector_view.dart @@ -8,7 +8,7 @@ import 'package:revanced_manager/ui/widgets/shared/search_bar.dart'; import 'package:stacked/stacked.dart' hide SkeletonLoader; class AppSelectorView extends StatefulWidget { - const AppSelectorView({Key? key}) : super(key: key); + const AppSelectorView({super.key}); @override State<AppSelectorView> createState() => _AppSelectorViewState(); @@ -28,7 +28,6 @@ class _AppSelectorViewState extends State<AppSelectorView> { icon: const Icon(Icons.sd_storage), onPressed: () { model.selectAppFromStorage(context); - Navigator.of(context).pop(); }, ), body: CustomScrollView( @@ -113,9 +112,13 @@ class _AppSelectorViewState extends State<AppSelectorView> { context, app.packageName, ), + onLinkTap: () => + model.searchSuggestedVersionOnWeb( + packageName: app.packageName, + ), ), ) - .toList(), + , ...model .getFilteredAppsNames(_query) .map( @@ -127,9 +130,13 @@ class _AppSelectorViewState extends State<AppSelectorView> { onTap: () { model.showDownloadToast(); }, + onLinkTap: () => + model.searchSuggestedVersionOnWeb( + packageName: app, + ), ), ) - .toList(), + , const SizedBox(height: 70.0), ], ), diff --git a/lib/ui/views/app_selector/app_selector_viewmodel.dart b/lib/ui/views/app_selector/app_selector_viewmodel.dart index 53c7a239..46c3eabf 100644 --- a/lib/ui/views/app_selector/app_selector_viewmodel.dart +++ b/lib/ui/views/app_selector/app_selector_viewmodel.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:device_apps/device_apps.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_file_dialog/flutter_file_dialog.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/app/app.locator.dart'; @@ -70,7 +71,53 @@ class AppSelectorViewModel extends BaseViewModel { return true; } - Future<void> selectApp(ApplicationWithIcon application) async { + Future<void> searchSuggestedVersionOnWeb({ + required String packageName, + }) async { + final String suggestedVersion = getSuggestedVersion(packageName); + + if (suggestedVersion.isNotEmpty) { + await openDefaultBrowser('$packageName apk version v$suggestedVersion'); + } else { + await openDefaultBrowser('$packageName apk'); + } + } + + Future<void> openDefaultBrowser(String query) async { + if (Platform.isAndroid) { + try { + const platform = MethodChannel('app.revanced.manager.flutter/browser'); + await platform.invokeMethod('openBrowser', {'query': query}); + } catch (e) { + if (kDebugMode) { + print(e); + } + } + } else { + throw 'Platform not supported'; + } + } + + Future<void> selectApp( + BuildContext context, + ApplicationWithIcon application, [ + bool isFromStorage = false, + ]) async { + final String suggestedVersion = + getSuggestedVersion(application.packageName); + if (application.versionName != suggestedVersion && suggestedVersion.isNotEmpty) { + _managerAPI.suggestedAppVersionSelected = false; + if (_managerAPI.isRequireSuggestedAppVersionEnabled() && + context.mounted) { + return showRequireSuggestedAppVersionDialog( + context, + application.versionName!, + suggestedVersion, + ); + } + } else { + _managerAPI.suggestedAppVersionSelected = true; + } locator<PatcherViewModel>().selectedApp = PatchedApplication( name: application.appName, packageName: application.packageName, @@ -78,8 +125,12 @@ class AppSelectorViewModel extends BaseViewModel { apkFilePath: application.apkFilePath, icon: application.icon, patchDate: DateTime.now(), + isFromStorage: isFromStorage, ); await locator<PatcherViewModel>().loadLastSelectedPatches(); + if (context.mounted) { + Navigator.pop(context); + } } Future<void> canSelectInstalled( @@ -89,23 +140,60 @@ class AppSelectorViewModel extends BaseViewModel { final app = await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?; if (app != null) { - if (await checkSplitApk(packageName) && !isRooted) { + final bool isSplitApk = await checkSplitApk(packageName); + if (isRooted || !isSplitApk) { + if (context.mounted) { + await selectApp(context, app); + } + final List<Option> requiredNullOptions = getNullRequiredOptions( + locator<PatcherViewModel>().selectedPatches, + packageName, + ); + if (requiredNullOptions.isNotEmpty) { + locator<PatcherViewModel>().showRequiredOptionDialog(); + } + } else { if (context.mounted) { return showSelectFromStorageDialog(context); } - } else if (!await checkSplitApk(packageName) || isRooted) { - await selectApp(app); - if (context.mounted) { - Navigator.pop(context); - } - final List<Option> requiredNullOptions = getNullRequiredOptions(locator<PatcherViewModel>().selectedPatches, packageName); - if(requiredNullOptions.isNotEmpty){ - locator<PatcherViewModel>().showRequiredOptionDialog(); - } } } } + Future showRequireSuggestedAppVersionDialog( + BuildContext context, + String selectedVersion, + String suggestedVersion, + ) async { + return showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + title: I18nText('warning'), + content: I18nText( + 'appSelectorView.requireSuggestedAppVersionDialogText', + translationParams: { + 'suggested': suggestedVersion, + 'selected': selectedVersion, + }, + child: const Text( + '', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + actions: [ + CustomMaterialButton( + label: I18nText('okButton'), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ), + ); + } + Future showSelectFromStorageDialog(BuildContext context) async { return showDialog( context: context, @@ -145,12 +233,10 @@ class AppSelectorViewModel extends BaseViewModel { ), const SizedBox(height: 30), CustomMaterialButton( - onPressed: () => selectAppFromStorage(context).then( - (_) { - Navigator.pop(context); - Navigator.pop(context); - }, - ), + onPressed: () async { + Navigator.pop(context); + await selectAppFromStorage(context); + }, label: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -203,17 +289,8 @@ class AppSelectorViewModel extends BaseViewModel { apkFile.path, true, ) as ApplicationWithIcon?; - if (application != null) { - locator<PatcherViewModel>().selectedApp = PatchedApplication( - name: application.appName, - packageName: application.packageName, - version: application.versionName!, - apkFilePath: result, - icon: application.icon, - patchDate: DateTime.now(), - isFromStorage: true, - ); - locator<PatcherViewModel>().loadLastSelectedPatches(); + if (application != null && context.mounted) { + await selectApp(context, application, true); } } } on Exception catch (e) { diff --git a/lib/ui/views/contributors/contributors_view.dart b/lib/ui/views/contributors/contributors_view.dart index a409c17e..2d9c8b74 100644 --- a/lib/ui/views/contributors/contributors_view.dart +++ b/lib/ui/views/contributors/contributors_view.dart @@ -7,7 +7,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:stacked/stacked.dart'; class ContributorsView extends StatelessWidget { - const ContributorsView({Key? key}) : super(key: key); + const ContributorsView({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/ui/views/home/home_view.dart b/lib/ui/views/home/home_view.dart index 06ed6e9f..b2fdcd86 100644 --- a/lib/ui/views/home/home_view.dart +++ b/lib/ui/views/home/home_view.dart @@ -9,7 +9,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:stacked/stacked.dart'; class HomeView extends StatelessWidget { - const HomeView({Key? key}) : super(key: key); + const HomeView({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/ui/views/installer/installer_view.dart b/lib/ui/views/installer/installer_view.dart index 7988d6fb..45d20519 100644 --- a/lib/ui/views/installer/installer_view.dart +++ b/lib/ui/views/installer/installer_view.dart @@ -8,17 +8,18 @@ import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:stacked/stacked.dart'; class InstallerView extends StatelessWidget { - const InstallerView({Key? key}) : super(key: key); + const InstallerView({super.key}); @override Widget build(BuildContext context) { return ViewModelBuilder<InstallerViewModel>.reactive( onViewModelReady: (model) => model.initialize(context), viewModelBuilder: () => InstallerViewModel(), - builder: (context, model, child) => WillPopScope( + builder: (context, model, child) => PopScope( + onPopInvoked: (bool didPop) => model.onPopInvoked(context, didPop), child: SafeArea( top: false, - bottom: false, + bottom: model.isPatching, child: Scaffold( floatingActionButton: Visibility( visible: !model.isPatching && !model.hasErrors, @@ -83,7 +84,7 @@ class InstallerView extends StatelessWidget { maxLines: 1, overflow: TextOverflow.ellipsis, ), - onBackButtonPressed: () => model.onWillPop(context), + onBackButtonPressed: () => model.onBackButtonInvoked(context), bottom: PreferredSize( preferredSize: const Size(double.infinity, 1.0), child: GradientProgressIndicator(progress: model.progress), @@ -111,7 +112,6 @@ class InstallerView extends StatelessWidget { ), ), ), - onWillPop: () => model.onWillPop(context), ), ); } diff --git a/lib/ui/views/installer/installer_viewmodel.dart b/lib/ui/views/installer/installer_viewmodel.dart index 73b23027..c8f7e8cd 100644 --- a/lib/ui/views/installer/installer_viewmodel.dart +++ b/lib/ui/views/installer/installer_viewmodel.dart @@ -181,6 +181,15 @@ class InstallerViewModel extends BaseViewModel { Future<void> copyLogs() async { final info = await AboutInfo.getInfo(); + dynamic getValue(String patchName, Option option) { + final Option? savedOption = + _managerAPI.getPatchOption(_app.packageName, patchName, option.key); + if (savedOption != null) { + return savedOption.value; + } else { + return option.value; + } + } final formattedLogs = [ '- Device Info', @@ -194,8 +203,7 @@ class InstallerViewModel extends BaseViewModel { '\n- Patch Info', 'App: ${_app.packageName} v${_app.version}', 'Patches version: ${_managerAPI.patchesVersion}', - 'Patches: ${_patches.map((p) => p.name + (p.options.isEmpty ? '' : ' [${p.options.map((o) => '${o.title}: ${o.value}').join(", ")}]')).toList().join(", ")}', - + 'Patches: ${_patches.map((p) => p.name + (p.options.isEmpty ? '' : ' [${p.options.map((o) => '${o.title}: ${getValue(p.name, o)}').join(", ")}]')).toList().join(", ")}', '\n- Settings', 'Allow changing patch selection: ${_managerAPI.isPatchesChangeEnabled()}', 'Version compatibility check: ${_managerAPI.isVersionCompatibilityCheckEnabled()}', @@ -419,25 +427,38 @@ class InstallerViewModel extends BaseViewModel { } } - Future<bool> onWillPop(BuildContext context) async { - if (isPatching) { - if (!cancel) { - cancel = true; - _toast.showBottom('installerView.pressBackAgain'); - } else if (!isCanceled) { - await stopPatcher(); - } else { - _toast.showBottom('installerView.noExit'); - } - return false; - } - if (!cancel) { - cleanPatcher(); + bool canPop() { + return !isPatching; + } + + void onBackButtonInvoked(BuildContext context) { + if (canPop()) { + onPopInvoked(context, true); } else { - _patcherAPI.cleanPatcher(); + onPopInvoked(context, false); + } + } + + Future<void> onPopInvoked(BuildContext context, bool didPop) async { + if (didPop) { + if (!cancel) { + cleanPatcher(); + } else { + _patcherAPI.cleanPatcher(); + } + screenshotCallback.dispose(); + Navigator.of(context).pop(); + } else { + if (isPatching) { + if (!cancel) { + cancel = true; + _toast.showBottom('installerView.pressBackAgain'); + } else if (!isCanceled) { + await stopPatcher(); + } else { + _toast.showBottom('installerView.noExit'); + } + } } - screenshotCallback.dispose(); - Navigator.of(context).pop(); - return true; } } diff --git a/lib/ui/views/navigation/navigation_view.dart b/lib/ui/views/navigation/navigation_view.dart index 7089d069..56c24d17 100644 --- a/lib/ui/views/navigation/navigation_view.dart +++ b/lib/ui/views/navigation/navigation_view.dart @@ -6,20 +6,18 @@ import 'package:revanced_manager/ui/views/navigation/navigation_viewmodel.dart'; import 'package:stacked/stacked.dart'; class NavigationView extends StatelessWidget { - const NavigationView({Key? key}) : super(key: key); + const NavigationView({super.key}); @override Widget build(BuildContext context) { return ViewModelBuilder<NavigationViewModel>.reactive( onViewModelReady: (model) => model.initialize(context), viewModelBuilder: () => locator<NavigationViewModel>(), - builder: (context, model, child) => WillPopScope( - onWillPop: () async { - if (model.currentIndex == 0) { - return true; - } else { + builder: (context, model, child) => PopScope( + canPop: model.currentIndex == 0, + onPopInvoked: (bool didPop) { + if (!didPop) { model.setIndex(0); - return false; } }, child: Scaffold( diff --git a/lib/ui/views/patch_options/patch_options_viewmodel.dart b/lib/ui/views/patch_options/patch_options_viewmodel.dart index c1da7992..520fd9c6 100644 --- a/lib/ui/views/patch_options/patch_options_viewmodel.dart +++ b/lib/ui/views/patch_options/patch_options_viewmodel.dart @@ -38,11 +38,11 @@ class PatchOptionsViewModel extends BaseViewModel { option.required && !savedOptions.any((sOption) => sOption.key == option.key), ) - .toList(), + , ]; } else { visibleOptions = [ - ...options.where((option) => option.required).toList(), + ...options.where((option) => option.required), ]; } } diff --git a/lib/ui/views/patcher/patcher_view.dart b/lib/ui/views/patcher/patcher_view.dart index c15a6943..0921bb1d 100644 --- a/lib/ui/views/patcher/patcher_view.dart +++ b/lib/ui/views/patcher/patcher_view.dart @@ -9,7 +9,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:stacked/stacked.dart'; class PatcherView extends StatelessWidget { - const PatcherView({Key? key}) : super(key: key); + const PatcherView({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/ui/views/patcher/patcher_viewmodel.dart b/lib/ui/views/patcher/patcher_viewmodel.dart index 95244c6d..19d70721 100644 --- a/lib/ui/views/patcher/patcher_viewmodel.dart +++ b/lib/ui/views/patcher/patcher_viewmodel.dart @@ -1,6 +1,10 @@ // ignore_for_file: use_build_context_synchronously +import 'dart:io'; + +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:injectable/injectable.dart'; import 'package:revanced_manager/app/app.locator.dart'; @@ -157,6 +161,29 @@ class PatcherViewModel extends BaseViewModel { return text; } + String getCurrentVersionString(BuildContext context) { + return '${FlutterI18n.translate( + context, + 'appSelectorCard.currentVersion', + )}: v${selectedApp!.version}'; + } + + Future<void> searchSuggestedVersionOnWeb() async { + final String suggestedVersion = + _patcherAPI.getSuggestedVersion(selectedApp!.packageName); + + if (suggestedVersion.isNotEmpty) { + await openDefaultBrowser( + '${selectedApp!.packageName} apk version v$suggestedVersion'); + } else { + await openDefaultBrowser('${selectedApp!.packageName} apk'); + } + } + + String getSuggestedVersion() { + return _patcherAPI.getSuggestedVersion(selectedApp!.packageName); + } + String getSuggestedVersionString(BuildContext context) { String suggestedVersion = _patcherAPI.getSuggestedVersion(selectedApp!.packageName); @@ -169,14 +196,26 @@ class PatcherViewModel extends BaseViewModel { suggestedVersion = 'v$suggestedVersion'; } return '${FlutterI18n.translate( - context, - 'appSelectorCard.currentVersion', - )}: v${selectedApp!.version}\n${FlutterI18n.translate( context, 'appSelectorCard.suggestedVersion', )}: $suggestedVersion'; } + Future<void> openDefaultBrowser(String query) async { + if (Platform.isAndroid) { + try { + const platform = MethodChannel('app.revanced.manager.flutter/browser'); + await platform.invokeMethod('openBrowser', {'query': query}); + } catch (e) { + if (kDebugMode) { + print(e); + } + } + } else { + throw 'Platform not supported'; + } + } + Future<void> loadLastSelectedPatches() async { this.selectedPatches.clear(); removedPatches.clear(); diff --git a/lib/ui/views/patches_selector/patches_selector_view.dart b/lib/ui/views/patches_selector/patches_selector_view.dart index eb20cf82..29489078 100644 --- a/lib/ui/views/patches_selector/patches_selector_view.dart +++ b/lib/ui/views/patches_selector/patches_selector_view.dart @@ -7,7 +7,7 @@ import 'package:revanced_manager/ui/widgets/shared/search_bar.dart'; import 'package:stacked/stacked.dart'; class PatchesSelectorView extends StatefulWidget { - const PatchesSelectorView({Key? key}) : super(key: key); + const PatchesSelectorView({super.key}); @override State<PatchesSelectorView> createState() => _PatchesSelectorViewState(); diff --git a/lib/ui/views/settings/settings_view.dart b/lib/ui/views/settings/settings_view.dart index fb623440..0d5b8e30 100644 --- a/lib/ui/views/settings/settings_view.dart +++ b/lib/ui/views/settings/settings_view.dart @@ -13,7 +13,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:stacked/stacked.dart'; class SettingsView extends StatelessWidget { - const SettingsView({Key? key}) : super(key: key); + const SettingsView({super.key}); static const _settingsDivider = Divider(thickness: 1.0, indent: 20.0, endIndent: 20.0); diff --git a/lib/ui/views/settings/settings_viewmodel.dart b/lib/ui/views/settings/settings_viewmodel.dart index 71730088..d1dbfd7e 100644 --- a/lib/ui/views/settings/settings_viewmodel.dart +++ b/lib/ui/views/settings/settings_viewmodel.dart @@ -140,6 +140,57 @@ class SettingsViewModel extends BaseViewModel { notifyListeners(); } + bool isRequireSuggestedAppVersionEnabled() { + return _managerAPI.isRequireSuggestedAppVersionEnabled(); + } + + Future<void>? showRequireSuggestedAppVersionDialog( + BuildContext context, bool value,) { + if (!value) { + return showDialog( + context: context, + builder: (context) => AlertDialog( + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + title: I18nText('warning'), + content: I18nText( + 'settingsView.requireSuggestedAppVersionDialogText', + child: const Text( + '', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ), + actions: [ + CustomMaterialButton( + isFilled: false, + label: I18nText('yesButton'), + onPressed: () { + _managerAPI.enableRequireSuggestedAppVersionStatus(false); + Navigator.of(context).pop(); + }, + ), + CustomMaterialButton( + label: I18nText('noButton'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ), + ); + } else { + _managerAPI.enableRequireSuggestedAppVersionStatus(true); + + if (!_managerAPI.suggestedAppVersionSelected) { + _patcherViewModel.selectedApp = null; + } + + return null; + } + } + void deleteKeystore() { _managerAPI.deleteKeystore(); _toast.showBottom('settingsView.regeneratedKeystore'); diff --git a/lib/ui/widgets/appInfoView/app_info_view.dart b/lib/ui/widgets/appInfoView/app_info_view.dart index 283beb12..0e7bed3d 100644 --- a/lib/ui/widgets/appInfoView/app_info_view.dart +++ b/lib/ui/widgets/appInfoView/app_info_view.dart @@ -9,9 +9,9 @@ import 'package:stacked/stacked.dart'; class AppInfoView extends StatelessWidget { const AppInfoView({ - Key? key, + super.key, required this.app, - }) : super(key: key); + }); final PatchedApplication app; @override diff --git a/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart b/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart index 0cb80428..2f98d2a8 100644 --- a/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart +++ b/lib/ui/widgets/appSelectorView/app_skeleton_loader.dart @@ -3,7 +3,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:skeletons/skeletons.dart'; class AppSkeletonLoader extends StatelessWidget { - const AppSkeletonLoader({Key? key}) : super(key: key); + const AppSkeletonLoader({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/ui/widgets/appSelectorView/installed_app_item.dart b/lib/ui/widgets/appSelectorView/installed_app_item.dart index ae129cbf..62dc1e1c 100644 --- a/lib/ui/widgets/appSelectorView/installed_app_item.dart +++ b/lib/ui/widgets/appSelectorView/installed_app_item.dart @@ -5,7 +5,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class InstalledAppItem extends StatefulWidget { const InstalledAppItem({ - Key? key, + super.key, required this.name, required this.pkgName, required this.icon, @@ -13,7 +13,9 @@ class InstalledAppItem extends StatefulWidget { required this.suggestedVersion, required this.installedVersion, this.onTap, - }) : super(key: key); + this.onLinkTap, + }); + final String name; final String pkgName; final Uint8List icon; @@ -21,6 +23,7 @@ class InstalledAppItem extends StatefulWidget { final String suggestedVersion; final String installedVersion; final Function()? onTap; + final Function()? onLinkTap; @override State<InstalledAppItem> createState() => _InstalledAppItemState(); @@ -71,17 +74,52 @@ class _InstalledAppItemState extends State<InstalledAppItem> { ), ), Wrap( + crossAxisAlignment: WrapCrossAlignment.center, children: [ - I18nText( - 'suggested', - translationParams: { - 'version': widget.suggestedVersion.isEmpty - ? FlutterI18n.translate( - context, - 'appSelectorCard.allVersions', - ) - : 'v${widget.suggestedVersion}', - }, + Material( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: InkWell( + onTap: widget.onLinkTap, + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: Container( + padding: const EdgeInsets.all(4), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + I18nText( + 'suggested', + translationParams: { + 'version': widget.suggestedVersion.isEmpty + ? FlutterI18n.translate( + context, + 'appSelectorCard.allVersions', + ) + : 'v${widget.suggestedVersion}', + }, + child: Text( + '', + style: TextStyle( + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), + ), + ), + const SizedBox(width: 4), + Icon( + Icons.search, + size: 16, + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), + ], + ), + ), + ), ), const SizedBox(width: 4), Text( diff --git a/lib/ui/widgets/appSelectorView/not_installed_app_item.dart b/lib/ui/widgets/appSelectorView/not_installed_app_item.dart index c2f3f52e..83ac7342 100644 --- a/lib/ui/widgets/appSelectorView/not_installed_app_item.dart +++ b/lib/ui/widgets/appSelectorView/not_installed_app_item.dart @@ -4,16 +4,19 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class NotInstalledAppItem extends StatefulWidget { const NotInstalledAppItem({ - Key? key, + super.key, required this.name, required this.patchesCount, required this.suggestedVersion, this.onTap, - }) : super(key: key); + this.onLinkTap, + }); + final String name; final int patchesCount; final String suggestedVersion; final Function()? onTap; + final Function()? onLinkTap; @override State<NotInstalledAppItem> createState() => _NotInstalledAppItem(); @@ -65,17 +68,52 @@ class _NotInstalledAppItem extends State<NotInstalledAppItem> { ), ), Wrap( + crossAxisAlignment: WrapCrossAlignment.center, children: [ - I18nText( - 'suggested', - translationParams: { - 'version': widget.suggestedVersion.isEmpty - ? FlutterI18n.translate( - context, - 'appSelectorCard.allVersions', - ) - : 'v${widget.suggestedVersion}', - }, + Material( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: InkWell( + onTap: widget.onLinkTap, + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: Container( + padding: const EdgeInsets.all(4), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + I18nText( + 'suggested', + translationParams: { + 'version': widget.suggestedVersion.isEmpty + ? FlutterI18n.translate( + context, + 'appSelectorCard.allVersions', + ) + : 'v${widget.suggestedVersion}', + }, + child: Text( + '', + style: TextStyle( + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), + ), + ), + const SizedBox(width: 4), + Icon( + Icons.search, + size: 16, + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), + ], + ), + ), + ), ), const SizedBox(width: 4), Text( diff --git a/lib/ui/widgets/contributorsView/contributors_card.dart b/lib/ui/widgets/contributorsView/contributors_card.dart index d0a4c624..d039e5b7 100644 --- a/lib/ui/widgets/contributorsView/contributors_card.dart +++ b/lib/ui/widgets/contributorsView/contributors_card.dart @@ -7,10 +7,10 @@ import 'package:url_launcher/url_launcher.dart'; class ContributorsCard extends StatefulWidget { const ContributorsCard({ - Key? key, + super.key, required this.title, required this.contributors, - }) : super(key: key); + }); final String title; final List<dynamic> contributors; diff --git a/lib/ui/widgets/homeView/installed_apps_card.dart b/lib/ui/widgets/homeView/installed_apps_card.dart index ec825340..e6ac9a02 100644 --- a/lib/ui/widgets/homeView/installed_apps_card.dart +++ b/lib/ui/widgets/homeView/installed_apps_card.dart @@ -10,7 +10,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; //ignore: must_be_immutable class InstalledAppsCard extends StatelessWidget { - InstalledAppsCard({Key? key}) : super(key: key); + InstalledAppsCard({super.key}); List<PatchedApplication> apps = locator<HomeViewModel>().patchedInstalledApps; final ManagerAPI _managerAPI = locator<ManagerAPI>(); diff --git a/lib/ui/widgets/homeView/latest_commit_card.dart b/lib/ui/widgets/homeView/latest_commit_card.dart index cb263e25..9d0625ce 100644 --- a/lib/ui/widgets/homeView/latest_commit_card.dart +++ b/lib/ui/widgets/homeView/latest_commit_card.dart @@ -7,10 +7,10 @@ import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; class LatestCommitCard extends StatefulWidget { const LatestCommitCard({ - Key? key, + super.key, required this.model, required this.parentContext, - }) : super(key: key); + }); final HomeViewModel model; final BuildContext parentContext; diff --git a/lib/ui/widgets/patcherView/app_selector_card.dart b/lib/ui/widgets/patcherView/app_selector_card.dart index e97a004d..f0c05b83 100644 --- a/lib/ui/widgets/patcherView/app_selector_card.dart +++ b/lib/ui/widgets/patcherView/app_selector_card.dart @@ -7,9 +7,10 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class AppSelectorCard extends StatelessWidget { const AppSelectorCard({ - Key? key, + super.key, required this.onPressed, - }) : super(key: key); + }); + final Function() onPressed; @override @@ -61,11 +62,52 @@ class AppSelectorCard extends StatelessWidget { Container() else Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ const SizedBox(height: 4), Text( - locator<PatcherViewModel>() - .getSuggestedVersionString(context), + locator<PatcherViewModel>().getCurrentVersionString(context), + ), + Row( + children: [ + Material( + color: Theme.of(context).colorScheme.secondaryContainer, + borderRadius: const BorderRadius.all(Radius.circular(8)), + child: InkWell( + onTap: () { + locator<PatcherViewModel>() + .searchSuggestedVersionOnWeb(); + }, + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: Container( + padding: const EdgeInsets.all(4), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + locator<PatcherViewModel>() + .getSuggestedVersionString(context), + style: TextStyle( + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), + ), + const SizedBox(width: 4), + Icon( + Icons.search, + size: 16, + color: Theme.of(context) + .colorScheme + .onSecondaryContainer, + ), + ], + ), + ), + ), + ), + ], ), ], ), diff --git a/lib/ui/widgets/patcherView/patch_selector_card.dart b/lib/ui/widgets/patcherView/patch_selector_card.dart index 56da8570..ceea41c9 100644 --- a/lib/ui/widgets/patcherView/patch_selector_card.dart +++ b/lib/ui/widgets/patcherView/patch_selector_card.dart @@ -7,9 +7,9 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; class PatchSelectorCard extends StatelessWidget { const PatchSelectorCard({ - Key? key, + super.key, required this.onPressed, - }) : super(key: key); + }); final Function() onPressed; @override diff --git a/lib/ui/widgets/patchesSelectorView/patch_item.dart b/lib/ui/widgets/patchesSelectorView/patch_item.dart index 92fe1454..11fd0839 100644 --- a/lib/ui/widgets/patchesSelectorView/patch_item.dart +++ b/lib/ui/widgets/patchesSelectorView/patch_item.dart @@ -10,7 +10,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart'; // ignore: must_be_immutable class PatchItem extends StatefulWidget { PatchItem({ - Key? key, + super.key, required this.name, required this.simpleName, required this.description, @@ -23,7 +23,7 @@ class PatchItem extends StatefulWidget { required this.onChanged, required this.navigateToOptions, required this.isChangeEnabled, - }) : super(key: key); + }); final String name; final String simpleName; final String description; diff --git a/lib/ui/widgets/settingsView/about_widget.dart b/lib/ui/widgets/settingsView/about_widget.dart index ebad5f92..1884b5e3 100644 --- a/lib/ui/widgets/settingsView/about_widget.dart +++ b/lib/ui/widgets/settingsView/about_widget.dart @@ -4,7 +4,7 @@ import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:revanced_manager/utils/about_info.dart'; class AboutWidget extends StatefulWidget { - const AboutWidget({Key? key, this.padding}) : super(key: key); + const AboutWidget({super.key, this.padding}); final EdgeInsetsGeometry? padding; diff --git a/lib/ui/widgets/settingsView/custom_switch.dart b/lib/ui/widgets/settingsView/custom_switch.dart index 8328c90b..75229bb0 100644 --- a/lib/ui/widgets/settingsView/custom_switch.dart +++ b/lib/ui/widgets/settingsView/custom_switch.dart @@ -2,10 +2,10 @@ import 'package:flutter/material.dart'; class CustomSwitch extends StatelessWidget { const CustomSwitch({ - Key? key, + super.key, required this.onChanged, required this.value, - }) : super(key: key); + }); final ValueChanged<bool> onChanged; final bool value; diff --git a/lib/ui/widgets/settingsView/custom_switch_tile.dart b/lib/ui/widgets/settingsView/custom_switch_tile.dart index f17f9670..3bf563a5 100644 --- a/lib/ui/widgets/settingsView/custom_switch_tile.dart +++ b/lib/ui/widgets/settingsView/custom_switch_tile.dart @@ -3,13 +3,13 @@ import 'package:revanced_manager/ui/widgets/settingsView/custom_switch.dart'; class CustomSwitchTile extends StatelessWidget { const CustomSwitchTile({ - Key? key, + super.key, required this.title, required this.subtitle, required this.value, required this.onTap, this.padding, - }) : super(key: key); + }); final Widget title; final Widget subtitle; final bool value; diff --git a/lib/ui/widgets/settingsView/custom_text_field.dart b/lib/ui/widgets/settingsView/custom_text_field.dart index 6f2b8a76..986b2ac6 100644 --- a/lib/ui/widgets/settingsView/custom_text_field.dart +++ b/lib/ui/widgets/settingsView/custom_text_field.dart @@ -2,13 +2,13 @@ import 'package:flutter/material.dart'; class CustomTextField extends StatelessWidget { const CustomTextField({ - Key? key, + super.key, required this.inputController, required this.label, required this.hint, this.leadingIcon, required this.onChanged, - }) : super(key: key); + }); final TextEditingController inputController; final Widget label; final String hint; diff --git a/lib/ui/widgets/settingsView/settings_advanced_section.dart b/lib/ui/widgets/settingsView/settings_advanced_section.dart index 8adce157..53b3cadf 100644 --- a/lib/ui/widgets/settingsView/settings_advanced_section.dart +++ b/lib/ui/widgets/settingsView/settings_advanced_section.dart @@ -5,6 +5,7 @@ import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_man import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_sources.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_auto_update_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_enable_patches_selection.dart'; +import 'package:revanced_manager/ui/widgets/settingsView/settings_require_suggested_app_version.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_universal_patches.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_version_compatibility_check.dart'; @@ -20,6 +21,7 @@ class SAdvancedSection extends StatelessWidget { children: const <Widget>[ SAutoUpdatePatches(), SEnablePatchesSelection(), + SRequireSuggestedAppVersion(), SVersionCompatibilityCheck(), SUniversalPatches(), SManageSourcesUI(), diff --git a/lib/ui/widgets/settingsView/settings_require_suggested_app_version.dart b/lib/ui/widgets/settingsView/settings_require_suggested_app_version.dart new file mode 100644 index 00000000..1d431e60 --- /dev/null +++ b/lib/ui/widgets/settingsView/settings_require_suggested_app_version.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_i18n/widgets/I18nText.dart'; +import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; + +class SRequireSuggestedAppVersion extends StatefulWidget { + const SRequireSuggestedAppVersion({super.key}); + + @override + State<SRequireSuggestedAppVersion> createState() => _SRequireSuggestedAppVersionState(); +} + +final _settingsViewModel = SettingsViewModel(); + +class _SRequireSuggestedAppVersionState extends State<SRequireSuggestedAppVersion> { + @override + Widget build(BuildContext context) { + return SwitchListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 20.0), + title: I18nText( + 'settingsView.requireSuggestedAppVersionLabel', + child: const Text( + '', + style: TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + ), + ), + ), + subtitle: I18nText('settingsView.requireSuggestedAppVersionHint'), + value: _settingsViewModel.isRequireSuggestedAppVersionEnabled(), + onChanged: (value) async { + await _settingsViewModel.showRequireSuggestedAppVersionDialog(context, value,); + setState(() {}); + }, + ); + } +} diff --git a/lib/ui/widgets/settingsView/settings_section.dart b/lib/ui/widgets/settingsView/settings_section.dart index 74570a14..56e9247e 100644 --- a/lib/ui/widgets/settingsView/settings_section.dart +++ b/lib/ui/widgets/settingsView/settings_section.dart @@ -3,10 +3,10 @@ import 'package:flutter_i18n/flutter_i18n.dart'; class SettingsSection extends StatelessWidget { const SettingsSection({ - Key? key, + super.key, required this.title, required this.children, - }) : super(key: key); + }); final String title; final List<Widget> children; diff --git a/lib/ui/widgets/settingsView/settings_tile_dialog.dart b/lib/ui/widgets/settingsView/settings_tile_dialog.dart index ce3a817d..822ffe6f 100644 --- a/lib/ui/widgets/settingsView/settings_tile_dialog.dart +++ b/lib/ui/widgets/settingsView/settings_tile_dialog.dart @@ -3,12 +3,12 @@ import 'package:flutter_i18n/flutter_i18n.dart'; class SettingsTileDialog extends StatelessWidget { const SettingsTileDialog({ - Key? key, + super.key, required this.title, required this.subtitle, required this.onTap, this.padding, - }) : super(key: key); + }); final String title; final String subtitle; final Function()? onTap; diff --git a/lib/ui/widgets/settingsView/social_media_item.dart b/lib/ui/widgets/settingsView/social_media_item.dart index 86971a27..78e8eb94 100644 --- a/lib/ui/widgets/settingsView/social_media_item.dart +++ b/lib/ui/widgets/settingsView/social_media_item.dart @@ -3,12 +3,12 @@ import 'package:url_launcher/url_launcher.dart'; class SocialMediaItem extends StatelessWidget { const SocialMediaItem({ - Key? key, + super.key, this.icon, required this.title, this.subtitle, this.url, - }) : super(key: key); + }); final Widget? icon; final Widget title; final Widget? subtitle; diff --git a/lib/ui/widgets/settingsView/social_media_widget.dart b/lib/ui/widgets/settingsView/social_media_widget.dart index 4431ac6a..c42c526d 100644 --- a/lib/ui/widgets/settingsView/social_media_widget.dart +++ b/lib/ui/widgets/settingsView/social_media_widget.dart @@ -8,9 +8,9 @@ import 'package:revanced_manager/ui/widgets/shared/custom_icon.dart'; class SocialMediaWidget extends StatelessWidget { const SocialMediaWidget({ - Key? key, + super.key, this.padding, - }) : super(key: key); + }); final EdgeInsetsGeometry? padding; @override diff --git a/lib/ui/widgets/shared/application_item.dart b/lib/ui/widgets/shared/application_item.dart index b7336435..5f527eb1 100644 --- a/lib/ui/widgets/shared/application_item.dart +++ b/lib/ui/widgets/shared/application_item.dart @@ -8,12 +8,12 @@ import 'package:timeago/timeago.dart'; class ApplicationItem extends StatefulWidget { const ApplicationItem({ - Key? key, + super.key, required this.icon, required this.name, required this.patchDate, required this.onPressed, - }) : super(key: key); + }); final Uint8List icon; final String name; final DateTime patchDate; diff --git a/lib/ui/widgets/shared/custom_card.dart b/lib/ui/widgets/shared/custom_card.dart index 34b3c728..17b3d0e1 100644 --- a/lib/ui/widgets/shared/custom_card.dart +++ b/lib/ui/widgets/shared/custom_card.dart @@ -2,13 +2,13 @@ import 'package:flutter/material.dart'; class CustomCard extends StatelessWidget { const CustomCard({ - Key? key, + super.key, this.isFilled = true, required this.child, this.onTap, this.padding, this.backgroundColor, - }) : super(key: key); + }); final bool isFilled; final Widget child; final Function()? onTap; diff --git a/lib/ui/widgets/shared/custom_chip.dart b/lib/ui/widgets/shared/custom_chip.dart index 8f3bb418..c0567ce2 100644 --- a/lib/ui/widgets/shared/custom_chip.dart +++ b/lib/ui/widgets/shared/custom_chip.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; class CustomChip extends StatelessWidget { const CustomChip({ - Key? key, + super.key, required this.label, this.isSelected = false, this.onSelected, - }) : super(key: key); + }); final Widget label; final bool isSelected; final Function(bool)? onSelected; diff --git a/lib/ui/widgets/shared/custom_material_button.dart b/lib/ui/widgets/shared/custom_material_button.dart index 2ff80e4c..c861a709 100644 --- a/lib/ui/widgets/shared/custom_material_button.dart +++ b/lib/ui/widgets/shared/custom_material_button.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; class CustomMaterialButton extends StatelessWidget { const CustomMaterialButton({ - Key? key, + super.key, required this.label, this.isFilled = true, this.isExpanded = false, required this.onPressed, - }) : super(key: key); + }); final Widget label; final bool isFilled; final bool isExpanded; @@ -49,13 +49,13 @@ class CustomMaterialButton extends StatelessWidget { // ignore: must_be_immutable class TimerButton extends StatefulWidget { TimerButton({ - Key? key, + super.key, required this.seconds, required this.isRunning, required this.onTimerEnd, this.label = const Text(''), this.isFilled = true, - }) : super(key: key); + }); Widget label; bool isFilled; int seconds; diff --git a/lib/ui/widgets/shared/custom_popup_menu.dart b/lib/ui/widgets/shared/custom_popup_menu.dart deleted file mode 100644 index aaf24125..00000000 --- a/lib/ui/widgets/shared/custom_popup_menu.dart +++ /dev/null @@ -1,39 +0,0 @@ -import 'package:flutter/material.dart'; - -class CustomPopupMenu extends StatelessWidget { - const CustomPopupMenu({ - Key? key, - required this.onSelected, - required this.children, - }) : super(key: key); - final Function(dynamic) onSelected; - final Map<int, Widget> children; - - @override - Widget build(BuildContext context) { - return Theme( - data: Theme.of(context).copyWith(useMaterial3: false), - child: PopupMenuButton<int>( - icon: Icon( - Icons.more_vert, - color: Theme.of(context).colorScheme.secondary, - ), - onSelected: onSelected, - itemBuilder: (context) => children.entries - .map( - (entry) => PopupMenuItem<int>( - padding: const EdgeInsets.all(16.0).copyWith(right: 20), - value: entry.key, - child: entry.value, - ), - ) - .toList(), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(24), - ), - color: Theme.of(context).colorScheme.secondaryContainer, - position: PopupMenuPosition.under, - ), - ); - } -} diff --git a/lib/ui/widgets/shared/custom_sliver_app_bar.dart b/lib/ui/widgets/shared/custom_sliver_app_bar.dart index 144bd6ab..08b75af2 100644 --- a/lib/ui/widgets/shared/custom_sliver_app_bar.dart +++ b/lib/ui/widgets/shared/custom_sliver_app_bar.dart @@ -2,13 +2,13 @@ import 'package:flutter/material.dart'; class CustomSliverAppBar extends StatelessWidget { const CustomSliverAppBar({ - Key? key, + super.key, required this.title, this.actions, this.bottom, this.isMainView = false, this.onBackButtonPressed, - }) : super(key: key); + }); final Widget title; final List<Widget>? actions; final PreferredSizeWidget? bottom; diff --git a/lib/ui/widgets/shared/open_container_wrapper.dart b/lib/ui/widgets/shared/open_container_wrapper.dart index f5b1c642..458e8937 100644 --- a/lib/ui/widgets/shared/open_container_wrapper.dart +++ b/lib/ui/widgets/shared/open_container_wrapper.dart @@ -3,10 +3,10 @@ import 'package:flutter/material.dart'; class OpenContainerWrapper extends StatelessWidget { const OpenContainerWrapper({ - Key? key, + super.key, required this.openBuilder, required this.closedBuilder, - }) : super(key: key); + }); final OpenContainerBuilder openBuilder; final CloseContainerBuilder closedBuilder; diff --git a/lib/ui/widgets/shared/search_bar.dart b/lib/ui/widgets/shared/search_bar.dart index e48e3031..862584af 100644 --- a/lib/ui/widgets/shared/search_bar.dart +++ b/lib/ui/widgets/shared/search_bar.dart @@ -2,12 +2,12 @@ import 'package:flutter/material.dart'; class SearchBar extends StatefulWidget { const SearchBar({ - Key? key, + super.key, required this.hintText, this.showSelectIcon = false, this.onSelectAll, required this.onQueryChanged, - }) : super(key: key); + }); final String? hintText; final bool showSelectIcon; final Function(bool)? onSelectAll; diff --git a/pubspec.yaml b/pubspec.yaml index e5d5c80b..0f9ea933 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -4,7 +4,7 @@ homepage: https://github.com/revanced/revanced-manager publish_to: 'none' -version: 1.15.1+101500100 +version: 1.16.0+101600000 environment: sdk: '>=3.0.0 <4.0.0' @@ -86,7 +86,7 @@ dev_dependencies: json_serializable: ^6.6.1 build_runner: any flutter_launcher_icons: ^0.13.0 - flutter_lints: ^2.0.1 + flutter_lints: ^3.0.1 flutter_test: sdk: flutter injectable_generator: ^2.1.5 diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index 2a7b4456..00000000 --- a/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -include ':build.gradle' -project(':build.gradle').projectDir = new File(rootDir, 'android/build.gradle')