Compare commits

..

38 Commits

Author SHA1 Message Date
Pun
768ad0c9bc chore: merge dev branch to main branch (#1011)
ReVanced Manager v1.4.1
2023-07-15 20:33:30 +07:00
29323d4e20 build: update app version to v1.4.1 2023-07-15 12:55:59 +07:00
630b22e193 refactor: applies changes from formatter & linter 2023-07-15 12:41:03 +07:00
79116f9e67 fix(patched-applications): non-patched app showing on Installed section (#1022) 2023-07-15 08:11:51 +07:00
eb58475259 fix: showing Installed when it's actually not (#1021) 2023-07-15 08:10:36 +07:00
a879ac30fb fix: prevent unsupported operation exception (#1018) 2023-07-14 17:55:04 +07:00
c5b0621323 fix(navigation-view): back button closing the app from any page (#1019) 2023-07-13 19:25:48 +05:45
0462815014 fix(app-selector): fix text overflow on small screen (#1017) 2023-07-13 00:16:53 +05:45
e64318c947 fix(app-selector): fix text overflow on small screen 2023-07-13 00:14:47 +05:45
b784482788 chore: update libsu to 5.1.0
This should fixes some issues with root
2023-07-11 19:28:59 +07:00
2834e8b348 fix: patchable apps not showing if none of them is installed (#1009) 2023-07-11 17:11:45 +07:00
b23dfd4289 chore: merge dev branch to main branch (#1010) 2023-07-11 01:24:54 +05:30
217d525cb2 build: update app version to v1.4.0 2023-07-11 01:22:57 +05:30
85b166cbda fix: update hardcoded patch name 2023-07-11 01:21:45 +05:30
9a57f8b858 ci(build): use correct JDK version
There's no reasons to go higher than JDK 11 since we compile the application using JDK 11
2023-07-10 21:42:24 +07:00
Pun
3bfdc932c2 chore: update app description
👍👍 Patch your favourite apps, right on your device.
2023-07-10 21:27:20 +07:00
48c878af21 chore: merge dev branch to main branch (#996) 2023-07-10 16:56:50 +03:00
490a7a58fc build: update app version to v1.3.9
ReVanced Manager, 1.3.9 (10030009)

See PR #996
2023-07-10 20:40:40 +07:00
567b1a3ace refactor: improve code readability according to linter 2023-07-10 19:45:50 +07:00
6a45db8a38 refactor: improve code readability according to formatter 2023-07-10 19:36:50 +07:00
Pun
b272988929 build: always compile with the latest SDK supported by Flutter
`targetSdkVersion` is still the same, we want to test the application first before bumping up to latest.
2023-07-10 18:43:07 +07:00
9828857570 fix: fixed typo 2023-07-10 12:16:51 +05:45
ecb54d8e44 docs: improve clarity of speech in issue template (#1005)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-07-09 23:15:20 +02:00
344717b021 fix: app crash after custom source (#1003) 2023-07-08 23:07:19 +05:45
da6cf585c0 fix: app crash after custom source 2023-07-08 22:26:31 +05:45
9e93177afd feat: show warning dialog when resetting stored patches
This prevent user from accidentally resetting stored patches by showing
them warning dialog.
2023-07-08 11:01:10 +07:00
16318efb01 refactor: seperate translation string by context 2023-07-08 10:45:13 +07:00
e83e13b6d4 refactor: fix more problem with analyser
Missing trailing comma in app_selector_view
2023-07-07 22:21:22 +07:00
7c2c695d88 refactor: apply changes from analyser 2023-07-07 22:15:12 +07:00
c7b227529d chore: disable unnecessary tooltip
Remove tooltip in Navigation View, there's no impact to accessibility.

Tested using: Android TalkBack
2023-07-07 22:11:13 +07:00
14f49e9d30 docs: fix description for next page 2023-07-05 15:43:40 +02:00
1875c4ee73 fix: update button being clickable when offline (#987) 2023-07-05 19:59:53 +07:00
76c68baa1f build: update gradle to v7.6.2 2023-07-01 18:21:49 +07:00
68876a4414 build: bump version to v1.3.8 and patcher dep 2023-07-01 14:33:25 +05:30
26d7e5b60f build: bump version to v1.3.7 and patcher dep 2023-07-01 02:46:43 +03:00
e78af6ae99 chore: merge dev to main (#976) 2023-07-01 02:41:57 +03:00
6fe05cd86e feat: show all the unseen changelogs on changelog section (#970) 2023-07-01 02:41:03 +03:00
4100d7a391 fix: different message when trying to patch spilt apk (#973) 2023-07-01 02:40:30 +03:00
29 changed files with 346 additions and 173 deletions

View File

@ -29,7 +29,7 @@ body:
- type: textarea - type: textarea
attributes: attributes:
label: Steps to reproduce label: Steps to reproduce
description: Add the steps to reproduce this bug including your environment. description: Add the steps to reproduce this bug, including your environment.
placeholder: Step 1. Download some files. Step 2. ... placeholder: Step 1. Download some files. Step 2. ...
validations: validations:
required: true required: true
@ -74,20 +74,20 @@ body:
- type: textarea - type: textarea
attributes: attributes:
label: Device logs (exported using Manager settings). label: Device logs (exported using Manager settings).
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. description: Please copy and paste any relevant log output. This will be automatically formatted into code, so there is no need for backticks.
render: shell render: shell
validations: validations:
required: true required: true
- type: textarea - type: textarea
attributes: attributes:
label: Installer logs (exported using Installer menu option) [unneeded if issue is not during patching]. label: Installer logs (exported using Installer menu option) [unneeded if the issue is not during patching].
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. description: Please copy and paste any relevant log output. This will be automatically formatted into code, so there is no need for backticks.
render: shell render: shell
validations: validations:
required: false required: false
- type: textarea - type: textarea
attributes: attributes:
label: Screenshots or videos label: Screenshots or video
description: Add screenshots or videos that show the bug here. description: Add screenshots or videos that show the bug here.
placeholder: Drag and drop the screenshots/videos into this box. placeholder: Drag and drop the screenshots/videos into this box.
validations: validations:
@ -105,16 +105,16 @@ body:
validations: validations:
required: false required: false
- type: checkboxes - type: checkboxes
id: acknowledgements id: acknowledgments
attributes: attributes:
label: Acknowledgements label: Acknowledgments
description: Your issue will be closed if you haven't done these steps. description: Your issue will be closed if you haven't done these steps.
options: options:
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue. - label: I have searched the existing issues; this is new and no duplicate or related to another open issue.
required: true required: true
- label: I have written a short but informative title. - label: I have written a short but informative title.
required: true required: true
- label: I filled out all of the requested information in this issue properly. - label: I properly filled out all of the requested information in this issue.
required: true required: true
- label: The issue is related solely to the ReVanced Manager and not related to patching errors or patches - label: The issue is solely related to ReVanced Manager and not caused by patches.
required: true required: true

View File

@ -18,7 +18,7 @@ jobs:
- name: Setup JDK - name: Setup JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
java-version: '17' java-version: '11'
distribution: 'zulu' distribution: 'zulu'
cache: 'gradle' cache: 'gradle'
- name: Setup Flutter - name: Setup Flutter

View File

@ -12,10 +12,10 @@ jobs:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- name: Set env - name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Set up JDK 12 - name: Set up JDK 11
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
java-version: "12" java-version: "11"
distribution: "zulu" distribution: "zulu"
- uses: subosito/flutter-action@v2 - uses: subosito/flutter-action@v2
with: with:

View File

@ -21,7 +21,7 @@ jobs:
- name: Setup JDK - name: Setup JDK
uses: actions/setup-java@v3 uses: actions/setup-java@v3
with: with:
java-version: '17' java-version: '11'
distribution: 'zulu' distribution: 'zulu'
cache: 'gradle' cache: 'gradle'
- name: Setup Node.js - name: Setup Node.js

View File

@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion 33 compileSdkVersion flutter.compileSdkVersion
ndkVersion flutter.ndkVersion ndkVersion flutter.ndkVersion
compileOptions { compileOptions {
@ -71,7 +71,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// ReVanced // ReVanced
implementation "app.revanced:revanced-patcher:11.0.1" implementation "app.revanced:revanced-patcher:11.0.4"
// Signing & aligning // Signing & aligning
implementation("org.bouncycastle:bcpkix-jdk15on:1.70") implementation("org.bouncycastle:bcpkix-jdk15on:1.70")

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip distributionSha256Sum=a01b6587e15fe7ed120a0ee299c25982a1eee045abd6a9dd5e216b2f628ef9ac
distributionSha256Sum=6147605a23b4eff6c334927a86ff3508cb5d6722cd624c97ded4c2e8640f1f87 distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.2-bin.zip
networkTimeout=10000 networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -17,23 +17,33 @@
"homeView": { "homeView": {
"refreshSuccess": "Refreshed successfully", "refreshSuccess": "Refreshed successfully",
"widgetTitle": "Dashboard", "widgetTitle": "Dashboard",
"updatesSubtitle": "Updates", "updatesSubtitle": "Updates",
"patchedSubtitle": "Patched applications", "patchedSubtitle": "Patched applications",
"updatesAvailable": "Updates available", "updatesAvailable": "Updates available",
"noUpdates": "No updates available", "noUpdates": "No updates available",
"WIP": "Work in progress...", "WIP": "Work in progress...",
"noInstallations": "No patched applications installed", "noInstallations": "No patched applications installed",
"installed": "Installed", "installed": "Installed",
"installUpdate": "Continue to install the update?", "installUpdate": "Continue to install the update?",
"updateDialogTitle": "Update Manager", "updateDialogTitle": "Update Manager",
"updateChangelogTitle": "Changelog", "updateChangelogTitle": "Changelog",
"notificationTitle": "Update downloaded", "notificationTitle": "Update downloaded",
"notificationText": "Tap to install the update", "notificationText": "Tap to install the update",
"downloadingMessage": "Downloading update...", "downloadingMessage": "Downloading update...",
"downloadedMessage": "Update downloaded!", "downloadedMessage": "Update downloaded!",
"installingMessage": "Installing update...", "installingMessage": "Installing update...",
"errorDownloadMessage": "Unable to download update", "errorDownloadMessage": "Unable to download update",
"errorInstallMessage": "Unable to install update", "errorInstallMessage": "Unable to install update",
"noConnection": "No internet connection", "noConnection": "No internet connection",
"updatesDisabled": "Updating a patched app is currently disabled. Repatch the app again." "updatesDisabled": "Updating a patched app is currently disabled. Repatch the app again."
}, },
@ -52,15 +62,19 @@
"patcherView": { "patcherView": {
"widgetTitle": "Patcher", "widgetTitle": "Patcher",
"patchButton": "Patch", "patchButton": "Patch",
"patchDialogText": "You have selected a resource patch and a split APK installation has been detected, so patching errors may occur.\nAre you sure you want to proceed?", "patchDialogText": "You have selected a resource patch and a split APK installation has been detected, so patching errors may occur.\nAre you sure you want to proceed?",
"armv7WarningDialogText": "Patching on ARMv7 devices is not yet supported and might fail. Proceed anyways?" "armv7WarningDialogText": "Patching on ARMv7 devices is not yet supported and might fail. Proceed anyways?",
"splitApkWarningDialogText": "Patching a split APK is not yet supported and might fail. Proceed anyways?"
}, },
"appSelectorCard": { "appSelectorCard": {
"widgetTitle": "Select an application", "widgetTitle": "Select an application",
"widgetTitleSelected": "Selected application", "widgetTitleSelected": "Selected application",
"widgetSubtitle": "No application selected", "widgetSubtitle": "No application selected",
"noAppsLabel": "No applications found", "noAppsLabel": "No applications found",
"notInstalled":"App not installed", "notInstalled":"App not installed",
"currentVersion": "Current", "currentVersion": "Current",
"suggestedVersion": "Suggested", "suggestedVersion": "Suggested",
"allVersions": "All versions" "allVersions": "All versions"
@ -68,6 +82,7 @@
"patchSelectorCard": { "patchSelectorCard": {
"widgetTitle": "Select patches", "widgetTitle": "Select patches",
"widgetTitleSelected": "Selected patches", "widgetTitleSelected": "Selected patches",
"widgetSubtitle": "Select an application first", "widgetSubtitle": "Select an application first",
"widgetEmptySubtitle": "No patches selected" "widgetEmptySubtitle": "No patches selected"
}, },
@ -78,24 +93,33 @@
"appSelectorView": { "appSelectorView": {
"viewTitle": "Select an application", "viewTitle": "Select an application",
"searchBarHint": "Search applications", "searchBarHint": "Search applications",
"selectFromStorageButton": "Select from storage",
"storageButton": "Storage", "storageButton": "Storage",
"selectFromStorageButton": "Select from storage",
"errorMessage": "Unable to use selected application", "errorMessage": "Unable to use selected application",
"downloadToast": "Download function is not available yet", "downloadToast": "Download function is not available yet",
"featureNotAvailable": "Feature not implemented", "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" "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"
}, },
"patchesSelectorView": { "patchesSelectorView": {
"viewTitle": "Select patches", "viewTitle": "Select patches",
"searchBarHint": "Search patches", "searchBarHint": "Search patches",
"doneButton": "Done", "doneButton": "Done",
"default": "Default", "default": "Default",
"defaultTooltip": "Select all default patches", "defaultTooltip": "Select all default patches",
"none": "None", "none": "None",
"noneTooltip": "Deselect all patches", "noneTooltip": "Deselect all patches",
"loadPatchesSelection": "Load patches selection", "loadPatchesSelection": "Load patches selection",
"noSavedPatches": "No saved patches for the selected app.\nPress Done to save current selection.", "noSavedPatches": "No saved patches for the selected app.\nPress Done to save current selection.",
"noPatchesFound": "No patches found for the selected app", "noPatchesFound": "No patches found for the selected app",
"selectAllPatchesWarningContent": "You are about to select all patches, that includes non-suggested patches and can cause unwanted behavior." "selectAllPatchesWarningContent": "You are about to select all patches, that includes non-suggested patches and can cause unwanted behavior."
}, },
"patchItem": { "patchItem": {
@ -108,11 +132,14 @@
"installRootButton": "Install as Root", "installRootButton": "Install as Root",
"openButton": "Open", "openButton": "Open",
"shareButton": "Share file", "shareButton": "Share file",
"notificationTitle": "ReVanced Manager is patching", "notificationTitle": "ReVanced Manager is patching",
"notificationText": "Tap to return to the installer", "notificationText": "Tap to return to the installer",
"shareApkMenuOption": "Share APK", "shareApkMenuOption": "Share APK",
"exportApkMenuOption": "Export APK", "exportApkMenuOption": "Export APK",
"shareLogMenuOption": "Share log", "shareLogMenuOption": "Share log",
"installErrorDialogTitle": "Error", "installErrorDialogTitle": "Error",
"installErrorDialogText1": "Root install is not possible with the current patches selection.\nRepatch your app or choose non-root install.", "installErrorDialogText1": "Root install is not possible with the current patches selection.\nRepatch your app or choose non-root install.",
"installErrorDialogText2": "Non-root install is not possible with the current patches selection.\nRepatch your app or choose root install if you have your device rooted.", "installErrorDialogText2": "Non-root install is not possible with the current patches selection.\nRepatch your app or choose root install if you have your device rooted.",
@ -121,74 +148,95 @@
}, },
"settingsView": { "settingsView": {
"widgetTitle": "Settings", "widgetTitle": "Settings",
"appearanceSectionTitle": "Appearance", "appearanceSectionTitle": "Appearance",
"teamSectionTitle": "Team", "teamSectionTitle": "Team",
"infoSectionTitle": "Info", "infoSectionTitle": "Info",
"advancedSectionTitle": "Advanced", "advancedSectionTitle": "Advanced",
"exportSectionTitle": "Import & export",
"logsSectionTitle": "Logs", "logsSectionTitle": "Logs",
"darkThemeLabel": "Dark mode", "darkThemeLabel": "Dark mode",
"darkThemeHint": "Welcome to the dark side", "darkThemeHint": "Welcome to the dark side",
"dynamicThemeLabel": "Material You", "dynamicThemeLabel": "Material You",
"dynamicThemeHint": "Enjoy an experience closer to your device", "dynamicThemeHint": "Enjoy an experience closer to your device",
"languageLabel": "Language", "languageLabel": "Language",
"englishOption": "English", "englishOption": "English",
"sourcesLabel": "Sources", "sourcesLabel": "Sources",
"sourcesLabelHint": "Configure your custom sources", "sourcesLabelHint": "Configure your custom sources",
"hostRepositoryLabel": "Repository API",
"orgPatchesLabel": "Patches organization",
"sourcesPatchesLabel": "Patches source",
"orgIntegrationsLabel": "Integrations organization",
"sourcesIntegrationsLabel": "Integrations source", "sourcesIntegrationsLabel": "Integrations source",
"sourcesResetDialogTitle": "Reset", "sourcesResetDialogTitle": "Reset",
"sourcesResetDialogText": "Are you sure you want to reset custom sources to their default values?", "sourcesResetDialogText": "Are you sure you want to reset custom sources to their default values?",
"apiURLResetDialogText": "Are you sure you want to reset API URL to its default value?", "apiURLResetDialogText": "Are you sure you want to reset API URL to its default value?",
"contributorsLabel": "Contributors",
"contributorsHint": "A list of contributors of ReVanced",
"logsLabel": "Logs",
"logsHint": "Share Manager's logs",
"apiURLLabel": "API URL", "apiURLLabel": "API URL",
"apiURLHint": "Configure your custom API URL", "apiURLHint": "Configure your custom API URL",
"selectApiURL": "API URL", "selectApiURL": "API URL",
"hostRepositoryLabel": "Repository API",
"orgPatchesLabel": "Patches organization",
"sourcesPatchesLabel": "Patches source",
"orgIntegrationsLabel": "Integrations organization",
"contributorsLabel": "Contributors",
"contributorsHint": "A list of contributors of ReVanced",
"logsLabel": "Logs",
"logsHint": "Share Manager's logs",
"experimentalUniversalPatchesLabel": "Experimental universal patches support", "experimentalUniversalPatchesLabel": "Experimental universal patches support",
"experimentalUniversalPatchesHint": "Display all applications to use with universal patches, loading list of apps may be slower", "experimentalUniversalPatchesHint": "Display all applications to use with universal patches, loading list of apps may be slower",
"experimentalPatchesLabel": "Experimental patches support", "experimentalPatchesLabel": "Experimental patches support",
"experimentalPatchesHint": "Enable usage of unsupported patches in any app version", "experimentalPatchesHint": "Enable usage of unsupported patches in any app version",
"enabledExperimentalPatches": "Experimental patches support enabled", "enabledExperimentalPatches": "Experimental patches support enabled",
"exportSectionTitle": "Import & export",
"aboutLabel": "About", "aboutLabel": "About",
"snackbarMessage": "Copied to clipboard", "snackbarMessage": "Copied to clipboard",
"restartAppForChanges": "Restart the app to apply changes", "restartAppForChanges": "Restart the app to apply changes",
"deleteKeystoreLabel": "Delete keystore",
"deleteKeystoreHint": "Delete the keystore used to sign the app",
"deleteKeystoreDialogText": "Are you sure you want to delete the keystore used to sign patched applications?",
"deletedKeystore": "Keystore deleted",
"deleteTempDirLabel": "Delete temporary files", "deleteTempDirLabel": "Delete temporary files",
"deleteTempDirHint": "Delete unused temporary files", "deleteTempDirHint": "Delete unused temporary files",
"deletedTempDir": "Temporary files deleted", "deletedTempDir": "Temporary files deleted",
"exportPatchesLabel": "Export patches selection", "exportPatchesLabel": "Export patches selection",
"exportPatchesHint": "Export patches selection to a JSON file", "exportPatchesHint": "Export patches selection to a JSON file",
"exportedPatches": "Patches selection exported", "exportedPatches": "Patches selection exported",
"noExportFileFound": "No patches selection to export", "noExportFileFound": "No patches selection to export",
"importPatchesLabel": "Import patches selection", "importPatchesLabel": "Import patches selection",
"importPatchesHint": "Import patches selection from a JSON file", "importPatchesHint": "Import patches selection from a JSON file",
"importedPatches": "Patches selection imported", "importedPatches": "Patches selection imported",
"resetStoredPatchesLabel": "Reset patches", "resetStoredPatchesLabel": "Reset patches",
"resetStoredPatchesHint": "Reset the stored patches selection", "resetStoredPatchesHint": "Reset the stored patches selection",
"resetStoredPatchesDialogText": "Are you sure you want to reset the stored patches selection?",
"resetStoredPatches": "Patches selection has been reset", "resetStoredPatches": "Patches selection has been reset",
"jsonSelectorErrorMessage": "Unable to use selected JSON file",
"deleteLogsLabel": "Delete logs", "deleteLogsLabel": "Delete logs",
"deleteLogsHint": "Delete collected manager logs", "deleteLogsHint": "Delete collected manager logs",
"deletedLogs": "Logs deleted", "deletedLogs": "Logs deleted",
"deleteKeystoreLabel": "Delete keystore",
"deleteKeystoreHint": "Delete the keystore used to sign the app",
"deleteKeystoreDialogText": "Are you sure you want to delete the keystore used to sign patched applications?",
"deletedKeystore": "Keystore deleted",
"exportKeystoreLabel": "Export keystore", "exportKeystoreLabel": "Export keystore",
"exportKeystoreHint": "Export keystore used to sign apps", "exportKeystoreHint": "Export keystore used to sign apps",
"exportedKeystore": "Keystore exported", "exportedKeystore": "Keystore exported",
"noKeystoreExportFileFound": "No keystore to export", "noKeystoreExportFileFound": "No keystore to export",
"importKeystoreLabel": "Import keystore", "importKeystoreLabel": "Import keystore",
"importKeystoreHint": "Import keystore used to sign apps", "importKeystoreHint": "Import keystore used to sign apps",
"importedKeystore": "Keystore imported", "importedKeystore": "Keystore imported",
"keystoreSelectorErrorMessage": "Unable to use selected KEYSTORE file",
"selectKeystorePassword": "Keystore Password", "selectKeystorePassword": "Keystore Password",
"selectKeystorePasswordHint": "Select keystore password used to sign the apk" "selectKeystorePasswordHint": "Select keystore password used to sign the apk",
"jsonSelectorErrorMessage": "Unable to use selected JSON file",
"keystoreSelectorErrorMessage": "Unable to use selected KEYSTORE file"
}, },
"appInfoView": { "appInfoView": {
"widgetTitle": "App info", "widgetTitle": "App info",
@ -196,18 +244,22 @@
"uninstallButton": "Uninstall", "uninstallButton": "Uninstall",
"patchButton": "Patch", "patchButton": "Patch",
"unpatchButton": "Unpatch", "unpatchButton": "Unpatch",
"unpatchDialogText": "Are you sure you want to unpatch this app?",
"rootDialogTitle": "Error", "rootDialogTitle": "Error",
"unpatchDialogText": "Are you sure you want to unpatch this app?",
"rootDialogText": "App was installed with superuser permissions, but currently ReVanced Manager has no permissions.\nPlease grant superuser permissions first.", "rootDialogText": "App was installed with superuser permissions, but currently ReVanced Manager has no permissions.\nPlease grant superuser permissions first.",
"packageNameLabel": "Package name", "packageNameLabel": "Package name",
"originalPackageNameLabel": "Original package name", "originalPackageNameLabel": "Original package name",
"installTypeLabel": "Installation type", "installTypeLabel": "Installation type",
"rootTypeLabel": "Root", "rootTypeLabel": "Root",
"nonRootTypeLabel": "Non-root", "nonRootTypeLabel": "Non-root",
"patchedDateLabel": "Patched date", "patchedDateLabel": "Patched date",
"patchedDateHint": "{date} at {time}",
"appliedPatchesLabel": "Applied patches", "appliedPatchesLabel": "Applied patches",
"patchedDateHint": "{date} at {time}",
"appliedPatchesHint": "{quantity} applied patches", "appliedPatchesHint": "{quantity} applied patches",
"updateNotImplemented": "This feature has not been implemented yet" "updateNotImplemented": "This feature has not been implemented yet"
}, },
"contributorsView": { "contributorsView": {

View File

@ -9,6 +9,6 @@ In order to use ReVanced on your Android device, ReVanced Manager must be instal
## ⏭️ What's next ## ⏭️ What's next
The next page will guide you through patching an app. The next page will guide you through using ReVanced Manager.
Continue: [🪛 Usage](2_usage.md) Continue: [🪛 Usage](2_usage.md)

View File

@ -1,6 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:dio_cache_interceptor/dio_cache_interceptor.dart'; import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
@ -8,6 +7,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter_cache_manager/flutter_cache_manager.dart'; import 'package:flutter_cache_manager/flutter_cache_manager.dart';
import 'package:injectable/injectable.dart'; import 'package:injectable/injectable.dart';
import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patch.dart';
import 'package:revanced_manager/services/manager_api.dart';
@lazySingleton @lazySingleton
class GithubAPI { class GithubAPI {
@ -72,6 +72,41 @@ class GithubAPI {
} }
} }
Future<Map<String, dynamic>?> getLatestManagerRelease(
String repoName,
) async {
try {
final response = await _dio.get(
'/repos/$repoName/releases',
);
final Map<String, dynamic> releases = response.data[0];
int updates = 0;
final String currentVersion =
await ManagerAPI().getCurrentManagerVersion();
while (response.data[updates]['tag_name'] != 'v$currentVersion') {
updates++;
}
for (int i = 1; i < updates; i++) {
releases.update(
'body',
(value) =>
value +
'\n' +
'# ' +
response.data[i]['tag_name'] +
'\n' +
response.data[i]['body'],
);
}
return releases;
} on Exception catch (e) {
if (kDebugMode) {
print(e);
}
return null;
}
}
Future<List<String>> getCommits( Future<List<String>> getCommits(
String packageName, String packageName,
String repoName, String repoName,

View File

@ -1,12 +1,12 @@
import 'dart:io'; import 'dart:io';
import 'package:app_installer/app_installer.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:cr_file_saver/file_saver.dart'; import 'package:cr_file_saver/file_saver.dart';
import 'package:device_apps/device_apps.dart'; import 'package:device_apps/device_apps.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:injectable/injectable.dart'; import 'package:injectable/injectable.dart';
import 'package:install_plugin/install_plugin.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/models/patch.dart'; import 'package:revanced_manager/models/patch.dart';
@ -232,10 +232,8 @@ class PatcherAPI {
); );
} }
} else { } else {
await AppInstaller.installApk(_outFile!.path); final install = await InstallPlugin.installApk(_outFile!.path);
return await DeviceApps.isAppInstalled( return install['isSuccess'];
patchedApp.packageName,
);
} }
} on Exception catch (e) { } on Exception catch (e) {
if (kDebugMode) { if (kDebugMode) {

View File

@ -140,7 +140,8 @@ class RevancedAPI {
return null; return null;
} }
StreamController<double> managerUpdateProgress = StreamController<double>.broadcast(); StreamController<double> managerUpdateProgress =
StreamController<double>.broadcast();
void updateManagerDownloadProgress(int progress) { void updateManagerDownloadProgress(int progress) {
managerUpdateProgress.add(progress.toDouble()); managerUpdateProgress.add(progress.toDouble());

View File

@ -73,7 +73,7 @@ class RootAPI {
} }
Future<List<String>> getInstalledApps() async { Future<List<String>> getInstalledApps() async {
final List<String> apps = List.empty(); final List<String> apps = List.empty(growable: true);
try { try {
String? res = await Root.exec( String? res = await Root.exec(
cmd: 'ls "$_revancedDirPath"', cmd: 'ls "$_revancedDirPath"',

View File

@ -88,7 +88,7 @@ class _AppSelectorViewState extends State<AppSelectorView> {
), ),
), ),
) )
: model.apps.isEmpty : model.allApps.isEmpty
? const AppSkeletonLoader() ? const AppSkeletonLoader()
: Padding( : Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0) padding: const EdgeInsets.symmetric(horizontal: 12.0)
@ -113,7 +113,9 @@ class _AppSelectorViewState extends State<AppSelectorView> {
), ),
installedVersion: app.versionName!, installedVersion: app.versionName!,
onTap: () => model.canSelectInstalled( onTap: () => model.canSelectInstalled(
context, app.packageName), context,
app.packageName,
),
), ),
) )
.toList(), .toList(),

View File

@ -45,9 +45,7 @@ class AppSelectorViewModel extends BaseViewModel {
.length .length
.compareTo(_patcherAPI.getFilteredPatches(a.packageName).length), .compareTo(_patcherAPI.getFilteredPatches(a.packageName).length),
); );
noApps = apps.isEmpty;
getAllApps(); getAllApps();
notifyListeners(); notifyListeners();
} }
@ -57,7 +55,7 @@ class AppSelectorViewModel extends BaseViewModel {
.toSet() .toSet()
.where((name) => !apps.any((app) => app.packageName == name)) .where((name) => !apps.any((app) => app.packageName == name))
.toList(); .toList();
noApps = allApps.isEmpty;
return allApps; return allApps;
} }

View File

@ -128,7 +128,7 @@ class HomeView extends StatelessWidget {
}, },
child: model.showUpdatableApps child: model.showUpdatableApps
? AvailableUpdatesCard() ? AvailableUpdatesCard()
: InstalledAppsCard(), : const InstalledAppsCard(),
), ),
], ],
), ),

View File

@ -1,13 +1,13 @@
// ignore_for_file: use_build_context_synchronously // ignore_for_file: use_build_context_synchronously
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:app_installer/app_installer.dart';
import 'package:cross_connectivity/cross_connectivity.dart'; import 'package:cross_connectivity/cross_connectivity.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:injectable/injectable.dart'; import 'package:injectable/injectable.dart';
import 'package:install_plugin/install_plugin.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/app/app.router.dart'; import 'package:revanced_manager/app/app.router.dart';
@ -51,7 +51,7 @@ class HomeViewModel extends BaseViewModel {
_toast.showBottom('homeView.installingMessage'); _toast.showBottom('homeView.installingMessage');
final File? managerApk = await _managerAPI.downloadManager(); final File? managerApk = await _managerAPI.downloadManager();
if (managerApk != null) { if (managerApk != null) {
await AppInstaller.installApk(managerApk.path); await InstallPlugin.installApk(managerApk.path);
} else { } else {
_toast.showBottom('homeView.errorDownloadMessage'); _toast.showBottom('homeView.errorDownloadMessage');
} }
@ -72,7 +72,7 @@ class HomeViewModel extends BaseViewModel {
_toast.showBottom('homeView.installingMessage'); _toast.showBottom('homeView.installingMessage');
final File? managerApk = await _managerAPI.downloadManager(); final File? managerApk = await _managerAPI.downloadManager();
if (managerApk != null) { if (managerApk != null) {
await AppInstaller.installApk(managerApk.path); await InstallPlugin.installApk(managerApk.path);
} else { } else {
_toast.showBottom('homeView.errorDownloadMessage'); _toast.showBottom('homeView.errorDownloadMessage');
} }
@ -112,13 +112,15 @@ class HomeViewModel extends BaseViewModel {
Future<bool> hasManagerUpdates() async { Future<bool> hasManagerUpdates() async {
String currentVersion = await _managerAPI.getCurrentManagerVersion(); String currentVersion = await _managerAPI.getCurrentManagerVersion();
_latestManagerVersion = await _managerAPI.getLatestManagerVersion();
// add v to current version // add v to current version
if (!currentVersion.startsWith('v')) { if (!currentVersion.startsWith('v')) {
currentVersion = 'v$currentVersion'; currentVersion = 'v$currentVersion';
} }
_latestManagerVersion =
await _managerAPI.getLatestManagerVersion() ?? currentVersion;
if (_latestManagerVersion != currentVersion) { if (_latestManagerVersion != currentVersion) {
return true; return true;
} }
@ -270,8 +272,9 @@ class HomeViewModel extends BaseViewModel {
child: CustomMaterialButton( child: CustomMaterialButton(
label: I18nText('updateButton'), label: I18nText('updateButton'),
onPressed: () async { onPressed: () async {
await AppInstaller.installApk( await InstallPlugin.installApk(
downloadedApk!.path,); downloadedApk!.path,
);
}, },
), ),
), ),
@ -315,7 +318,7 @@ class HomeViewModel extends BaseViewModel {
// UILocalNotificationDateInterpretation.absoluteTime, // UILocalNotificationDateInterpretation.absoluteTime,
// ); // );
_toast.showBottom('homeView.installingMessage'); _toast.showBottom('homeView.installingMessage');
await AppInstaller.installApk(managerApk.path); await InstallPlugin.installApk(managerApk.path);
} else { } else {
_toast.showBottom('homeView.errorDownloadMessage'); _toast.showBottom('homeView.errorDownloadMessage');
} }
@ -345,7 +348,7 @@ class HomeViewModel extends BaseViewModel {
} }
Future<Map<String, dynamic>?> getLatestManagerRelease() { Future<Map<String, dynamic>?> getLatestManagerRelease() {
return _githubAPI.getLatestRelease(_managerAPI.defaultManagerRepo); return _githubAPI.getLatestManagerRelease(_managerAPI.defaultManagerRepo);
} }
Future<String?> getLatestPatcherReleaseTime() { Future<String?> getLatestPatcherReleaseTime() {

View File

@ -166,7 +166,7 @@ class InstallerViewModel extends BaseViewModel {
try { try {
_app.isRooted = installAsRoot; _app.isRooted = installAsRoot;
final bool hasMicroG = final bool hasMicroG =
_patches.any((p) => p.name.endsWith('microg-support')); _patches.any((p) => p.name.endsWith('MicroG support'));
final bool rootMicroG = installAsRoot && hasMicroG; final bool rootMicroG = installAsRoot && hasMicroG;
final bool rootFromStorage = installAsRoot && _app.isFromStorage; final bool rootFromStorage = installAsRoot && _app.isFromStorage;
final bool ytWithoutRootMicroG = final bool ytWithoutRootMicroG =

View File

@ -13,7 +13,16 @@ class NavigationView extends StatelessWidget {
return ViewModelBuilder<NavigationViewModel>.reactive( return ViewModelBuilder<NavigationViewModel>.reactive(
onViewModelReady: (model) => model.initialize(context), onViewModelReady: (model) => model.initialize(context),
viewModelBuilder: () => locator<NavigationViewModel>(), viewModelBuilder: () => locator<NavigationViewModel>(),
builder: (context, model, child) => Scaffold( builder: (context, model, child) => WillPopScope(
onWillPop: () async {
if (model.currentIndex == 0) {
return true;
} else {
model.setIndex(0);
return false;
}
},
child: Scaffold(
body: PageTransitionSwitcher( body: PageTransitionSwitcher(
duration: const Duration(milliseconds: 400), duration: const Duration(milliseconds: 400),
transitionBuilder: ( transitionBuilder: (
@ -42,6 +51,7 @@ class NavigationView extends StatelessWidget {
context, context,
'navigationView.dashboardTab', 'navigationView.dashboardTab',
), ),
tooltip: '',
), ),
NavigationDestination( NavigationDestination(
icon: model.isIndexSelected(1) icon: model.isIndexSelected(1)
@ -51,6 +61,7 @@ class NavigationView extends StatelessWidget {
context, context,
'navigationView.patcherTab', 'navigationView.patcherTab',
), ),
tooltip: '',
), ),
NavigationDestination( NavigationDestination(
icon: model.isIndexSelected(2) icon: model.isIndexSelected(2)
@ -60,10 +71,12 @@ class NavigationView extends StatelessWidget {
context, context,
'navigationView.settingsTab', 'navigationView.settingsTab',
), ),
tooltip: '',
), ),
], ],
), ),
), ),
),
); );
} }
} }

View File

@ -64,7 +64,7 @@ class PatcherViewModel extends BaseViewModel {
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: I18nText('warning'), title: I18nText('warning'),
backgroundColor: Theme.of(context).colorScheme.secondaryContainer, backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
content: I18nText('patcherView.armv7WarningDialogText'), content: I18nText('patcherView.splitApkWarningDialogText'),
actions: <Widget>[ actions: <Widget>[
CustomMaterialButton( CustomMaterialButton(
label: I18nText('noButton'), label: I18nText('noButton'),

View File

@ -17,8 +17,7 @@ import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart'; import 'package:stacked_services/stacked_services.dart';
class SettingsViewModel extends BaseViewModel { class SettingsViewModel extends BaseViewModel {
final NavigationService _navigationService = final NavigationService _navigationService = locator<NavigationService>();
locator<NavigationService>();
final ManagerAPI _managerAPI = locator<ManagerAPI>(); final ManagerAPI _managerAPI = locator<ManagerAPI>();
final Toast _toast = locator<Toast>(); final Toast _toast = locator<Toast>();
@ -63,11 +62,8 @@ class SettingsViewModel extends BaseViewModel {
try { try {
final File outFile = File(_managerAPI.storedPatchesFile); final File outFile = File(_managerAPI.storedPatchesFile);
if (outFile.existsSync()) { if (outFile.existsSync()) {
final String dateTime = DateTime.now() final String dateTime =
.toString() DateTime.now().toString().replaceAll(' ', '_').split('.').first;
.replaceAll(' ', '_')
.split('.')
.first;
await CRFileSaver.saveFileWithDialog( await CRFileSaver.saveFileWithDialog(
SaveFileDialogParams( SaveFileDialogParams(
sourceFilePath: outFile.path, sourceFilePath: outFile.path,
@ -87,8 +83,7 @@ class SettingsViewModel extends BaseViewModel {
Future<void> importPatches() async { Future<void> importPatches() async {
try { try {
final FilePickerResult? result = final FilePickerResult? result = await FilePicker.platform.pickFiles(
await FilePicker.platform.pickFiles(
type: FileType.custom, type: FileType.custom,
allowedExtensions: ['json'], allowedExtensions: ['json'],
); );

View File

@ -34,7 +34,8 @@ class AppSkeletonLoader extends StatelessWidget {
style: SkeletonLineStyle( style: SkeletonLineStyle(
height: 20, height: 20,
width: screenWidth * 0.4, width: screenWidth * 0.4,
borderRadius: const BorderRadius.all(Radius.circular(10)), borderRadius:
const BorderRadius.all(Radius.circular(10)),
), ),
), ),
), ),
@ -45,7 +46,8 @@ class AppSkeletonLoader extends StatelessWidget {
style: SkeletonLineStyle( style: SkeletonLineStyle(
height: 15, height: 15,
width: screenWidth * 0.6, width: screenWidth * 0.6,
borderRadius: const BorderRadius.all(Radius.circular(10)), borderRadius:
const BorderRadius.all(Radius.circular(10)),
), ),
), ),
), ),
@ -56,7 +58,8 @@ class AppSkeletonLoader extends StatelessWidget {
style: SkeletonLineStyle( style: SkeletonLineStyle(
height: 15, height: 15,
width: screenWidth * 0.5, width: screenWidth * 0.5,
borderRadius: const BorderRadius.all(Radius.circular(10)), borderRadius:
const BorderRadius.all(Radius.circular(10)),
), ),
), ),
), ),

View File

@ -66,7 +66,7 @@ class _InstalledAppItemState extends State<InstalledAppItem> {
context, context,
'installed', 'installed',
translationParams: { translationParams: {
'version':'v${widget.installedVersion}' 'version': 'v${widget.installedVersion}'
}, },
), ),
), ),
@ -75,20 +75,27 @@ class _InstalledAppItemState extends State<InstalledAppItem> {
I18nText( I18nText(
'suggested', 'suggested',
translationParams: { translationParams: {
'version' : widget.suggestedVersion.isEmpty 'version': widget.suggestedVersion.isEmpty
? FlutterI18n.translate(context, 'appSelectorCard.allVersions') ? FlutterI18n.translate(
context,
'appSelectorCard.allVersions',
)
: 'v${widget.suggestedVersion}', : 'v${widget.suggestedVersion}',
}, },
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Flexible(
child: Text(
widget.patchesCount == 1 widget.patchesCount == 1
? '${widget.patchesCount} patch' ? '${widget.patchesCount} patch'
: '${widget.patchesCount} patches', : '${widget.patchesCount} patches',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.secondary, color: Theme.of(context).colorScheme.secondary,
), ),
), ),
),
], ],
), ),
], ],

View File

@ -60,8 +60,7 @@ class _NotInstalledAppItem extends State<NotInstalledAppItem> {
child: Text( child: Text(
'', '',
style: TextStyle( style: TextStyle(
color: color: Theme.of(context).textTheme.titleLarge!.color,
Theme.of(context).textTheme.titleLarge!.color,
), ),
), ),
), ),
@ -70,20 +69,27 @@ class _NotInstalledAppItem extends State<NotInstalledAppItem> {
I18nText( I18nText(
'suggested', 'suggested',
translationParams: { translationParams: {
'version' : widget.suggestedVersion.isEmpty 'version': widget.suggestedVersion.isEmpty
? FlutterI18n.translate(context, 'appSelectorCard.allVersions') ? FlutterI18n.translate(
context,
'appSelectorCard.allVersions',
)
: 'v${widget.suggestedVersion}', : 'v${widget.suggestedVersion}',
}, },
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Text( Flexible(
child: Text(
widget.patchesCount == 1 widget.patchesCount == 1
? '${widget.patchesCount} patch' ? '${widget.patchesCount} patch'
: '${widget.patchesCount} patches', : '${widget.patchesCount} patches',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle( style: TextStyle(
color: Theme.of(context).colorScheme.secondary, color: Theme.of(context).colorScheme.secondary,
), ),
), ),
),
], ],
), ),
], ],

View File

@ -1,16 +1,49 @@
import 'package:device_apps/device_apps.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:revanced_manager/app/app.locator.dart'; import 'package:revanced_manager/app/app.locator.dart';
import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/models/patched_application.dart';
import 'package:revanced_manager/services/manager_api.dart';
import 'package:revanced_manager/ui/views/home/home_viewmodel.dart'; import 'package:revanced_manager/ui/views/home/home_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/shared/application_item.dart'; import 'package:revanced_manager/ui/widgets/shared/application_item.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
class InstalledAppsCard extends StatelessWidget { class InstalledAppsCard extends StatefulWidget {
InstalledAppsCard({Key? key}) : super(key: key); const InstalledAppsCard({Key? key}) : super(key: key);
final List<PatchedApplication> apps = @override
locator<HomeViewModel>().patchedInstalledApps; State<InstalledAppsCard> createState() => _InstalledAppsCardState();
}
class _InstalledAppsCardState extends State<InstalledAppsCard> {
List<PatchedApplication> apps = locator<HomeViewModel>().patchedInstalledApps;
final ManagerAPI _managerAPI = locator<ManagerAPI>();
List<PatchedApplication> patchedApps = [];
@override
void initState() {
super.initState();
_getApps();
}
Future _getApps() async {
if (apps.isNotEmpty) {
patchedApps = [...apps];
for (final element in apps) {
await DeviceApps.getApp(element.packageName).then((value) {
if (element.version != value?.versionName) {
patchedApps.remove(element);
}
});
}
if (apps.length != patchedApps.length) {
await _managerAPI.setPatchedApps(patchedApps);
apps.clear();
apps = [...patchedApps];
}
setState(() {});
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -45,8 +45,7 @@ class UpdateConfirmationDialog extends StatelessWidget {
children: [ children: [
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: crossAxisAlignment: CrossAxisAlignment.start,
CrossAxisAlignment.start,
children: [ children: [
I18nText( I18nText(
'homeView.updateDialogTitle', 'homeView.updateDialogTitle',
@ -63,14 +62,12 @@ class UpdateConfirmationDialog extends StatelessWidget {
children: [ children: [
Icon( Icon(
Icons.new_releases_outlined, Icons.new_releases_outlined,
color: Theme.of(context) color:
.colorScheme Theme.of(context).colorScheme.secondary,
.secondary,
), ),
const SizedBox(width: 8.0), const SizedBox(width: 8.0),
Text( Text(
snapshot.data!['tag_name'] ?? snapshot.data!['tag_name'] ?? 'Unknown',
'Unknown',
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -96,8 +93,7 @@ class UpdateConfirmationDialog extends StatelessWidget {
), ),
), ),
Padding( Padding(
padding: padding: const EdgeInsets.only(left: 24.0, bottom: 12.0),
const EdgeInsets.only(left: 24.0, bottom: 12.0),
child: I18nText( child: I18nText(
'homeView.updateChangelogTitle', 'homeView.updateChangelogTitle',
child: Text( child: Text(
@ -113,12 +109,9 @@ class UpdateConfirmationDialog extends StatelessWidget {
), ),
), ),
Container( Container(
margin: margin: const EdgeInsets.symmetric(horizontal: 24.0),
const EdgeInsets.symmetric(horizontal: 24.0),
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context) color: Theme.of(context).colorScheme.secondaryContainer,
.colorScheme
.secondaryContainer,
borderRadius: BorderRadius.circular(12.0), borderRadius: BorderRadius.circular(12.0),
), ),
child: Markdown( child: Markdown(

View File

@ -42,7 +42,9 @@ class PatchItem extends StatefulWidget {
class _PatchItemState extends State<PatchItem> { class _PatchItemState extends State<PatchItem> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
widget.isSelected = widget.isSelected && (!widget.isUnsupported || widget._managerAPI.areExperimentalPatchesEnabled()); widget.isSelected = widget.isSelected &&
(!widget.isUnsupported ||
widget._managerAPI.areExperimentalPatchesEnabled());
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0), padding: const EdgeInsets.symmetric(vertical: 4.0),
child: Opacity( child: Opacity(
@ -128,14 +130,16 @@ class _PatchItemState extends State<PatchItem> {
!widget._managerAPI !widget._managerAPI
.areExperimentalPatchesEnabled()) { .areExperimentalPatchesEnabled()) {
widget.isSelected = false; widget.isSelected = false;
widget.toast widget.toast.showBottom(
.showBottom('patchItem.unsupportedPatchVersion'); 'patchItem.unsupportedPatchVersion',
);
} else { } else {
widget.isSelected = newValue!; widget.isSelected = newValue!;
} }
if (widget.isUnsupported && if (widget.isUnsupported &&
widget.isSelected && widget.isSelected &&
!selectedUnsupportedPatches.contains(widget.name)) { !selectedUnsupportedPatches
.contains(widget.name)) {
selectedUnsupportedPatches.add(widget.name); selectedUnsupportedPatches.add(widget.name);
} }
}); });

View File

@ -34,9 +34,11 @@ class _SExperimentalPatchesState extends State<SExperimentalPatches> {
setState(() { setState(() {
_settingsViewModel.useExperimentalPatches(value); _settingsViewModel.useExperimentalPatches(value);
}); });
if(!value) { if (!value) {
for (final patch in selectedUnsupportedPatches) { for (final patch in selectedUnsupportedPatches) {
PatchesSelectorViewModel().selectedPatches.removeWhere((element) => patch == element.name); PatchesSelectorViewModel()
.selectedPatches
.removeWhere((element) => patch == element.name);
} }
selectedUnsupportedPatches.clear(); selectedUnsupportedPatches.clear();
} }

View File

@ -3,6 +3,7 @@ import 'package:flutter_i18n/widgets/I18nText.dart';
import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart'; import 'package:revanced_manager/ui/views/settings/settingsFragment/settings_manage_keystore_password.dart';
import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart'; import 'package:revanced_manager/ui/views/settings/settings_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart'; import 'package:revanced_manager/ui/widgets/settingsView/settings_section.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_material_button.dart';
final _settingsViewModel = SettingsViewModel(); final _settingsViewModel = SettingsViewModel();
@ -91,9 +92,36 @@ class SExportSection extends StatelessWidget {
), ),
), ),
subtitle: I18nText('settingsView.resetStoredPatchesHint'), subtitle: I18nText('settingsView.resetStoredPatchesHint'),
onTap: () => _settingsViewModel.resetSelectedPatches(), onTap: () => _showResetStoredPatchesDialog(context),
), ),
], ],
); );
} }
Future<void> _showResetStoredPatchesDialog(context) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
title: I18nText('warning'),
backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
content: I18nText(
'settingsView.resetStoredPatchesDialogText',
),
actions: <Widget>[
CustomMaterialButton(
isFilled: false,
label: I18nText('noButton'),
onPressed: () => Navigator.of(context).pop(),
),
CustomMaterialButton(
label: I18nText('yesButton'),
onPressed: () => {
Navigator.of(context).pop(),
_settingsViewModel.resetSelectedPatches()
},
)
],
),
);
}
} }

View File

@ -1,17 +1,16 @@
name: revanced_manager name: revanced_manager
description: The official ReVanced Manager. description: Patch your favourite apps, right on your device.
homepage: https://github.com/revanced/revanced-manager homepage: https://github.com/revanced/revanced-manager
publish_to: 'none' publish_to: 'none'
version: 1.3.6+100300006 version: 1.4.1+100400001
environment: environment:
sdk: '>=3.0.0 <4.0.0' sdk: '>=3.0.0 <4.0.0'
dependencies: dependencies:
animations: ^2.0.7 animations: ^2.0.7
app_installer: ^1.1.0
collection: ^1.17.0 collection: ^1.17.0
cross_connectivity: ^3.0.5 cross_connectivity: ^3.0.5
cr_file_saver: cr_file_saver:
@ -59,8 +58,8 @@ dependencies:
pull_to_refresh: ^2.0.0 pull_to_refresh: ^2.0.0
root: root:
git: git:
url: https://github.com/gokul1630/root url: https://github.com/EvadeMaster/root
ref: main ref: 9bcf0dc06b8e2e3ccd5fbd16bc849938e817b36b
share_extend: ^2.0.0 share_extend: ^2.0.0
shared_preferences: ^2.1.0 shared_preferences: ^2.1.0
skeletons: ^0.0.3 skeletons: ^0.0.3
@ -75,6 +74,7 @@ dependencies:
flutter_dotenv: ^5.0.2 flutter_dotenv: ^5.0.2
flutter_markdown: ^0.6.14 flutter_markdown: ^0.6.14
dio_cache_interceptor: ^3.4.0 dio_cache_interceptor: ^3.4.0
install_plugin: ^2.1.0
dev_dependencies: dev_dependencies:
json_serializable: ^6.6.1 json_serializable: ^6.6.1