mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2026-01-11 21:56:17 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8af62b917c | ||
|
|
311f114132 | ||
|
|
d015bd03f7 | ||
|
|
a61b9de0fa | ||
|
|
ef1b283917 | ||
|
|
c677f00105 | ||
|
|
8d2f778dfe | ||
|
|
c549d102f6 | ||
|
|
39a9ee4e9d | ||
|
|
a27dc6ad1c | ||
|
|
8ccb75fc8d | ||
|
|
8fc86dbe02 | ||
|
|
359f052608 | ||
|
|
4150e2265c | ||
|
|
b803ce7435 | ||
|
|
289c6cd7a9 | ||
|
|
31fc7b74c2 | ||
|
|
3e565f25be | ||
|
|
e509be4e21 | ||
|
|
170fc537ac | ||
|
|
3fe5882145 | ||
|
|
a290791410 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -138,4 +138,7 @@ app.*.map.json
|
||||
.firebase
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
node_modules/
|
||||
|
||||
# FVM
|
||||
.fvm
|
||||
@@ -98,7 +98,6 @@ linter:
|
||||
- prefer_const_declarations
|
||||
- prefer_const_literals_to_create_immutables
|
||||
- prefer_contains
|
||||
- prefer_equal_for_default_values
|
||||
- prefer_final_fields
|
||||
- prefer_final_in_for_each
|
||||
- prefer_final_locals
|
||||
|
||||
@@ -30,7 +30,6 @@ android {
|
||||
ndkVersion flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
coreLibraryDesugaringEnabled true
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
@@ -49,7 +48,6 @@ android {
|
||||
targetSdkVersion 33
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -73,21 +71,10 @@ dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
|
||||
// ReVanced
|
||||
implementation "app.revanced:revanced-patcher:7.0.0"
|
||||
implementation "app.revanced:revanced-patcher:9.0.0"
|
||||
|
||||
// Signing & aligning
|
||||
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
|
||||
implementation("com.android.tools.build:apksig:7.2.2")
|
||||
|
||||
// MicroG cronet
|
||||
implementation("org.microg:cronet-common:$cronetVersion")
|
||||
implementation("org.microg:cronet-native:$cronetVersion")
|
||||
|
||||
// Core libraries
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
// Window
|
||||
implementation 'androidx.window:window:1.0.0'
|
||||
implementation 'androidx.window:window-java:1.0.0'
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
buildscript {
|
||||
ext.cronetVersion = '102.5005.125'
|
||||
ext.kotlin_version = '1.7.10'
|
||||
repositories {
|
||||
google()
|
||||
@@ -32,6 +31,6 @@ subprojects {
|
||||
project.evaluationDependsOn(':app')
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
tasks.register("clean", Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"errorMessage": "Unable to use selected application",
|
||||
"downloadToast": "Download function is not available yet",
|
||||
"featureNotAvailable": "Feature not implemented",
|
||||
"featureNotAvailableText": "This feature has not been added yet for non-root. You'll need to select APK files from storage for now."
|
||||
"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": {
|
||||
"viewTitle": "Select patches",
|
||||
|
||||
@@ -7,13 +7,12 @@ import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:native_dio_adapter/native_dio_adapter.dart';
|
||||
import 'package:revanced_manager/models/patch.dart';
|
||||
|
||||
@lazySingleton
|
||||
class GithubAPI {
|
||||
late Dio _dio = Dio();
|
||||
|
||||
|
||||
final _cacheOptions = CacheOptions(
|
||||
store: MemCacheStore(),
|
||||
maxStale: const Duration(days: 1),
|
||||
@@ -33,22 +32,6 @@ class GithubAPI {
|
||||
|
||||
Future<void> initialize(String repoUrl) async {
|
||||
try {
|
||||
if (Platform.isIOS || Platform.isMacOS || Platform.isAndroid) {
|
||||
final CronetEngine androidCronetEngine = await CronetEngine.build(
|
||||
userAgent: 'ReVanced Manager',
|
||||
enableBrotli: true,
|
||||
enableQuic: true,
|
||||
);
|
||||
_dio.httpClientAdapter =
|
||||
NativeAdapter(androidCronetEngine: androidCronetEngine);
|
||||
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: repoUrl,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: repoUrl,
|
||||
@@ -107,7 +90,7 @@ class GithubAPI {
|
||||
final List<dynamic> commits = response.data;
|
||||
return commits
|
||||
.map(
|
||||
(commit) => (commit['commit']['message']).split('\n')[0] +
|
||||
(commit) => commit['commit']['message'].split('\n')[0] +
|
||||
' - ' +
|
||||
commit['commit']['author']['name'] +
|
||||
'\n' as String,
|
||||
@@ -126,8 +109,7 @@ class GithubAPI {
|
||||
String repoName,
|
||||
) async {
|
||||
try {
|
||||
final Map<String, dynamic>? release =
|
||||
await getLatestRelease(repoName);
|
||||
final Map<String, dynamic>? release = await getLatestRelease(repoName);
|
||||
if (release != null) {
|
||||
final Map<String, dynamic>? asset =
|
||||
(release['assets'] as List<dynamic>).firstWhereOrNull(
|
||||
@@ -166,8 +148,7 @@ class GithubAPI {
|
||||
|
||||
Future<String> getLastestReleaseVersion(String repoName) async {
|
||||
try {
|
||||
final Map<String, dynamic>? release =
|
||||
await getLatestRelease(repoName);
|
||||
final Map<String, dynamic>? release = await getLatestRelease(repoName);
|
||||
if (release != null) {
|
||||
return release['tag_name'];
|
||||
} else {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:developer';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
@@ -8,9 +7,7 @@ import 'package:dio_cache_interceptor/dio_cache_interceptor.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:native_dio_adapter/native_dio_adapter.dart';
|
||||
import 'package:revanced_manager/models/patch.dart';
|
||||
import 'package:revanced_manager/utils/check_for_gms.dart';
|
||||
import 'package:timeago/timeago.dart';
|
||||
|
||||
@lazySingleton
|
||||
@@ -25,34 +22,12 @@ class RevancedAPI {
|
||||
|
||||
Future<void> initialize(String apiUrl) async {
|
||||
try {
|
||||
final bool isGMSInstalled = await checkForGMS();
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: apiUrl,
|
||||
),
|
||||
);
|
||||
|
||||
if (!isGMSInstalled) {
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: apiUrl,
|
||||
),
|
||||
);
|
||||
log('ReVanced API: Using default engine + $isGMSInstalled');
|
||||
} else {
|
||||
if (Platform.isIOS || Platform.isMacOS || Platform.isAndroid) {
|
||||
final CronetEngine androidCronetEngine = await CronetEngine.build(
|
||||
userAgent: 'ReVanced Manager',
|
||||
enableBrotli: true,
|
||||
enableQuic: true,
|
||||
);
|
||||
_dio.httpClientAdapter =
|
||||
NativeAdapter(androidCronetEngine: androidCronetEngine);
|
||||
|
||||
_dio = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: apiUrl,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
log('ReVanced API: Using CronetEngine + $isGMSInstalled');
|
||||
}
|
||||
_dio.interceptors.add(DioCacheInterceptor(options: _cacheOptions));
|
||||
} on Exception catch (e) {
|
||||
if (kDebugMode) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/material.dart' hide SearchBar;
|
||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||
import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart';
|
||||
import 'package:revanced_manager/ui/widgets/appSelectorView/app_skeleton_loader.dart';
|
||||
@@ -78,7 +78,7 @@ class _AppSelectorViewState extends State<AppSelectorView> {
|
||||
child: model.noApps
|
||||
? Center(
|
||||
child: I18nText(
|
||||
'appSelectorView.noApps',
|
||||
'appSelectorView.noAppsLabel',
|
||||
child: Text(
|
||||
'',
|
||||
style: TextStyle(
|
||||
@@ -92,7 +92,10 @@ class _AppSelectorViewState extends State<AppSelectorView> {
|
||||
? const AppSkeletonLoader()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0)
|
||||
.copyWith(bottom: 80),
|
||||
.copyWith(
|
||||
bottom:
|
||||
MediaQuery.of(context).viewPadding.bottom + 8.0,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
...model
|
||||
@@ -108,16 +111,7 @@ class _AppSelectorViewState extends State<AppSelectorView> {
|
||||
model.getSuggestedVersion(
|
||||
app.packageName,
|
||||
),
|
||||
onTap: () {
|
||||
model.isRooted
|
||||
? model.selectApp(app).then(
|
||||
(_) => Navigator.of(context)
|
||||
.pop(),
|
||||
)
|
||||
: model.showSelectFromStorageDialog(
|
||||
context,
|
||||
);
|
||||
},
|
||||
onTap: () => model.canSelectInstalled(context, app.packageName),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
|
||||
@@ -65,6 +65,14 @@ class AppSelectorViewModel extends BaseViewModel {
|
||||
return _patcherAPI.getSuggestedVersion(packageName);
|
||||
}
|
||||
|
||||
Future<bool> checkSplitApk(String packageName) async {
|
||||
final app = await DeviceApps.getApp(packageName);
|
||||
if (app != null) {
|
||||
return app.isSplit;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> selectApp(ApplicationWithIcon application) async {
|
||||
locator<PatcherViewModel>().selectedApp = PatchedApplication(
|
||||
name: application.appName,
|
||||
@@ -78,6 +86,22 @@ class AppSelectorViewModel extends BaseViewModel {
|
||||
locator<PatcherViewModel>().loadLastSelectedPatches();
|
||||
}
|
||||
|
||||
Future<void> canSelectInstalled(
|
||||
BuildContext context,
|
||||
String packageName,
|
||||
) async {
|
||||
final app =
|
||||
await DeviceApps.getApp(packageName, true) as ApplicationWithIcon?;
|
||||
if (app != null) {
|
||||
if (await checkSplitApk(packageName) && !isRooted) {
|
||||
return showSelectFromStorageDialog(context);
|
||||
} else if (!await checkSplitApk(packageName) || isRooted) {
|
||||
selectApp(app);
|
||||
Navigator.pop(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future showSelectFromStorageDialog(BuildContext context) async {
|
||||
return showDialog(
|
||||
context: context,
|
||||
@@ -137,7 +161,6 @@ class AppSelectorViewModel extends BaseViewModel {
|
||||
isFilled: false,
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.pop(context);
|
||||
},
|
||||
label: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
|
||||
@@ -57,6 +57,7 @@ class ContributorsView extends StatelessWidget {
|
||||
title: 'contributorsView.managerContributors',
|
||||
contributors: model.managerContributors,
|
||||
),
|
||||
SizedBox(height: MediaQuery.of(context).viewPadding.bottom)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -39,13 +39,10 @@ class HomeViewModel extends BaseViewModel {
|
||||
bool showUpdatableApps = false;
|
||||
List<PatchedApplication> patchedInstalledApps = [];
|
||||
List<PatchedApplication> patchedUpdatableApps = [];
|
||||
String _managerVersion = '';
|
||||
String? _latestManagerVersion = '';
|
||||
|
||||
Future<void> initialize(BuildContext context) async {
|
||||
_managerVersion = await AboutInfo.getInfo().then(
|
||||
(value) => value.keys.contains('version') ? value['version']! : '',
|
||||
);
|
||||
_managerVersion = await _managerAPI.getCurrentManagerVersion();
|
||||
_latestManagerVersion = await _managerAPI.getLatestManagerVersion();
|
||||
await flutterLocalNotificationsPlugin.initialize(
|
||||
const InitializationSettings(
|
||||
android: AndroidInitializationSettings('ic_notification'),
|
||||
@@ -115,7 +112,6 @@ class HomeViewModel extends BaseViewModel {
|
||||
}
|
||||
|
||||
Future<bool> hasManagerUpdates() async {
|
||||
final String? latestVersion = await _managerAPI.getLatestManagerVersion();
|
||||
String currentVersion = await _managerAPI.getCurrentManagerVersion();
|
||||
|
||||
// add v to current version
|
||||
@@ -123,7 +119,7 @@ class HomeViewModel extends BaseViewModel {
|
||||
currentVersion = 'v$currentVersion';
|
||||
}
|
||||
|
||||
if (latestVersion != currentVersion) {
|
||||
if (_latestManagerVersion != currentVersion) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -194,7 +190,7 @@ class HomeViewModel extends BaseViewModel {
|
||||
),
|
||||
const SizedBox(width: 8.0),
|
||||
Text(
|
||||
'v$_managerVersion',
|
||||
'v$_latestManagerVersion',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w500,
|
||||
|
||||
@@ -20,6 +20,7 @@ class InstallerView extends StatelessWidget {
|
||||
builder: (context, model, child) => WillPopScope(
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: Scaffold(
|
||||
body: CustomScrollView(
|
||||
controller: model.scrollController,
|
||||
@@ -153,6 +154,11 @@ class InstallerView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
SliverFillRemaining(
|
||||
hasScrollBody: false,
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).viewPadding.bottom),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -86,13 +86,11 @@ class PatcherViewModel extends BaseViewModel {
|
||||
}
|
||||
|
||||
Future<void> showArmv7WarningDialog(BuildContext context) async {
|
||||
final bool armv7 = await AboutInfo.getInfo().then(
|
||||
(info) =>
|
||||
info['arch'] != null &&
|
||||
info['arch']!.contains('armeabi-v7a') &&
|
||||
!info['arch']!.contains('arm64-v8a'),
|
||||
);
|
||||
|
||||
final bool armv7 = await AboutInfo.getInfo().then((info) {
|
||||
final List<String> archs = info['arch'];
|
||||
final supportedAbis = ['arm64-v8a', 'x86', 'x86_64'];
|
||||
return !archs.any((arch) => supportedAbis.contains(arch));
|
||||
});
|
||||
if (context.mounted && armv7) {
|
||||
return showDialog(
|
||||
context: context,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/material.dart' hide SearchBar;
|
||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
|
||||
import 'package:revanced_manager/ui/widgets/patchesSelectorView/patch_item.dart';
|
||||
@@ -129,8 +129,10 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
|
||||
),
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0)
|
||||
.copyWith(bottom: 80),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12.0).copyWith(
|
||||
bottom: MediaQuery.of(context).viewPadding.bottom + 8.0,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
|
||||
@@ -33,8 +33,8 @@ class _LatestCommitCardState extends State<LatestCommitCard> {
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: const <Widget>[
|
||||
const Row(
|
||||
children: <Widget>[
|
||||
Text('ReVanced Manager'),
|
||||
],
|
||||
),
|
||||
@@ -82,8 +82,8 @@ class _LatestCommitCardState extends State<LatestCommitCard> {
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: const <Widget>[
|
||||
const Row(
|
||||
children: <Widget>[
|
||||
Text('ReVanced Patches'),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -39,9 +39,9 @@ class SocialMediaWidget extends StatelessWidget {
|
||||
),
|
||||
expanded: Padding(
|
||||
padding: padding ?? EdgeInsets.zero,
|
||||
child: CustomCard(
|
||||
child: const CustomCard(
|
||||
child: Column(
|
||||
children: const <Widget>[
|
||||
children: <Widget>[
|
||||
SocialMediaItem(
|
||||
icon: FaIcon(FontAwesomeIcons.github),
|
||||
title: Text('GitHub'),
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
// Check for google mobile services on device
|
||||
|
||||
import 'package:device_apps/device_apps.dart';
|
||||
|
||||
Future<bool> checkForGMS() async {
|
||||
bool isGMSInstalled = true;
|
||||
isGMSInstalled = await DeviceApps.isAppInstalled('com.google.android.gms') ||
|
||||
await DeviceApps.isAppInstalled('com.android.vending');
|
||||
return isGMSInstalled;
|
||||
}
|
||||
14
pubspec.yaml
14
pubspec.yaml
@@ -4,10 +4,10 @@ homepage: https://github.com/revanced/revanced-manager
|
||||
|
||||
publish_to: 'none'
|
||||
|
||||
version: 1.0.0+100000000
|
||||
version: 1.3.0+100300000
|
||||
|
||||
environment:
|
||||
sdk: ">=2.17.5 <3.0.0"
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
|
||||
dependencies:
|
||||
animations: ^2.0.7
|
||||
@@ -16,8 +16,8 @@ dependencies:
|
||||
cross_connectivity: ^3.0.5
|
||||
cr_file_saver:
|
||||
git:
|
||||
url: https://github.com/dhruvanbhalara/cr_file_saver.git
|
||||
ref: a08326ecb48f581b4b09e2e2665d31ed1704c7af
|
||||
url: https://github.com/dhruvanbhalara/cr_file_saver
|
||||
ref: "fix/incorrect_file_name"
|
||||
device_apps:
|
||||
git:
|
||||
url: https://github.com/ponces/flutter_plugin_device_apps
|
||||
@@ -36,7 +36,7 @@ dependencies:
|
||||
sdk: flutter
|
||||
flutter_background: ^1.2.0
|
||||
flutter_cache_manager: ^3.3.0
|
||||
flutter_i18n: ^0.32.4
|
||||
flutter_i18n: ^0.33.0
|
||||
flutter_local_notifications: ^13.0.0
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
@@ -47,7 +47,7 @@ dependencies:
|
||||
google_fonts: ^4.0.3
|
||||
http: ^0.13.5
|
||||
injectable: ^2.1.1
|
||||
intl: ^0.17.0
|
||||
intl: ^0.18.0
|
||||
json_annotation: ^4.8.0
|
||||
logcat:
|
||||
git:
|
||||
@@ -56,7 +56,6 @@ dependencies:
|
||||
package_info_plus: ^3.0.3
|
||||
path_provider: ^2.0.14
|
||||
permission_handler: ^10.2.0
|
||||
native_dio_adapter: ^0.1.0
|
||||
pull_to_refresh: ^2.0.0
|
||||
root:
|
||||
git:
|
||||
@@ -75,7 +74,6 @@ dependencies:
|
||||
wakelock: ^0.6.2
|
||||
flutter_dotenv: ^5.0.2
|
||||
flutter_markdown: ^0.6.14
|
||||
pub_release: ^8.0.3
|
||||
dio_cache_interceptor: ^3.4.0
|
||||
|
||||
dev_dependencies:
|
||||
|
||||
Reference in New Issue
Block a user