feat: Improve experience of rooted patched app installations (#59)

This commit is contained in:
Alberto Ponces
2022-09-06 14:40:49 +01:00
committed by GitHub
parent 9e178ba584
commit 27ef74b561
22 changed files with 203 additions and 299 deletions

View File

@ -1,4 +1,3 @@
import 'package:device_apps/device_apps.dart';
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:google_fonts/google_fonts.dart';
@ -19,7 +18,6 @@ class AppInfoView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ViewModelBuilder<AppInfoViewModel>.reactive(
onModelReady: (model) => model.initialize(),
viewModelBuilder: () => AppInfoViewModel(),
builder: (context, model, child) => Scaffold(
body: CustomScrollView(
@ -68,9 +66,7 @@ class AppInfoView extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
InkWell(
onTap: () => DeviceApps.openApp(
app.packageName,
),
onTap: () => model.openApp(app),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@ -180,7 +176,7 @@ class AppInfoView extends StatelessWidget {
ListTile(
contentPadding: EdgeInsets.zero,
title: I18nText(
'appInfoView.rootModeLabel',
'appInfoView.installTypeLabel',
child: const Text(
'',
style: TextStyle(
@ -189,9 +185,9 @@ class AppInfoView extends StatelessWidget {
),
),
),
subtitle: model.isRooted
? I18nText('enabledLabel')
: I18nText('disabledLabel'),
subtitle: app.isRooted
? I18nText('appInfoView.rootTypeLabel')
: I18nText('appInfoView.nonRootTypeLabel'),
),
const SizedBox(height: 4),
ListTile(

View File

@ -17,11 +17,6 @@ class AppInfoViewModel extends BaseViewModel {
final ManagerAPI _managerAPI = locator<ManagerAPI>();
final PatcherAPI _patcherAPI = locator<PatcherAPI>();
final RootAPI _rootAPI = RootAPI();
bool isRooted = false;
void initialize() {
isRooted = _managerAPI.isRooted() ?? false;
}
void uninstallApp(PatchedApplication app) {
if (app.isRooted) {
@ -45,7 +40,8 @@ class AppInfoViewModel extends BaseViewModel {
BuildContext context,
PatchedApplication app,
) async {
if (app.isRooted && !isRooted) {
bool hasRootPermissions = await _rootAPI.hasRootPermissions();
if (app.isRooted && !hasRootPermissions) {
return showDialog(
context: context,
builder: (context) => AlertDialog(
@ -129,4 +125,8 @@ class AppInfoViewModel extends BaseViewModel {
.toList();
return '\u2022 ${names.join('\n\u2022 ')}';
}
void openApp(PatchedApplication app) {
DeviceApps.openApp(app.packageName);
}
}

View File

@ -23,7 +23,16 @@ class CustomMaterialButton extends StatelessWidget {
? const EdgeInsets.symmetric(horizontal: 24, vertical: 12)
: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
),
shape: MaterialStateProperty.all(const StadiumBorder()),
shape: MaterialStateProperty.all(
StadiumBorder(
side: isFilled
? BorderSide.none
: BorderSide(
width: 1,
color: Theme.of(context).colorScheme.primary,
),
),
),
backgroundColor: MaterialStateProperty.all(
isFilled ? Theme.of(context).colorScheme.primary : Colors.transparent,
),

View File

@ -1,42 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart';
import 'package:flutter_svg/flutter_svg.dart';
class MagiskButton extends StatelessWidget {
final Function() onPressed;
const MagiskButton({
Key? key,
required this.onPressed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
GestureDetector(
onTap: onPressed,
child: CircleAvatar(
radius: 32,
backgroundColor: Theme.of(context).colorScheme.primary,
child: SvgPicture.asset(
'assets/images/magisk.svg',
color: Theme.of(context).colorScheme.surface,
height: 40,
width: 40,
),
),
),
const SizedBox(height: 8),
I18nText(
'rootCheckerView.grantPermission',
child: const Text(
'',
style: TextStyle(fontSize: 15),
),
),
],
);
}
}

View File

@ -0,0 +1,36 @@
import 'package:flutter/material.dart';
class CustomPopupMenu extends StatelessWidget {
final Function(dynamic) onSelected;
final Map<int, Widget> children;
const CustomPopupMenu({
Key? key,
required this.onSelected,
required this.children,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(useMaterial3: false),
child: PopupMenuButton<int>(
onSelected: onSelected,
itemBuilder: (context) => children.entries
.map(
(entry) => PopupMenuItem<int>(
padding: const EdgeInsets.all(16.0).copyWith(right: 20),
value: entry.key,
child: entry.value,
),
)
.toList(),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(24),
),
color: Theme.of(context).colorScheme.secondaryContainer,
position: PopupMenuPosition.under,
),
);
}
}

View File

@ -2,11 +2,13 @@ import 'package:flutter/material.dart';
class CustomSliverAppBar extends StatelessWidget {
final Widget title;
final List<Widget>? actions;
final PreferredSizeWidget? bottom;
const CustomSliverAppBar({
Key? key,
required this.title,
this.actions,
this.bottom,
}) : super(key: key);
@ -30,6 +32,7 @@ class CustomSliverAppBar extends StatelessWidget {
),
title: title,
),
actions: actions,
bottom: bottom,
);
}