fix: improve patches selector.

This commit is contained in:
Alberto Ponces 2022-08-09 02:30:12 +01:00
parent 6338eb5dd1
commit 84923127e2
9 changed files with 95 additions and 26 deletions

View File

@ -37,7 +37,9 @@
}, },
"patchSelectorCard": { "patchSelectorCard": {
"widgetTitle": "Select patches", "widgetTitle": "Select patches",
"widgetSubtitle": "Select an application first." "widgetFirstSubtitle": "Select an application first.",
"widgetSecondSubtitle": "No patches selected.",
"widgetThirdSubtitle": "{selected} patch(es) selected."
}, },
"appSelectorView": { "appSelectorView": {
"searchBarHint": "Search applications" "searchBarHint": "Search applications"

View File

@ -5,7 +5,6 @@ import 'package:path_provider/path_provider.dart' as p;
import 'package:revanced_manager/constants.dart'; import 'package:revanced_manager/constants.dart';
import 'package:revanced_manager/services/github_api.dart'; import 'package:revanced_manager/services/github_api.dart';
// use path_provider to get the path of the storage directory
@lazySingleton @lazySingleton
class ManagerAPI { class ManagerAPI {
Dio dio = Dio(); Dio dio = Dio();

View File

@ -21,6 +21,7 @@ class AppSelectorViewModel extends BaseViewModel {
void selectApp(AppInfo appInfo) { void selectApp(AppInfo appInfo) {
locator<AppSelectorViewModel>().selectedApp = appInfo; locator<AppSelectorViewModel>().selectedApp = appInfo;
locator<PatcherViewModel>().dimPatchCard = false;
locator<PatcherViewModel>().notifyListeners(); locator<PatcherViewModel>().notifyListeners();
} }
} }

View File

@ -17,12 +17,15 @@ class PatcherView extends StatelessWidget {
disposeViewModel: false, disposeViewModel: false,
viewModelBuilder: () => locator<PatcherViewModel>(), viewModelBuilder: () => locator<PatcherViewModel>(),
builder: (context, model, child) => Scaffold( builder: (context, model, child) => Scaffold(
floatingActionButton: FloatingActionButton.extended( floatingActionButton: Visibility(
onPressed: () => {}, visible: locator<PatcherViewModel>().hideFabButton,
label: I18nText('patcherView.fabButton'), child: FloatingActionButton.extended(
icon: const Icon(Icons.build), onPressed: () => {},
backgroundColor: const Color(0xff7792BA), label: I18nText('patcherView.fabButton'),
foregroundColor: Colors.white, icon: const Icon(Icons.build),
backgroundColor: const Color(0xff7792BA),
foregroundColor: Colors.white,
),
), ),
body: SafeArea( body: SafeArea(
child: Padding( child: Padding(
@ -46,8 +49,11 @@ class PatcherView extends StatelessWidget {
onPressed: model.navigateToAppSelector, onPressed: model.navigateToAppSelector,
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
PatchSelectorCard( Opacity(
onPressed: model.navigateToPatchesSelector, opacity: model.dimPatchCard ? 0.5 : 1,
child: PatchSelectorCard(
onPressed: model.navigateToPatchesSelector,
),
), ),
], ],
), ),

View File

@ -5,6 +5,8 @@ import 'package:stacked_services/stacked_services.dart';
class PatcherViewModel extends BaseViewModel { class PatcherViewModel extends BaseViewModel {
final _navigationService = locator<NavigationService>(); final _navigationService = locator<NavigationService>();
bool dimPatchCard = true;
bool hideFabButton = true;
void navigateToAppSelector() { void navigateToAppSelector() {
_navigationService.navigateTo(Routes.appSelectorView); _navigationService.navigateTo(Routes.appSelectorView);

View File

@ -14,6 +14,7 @@ class PatchesSelectorView extends StatefulWidget {
} }
class _PatchesSelectorViewState extends State<PatchesSelectorView> { class _PatchesSelectorViewState extends State<PatchesSelectorView> {
final List<PatchItem> patches = [];
String query = ''; String query = '';
@override @override
@ -24,7 +25,10 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
viewModelBuilder: () => locator<PatchesSelectorViewModel>(), viewModelBuilder: () => locator<PatchesSelectorViewModel>(),
builder: (context, model, child) => Scaffold( builder: (context, model, child) => Scaffold(
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
onPressed: () => {}, onPressed: () {
model.selectPatches(patches);
Navigator.of(context).pop();
},
label: I18nText('patchesSelectorView.fabButton'), label: I18nText('patchesSelectorView.fabButton'),
icon: const Icon(Icons.check), icon: const Icon(Icons.check),
backgroundColor: const Color(0xff7792BA), backgroundColor: const Color(0xff7792BA),
@ -66,23 +70,30 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
} }
Widget _getAllResults(PatchesSelectorViewModel model) { Widget _getAllResults(PatchesSelectorViewModel model) {
patches.clear();
return Expanded( return Expanded(
child: ListView.builder( child: ListView.builder(
itemCount: model.patches!.length, itemCount: model.patches!.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
model.patches!.sort((a, b) => a.simpleName.compareTo(b.simpleName)); model.patches!.sort((a, b) => a.simpleName.compareTo(b.simpleName));
return PatchItem( PatchItem item = PatchItem(
name: model.patches![index].simpleName, name: model.patches![index].name,
simpleName: model.patches![index].simpleName,
version: model.patches![index].version, version: model.patches![index].version,
description: model.patches![index].description, description: model.patches![index].description,
isSelected: false, isSelected: model.selectedPatches.any(
(element) => element.name == model.patches![index].name,
),
); );
patches.add(item);
return item;
}, },
), ),
); );
} }
Widget _getFilteredResults(PatchesSelectorViewModel model) { Widget _getFilteredResults(PatchesSelectorViewModel model) {
patches.clear();
return Expanded( return Expanded(
child: ListView.builder( child: ListView.builder(
itemCount: model.patches!.length, itemCount: model.patches!.length,
@ -91,12 +102,17 @@ class _PatchesSelectorViewState extends State<PatchesSelectorView> {
if (model.patches![index].simpleName.toLowerCase().contains( if (model.patches![index].simpleName.toLowerCase().contains(
query.toLowerCase(), query.toLowerCase(),
)) { )) {
return PatchItem( PatchItem item = PatchItem(
name: model.patches![index].simpleName, name: model.patches![index].name,
simpleName: model.patches![index].simpleName,
version: model.patches![index].version, version: model.patches![index].version,
description: model.patches![index].description, description: model.patches![index].description,
isSelected: false, isSelected: model.selectedPatches.any(
(element) => element.name == model.patches![index].name,
),
); );
patches.add(item);
return item;
} else { } else {
return const SizedBox(); return const SizedBox();
} }

View File

@ -3,6 +3,8 @@ 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/services/patcher_api.dart'; import 'package:revanced_manager/services/patcher_api.dart';
import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart'; import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart';
import 'package:revanced_manager/ui/views/patcher/patcher_viewmodel.dart';
import 'package:revanced_manager/ui/widgets/patch_item.dart';
import 'package:stacked/stacked.dart'; import 'package:stacked/stacked.dart';
class PatchesSelectorViewModel extends BaseViewModel { class PatchesSelectorViewModel extends BaseViewModel {
@ -20,5 +22,19 @@ class PatchesSelectorViewModel extends BaseViewModel {
patches = await patcherAPI.getFilteredPatches(appInfo); patches = await patcherAPI.getFilteredPatches(appInfo);
} }
void selectPatches(List<Patch> patches) {} void selectPatches(List<PatchItem> patchItems) {
selectedPatches.clear();
if (patches != null) {
for (PatchItem patch in patchItems) {
if (patch.isSelected) {
selectedPatches.add(
patches!.firstWhere((element) => element.name == patch.name),
);
}
}
}
locator<PatcherViewModel>().hideFabButton =
selectedPatches.isEmpty ? true : false;
locator<PatcherViewModel>().notifyListeners();
}
} }

View File

@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart';
// ignore: must_be_immutable // ignore: must_be_immutable
class PatchItem extends StatefulWidget { class PatchItem extends StatefulWidget {
final String name; final String name;
final String simpleName;
final String description; final String description;
final String version; final String version;
bool isSelected; bool isSelected;
@ -11,6 +12,7 @@ class PatchItem extends StatefulWidget {
PatchItem({ PatchItem({
Key? key, Key? key,
required this.name, required this.name,
required this.simpleName,
required this.description, required this.description,
required this.version, required this.version,
required this.isSelected, required this.isSelected,
@ -43,7 +45,7 @@ class _PatchItemState extends State<PatchItem> {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Text( Text(
widget.name, widget.simpleName,
style: GoogleFonts.inter( style: GoogleFonts.inter(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,

View File

@ -1,7 +1,10 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_i18n/flutter_i18n.dart'; 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/app/app.locator.dart';
import 'package:revanced_manager/constants.dart'; import 'package:revanced_manager/constants.dart';
import 'package:revanced_manager/ui/views/app_selector/app_selector_viewmodel.dart';
import 'package:revanced_manager/ui/views/patches_selector/patches_selector_viewmodel.dart';
class PatchSelectorCard extends StatelessWidget { class PatchSelectorCard extends StatelessWidget {
final Function()? onPressed; final Function()? onPressed;
@ -35,13 +38,35 @@ class PatchSelectorCard extends StatelessWidget {
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
I18nText( locator<AppSelectorViewModel>().selectedApp == null
'patchSelectorCard.widgetSubtitle', ? I18nText(
child: Text( 'patchSelectorCard.widgetFirstSubtitle',
'', child: Text(
style: robotoTextStyle, '',
), style: robotoTextStyle,
), ),
)
: locator<PatchesSelectorViewModel>().selectedPatches.isEmpty
? I18nText(
'patchSelectorCard.widgetSecondSubtitle',
child: Text(
'',
style: robotoTextStyle,
),
)
: I18nText(
'patchSelectorCard.widgetThirdSubtitle',
translationParams: {
'selected': locator<PatchesSelectorViewModel>()
.selectedPatches
.length
.toString()
},
child: Text(
'',
style: robotoTextStyle,
),
),
], ],
), ),
), ),