Skip to content

Commit

Permalink
[Application] [Presentation] Added a reset button to the character, w…
Browse files Browse the repository at this point in the history
…eapon and artifact pages
  • Loading branch information
Wolfteam committed Jul 10, 2021
1 parent 2d5a107 commit c3e198b
Show file tree
Hide file tree
Showing 10 changed files with 203 additions and 47 deletions.
1 change: 1 addition & 0 deletions lib/application/artifacts/artifacts_bloc.dart
Expand Up @@ -44,6 +44,7 @@ class ArtifactsBloc extends Bloc<ArtifactsEvent, ArtifactsState> {
tempSortDirectionType: currentState.sortDirectionType,
),
collapseNotes: (e) => currentState.copyWith.call(collapseNotes: e.collapse),
resetFilters: (_) => _buildInitialState(excludeKeys: state.maybeMap(loaded: (state) => state.excludeKeys, orElse: () => [])),
);

yield s;
Expand Down
2 changes: 2 additions & 0 deletions lib/application/artifacts/artifacts_event.dart
Expand Up @@ -19,4 +19,6 @@ class ArtifactsEvent with _$ArtifactsEvent {
const factory ArtifactsEvent.applyFilterChanges() = _ApplyFilterChanges;

const factory ArtifactsEvent.cancelChanges() = _CancelChanges;

const factory ArtifactsEvent.resetFilters() = _ResetFilters;
}
4 changes: 4 additions & 0 deletions lib/application/weapons/weapons_bloc.dart
Expand Up @@ -68,6 +68,10 @@ class WeaponsBloc extends Bloc<WeaponsEvent, WeaponsState> {
tempWeaponLocationType: currentState.weaponLocationType,
excludeKeys: currentState.excludeKeys,
),
resetFilters: (_) => _buildInitialState(
excludeKeys: state.maybeMap(loaded: (state) => state.excludeKeys, orElse: () => []),
weaponTypes: WeaponType.values,
),
);

yield s;
Expand Down
2 changes: 2 additions & 0 deletions lib/application/weapons/weapons_event.dart
Expand Up @@ -25,4 +25,6 @@ class WeaponsEvent with _$WeaponsEvent {
const factory WeaponsEvent.weaponLocationTypeChanged(ItemLocationType locationType) = _WeaponLocationTypeChanged;

const factory WeaponsEvent.cancelChanges() = _CancelChanges;

const factory WeaponsEvent.resetFilters() = _ResetFilters;
}
38 changes: 30 additions & 8 deletions lib/presentation/artifacts/widgets/artifact_bottom_sheet.dart
Expand Up @@ -10,22 +10,18 @@ import 'package:genshindb/presentation/shared/item_popupmenu_filter.dart';
import 'package:genshindb/presentation/shared/loading.dart';
import 'package:genshindb/presentation/shared/rarity_rating.dart';
import 'package:genshindb/presentation/shared/sort_direction_popupmenu_filter.dart';
import 'package:genshindb/presentation/shared/styles.dart';

class ArtifactBottomSheet extends StatelessWidget {
@override
Widget build(BuildContext context) {
final s = S.of(context);
final theme = Theme.of(context);
return CommonBottomSheet(
titleIcon: GenshinDb.filter,
title: s.filters,
onOk: () {
context.read<ArtifactsBloc>().add(const ArtifactsEvent.applyFilterChanges());
Navigator.pop(context);
},
onCancel: () {
context.read<ArtifactsBloc>().add(const ArtifactsEvent.cancelChanges());
Navigator.pop(context);
},
showCancelButton: false,
showOkButton: false,
child: BlocBuilder<ArtifactsBloc, ArtifactsState>(
builder: (context, state) => state.map(
loading: (_) => const Loading(),
Expand Down Expand Up @@ -55,6 +51,32 @@ class ArtifactBottomSheet extends StatelessWidget {
)
],
),
ButtonBar(
buttonPadding: Styles.edgeInsetHorizontal10,
children: <Widget>[
OutlinedButton(
onPressed: () {
context.read<ArtifactsBloc>().add(const ArtifactsEvent.cancelChanges());
Navigator.pop(context);
},
child: Text(s.cancel, style: TextStyle(color: theme.primaryColor)),
),
OutlinedButton(
onPressed: () {
context.read<ArtifactsBloc>().add(const ArtifactsEvent.resetFilters());
Navigator.pop(context);
},
child: Text(s.reset, style: TextStyle(color: theme.primaryColor)),
),
ElevatedButton(
onPressed: () {
context.read<ArtifactsBloc>().add(const ArtifactsEvent.applyFilterChanges());
Navigator.pop(context);
},
child: Text(s.ok),
)
],
),
],
),
),
Expand Down
63 changes: 47 additions & 16 deletions lib/presentation/characters/widgets/character_bottom_sheet.dart
Expand Up @@ -11,6 +11,7 @@ import 'package:genshindb/presentation/shared/item_popupmenu_filter.dart';
import 'package:genshindb/presentation/shared/loading.dart';
import 'package:genshindb/presentation/shared/rarity_rating.dart';
import 'package:genshindb/presentation/shared/sort_direction_popupmenu_filter.dart';
import 'package:genshindb/presentation/shared/styles.dart';
import 'package:genshindb/presentation/shared/weapons_button_bar.dart';

class CharacterBottomSheet extends StatelessWidget {
Expand All @@ -19,20 +20,15 @@ class CharacterBottomSheet extends StatelessWidget {
@override
Widget build(BuildContext context) {
final s = S.of(context);
final theme = Theme.of(context);
return CommonBottomSheet(
titleIcon: GenshinDb.filter,
title: s.filters,
onOk: () {
context.read<CharactersBloc>().add(const CharactersEvent.applyFilterChanges());
Navigator.pop(context);
},
onCancel: () {
context.read<CharactersBloc>().add(const CharactersEvent.cancelChanges());
Navigator.pop(context);
},
showCancelButton: false,
showOkButton: false,
child: BlocBuilder<CharactersBloc, CharactersState>(
builder: (context, state) => state.map(
loading: (_) => const Loading(),
loading: (_) => const Loading(useScaffold: false),
loaded: (state) => Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
Expand All @@ -56,6 +52,14 @@ class CharacterBottomSheet extends StatelessWidget {
ButtonBar(
alignment: MainAxisAlignment.spaceEvenly,
children: [
ItemPopupMenuFilter<ItemStatusType>(
tooltipText: '${s.released} / ${s.brandNew} / ${s.comingSoon}',
values: ItemStatusType.values,
selectedValue: state.tempStatusType,
onSelected: (v) => context.read<CharactersBloc>().add(CharactersEvent.itemStatusChanged(v)),
icon: const Icon(GenshinDb.sliders_h, size: 18),
itemText: (val) => s.translateReleasedUnreleasedType(val),
),
ItemPopupMenuFilter<CharacterRoleType>(
tooltipText: s.role,
values: CharacterRoleType.values.where((el) => el != CharacterRoleType.na).toList(),
Expand All @@ -64,13 +68,14 @@ class CharacterBottomSheet extends StatelessWidget {
itemText: (val) => s.translateCharacterType(val),
icon: const Icon(GenshinDb.trefoil_lily, size: 18),
),
ItemPopupMenuFilter<ItemStatusType>(
tooltipText: '${s.released} / ${s.brandNew} / ${s.comingSoon}',
values: ItemStatusType.values,
selectedValue: state.tempStatusType,
onSelected: (v) => context.read<CharactersBloc>().add(CharactersEvent.itemStatusChanged(v)),
icon: const Icon(GenshinDb.sliders_h, size: 18),
itemText: (val) => s.translateReleasedUnreleasedType(val),
ItemPopupMenuFilterWithAllValue(
tooltipText: s.region,
values: RegionType.values.map((e) => e.index).toList(),
selectedValue: state.tempRegionType?.index,
onAllOrValueSelected: (v) =>
context.read<CharactersBloc>().add(CharactersEvent.regionTypeChanged(v == null ? null : RegionType.values[v])),
itemText: (val) => s.translateRegionType(RegionType.values[val]),
icon: const Icon(GenshinDb.reactor, size: 18),
),
ItemPopupMenuFilter<CharacterFilterType>(
tooltipText: s.sortBy,
Expand All @@ -85,6 +90,32 @@ class CharacterBottomSheet extends StatelessWidget {
)
],
),
ButtonBar(
buttonPadding: Styles.edgeInsetHorizontal10,
children: <Widget>[
OutlinedButton(
onPressed: () {
context.read<CharactersBloc>().add(const CharactersEvent.cancelChanges());
Navigator.pop(context);
},
child: Text(s.cancel, style: TextStyle(color: theme.primaryColor)),
),
OutlinedButton(
onPressed: () {
context.read<CharactersBloc>().add(const CharactersEvent.resetFilters());
Navigator.pop(context);
},
child: Text(s.reset, style: TextStyle(color: theme.primaryColor)),
),
ElevatedButton(
onPressed: () {
context.read<CharactersBloc>().add(const CharactersEvent.applyFilterChanges());
Navigator.pop(context);
},
child: Text(s.ok),
)
],
),
],
),
),
Expand Down
78 changes: 66 additions & 12 deletions lib/presentation/shared/item_popupmenu_filter.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:genshindb/generated/l10n.dart';

import 'utils/enum_utils.dart';

Expand All @@ -7,7 +8,7 @@ typedef PopupMenuItemText<T> = String Function(T value);
class ItemPopupMenuFilter<TEnum> extends StatelessWidget {
final String tooltipText;
final TEnum selectedValue;
final Function(TEnum) onSelected;
final Function(TEnum)? onSelected;
final List<TEnum> values;
final List<TEnum> exclude;
final Icon icon;
Expand All @@ -18,31 +19,84 @@ class ItemPopupMenuFilter<TEnum> extends StatelessWidget {
required this.tooltipText,
required this.selectedValue,
required this.values,
required this.onSelected,
this.onSelected,
required this.itemText,
this.exclude = const [],
this.icon = const Icon(Icons.filter_list),
}) : super(key: key);

@override
Widget build(BuildContext context) {
final translatedValues = EnumUtils.getTranslatedAndSortedEnum<TEnum>(values, itemText, exclude: exclude);
final translatedValues = getTranslatedValues(context);
final valuesToUse = getValuesToUse(translatedValues);
return PopupMenuButton<TEnum>(
padding: const EdgeInsets.all(0),
initialValue: selectedValue,
icon: icon,
onSelected: handleItemSelected,
itemBuilder: (context) => valuesToUse,
tooltip: tooltipText,
);
}

final valuesToUse = translatedValues
List<TranslatedEnum<TEnum>> getTranslatedValues(BuildContext context) {
return EnumUtils.getTranslatedAndSortedEnum<TEnum>(values, itemText, exclude: exclude);
}

List<CheckedPopupMenuItem<TEnum>> getValuesToUse(List<TranslatedEnum<TEnum>> translatedValues) {
return translatedValues
.map((e) => CheckedPopupMenuItem<TEnum>(
checked: selectedValue == e.enumValue,
value: e.enumValue,
child: Text(e.translation),
))
.toList();
}

return PopupMenuButton<TEnum>(
padding: const EdgeInsets.all(0),
initialValue: selectedValue,
icon: icon,
onSelected: onSelected,
itemBuilder: (context) => valuesToUse,
tooltip: tooltipText,
);
void handleItemSelected(TEnum value) {
if (onSelected != null) {
onSelected!(value);
}
}
}

class ItemPopupMenuFilterWithAllValue extends ItemPopupMenuFilter<int> {
static int allValue = -1;

final Function(int?)? onAllOrValueSelected;

ItemPopupMenuFilterWithAllValue({
Key? key,
required String tooltipText,
int? selectedValue,
this.onAllOrValueSelected,
required List<int> values,
required PopupMenuItemText<int> itemText,
List<int> exclude = const [],
Icon icon = const Icon(Icons.filter_list),
}) : super(
key: key,
tooltipText: tooltipText,
selectedValue: selectedValue ?? allValue,
itemText: itemText,
exclude: exclude,
icon: icon,
values: values..add(allValue),
);

@override
List<TranslatedEnum<int>> getTranslatedValues(BuildContext context) {
final s = S.of(context);
return EnumUtils.getTranslatedAndSortedEnumWithAllValue<int>(allValue, s.all, values, itemText, exclude: exclude);
}

@override
void handleItemSelected(int value) {
if (onAllOrValueSelected == null) {
return;
}

final valueToUse = value == allValue ? null : value;
onAllOrValueSelected!(valueToUse);
}
}
1 change: 1 addition & 0 deletions lib/presentation/shared/styles.dart
Expand Up @@ -28,6 +28,7 @@ class Styles {
static const edgeInsetHorizontal5 = EdgeInsets.symmetric(horizontal: 5);
static const edgeInsetVertical16 = EdgeInsets.symmetric(vertical: 16);
static const edgeInsetVertical10 = EdgeInsets.symmetric(vertical: 10);
static const edgeInsetHorizontal10 = EdgeInsets.symmetric(horizontal: 10);

static const modalBottomSheetShape = RoundedRectangleBorder(
borderRadius: BorderRadius.only(
Expand Down
22 changes: 20 additions & 2 deletions lib/presentation/shared/utils/enum_utils.dart
Expand Up @@ -6,11 +6,29 @@ class TranslatedEnum<TEnum> {
}

class EnumUtils {
static List<TranslatedEnum<TEnum>> getTranslatedAndSortedEnum<TEnum>(List<TEnum> values, String Function(TEnum) itemText,
{List<TEnum> exclude = const []}) {
static List<TranslatedEnum<TEnum>> getTranslatedAndSortedEnum<TEnum>(
List<TEnum> values,
String Function(TEnum) itemText, {
List<TEnum> exclude = const [],
}) {
final filterValues = exclude.isNotEmpty ? values.where((el) => !exclude.contains(el)) : values;
final translatedValues = filterValues.map((filter) => TranslatedEnum<TEnum>(filter, itemText(filter))).toList()
..sort((x, y) => x.translation.compareTo(y.translation));
return translatedValues;
}

static List<TranslatedEnum<TEnum>> getTranslatedAndSortedEnumWithAllValue<TEnum>(
TEnum allValue,
String allValueText,
List<TEnum> values,
String Function(TEnum) itemText, {
List<TEnum> exclude = const [],
}) {
final filterValues = exclude.isNotEmpty ? values.where((el) => !exclude.contains(el)) : values;
final translatedValues = filterValues
.map((filter) => TranslatedEnum<TEnum>(filter, filter == allValue ? allValueText : itemText(filter)))
.toList()
..sort((x, y) => x.translation.compareTo(y.translation));
return translatedValues;
}
}

0 comments on commit c3e198b

Please sign in to comment.