mirror of
https://github.com/ReVanced/revanced-manager.git
synced 2024-11-10 01:01:56 +01:00
fix: add animations and fix some UI incoherences
This commit is contained in:
parent
596d4f0def
commit
a580375078
16 changed files with 153 additions and 122 deletions
|
@ -91,6 +91,7 @@
|
|||
"widgetTitle": "Is your device rooted?",
|
||||
"widgetDescription": "Don't know what this means or prefer to use non-root version? Just click on the button below!",
|
||||
"grantPermission": "Grant Root Permission",
|
||||
"grantedPermission": "Magisk permission granted: {isRooted}"
|
||||
"grantedPermission": "Magisk permission granted: {isRooted}",
|
||||
"nonRootButton": "Nonroot"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:animations/animations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||
// ignore: depend_on_referenced_packages
|
||||
|
@ -89,7 +90,21 @@ class Navigation extends StatelessWidget {
|
|||
return ViewModelBuilder<MainViewModel>.reactive(
|
||||
viewModelBuilder: () => locator<MainViewModel>(),
|
||||
builder: (context, model, child) => Scaffold(
|
||||
body: getViewForIndex(model.currentIndex),
|
||||
body: PageTransitionSwitcher(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
transitionBuilder: (
|
||||
Widget child,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
) {
|
||||
return FadeThroughTransition(
|
||||
animation: animation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
child: getViewForIndex(model.currentIndex),
|
||||
),
|
||||
bottomNavigationBar: NavigationBar(
|
||||
onDestinationSelected: model.setIndex,
|
||||
selectedIndex: model.currentIndex,
|
||||
|
|
|
@ -29,13 +29,11 @@ class _AppSelectorViewState extends State<AppSelectorView> {
|
|||
model.selectAppFromStorage(context);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(16.0),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
foregroundColor: Colors.white,
|
||||
foregroundColor: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
|
@ -73,6 +71,7 @@ class _AppSelectorViewState extends State<AppSelectorView> {
|
|||
const SizedBox(height: 12),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
children: model
|
||||
.getFilteredApps(_query)
|
||||
.map((app) => InkWell(
|
||||
|
|
|
@ -70,7 +70,7 @@ class InstallerView extends StatelessWidget {
|
|||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
model.logs,
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import 'package:animations/animations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:revanced_manager/app/app.locator.dart';
|
||||
import 'package:revanced_manager/theme.dart';
|
||||
import 'package:revanced_manager/ui/views/app_selector/app_selector_view.dart';
|
||||
import 'package:revanced_manager/ui/views/installer/installer_view.dart';
|
||||
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
|
||||
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_view.dart';
|
||||
import 'package:revanced_manager/ui/widgets/patcherView/app_selector_card.dart';
|
||||
import 'package:revanced_manager/ui/widgets/patcherView/patch_selector_card.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
|
@ -19,17 +23,24 @@ class PatcherView extends StatelessWidget {
|
|||
builder: (context, model, child) => Scaffold(
|
||||
floatingActionButton: Visibility(
|
||||
visible: model.showPatchButton(),
|
||||
child: FloatingActionButton.extended(
|
||||
label: I18nText('patcherView.patchButton'),
|
||||
icon: const Icon(Icons.build),
|
||||
onPressed: () => model.navigateToInstaller(),
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(16.0),
|
||||
),
|
||||
child: OpenContainer(
|
||||
transitionDuration: const Duration(milliseconds: 400),
|
||||
openBuilder: (_, openContainer) => const InstallerView(),
|
||||
openColor: Theme.of(context).colorScheme.primary,
|
||||
closedColor: Colors.transparent,
|
||||
closedShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
closedBuilder: (_, openContainer) => FloatingActionButton.extended(
|
||||
label: I18nText('patcherView.patchButton'),
|
||||
icon: const Icon(Icons.build),
|
||||
onPressed: openContainer,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
foregroundColor: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
),
|
||||
body: CustomScrollView(
|
||||
|
@ -69,20 +80,39 @@ class PatcherView extends StatelessWidget {
|
|||
sliver: SliverList(
|
||||
delegate: SliverChildListDelegate.fixed(
|
||||
<Widget>[
|
||||
AppSelectorCard(
|
||||
onPressed: model.navigateToAppSelector,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
OpenContainer(
|
||||
transitionDuration: const Duration(milliseconds: 400),
|
||||
openBuilder: (_, openContainer) =>
|
||||
const AppSelectorView(),
|
||||
openColor: Theme.of(context).colorScheme.primary,
|
||||
closedColor: Colors.transparent,
|
||||
closedShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
closedBuilder: (_, openContainer) => AppSelectorCard(
|
||||
onPressed: openContainer,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Opacity(
|
||||
opacity: isDark
|
||||
? (model.dimPatchesCard() ? 0.5 : 1)
|
||||
: (model.dimPatchesCard() ? 0.75 : 1),
|
||||
child: PatchSelectorCard(
|
||||
onPressed: model.dimPatchesCard()
|
||||
? () => {}
|
||||
: model.navigateToPatchesSelector,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
child: OpenContainer(
|
||||
transitionDuration: const Duration(milliseconds: 400),
|
||||
openBuilder: (_, openContainer) =>
|
||||
const PatchesSelectorView(),
|
||||
openColor: Theme.of(context).colorScheme.primary,
|
||||
closedColor: Colors.transparent,
|
||||
closedShape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
closedBuilder: (_, openContainer) => PatchSelectorCard(
|
||||
onPressed:
|
||||
model.dimPatchesCard() ? () => {} : openContainer,
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -1,30 +1,13 @@
|
|||
import 'package:injectable/injectable.dart';
|
||||
import 'package:revanced_manager/app/app.locator.dart';
|
||||
import 'package:revanced_manager/app/app.router.dart';
|
||||
import 'package:revanced_manager/models/patch.dart';
|
||||
import 'package:revanced_manager/models/patched_application.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
import 'package:stacked_services/stacked_services.dart';
|
||||
|
||||
@lazySingleton
|
||||
class PatcherViewModel extends BaseViewModel {
|
||||
PatchedApplication? selectedApp;
|
||||
List<Patch> selectedPatches = [];
|
||||
|
||||
final NavigationService _navigationService = locator<NavigationService>();
|
||||
|
||||
void navigateToAppSelector() {
|
||||
_navigationService.navigateTo(Routes.appSelectorView);
|
||||
}
|
||||
|
||||
void navigateToPatchesSelector() {
|
||||
_navigationService.navigateTo(Routes.patchesSelectorView);
|
||||
}
|
||||
|
||||
void navigateToInstaller() {
|
||||
_navigationService.navigateTo(Routes.installerView);
|
||||
}
|
||||
|
||||
bool showPatchButton() {
|
||||
return selectedPatches.isNotEmpty;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,22 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
|
|||
onModelReady: (model) => model.initialize(),
|
||||
viewModelBuilder: () => PatchesSelectorViewModel(),
|
||||
builder: (context, model, child) => Scaffold(
|
||||
floatingActionButton: Visibility(
|
||||
visible: model.patches.isNotEmpty,
|
||||
child: FloatingActionButton.extended(
|
||||
label: I18nText('patchesSelectorView.doneButton'),
|
||||
icon: const Icon(Icons.check),
|
||||
onPressed: () {
|
||||
model.selectPatches();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
foregroundColor: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding:
|
||||
|
@ -53,6 +69,7 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
|
|||
const SizedBox(height: 12),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: const EdgeInsets.only(bottom: 80),
|
||||
children: model
|
||||
.getQueriedPatches(_query)
|
||||
.map((patch) => PatchItem(
|
||||
|
@ -72,23 +89,6 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
|
|||
.toList(),
|
||||
),
|
||||
),
|
||||
MaterialButton(
|
||||
textColor: Colors.white,
|
||||
color: Theme.of(context).colorScheme.secondary,
|
||||
minWidth: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 8,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
onPressed: () {
|
||||
model.selectPatches();
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: I18nText('patchesSelectorView.doneButton'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -13,30 +13,20 @@ class RootCheckerView extends StatelessWidget {
|
|||
return ViewModelBuilder<RootCheckerViewModel>.reactive(
|
||||
viewModelBuilder: () => RootCheckerViewModel(),
|
||||
builder: (context, model, child) => Scaffold(
|
||||
floatingActionButton: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
const Text('nonroot'),
|
||||
const SizedBox(height: 8),
|
||||
FloatingActionButton(
|
||||
onPressed: model.navigateToHome,
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(48),
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.keyboard_arrow_right,
|
||||
size: 32,
|
||||
),
|
||||
),
|
||||
],
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
label: I18nText('rootCheckerView.nonRootButton'),
|
||||
icon: const Icon(Icons.keyboard_arrow_right),
|
||||
onPressed: () => model.navigateAsNonRoot(),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
foregroundColor: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
body: Container(
|
||||
height: double.infinity,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 28.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
const SizedBox(height: 120),
|
||||
I18nText(
|
||||
|
@ -60,18 +50,24 @@ class RootCheckerView extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 170),
|
||||
MagiskButton(
|
||||
onPressed: () => model.checkRoot(),
|
||||
),
|
||||
I18nText(
|
||||
'rootCheckerView.grantedPermission',
|
||||
translationParams: {
|
||||
'isRooted': model.isRooted.toString(),
|
||||
},
|
||||
child: Text(
|
||||
'',
|
||||
style: GoogleFonts.poppins(),
|
||||
Expanded(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
MagiskButton(
|
||||
onPressed: () => model.navigateAsRoot(),
|
||||
),
|
||||
I18nText(
|
||||
'rootCheckerView.grantedPermission',
|
||||
translationParams: {
|
||||
'isRooted': model.isRooted.toString(),
|
||||
},
|
||||
child: Text(
|
||||
'',
|
||||
style: GoogleFonts.poppins(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -9,19 +9,24 @@ class RootCheckerViewModel extends BaseViewModel {
|
|||
final NavigationService _navigationService = locator<NavigationService>();
|
||||
bool isRooted = false;
|
||||
|
||||
Future<void> checkRoot() async {
|
||||
Future<void> navigateAsRoot() async {
|
||||
bool? res = await Root.isRooted();
|
||||
isRooted = res != null && res == true;
|
||||
if (isRooted) {
|
||||
navigateToHome();
|
||||
await navigateToHome();
|
||||
} else {
|
||||
notifyListeners();
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> navigateAsNonRoot() async {
|
||||
isRooted = false;
|
||||
await navigateToHome();
|
||||
}
|
||||
|
||||
Future<void> navigateToHome() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('isRooted', isRooted);
|
||||
_navigationService.navigateTo(Routes.navigation);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ class _ContributorsCardState extends State<ContributorsCard> {
|
|||
padding: const EdgeInsets.all(4.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.tertiary,
|
||||
borderRadius: BorderRadius.circular(8.0),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
height: widget.height,
|
||||
child: GridView.builder(
|
||||
|
|
|
@ -34,7 +34,7 @@ class DashboardChip extends StatelessWidget {
|
|||
isDark ? Theme.of(context).colorScheme.background : Colors.white,
|
||||
selectedColor: const Color.fromRGBO(118, 155, 209, 0.42),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
side: BorderSide(
|
||||
width: 1,
|
||||
color: isDark
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_i18n/flutter_i18n.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:revanced_manager/theme.dart';
|
||||
import 'package:revanced_manager/ui/widgets/shared/patch_text_button.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class PatchItem extends StatefulWidget {
|
||||
|
@ -87,7 +87,7 @@ class _PatchItemState extends State<PatchItem> {
|
|||
scale: 1.2,
|
||||
child: Checkbox(
|
||||
value: widget.isSelected,
|
||||
activeColor: Colors.blueGrey[500],
|
||||
activeColor: Theme.of(context).colorScheme.secondary,
|
||||
onChanged: (newValue) {
|
||||
setState(() => widget.isSelected = newValue!);
|
||||
widget.onChanged(widget.isSelected);
|
||||
|
@ -117,9 +117,7 @@ class _PatchItemState extends State<PatchItem> {
|
|||
),
|
||||
),
|
||||
backgroundColor: MaterialStateProperty.all(
|
||||
isDark
|
||||
? Theme.of(context).colorScheme.background
|
||||
: Colors.white,
|
||||
Colors.transparent,
|
||||
),
|
||||
foregroundColor: MaterialStateProperty.all(
|
||||
Theme.of(context).colorScheme.secondary,
|
||||
|
@ -137,10 +135,12 @@ class _PatchItemState extends State<PatchItem> {
|
|||
}
|
||||
|
||||
Future<void> _showUnsupportedWarningDialog() {
|
||||
return showDialog(
|
||||
return showGeneralDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return AlertDialog(
|
||||
pageBuilder: (ctx, a1, a2) => Container(),
|
||||
transitionBuilder: (ctx, a1, a2, child) => Transform.scale(
|
||||
scale: Curves.easeInOut.transform(a1.value),
|
||||
child: AlertDialog(
|
||||
title: I18nText('patchItem.alertDialogTitle'),
|
||||
content: I18nText(
|
||||
'patchItem.alertDialogText',
|
||||
|
@ -151,13 +151,17 @@ class _PatchItemState extends State<PatchItem> {
|
|||
},
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: I18nText('okButton'),
|
||||
PatchTextButton(
|
||||
text: FlutterI18n.translate(context, 'okButton'),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
borderColor: Theme.of(context).colorScheme.secondary,
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
),
|
||||
),
|
||||
transitionDuration: const Duration(milliseconds: 400),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_i18n/widgets/I18nText.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:revanced_manager/theme.dart';
|
||||
|
||||
class MagiskButton extends StatelessWidget {
|
||||
final Function() onPressed;
|
||||
|
@ -20,14 +19,12 @@ class MagiskButton extends StatelessWidget {
|
|||
onTap: onPressed,
|
||||
child: CircleAvatar(
|
||||
radius: 32,
|
||||
backgroundColor: isDark
|
||||
? Theme.of(context).colorScheme.secondary
|
||||
: const Color(0xffCBDFFC),
|
||||
backgroundColor: Theme.of(context).colorScheme.secondary,
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/magisk.svg',
|
||||
color: isDark ? Colors.white70 : Colors.grey[900],
|
||||
height: 50,
|
||||
width: 50,
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
height: 40,
|
||||
width: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -36,9 +36,7 @@ class ApplicationItem extends StatelessWidget {
|
|||
header: Container(
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(
|
||||
Radius.circular(16),
|
||||
),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 12.0),
|
||||
|
|
|
@ -49,6 +49,7 @@ class _SearchBarState extends State<SearchBar> {
|
|||
child: TextFormField(
|
||||
onChanged: widget.onQueryChanged,
|
||||
controller: _textController,
|
||||
cursorColor: Theme.of(context).textTheme.headline5!.color,
|
||||
decoration: InputDecoration(
|
||||
fillColor: widget.fillColor,
|
||||
filled: true,
|
||||
|
@ -58,9 +59,10 @@ class _SearchBarState extends State<SearchBar> {
|
|||
color: widget.hintTextColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
prefixIcon: const Icon(
|
||||
prefixIcon: Icon(
|
||||
Icons.search,
|
||||
size: 24.0,
|
||||
color: Theme.of(context).iconTheme.color,
|
||||
),
|
||||
suffixIcon: _textController.text.isNotEmpty
|
||||
? IconButton(
|
||||
|
@ -88,12 +90,12 @@ class _SearchBarState extends State<SearchBar> {
|
|||
)
|
||||
: null,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
),
|
||||
style: GoogleFonts.poppins(
|
||||
color: Colors.white,
|
||||
color: Theme.of(context).textTheme.headline5!.color,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 16,
|
||||
),
|
||||
|
|
|
@ -10,6 +10,7 @@ environment:
|
|||
sdk: ">=2.17.5 <3.0.0"
|
||||
|
||||
dependencies:
|
||||
animations: ^2.0.4
|
||||
app_installer: ^1.1.0
|
||||
cupertino_icons: ^1.0.2
|
||||
device_apps:
|
||||
|
|
Loading…
Reference in a new issue