Compare commits

...

17 Commits

Author SHA1 Message Date
Aunali321
4c6b93320f build: Bump bump version to v0.0.13 2022-09-18 12:22:39 +05:30
Aunali321
2f3bb6cfe4 refactor: better wording. 2022-09-18 12:18:47 +05:30
oSumAtrIX
0e1fa1a5d6 build: bump patcher dependency 2022-09-18 08:38:03 +02:00
Alberto Ponces
38fb3444e4 build: Bump version to v0.0.12 2022-09-18 05:07:12 +01:00
Alberto Ponces
f10b5aebac fix: Decrease app name space a bit to prevent overflowing 2022-09-18 05:06:51 +01:00
Alberto Ponces
5a3884e159 fix: Fix uninstall apps 2022-09-18 05:06:23 +01:00
Alberto Ponces
41ac2b0df8 build: Bump version to v0.0.11 2022-09-18 04:47:23 +01:00
Alberto Ponces
52e7d76c9d fix: Fix spacing of App Info buttons 2022-09-18 04:46:21 +01:00
Alberto Ponces
3aa80cacc0 fix: Fix duplicate entries on non-root installations 2022-09-18 04:44:44 +01:00
Alberto Ponces
dd52c379b4 fix: Show updatable app item only on updatable apps listing 2022-09-18 04:12:33 +01:00
Alberto Ponces
5d073bddf2 fix: Minor i18n typo 2022-09-18 03:41:16 +01:00
Alberto Ponces
7d09169c06 build: Bump version to v0.0.10 2022-09-18 03:35:32 +01:00
Alberto Ponces
ce6f11f3f2 feat: Show recommendation version when possible 2022-09-18 03:14:48 +01:00
Alberto Ponces
d0fb6ac3c0 fix: Ignore empty results on root installed apps listing 2022-09-18 02:41:11 +01:00
Alberto Ponces
ae801a2918 fix: Fix apps reassess on root 2022-09-18 01:54:25 +01:00
Alberto Ponces
257fd46e27 fix: Improve quality of launcher and splash icons 2022-09-18 01:23:21 +01:00
Alberto Ponces
bb96c3ed63 fix: Make sure aapt lib gets extracted to native lib dir during install 2022-09-17 22:54:38 +01:00
23 changed files with 207 additions and 94 deletions

View File

@@ -71,7 +71,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// ReVanced
implementation "app.revanced:revanced-patcher:4.4.1"
implementation "app.revanced:revanced-patcher:4.4.2"
// Signing & aligning
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")

View File

@@ -1,21 +1,23 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.revanced.manager.flutter">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:label="ReVanced Manager"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:largeHeap="true">
android:largeHeap="true"
android:extractNativeLibs="true">
<activity
android:name=".MainActivity"
android:exported="true"

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

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

View File

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

View File

@@ -25,7 +25,7 @@
"downloadingMessage": "Downloading update!",
"installingMessage": "Installing update... Hang on!",
"errorDownloadMessage": "Unable to download update!",
"errorInstallMessage": "Unable to download update!",
"errorInstallMessage": "Unable to install update!",
"noConnection": "No internet connection"
},
"applicationItem": {
@@ -50,7 +50,10 @@
"widgetTitle": "Select application",
"widgetTitleSelected": "Selected application",
"widgetSubtitle": "No application selected.",
"noAppsLabel": "No applications found."
"noAppsLabel": "No applications found.",
"currentVersion": "Current",
"recommendedVersion": "Recommended",
"anyVersion": "any"
},
"patchSelectorCard": {
"widgetTitle": "Select patches",
@@ -75,7 +78,7 @@
"patchItem": {
"unsupportedWarningButton": "Unsupported version",
"unsupportedDialogTitle": "Warning",
"unsupportedDialogText": "Selecting this patch may or may not result in patching errors.\n\nApp version: {packageVersion}\nCurrent supported versions:\n{supportedVersions}"
"unsupportedDialogText": "Selecting this patch may result in patching errors.\n\nApp version: {packageVersion}\nCurrent supported versions:\n{supportedVersions}"
},
"installerView": {
"widgetTitle": "Installer",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -182,23 +182,27 @@ class ManagerAPI {
List<PatchedApplication> patchedApps,
) async {
List<PatchedApplication> unsavedApps = [];
List<String> installedApps = await _rootAPI.getInstalledApps();
for (String packageName in installedApps) {
if (!patchedApps.any((app) => app.packageName == packageName)) {
ApplicationWithIcon? application =
await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?;
if (application != null) {
unsavedApps.add(
PatchedApplication(
name: application.appName,
packageName: application.packageName,
version: application.versionName!,
apkFilePath: application.apkFilePath,
icon: application.icon,
patchDate: DateTime.now(),
isRooted: true,
),
);
bool hasRootPermissions = await _rootAPI.hasRootPermissions();
if (hasRootPermissions) {
List<String> installedApps = await _rootAPI.getInstalledApps();
for (String packageName in installedApps) {
if (!patchedApps.any((app) => app.packageName == packageName)) {
ApplicationWithIcon? application =
await DeviceApps.getApp(packageName, true)
as ApplicationWithIcon?;
if (application != null) {
unsavedApps.add(
PatchedApplication(
name: application.appName,
packageName: application.packageName,
version: application.versionName!,
apkFilePath: application.apkFilePath,
icon: application.icon,
patchDate: DateTime.now(),
isRooted: true,
),
);
}
}
}
}
@@ -208,7 +212,8 @@ class ManagerAPI {
);
for (Application app in userApps) {
if (app.packageName.startsWith('app.revanced') &&
!app.packageName.startsWith('app.revanced.manager.')) {
!app.packageName.startsWith('app.revanced.manager.') &&
!patchedApps.any((uapp) => uapp.packageName == app.packageName)) {
ApplicationWithIcon? application =
await DeviceApps.getApp(app.packageName, true)
as ApplicationWithIcon?;
@@ -227,7 +232,6 @@ class ManagerAPI {
}
}
}
return unsavedApps;
}
@@ -260,14 +264,15 @@ class ManagerAPI {
Future<bool> isAppUninstalled(PatchedApplication app) async {
bool existsRoot = false;
bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName);
if (app.isRooted) {
bool hasRootPermissions = await _rootAPI.hasRootPermissions();
if (hasRootPermissions) {
existsRoot = await _rootAPI.isAppInstalled(app.packageName);
}
return !existsRoot || !existsNonRoot;
}
bool existsNonRoot = await DeviceApps.isAppInstalled(app.packageName);
return !existsRoot && !existsNonRoot;
return !existsNonRoot;
}
Future<bool> hasAppUpdates(String packageName, DateTime patchDate) async {

View File

@@ -220,4 +220,32 @@ class PatcherAPI {
log.writeAsStringSync(logs);
ShareExtend.share(log.path, 'file');
}
String getRecommendedVersion(String packageName) {
Map<String, int> versions = {};
for (Patch patch in _patches) {
Package? package = patch.compatiblePackages.firstWhereOrNull(
(pack) => pack.name == packageName,
);
if (package != null) {
for (String version in package.versions) {
versions.update(
version,
(value) => versions[version]! + 1,
ifAbsent: () => 1,
);
}
}
}
if (versions.isNotEmpty) {
var entries = versions.entries.toList()
..sort((a, b) => a.value.compareTo(b.value));
versions
..clear()
..addEntries(entries);
versions.removeWhere((key, value) => value != versions.values.last);
return (versions.keys.toList()..sort()).last;
}
return '';
}
}

View File

@@ -59,15 +59,8 @@ class RootAPI {
);
if (res != null) {
List<String> apps = res.split('\n');
List<String> toRemove = [];
for (String packageName in apps) {
bool isInstalled = await isAppInstalled(packageName);
if (!isInstalled) {
toRemove.add(packageName);
}
}
apps.removeWhere((a) => toRemove.contains(a));
return apps;
apps.removeWhere((pack) => pack.isEmpty);
return apps.map((pack) => pack.trim()).toList();
}
} on Exception {
return List.empty();

View File

@@ -74,7 +74,10 @@ class HomeViewModel extends BaseViewModel {
}
void _getPatchedApps() {
patchedInstalledApps = _managerAPI.getPatchedApps().toList();
patchedInstalledApps = _managerAPI
.getPatchedApps()
.where((app) => app.hasUpdates == false)
.toList();
patchedUpdatableApps = _managerAPI
.getPatchedApps()
.where((app) => app.hasUpdates == true)

View File

@@ -79,4 +79,32 @@ class PatcherViewModel extends BaseViewModel {
);
}
}
String getAppSelectionString() {
String text = '${selectedApp!.name} (${selectedApp!.packageName})';
if (text.length > 32) {
text = '${text.substring(0, 32)}...)';
}
return text;
}
String getRecommendedVersionString(BuildContext context) {
String recommendedVersion =
_patcherAPI.getRecommendedVersion(selectedApp!.packageName);
if (recommendedVersion.isEmpty) {
recommendedVersion = FlutterI18n.translate(
context,
'appSelectorCard.anyVersion',
);
} else {
recommendedVersion = 'v$recommendedVersion';
}
return '${FlutterI18n.translate(
context,
'appSelectorCard.currentVersion',
)}: v${selectedApp!.version}\n${FlutterI18n.translate(
context,
'appSelectorCard.recommendedVersion',
)}: $recommendedVersion';
}
}

View File

@@ -64,8 +64,9 @@ class AppInfoView extends StatelessWidget {
CustomCard(
child: IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
!app.isRooted ? const Spacer() : Container(),
InkWell(
onTap: () => model.openApp(app),
child: Column(
@@ -92,9 +93,11 @@ class AppInfoView extends StatelessWidget {
],
),
),
const Spacer(),
VerticalDivider(
color: Theme.of(context).canvasColor,
),
const Spacer(),
InkWell(
onTap: () => model.showUninstallAlertDialog(
context,
@@ -125,9 +128,11 @@ class AppInfoView extends StatelessWidget {
],
),
),
const Spacer(),
VerticalDivider(
color: Theme.of(context).canvasColor,
),
const Spacer(),
InkWell(
onTap: () {
model.navigateToPatcher(app);
@@ -157,45 +162,49 @@ class AppInfoView extends StatelessWidget {
],
),
),
Visibility(
visible: app.isRooted,
child: VerticalDivider(
color: Theme.of(context).canvasColor,
),
),
Visibility(
visible: app.isRooted,
child: InkWell(
onTap: () => model.showUninstallAlertDialog(
context,
app,
true,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons.settings_backup_restore_outlined,
color:
Theme.of(context).colorScheme.primary,
app.isRooted ? const Spacer() : Container(),
app.isRooted
? VerticalDivider(
color: Theme.of(context).canvasColor,
)
: Container(),
app.isRooted ? const Spacer() : Container(),
app.isRooted
? InkWell(
onTap: () => model.showUninstallAlertDialog(
context,
app,
true,
),
const SizedBox(height: 10),
I18nText(
'appInfoView.unpatchButton',
child: Text(
'',
style: TextStyle(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
Icon(
Icons
.settings_backup_restore_outlined,
color: Theme.of(context)
.colorScheme
.primary,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
I18nText(
'appInfoView.unpatchButton',
child: Text(
'',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.primary,
fontWeight: FontWeight.bold,
),
),
),
],
),
],
),
),
),
)
: Container(),
!app.isRooted ? const Spacer() : Container(),
],
),
),

View File

@@ -30,8 +30,9 @@ class AppInfoViewModel extends BaseViewModel {
}
}
} else {
DeviceApps.uninstallApp(app.packageName);
_managerAPI.deletePatchedApp(app);
DeviceApps.uninstallApp(app.packageName).then(
(value) => _managerAPI.deletePatchedApp(app),
);
}
}

View File

@@ -39,7 +39,7 @@ class AppSelectorCard extends StatelessWidget {
: Row(
children: <Widget>[
SizedBox(
height: 16.0,
height: 18.0,
child: ClipOval(
child: Image.memory(
locator<PatcherViewModel>().selectedApp == null
@@ -49,8 +49,23 @@ class AppSelectorCard extends StatelessWidget {
),
),
),
const SizedBox(width: 4),
Text(_getAppSelection()),
const SizedBox(width: 6),
Text(locator<PatcherViewModel>().getAppSelectionString()),
],
),
locator<PatcherViewModel>().selectedApp == null
? Container()
: Column(
children: [
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.only(left: 20),
child: Text(
locator<PatcherViewModel>()
.getRecommendedVersionString(context),
style: const TextStyle(fontStyle: FontStyle.italic),
),
),
],
),
],
@@ -58,10 +73,4 @@ class AppSelectorCard extends StatelessWidget {
),
);
}
String _getAppSelection() {
String name = locator<PatcherViewModel>().selectedApp!.name;
String version = locator<PatcherViewModel>().selectedApp!.version;
return '$name (v$version)';
}
}

View File

@@ -74,8 +74,8 @@ class _ApplicationItemState extends State<ApplicationItem>
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
widget.name.length > 10
? '${widget.name.substring(0, 10)}...'
widget.name.length > 9
? '${widget.name.substring(0, 9)}...'
: widget.name,
style: const TextStyle(
fontSize: 16,

View File

@@ -4,7 +4,7 @@ homepage: https://github.com/revanced/revanced-manager
publish_to: 'none'
version: 0.0.9+9
version: 0.0.13+13
environment:
sdk: ">=2.17.5 <3.0.0"
@@ -75,13 +75,6 @@ dev_dependencies:
injectable_generator: ^1.5.4
json_serializable: ^6.3.1
flutter_icons:
android: true
ios: false
image_path: "assets/images/ic_launcher_round.png"
adaptive_icon_background: "#1B1B1B"
adaptive_icon_foreground: "assets/images/ic_launcher.png"
flutter:
uses-material-design: true
assets: