Compare commits

...

21 Commits

Author SHA1 Message Date
Aunali321
4cfb620d63 build: Bump version to v0.0.8. 2022-09-17 20:58:19 +05:30
Aunali321
55739a9c78 fix: background should be more opaque. 2022-09-17 20:56:44 +05:30
Alberto Ponces
482599bb4e fix: Do not import dart:html 2022-09-17 14:59:23 +01:00
Alberto Ponces
3aaf49fee0 fix: Only init foreground service if user allowed IGNORE_BATTERY_OPTIMIZATIONS permission 2022-09-17 14:55:00 +01:00
Alberto Ponces
0424ee235c build: Bump patcher dependency version 2022-09-17 14:51:09 +01:00
Alberto Ponces
a178afce99 fix: Fix typo on menu options visibility 2022-09-17 14:47:03 +01:00
Alberto Ponces
ef3685c817 fix: Add Unpatch option on App Info view 2022-09-17 14:45:43 +01:00
Alberto Ponces
e74fce8574 Merge branch 'flutter' of github.com:revanced/revanced-manager into flutter 2022-09-17 14:42:58 +01:00
Aunali321
73e4ae1416 build: restrict manager to android 8. 2022-09-17 16:14:24 +03:00
afnzmn
bcf3b36b13 feat: tweak UI 2022-09-17 16:13:41 +03:00
Alberto Ponces
9c3626c8ed fix: Request permissions a single time at boot 2022-09-16 17:29:32 +01:00
Alberto Ponces
a3dca8c142 fix: Add build mode to about widget 2022-09-16 16:39:57 +01:00
Alberto Ponces
ef0c59f693 fix: Surround isRooted with a try/catch just to be safe 2022-09-16 16:39:37 +01:00
Aunali321
31756884b6 build: Bump version to v0.0.7. 2022-09-16 03:48:23 +05:30
Aunali321
0a2a495ab0 feat: custom animated progressbar. 2022-09-16 03:46:46 +05:30
Aunali321
8300cc4071 feat: dropdown for changelogs. 2022-09-16 00:49:11 +05:30
Alberto Ponces
9f58757caf feat: Apply dark/light mode to system navigation bar too 2022-09-15 13:27:48 +01:00
Alberto Ponces
5d296038b7 fix: Increase API's maxAge to 1 day 2022-09-15 12:33:19 +01:00
Alberto Ponces
9f85450c6c build: Bump version to v0.0.6 2022-09-15 09:14:43 +01:00
Alberto Ponces
cba4e175a3 build: Bump version to v0.0.5 2022-09-15 02:27:36 +01:00
Alberto Ponces
cf3fa935ce fix: Fix select from storage for Android 13 devices 2022-09-15 02:18:07 +01:00
23 changed files with 304 additions and 112 deletions

View File

@@ -44,7 +44,7 @@ android {
defaultConfig { defaultConfig {
applicationId "app.revanced.manager.flutter" applicationId "app.revanced.manager.flutter"
minSdkVersion 21 minSdkVersion 26
targetSdkVersion 33 targetSdkVersion 33
versionCode flutterVersionCode.toInteger() versionCode flutterVersionCode.toInteger()
versionName flutterVersionName versionName flutterVersionName
@@ -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:4.4.0" implementation "app.revanced:revanced-patcher:4.4.1"
// Signing & aligning // Signing & aligning
implementation("org.bouncycastle:bcpkix-jdk15on:1.70") implementation("org.bouncycastle:bcpkix-jdk15on:1.70")

View File

@@ -1,6 +1,9 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="app.revanced.manager.flutter"> package="app.revanced.manager.flutter">
<uses-permission android:name="android.permission.INTERNET" /> <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.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

View File

@@ -69,7 +69,8 @@
}, },
"patchesSelectorView": { "patchesSelectorView": {
"searchBarHint": "Search patches", "searchBarHint": "Search patches",
"doneButton": "Done" "doneButton": "Done",
"noPatchesFound": "No patches found for the selected app."
}, },
"patchItem": { "patchItem": {
"unsupportedWarningButton": "Unsupported version", "unsupportedWarningButton": "Unsupported version",
@@ -120,8 +121,11 @@
"openButton": "Open", "openButton": "Open",
"uninstallButton": "Uninstall", "uninstallButton": "Uninstall",
"patchButton": "Patch", "patchButton": "Patch",
"unpatchButton": "Unpatch",
"uninstallDialogTitle": "Uninstall", "uninstallDialogTitle": "Uninstall",
"uninstallDialogText": "Are you sure you want to uninstall this app?", "uninstallDialogText": "Are you sure you want to uninstall this app?",
"unpatchDialogTitle": "Unpatch",
"unpatchDialogText": "Are you sure you want to unpatch this app?",
"rootDialogTitle": "Error", "rootDialogTitle": "Error",
"rootDialogText": "App was installed with root mode enabled but currently root mode is disabled.\nPlease enable root mode first.", "rootDialogText": "App was installed with root mode enabled but currently root mode is disabled.\nPlease enable root mode first.",
"packageNameLabel": "Package Name", "packageNameLabel": "Package Name",

View File

@@ -13,7 +13,7 @@ class GithubAPI {
final Dio _dio = Dio(); final Dio _dio = Dio();
final DioCacheManager _dioCacheManager = DioCacheManager(CacheConfig()); final DioCacheManager _dioCacheManager = DioCacheManager(CacheConfig());
final Options _cacheOptions = buildCacheOptions( final Options _cacheOptions = buildCacheOptions(
const Duration(hours: 1), const Duration(days: 1),
maxStale: const Duration(days: 7), maxStale: const Duration(days: 7),
); );
final Map<String, String> repoAppPath = { final Map<String, String> repoAppPath = {

View File

@@ -13,7 +13,7 @@ class RevancedAPI {
final Dio _dio = Dio(); final Dio _dio = Dio();
final DioCacheManager _dioCacheManager = DioCacheManager(CacheConfig()); final DioCacheManager _dioCacheManager = DioCacheManager(CacheConfig());
final Options _cacheOptions = buildCacheOptions( final Options _cacheOptions = buildCacheOptions(
const Duration(hours: 1), const Duration(days: 1),
maxStale: const Duration(days: 7), maxStale: const Duration(days: 7),
); );

View File

@@ -6,8 +6,12 @@ class RootAPI {
final String _serviceDDirPath = '/data/adb/service.d'; final String _serviceDDirPath = '/data/adb/service.d';
Future<bool> hasRootPermissions() async { Future<bool> hasRootPermissions() async {
bool? isRooted = await Root.isRooted(); try {
return isRooted != null && isRooted; bool? isRooted = await Root.isRooted();
return isRooted != null && isRooted;
} on Exception {
return false;
}
} }
Future<void> setPermissions( Future<void> setPermissions(

View File

@@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart';
var lightCustomColorScheme = ColorScheme.fromSeed( var lightCustomColorScheme = ColorScheme.fromSeed(
seedColor: Colors.blue, seedColor: Colors.blue,
brightness: Brightness.light, brightness: Brightness.light,
primary: const Color(0xff1B73E8),
); );
var lightCustomTheme = ThemeData( var lightCustomTheme = ThemeData(
@@ -23,8 +24,8 @@ var lightCustomTheme = ThemeData(
var darkCustomColorScheme = ColorScheme.fromSeed( var darkCustomColorScheme = ColorScheme.fromSeed(
seedColor: Colors.blue, seedColor: Colors.blue,
brightness: Brightness.dark, brightness: Brightness.dark,
primary: const Color(0xff7792BA), primary: const Color(0xffA5CAFF),
surface: const Color(0xff0A0D11), surface: const Color(0xff1B1A1D),
); );
var darkCustomTheme = ThemeData( var darkCustomTheme = ThemeData(
@@ -38,8 +39,8 @@ var darkCustomTheme = ThemeData(
), ),
), ),
), ),
canvasColor: const Color(0xff0A0D11), canvasColor: const Color(0xff1B1A1D),
scaffoldBackgroundColor: const Color(0xff0A0D11), scaffoldBackgroundColor: const Color(0xff1B1A1D),
toggleableActiveColor: const Color(0xff7792BA), toggleableActiveColor: const Color(0xffA5CAFF),
textTheme: GoogleFonts.robotoTextTheme(ThemeData.dark().textTheme), textTheme: GoogleFonts.robotoTextTheme(ThemeData.dark().textTheme),
); );

View File

@@ -3,6 +3,7 @@ import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart'; import 'package:revanced_manager/ui/views/installer/installer_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/installerView/custom_material_button.dart'; import 'package:revanced_manager/ui/widgets/installerView/custom_material_button.dart';
import 'package:revanced_manager/ui/widgets/installerView/gradient_progress_indicator.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_card.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_popup_menu.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_popup_menu.dart';
import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart'; import 'package:revanced_manager/ui/widgets/shared/custom_sliver_app_bar.dart';
@@ -30,7 +31,7 @@ class InstallerView extends StatelessWidget {
), ),
actions: <Widget>[ actions: <Widget>[
Visibility( Visibility(
visible: !model.isPatching && model.hasErrors, visible: !model.isPatching && !model.hasErrors,
child: CustomPopupMenu( child: CustomPopupMenu(
onSelected: (value) => model.onMenuSelection(value), onSelected: (value) => model.onMenuSelection(value),
children: { children: {
@@ -57,14 +58,9 @@ class InstallerView extends StatelessWidget {
), ),
], ],
bottom: PreferredSize( bottom: PreferredSize(
preferredSize: const Size(double.infinity, 1.0), preferredSize: const Size(double.infinity, 1.0),
child: LinearProgressIndicator( child:
color: Theme.of(context).colorScheme.primary, GradientProgressIndicator(progress: model.progress!)),
backgroundColor:
Theme.of(context).colorScheme.primaryContainer,
value: model.progress,
),
),
), ),
SliverPadding( SliverPadding(
padding: const EdgeInsets.all(20.0), padding: const EdgeInsets.all(20.0),

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_background/flutter_background.dart'; import 'package:flutter_background/flutter_background.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:permission_handler/permission_handler.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';
import 'package:revanced_manager/models/patched_application.dart'; import 'package:revanced_manager/models/patched_application.dart';
@@ -29,29 +30,31 @@ class InstallerViewModel extends BaseViewModel {
bool hasErrors = false; bool hasErrors = false;
Future<void> initialize(BuildContext context) async { Future<void> initialize(BuildContext context) async {
try { if (await Permission.ignoreBatteryOptimizations.isGranted) {
await FlutterBackground.initialize( try {
androidConfig: FlutterBackgroundAndroidConfig( await FlutterBackground.initialize(
notificationTitle: FlutterI18n.translate( androidConfig: FlutterBackgroundAndroidConfig(
context, notificationTitle: FlutterI18n.translate(
'installerView.notificationTitle', context,
'installerView.notificationTitle',
),
notificationText: FlutterI18n.translate(
context,
'installerView.notificationText',
),
notificationImportance: AndroidNotificationImportance.Default,
notificationIcon: const AndroidResource(
name: 'ic_notification',
defType: 'drawable',
),
), ),
notificationText: FlutterI18n.translate( );
context, await FlutterBackground.enableBackgroundExecution();
'installerView.notificationText', } on Exception {
), // ignore
notificationImportance: AndroidNotificationImportance.Default, }
notificationIcon: const AndroidResource(
name: 'ic_notification',
defType: 'drawable',
),
),
);
await FlutterBackground.enableBackgroundExecution();
await Wakelock.enable();
} on Exception {
// ignore
} }
await Wakelock.enable();
await handlePlatformChannelMethods(); await handlePlatformChannelMethods();
await runPatcher(); await runPatcher();
} }
@@ -119,12 +122,14 @@ class InstallerViewModel extends BaseViewModel {
hasErrors = true; hasErrors = true;
update(-1.0, 'Aborting...', 'No app or patches selected! Aborting'); update(-1.0, 'Aborting...', 'No app or patches selected! Aborting');
} }
try { if (await Permission.ignoreBatteryOptimizations.isGranted) {
await FlutterBackground.disableBackgroundExecution(); try {
await Wakelock.disable(); await FlutterBackground.disableBackgroundExecution();
} on Exception { } on Exception {
// ignore // ignore
}
} }
await Wakelock.disable();
isPatching = false; isPatching = false;
} }

View File

@@ -42,6 +42,7 @@ class NavigationView extends StatelessWidget {
context, context,
'navigationView.dashboardTab', 'navigationView.dashboardTab',
), ),
tooltip: '',
), ),
NavigationDestination( NavigationDestination(
icon: model.isIndexSelected(1) icon: model.isIndexSelected(1)
@@ -51,6 +52,7 @@ class NavigationView extends StatelessWidget {
context, context,
'navigationView.patcherTab', 'navigationView.patcherTab',
), ),
tooltip: '',
), ),
NavigationDestination( NavigationDestination(
icon: model.isIndexSelected(2) icon: model.isIndexSelected(2)
@@ -60,6 +62,7 @@ class NavigationView extends StatelessWidget {
context, context,
'navigationView.settingsTab', 'navigationView.settingsTab',
), ),
tooltip: '',
), ),
], ],
), ),

View File

@@ -1,6 +1,7 @@
// ignore_for_file: use_build_context_synchronously // ignore_for_file: use_build_context_synchronously
import 'package:dynamic_themes/dynamic_themes.dart'; import 'package:dynamic_themes/dynamic_themes.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:injectable/injectable.dart'; import 'package:injectable/injectable.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:revanced_manager/services/root_api.dart'; import 'package:revanced_manager/services/root_api.dart';
@@ -15,17 +16,27 @@ class NavigationViewModel extends IndexTrackingViewModel {
void initialize(BuildContext context) async { void initialize(BuildContext context) async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
if (prefs.getBool('useDarkTheme') == null) { if (prefs.getBool('useDarkTheme') == null) {
if (MediaQuery.of(context).platformBrightness == Brightness.light) { bool isDark =
await prefs.setBool('useDarkTheme', false); MediaQuery.of(context).platformBrightness != Brightness.light;
DynamicTheme.of(context)!.setTheme(0); await prefs.setBool('useDarkTheme', isDark);
} else { await DynamicTheme.of(context)!.setTheme(isDark ? 1 : 0);
await prefs.setBool('useDarkTheme', true); }
DynamicTheme.of(context)!.setTheme(1); SystemChrome.setSystemUIOverlayStyle(
} SystemUiOverlayStyle(
systemNavigationBarColor:
DynamicTheme.of(context)!.theme.colorScheme.surface,
systemNavigationBarIconBrightness:
DynamicTheme.of(context)!.theme.brightness == Brightness.light
? Brightness.dark
: Brightness.light,
),
);
if (prefs.getBool('permissionsRequested') == null) {
await prefs.setBool('permissionsRequested', true);
RootAPI().hasRootPermissions();
Permission.requestInstallPackages.request();
Permission.ignoreBatteryOptimizations.request();
} }
RootAPI().hasRootPermissions();
Permission.requestInstallPackages.request();
Permission.ignoreBatteryOptimizations.request();
} }
Widget getViewForIndex(int index) { Widget getViewForIndex(int index) {

View File

@@ -55,9 +55,16 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
const SizedBox(height: 12), const SizedBox(height: 12),
Expanded( Expanded(
child: model.patches.isEmpty child: model.patches.isEmpty
? Center( ? Padding(
child: CircularProgressIndicator( padding: const EdgeInsets.all(8.0),
color: Theme.of(context).colorScheme.primary, child: Center(
child: I18nText(
'patchesSelectorView.noPatchesFound',
child: Text(
'',
style: Theme.of(context).textTheme.bodyMedium,
),
),
), ),
) )
: ListView( : ListView(

View File

@@ -3,6 +3,7 @@ import 'dart:io';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:dynamic_themes/dynamic_themes.dart'; import 'package:dynamic_themes/dynamic_themes.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:logcat/logcat.dart'; import 'package:logcat/logcat.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
@@ -50,10 +51,16 @@ class SettingsViewModel extends BaseViewModel {
await _managerAPI.setUseDynamicTheme(value); await _managerAPI.setUseDynamicTheme(value);
int currentTheme = DynamicTheme.of(context)!.themeId; int currentTheme = DynamicTheme.of(context)!.themeId;
if (currentTheme.isEven) { if (currentTheme.isEven) {
DynamicTheme.of(context)!.setTheme(value ? 2 : 0); await DynamicTheme.of(context)!.setTheme(value ? 2 : 0);
} else { } else {
DynamicTheme.of(context)!.setTheme(value ? 3 : 1); await DynamicTheme.of(context)!.setTheme(value ? 3 : 1);
} }
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
systemNavigationBarColor:
DynamicTheme.of(context)!.theme.colorScheme.surface,
),
);
notifyListeners(); notifyListeners();
} }
@@ -65,10 +72,18 @@ class SettingsViewModel extends BaseViewModel {
await _managerAPI.setUseDarkTheme(value); await _managerAPI.setUseDarkTheme(value);
int currentTheme = DynamicTheme.of(context)!.themeId; int currentTheme = DynamicTheme.of(context)!.themeId;
if (currentTheme < 2) { if (currentTheme < 2) {
DynamicTheme.of(context)!.setTheme(value ? 1 : 0); await DynamicTheme.of(context)!.setTheme(value ? 1 : 0);
} else { } else {
DynamicTheme.of(context)!.setTheme(value ? 3 : 2); await DynamicTheme.of(context)!.setTheme(value ? 3 : 2);
} }
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
systemNavigationBarColor:
DynamicTheme.of(context)!.theme.colorScheme.surface,
systemNavigationBarIconBrightness:
value ? Brightness.light : Brightness.dark,
),
);
notifyListeners(); notifyListeners();
} }

View File

@@ -64,7 +64,7 @@ class AppInfoView extends StatelessWidget {
CustomCard( CustomCard(
child: IntrinsicHeight( child: IntrinsicHeight(
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[ children: <Widget>[
InkWell( InkWell(
onTap: () => model.openApp(app), onTap: () => model.openApp(app),
@@ -96,8 +96,11 @@ class AppInfoView extends StatelessWidget {
color: Theme.of(context).canvasColor, color: Theme.of(context).canvasColor,
), ),
InkWell( InkWell(
onTap: () => onTap: () => model.showUninstallAlertDialog(
model.showUninstallAlertDialog(context, app), context,
app,
false,
),
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[ children: <Widget>[
@@ -154,6 +157,45 @@ 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,
),
const SizedBox(height: 10),
I18nText(
'appInfoView.unpatchButton',
child: Text(
'',
style: TextStyle(
color: Theme.of(context)
.colorScheme
.primary,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
], ],
), ),
), ),

View File

@@ -19,12 +19,15 @@ class AppInfoViewModel extends BaseViewModel {
final PatcherAPI _patcherAPI = locator<PatcherAPI>(); final PatcherAPI _patcherAPI = locator<PatcherAPI>();
final RootAPI _rootAPI = RootAPI(); final RootAPI _rootAPI = RootAPI();
Future<void> uninstallApp(PatchedApplication app) async { Future<void> uninstallApp(PatchedApplication app, bool onlyUnpatch) async {
if (app.isRooted) { if (app.isRooted) {
bool hasRootPermissions = await _rootAPI.hasRootPermissions(); bool hasRootPermissions = await _rootAPI.hasRootPermissions();
if (hasRootPermissions) { if (hasRootPermissions) {
_rootAPI.deleteApp(app.packageName, app.apkFilePath); _rootAPI.deleteApp(app.packageName, app.apkFilePath);
_managerAPI.deletePatchedApp(app); _managerAPI.deletePatchedApp(app);
if (!onlyUnpatch) {
DeviceApps.uninstallApp(app.packageName);
}
} }
} else { } else {
DeviceApps.uninstallApp(app.packageName); DeviceApps.uninstallApp(app.packageName);
@@ -43,32 +46,39 @@ class AppInfoViewModel extends BaseViewModel {
Future<void> showUninstallAlertDialog( Future<void> showUninstallAlertDialog(
BuildContext context, BuildContext context,
PatchedApplication app, PatchedApplication app,
bool onlyUnpatch,
) async { ) async {
if (app.isRooted) { bool hasRootPermissions = await _rootAPI.hasRootPermissions();
bool hasRootPermissions = await _rootAPI.hasRootPermissions(); if (app.isRooted && !hasRootPermissions) {
if (!hasRootPermissions) { return showDialog(
return showDialog( context: context,
context: context, builder: (context) => AlertDialog(
builder: (context) => AlertDialog( title: I18nText('appInfoView.rootDialogTitle'),
title: I18nText('appInfoView.rootDialogTitle'), backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
backgroundColor: Theme.of(context).colorScheme.secondaryContainer, content: I18nText('appInfoView.rootDialogText'),
content: I18nText('appInfoView.rootDialogText'), actions: <Widget>[
actions: <Widget>[ CustomMaterialButton(
CustomMaterialButton( label: I18nText('okButton'),
label: I18nText('okButton'), onPressed: () => Navigator.of(context).pop(),
onPressed: () => Navigator.of(context).pop(), )
) ],
], ),
), );
);
}
} else { } else {
return showDialog( return showDialog(
context: context, context: context,
builder: (context) => AlertDialog( builder: (context) => AlertDialog(
title: I18nText('appInfoView.uninstallDialogTitle'), title: I18nText(
onlyUnpatch
? 'appInfoView.unpatchDialogTitle'
: 'appInfoView.uninstallDialogTitle',
),
backgroundColor: Theme.of(context).colorScheme.secondaryContainer, backgroundColor: Theme.of(context).colorScheme.secondaryContainer,
content: I18nText('appInfoView.uninstallDialogText'), content: I18nText(
onlyUnpatch
? 'appInfoView.unpatchDialogText'
: 'appInfoView.uninstallDialogText',
),
actions: <Widget>[ actions: <Widget>[
CustomMaterialButton( CustomMaterialButton(
isFilled: false, isFilled: false,
@@ -78,7 +88,7 @@ class AppInfoViewModel extends BaseViewModel {
CustomMaterialButton( CustomMaterialButton(
label: I18nText('okButton'), label: I18nText('okButton'),
onPressed: () { onPressed: () {
uninstallApp(app); uninstallApp(app, onlyUnpatch);
locator<HomeViewModel>().initialize(context); locator<HomeViewModel>().initialize(context);
Navigator.of(context).pop(); Navigator.of(context).pop();
Navigator.of(context).pop(); Navigator.of(context).pop();

View File

@@ -71,7 +71,7 @@ class _LatestCommitCardState extends State<LatestCommitCard> {
future: locator<HomeViewModel>().hasManagerUpdates(), future: locator<HomeViewModel>().hasManagerUpdates(),
initialData: false, initialData: false,
builder: (context, snapshot) => Opacity( builder: (context, snapshot) => Opacity(
opacity: snapshot.hasData && snapshot.data! ? 1.0 : 0.5, opacity: snapshot.hasData && snapshot.data! ? 1.0 : 0.25,
child: CustomMaterialButton( child: CustomMaterialButton(
isExpanded: false, isExpanded: false,
label: I18nText('latestCommitCard.updateButton'), label: I18nText('latestCommitCard.updateButton'),

View File

@@ -0,0 +1,32 @@
import 'package:flutter/material.dart';
class GradientProgressIndicator extends StatefulWidget {
final double? progress;
const GradientProgressIndicator({required this.progress, super.key});
@override
State<GradientProgressIndicator> createState() =>
_GradientProgressIndicatorState();
}
class _GradientProgressIndicatorState extends State<GradientProgressIndicator> {
@override
Widget build(BuildContext context) {
return Align(
alignment: Alignment.centerLeft,
child: AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.secondary,
],
),
),
height: 5,
width: MediaQuery.of(context).size.width * widget.progress!,
),
);
}
}

View File

@@ -61,6 +61,13 @@ class _AboutWidgetState extends State<AboutWidget> {
fontWeight: FontWeight.w300, fontWeight: FontWeight.w300,
), ),
), ),
Text(
'Build: ${snapshot.data!['flavor']}',
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
),
Text( Text(
'Model: ${snapshot.data!['model']}', 'Model: ${snapshot.data!['model']}',
style: const TextStyle( style: const TextStyle(

View File

@@ -6,7 +6,7 @@ import 'package:revanced_manager/ui/widgets/shared/custom_card.dart';
import 'package:expandable/expandable.dart'; import 'package:expandable/expandable.dart';
import 'package:timeago/timeago.dart'; import 'package:timeago/timeago.dart';
class ApplicationItem extends StatelessWidget { class ApplicationItem extends StatefulWidget {
final Uint8List icon; final Uint8List icon;
final String name; final String name;
final DateTime patchDate; final DateTime patchDate;
@@ -24,10 +24,39 @@ class ApplicationItem extends StatelessWidget {
required this.onPressed, required this.onPressed,
}) : super(key: key); }) : super(key: key);
@override
State<ApplicationItem> createState() => _ApplicationItemState();
}
class _ApplicationItemState extends State<ApplicationItem>
with TickerProviderStateMixin {
late AnimationController _animationController;
@override
initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 300),
);
}
@override
void dispose() {
_animationController.dispose();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
ExpandableController expController = ExpandableController();
return ExpandablePanel( return ExpandablePanel(
controller: expController,
theme: const ExpandableThemeData( theme: const ExpandableThemeData(
inkWellBorderRadius: BorderRadius.all(Radius.circular(16)),
tapBodyToCollapse: false,
tapBodyToExpand: false,
tapHeaderToExpand: false,
hasIcon: false, hasIcon: false,
animationDuration: Duration(milliseconds: 450), animationDuration: Duration(milliseconds: 450),
), ),
@@ -35,33 +64,51 @@ class ApplicationItem extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
SizedBox( SizedBox(
width: 60, width: 40,
child: Image.memory(icon, height: 39, width: 39), child: Image.memory(widget.icon, height: 40, width: 40),
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
Column( Padding(
crossAxisAlignment: CrossAxisAlignment.start, padding: const EdgeInsets.only(left: 15.0),
children: <Widget>[ child: Column(
Text( crossAxisAlignment: CrossAxisAlignment.start,
name, children: <Widget>[
style: const TextStyle( Text(
fontSize: 16, widget.name,
fontWeight: FontWeight.w500, style: const TextStyle(
), fontSize: 16,
fontWeight: FontWeight.w500,
),
),
Text(format(widget.patchDate)),
],
), ),
Text(format(patchDate)),
],
), ),
const Spacer(), const Spacer(),
Padding(
padding: const EdgeInsets.only(right: 5.0),
child: RotationTransition(
turns: Tween(begin: 0.0, end: 0.50).animate(_animationController),
child: IconButton(
onPressed: () {
expController.toggle();
_animationController.isCompleted
? _animationController.reverse()
: _animationController.forward();
},
icon: const Icon(Icons.arrow_drop_down),
),
),
),
Column( Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[ children: <Widget>[
CustomMaterialButton( CustomMaterialButton(
label: isUpdatableApp label: widget.isUpdatableApp
? I18nText('applicationItem.patchButton') ? I18nText('applicationItem.patchButton')
: I18nText('applicationItem.infoButton'), : I18nText('applicationItem.infoButton'),
onPressed: onPressed, onPressed: widget.onPressed,
), ),
], ],
), ),
@@ -70,7 +117,7 @@ class ApplicationItem extends StatelessWidget {
), ),
collapsed: const Text(''), collapsed: const Text(''),
expanded: Padding( expanded: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0), padding: const EdgeInsets.symmetric(vertical: 16.0, horizontal: 16.0),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
@@ -82,7 +129,7 @@ class ApplicationItem extends StatelessWidget {
), ),
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
Text('\u2022 ${changelog.join('\n\u2022 ')}'), Text('\u2022 ${widget.changelog.join('\n\u2022 ')}'),
], ],
), ),
), ),

View File

@@ -16,7 +16,7 @@ class CustomCard extends StatelessWidget {
decoration: BoxDecoration( decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
color: isFilled color: isFilled
? Theme.of(context).colorScheme.secondaryContainer ? Theme.of(context).colorScheme.secondaryContainer.withOpacity(0.40)
: Colors.transparent, : Colors.transparent,
border: isFilled border: isFilled
? null ? null

View File

@@ -22,7 +22,7 @@ class DashboardChip extends StatelessWidget {
color: isSelected color: isSelected
? Theme.of(context).colorScheme.primary ? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.secondary, : Theme.of(context).colorScheme.secondary,
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
), ),
backgroundColor: Colors.transparent, backgroundColor: Colors.transparent,
selectedColor: Theme.of(context).colorScheme.secondaryContainer, selectedColor: Theme.of(context).colorScheme.secondaryContainer,

View File

@@ -1,3 +1,4 @@
import 'package:flutter/foundation.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
@@ -7,6 +8,7 @@ class AboutInfo {
final info = await DeviceInfoPlugin().androidInfo; final info = await DeviceInfoPlugin().androidInfo;
return { return {
'version': packageInfo.version, 'version': packageInfo.version,
'flavor': kReleaseMode ? 'release' : 'debug',
'model': info.model, 'model': info.model,
'androidVersion': info.version.release, 'androidVersion': info.version.release,
'arch': info.supportedAbis.first 'arch': info.supportedAbis.first

View File

@@ -4,7 +4,7 @@ homepage: https://github.com/revanced/revanced-manager
publish_to: 'none' publish_to: 'none'
version: 0.0.4+4 version: 0.0.8+8
environment: environment:
sdk: ">=2.17.5 <3.0.0" sdk: ">=2.17.5 <3.0.0"
@@ -24,7 +24,10 @@ dependencies:
dynamic_color: ^1.5.4 dynamic_color: ^1.5.4
dynamic_themes: ^1.1.0 dynamic_themes: ^1.1.0
expandable: ^5.0.1 expandable: ^5.0.1
file_picker: ^5.0.1 file_picker:
git:
url: https://github.com/alexmercerind/flutter_file_picker
ref: master
flex_color_scheme: ^6.0.0 flex_color_scheme: ^6.0.0
flutter: flutter:
sdk: flutter sdk: flutter