From 833388c10c308310a0e5a0715fb46275ee7fe70b Mon Sep 17 00:00:00 2001 From: Efrain Date: Sun, 14 Mar 2021 00:48:59 -0500 Subject: [PATCH] Added initial materials bloc --- lib/application/bloc.dart | 1 + .../calculator_asc_materials_bloc.dart | 2 +- lib/application/materials/materials_bloc.dart | 161 +++++++++++++----- .../materials/materials_event.dart | 13 +- .../materials/materials_state.dart | 15 +- .../today_materials/today_materials_bloc.dart | 64 +++++++ .../today_materials_event.dart | 6 + .../today_materials_state.dart | 10 ++ .../db/materials/material_file_model.dart | 1 + .../models/db/materials/materials_file.dart | 4 +- .../models/materials/material_card_model.dart | 18 ++ lib/domain/models/models.dart | 1 + lib/domain/services/genshin_service.dart | 1 + lib/infrastructure/genshin_service.dart | 8 + lib/main.dart | 8 +- lib/presentation/main_tab_page.dart | 1 + ...ls_page.dart => today_materials_page.dart} | 4 +- 17 files changed, 269 insertions(+), 49 deletions(-) create mode 100644 lib/application/today_materials/today_materials_bloc.dart create mode 100644 lib/application/today_materials/today_materials_event.dart create mode 100644 lib/application/today_materials/today_materials_state.dart create mode 100644 lib/domain/models/materials/material_card_model.dart rename lib/presentation/today_materials/{materials_page.dart => today_materials_page.dart} (94%) diff --git a/lib/application/bloc.dart b/lib/application/bloc.dart index bc0d03ee4..8b1799c9e 100644 --- a/lib/application/bloc.dart +++ b/lib/application/bloc.dart @@ -12,6 +12,7 @@ export 'main_tab/main_tab_bloc.dart'; export 'materials/materials_bloc.dart'; export 'settings/settings_bloc.dart'; export 'tierlist/tier_list_bloc.dart'; +export 'today_materials/today_materials_bloc.dart'; export 'url_page/url_page_bloc.dart'; export 'weapon/weapon_bloc.dart'; export 'weapons/weapons_bloc.dart'; diff --git a/lib/application/calculator_asc_materials/calculator_asc_materials_bloc.dart b/lib/application/calculator_asc_materials/calculator_asc_materials_bloc.dart index 002db7d9d..115bbe3bd 100644 --- a/lib/application/calculator_asc_materials/calculator_asc_materials_bloc.dart +++ b/lib/application/calculator_asc_materials/calculator_asc_materials_bloc.dart @@ -161,7 +161,7 @@ class CalculatorAscMaterialsBloc extends Bloc { final GenshinService _genshinService; - final TelemetryService _telemetryService; - MaterialsBloc(this._genshinService, this._telemetryService) : super(const MaterialsState.loading()); + _LoadedState get currentState => state as _LoadedState; + + MaterialsBloc(this._genshinService) : super(const MaterialsState.loading()); @override - Stream mapEventToState( - MaterialsEvent event, - ) async* { - await _telemetryService.trackAscensionMaterialsOpened(); - final s = event.when( - init: () { - final days = [ - DateTime.monday, - DateTime.tuesday, - DateTime.wednesday, - DateTime.thursday, - DateTime.friday, - DateTime.saturday, - DateTime.sunday, - ]; + Stream mapEventToState(MaterialsEvent event) async* { + final s = event.map( + init: (e) => _buildInitialState(), + rarityChanged: (e) => currentState.copyWith.call(tempRarity: e.rarity), + sortDirectionTypeChanged: (e) => currentState.copyWith.call(tempSortDirectionType: e.sortDirectionType), + typeChanged: (e) => currentState.copyWith.call(tempType: e.type), + filterTypeChanged: (e) => currentState.copyWith.call(tempFilterType: e.type), + searchChanged: (e) => _buildInitialState( + search: e.search, + rarity: currentState.rarity, + type: currentState.type, + filterType: currentState.filterType, + sortDirectionType: currentState.sortDirectionType, + ), + applyFilterChanges: (_) => _buildInitialState( + search: currentState.search, + rarity: currentState.tempRarity, + type: currentState.tempType, + filterType: currentState.tempFilterType, + sortDirectionType: currentState.tempSortDirectionType, + ), + cancelChanges: (_) => currentState.copyWith.call( + tempFilterType: currentState.filterType, + tempRarity: currentState.rarity, + tempSortDirectionType: currentState.sortDirectionType, + tempType: currentState.type, + ), + ); - final charMaterials = []; - final weaponMaterials = []; -//TODO: YOU MAY WANT TO SHOW THE BOSS ITEMS AS WELL - for (final day in days) { - final charMaterialsForDay = _genshinService.getCharacterAscensionMaterials(day); - final weaponMaterialsForDay = _genshinService.getWeaponAscensionMaterials(day); + yield s; + } - for (final material in charMaterialsForDay) { - if (charMaterials.any((m) => m.name == material.name)) { - continue; - } - charMaterials.add(material); - } + MaterialsState _buildInitialState({ + String search, + int rarity = 0, + MaterialType type = MaterialType.all, + MaterialFilterType filterType = MaterialFilterType.rarity, + SortDirectionType sortDirectionType = SortDirectionType.asc, + }) { + final isLoaded = state is _LoadedState; + var data = _genshinService.getAllMaterials(); - for (final material in weaponMaterialsForDay) { - if (weaponMaterials.any((m) => m.name == material.name)) { - continue; - } - weaponMaterials.add(material); - } - } + if (!isLoaded) { + _sortData(data, filterType, sortDirectionType); + return MaterialsState.loaded( + materials: data, + search: search, + rarity: rarity, + tempRarity: rarity, + type: type, + tempType: type, + filterType: filterType, + tempFilterType: filterType, + sortDirectionType: sortDirectionType, + tempSortDirectionType: sortDirectionType, + ); + } + + if (search != null && search.isNotEmpty) { + data = data.where((el) => el.name.toLowerCase().contains(search.toLowerCase())).toList(); + } + + if (rarity > 0) { + data = data.where((el) => el.rarity == rarity).toList(); + } - return MaterialsState.loaded(charAscMaterials: charMaterials, weaponAscMaterials: weaponMaterials); - }, + if (type != MaterialType.all) { + switch (type) { + case MaterialType.expWeapon: + case MaterialType.expCharacter: + data = data.where((el) => [MaterialType.expWeapon, MaterialType.expCharacter].contains(el.type)).toList(); + break; + case MaterialType.weaponPrimary: + case MaterialType.weapon: + data = data.where((el) => [MaterialType.weaponPrimary, MaterialType.weapon].contains(el.type)).toList(); + break; + default: + data = data.where((el) => el.type == type).toList(); + break; + } + } + + _sortData(data, filterType, sortDirectionType); + + final s = currentState.copyWith.call( + materials: data, + search: search, + rarity: rarity, + tempRarity: rarity, + type: type, + tempType: type, + filterType: filterType, + tempFilterType: filterType, + sortDirectionType: sortDirectionType, + tempSortDirectionType: sortDirectionType, ); + return s; + } - yield s; + void _sortData( + List data, + MaterialFilterType filterType, + SortDirectionType sortDirectionType, + ) { + switch (filterType) { + case MaterialFilterType.name: + if (sortDirectionType == SortDirectionType.asc) { + data.sort((x, y) => x.name.compareTo(y.name)); + } else { + data.sort((x, y) => y.name.compareTo(x.name)); + } + break; + case MaterialFilterType.rarity: + if (sortDirectionType == SortDirectionType.asc) { + data.sort((x, y) => x.rarity.compareTo(y.rarity)); + } else { + data.sort((x, y) => y.rarity.compareTo(x.rarity)); + } + break; + default: + break; + } } } diff --git a/lib/application/materials/materials_event.dart b/lib/application/materials/materials_event.dart index cf113e95b..78538297f 100644 --- a/lib/application/materials/materials_event.dart +++ b/lib/application/materials/materials_event.dart @@ -1,6 +1,17 @@ part of 'materials_bloc.dart'; @freezed -abstract class MaterialsEvent with _$MaterialsEvent { +abstract class MaterialsEvent implements _$MaterialsEvent { const factory MaterialsEvent.init() = _Init; + const factory MaterialsEvent.searchChanged({ + @required String search, + }) = _SearchChanged; + + const factory MaterialsEvent.rarityChanged(int rarity) = _RarityChanged; + const factory MaterialsEvent.typeChanged(MaterialType type) = _TypeChanged; + const factory MaterialsEvent.filterTypeChanged(MaterialFilterType type) = _FilterTypeChanged; + const factory MaterialsEvent.applyFilterChanges() = _ApplyFilterChanges; + const factory MaterialsEvent.sortDirectionTypeChanged(SortDirectionType sortDirectionType) = _SortDirectionTypeChanged; + + const factory MaterialsEvent.cancelChanges() = _CancelChanges; } diff --git a/lib/application/materials/materials_state.dart b/lib/application/materials/materials_state.dart index 2b82bb55e..1c43c9bd6 100644 --- a/lib/application/materials/materials_state.dart +++ b/lib/application/materials/materials_state.dart @@ -1,10 +1,19 @@ part of 'materials_bloc.dart'; @freezed -abstract class MaterialsState with _$MaterialsState { +abstract class MaterialsState implements _$MaterialsState { const factory MaterialsState.loading() = _LoadingState; + const factory MaterialsState.loaded({ - @required List charAscMaterials, - @required List weaponAscMaterials, + @required List materials, + String search, + @required int rarity, + @required int tempRarity, + @required MaterialFilterType filterType, + @required MaterialFilterType tempFilterType, + @required MaterialType type, + @required MaterialType tempType, + @required SortDirectionType sortDirectionType, + @required SortDirectionType tempSortDirectionType, }) = _LoadedState; } diff --git a/lib/application/today_materials/today_materials_bloc.dart b/lib/application/today_materials/today_materials_bloc.dart new file mode 100644 index 000000000..212023ec2 --- /dev/null +++ b/lib/application/today_materials/today_materials_bloc.dart @@ -0,0 +1,64 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:genshindb/domain/models/models.dart'; +import 'package:genshindb/domain/services/genshin_service.dart'; +import 'package:genshindb/domain/services/telemetry_service.dart'; + +part 'today_materials_bloc.freezed.dart'; +part 'today_materials_event.dart'; +part 'today_materials_state.dart'; + +class TodayMaterialsBloc extends Bloc { + final GenshinService _genshinService; + final TelemetryService _telemetryService; + + TodayMaterialsBloc(this._genshinService, this._telemetryService) : super(const TodayMaterialsState.loading()); + + @override + Stream mapEventToState( + TodayMaterialsEvent event, + ) async* { + await _telemetryService.trackAscensionMaterialsOpened(); + final s = event.when( + init: () { + final days = [ + DateTime.monday, + DateTime.tuesday, + DateTime.wednesday, + DateTime.thursday, + DateTime.friday, + DateTime.saturday, + DateTime.sunday, + ]; + + final charMaterials = []; + final weaponMaterials = []; +//TODO: YOU MAY WANT TO SHOW THE BOSS ITEMS AS WELL + for (final day in days) { + final charMaterialsForDay = _genshinService.getCharacterAscensionMaterials(day); + final weaponMaterialsForDay = _genshinService.getWeaponAscensionMaterials(day); + + for (final material in charMaterialsForDay) { + if (charMaterials.any((m) => m.name == material.name)) { + continue; + } + charMaterials.add(material); + } + + for (final material in weaponMaterialsForDay) { + if (weaponMaterials.any((m) => m.name == material.name)) { + continue; + } + weaponMaterials.add(material); + } + } + + return TodayMaterialsState.loaded(charAscMaterials: charMaterials, weaponAscMaterials: weaponMaterials); + }, + ); + + yield s; + } +} diff --git a/lib/application/today_materials/today_materials_event.dart b/lib/application/today_materials/today_materials_event.dart new file mode 100644 index 000000000..9aee74ab0 --- /dev/null +++ b/lib/application/today_materials/today_materials_event.dart @@ -0,0 +1,6 @@ +part of 'today_materials_bloc.dart'; + +@freezed +abstract class TodayMaterialsEvent with _$TodayMaterialsEvent { + const factory TodayMaterialsEvent.init() = _Init; +} diff --git a/lib/application/today_materials/today_materials_state.dart b/lib/application/today_materials/today_materials_state.dart new file mode 100644 index 000000000..ae7554787 --- /dev/null +++ b/lib/application/today_materials/today_materials_state.dart @@ -0,0 +1,10 @@ +part of 'today_materials_bloc.dart'; + +@freezed +abstract class TodayMaterialsState with _$TodayMaterialsState { + const factory TodayMaterialsState.loading() = _LoadingState; + const factory TodayMaterialsState.loaded({ + @required List charAscMaterials, + @required List weaponAscMaterials, + }) = _LoadedState; +} diff --git a/lib/domain/models/db/materials/material_file_model.dart b/lib/domain/models/db/materials/material_file_model.dart index 924d92e79..fb02d726d 100644 --- a/lib/domain/models/db/materials/material_file_model.dart +++ b/lib/domain/models/db/materials/material_file_model.dart @@ -20,6 +20,7 @@ abstract class MaterialFileModel implements _$MaterialFileModel { factory MaterialFileModel({ @required String key, + @required int rarity, @required String image, @required bool isFromBoss, @required bool isForCharacters, diff --git a/lib/domain/models/db/materials/materials_file.dart b/lib/domain/models/db/materials/materials_file.dart index 54d30b373..45fa4bc81 100644 --- a/lib/domain/models/db/materials/materials_file.dart +++ b/lib/domain/models/db/materials/materials_file.dart @@ -8,7 +8,8 @@ part 'materials_file.g.dart'; @freezed abstract class MaterialsFile implements _$MaterialsFile { @late - List get materials => talents + weapon + weaponPrimary + common + currency + elemental + jewels + locals + experience; + List get materials => + talents + weapon + weaponPrimary + common + currency + elemental + jewels + locals + experience + ingredient; factory MaterialsFile({ @required List talents, @@ -20,6 +21,7 @@ abstract class MaterialsFile implements _$MaterialsFile { @required List jewels, @required List locals, @required List experience, + @required List ingredient, }) = _MaterialsFile; MaterialsFile._(); diff --git a/lib/domain/models/materials/material_card_model.dart b/lib/domain/models/materials/material_card_model.dart new file mode 100644 index 000000000..65caba377 --- /dev/null +++ b/lib/domain/models/materials/material_card_model.dart @@ -0,0 +1,18 @@ +import 'package:flutter/foundation.dart'; +import 'package:genshindb/domain/enums/material_type.dart'; + +class MaterialCardModel { + final String key; + final String name; + final int rarity; + final String image; + final MaterialType type; + + MaterialCardModel({ + @required this.key, + @required this.name, + @required this.rarity, + @required this.image, + @required this.type, + }); +} diff --git a/lib/domain/models/models.dart b/lib/domain/models/models.dart index 8b135caf7..c2c35fbe2 100644 --- a/lib/domain/models/models.dart +++ b/lib/domain/models/models.dart @@ -34,6 +34,7 @@ export 'home/today_weapon_ascension_material_model.dart'; export 'items/item_ascension_material_model.dart'; export 'items/item_experience_model.dart'; export 'language_model.dart'; +export 'materials/material_card_model.dart'; export 'settings/app_settings.dart'; export 'tierlist/tierlist_row_model.dart'; export 'weapons/weapon_card_model.dart'; diff --git a/lib/domain/services/genshin_service.dart b/lib/domain/services/genshin_service.dart index 1b995edf0..7a66d9ec0 100644 --- a/lib/domain/services/genshin_service.dart +++ b/lib/domain/services/genshin_service.dart @@ -39,6 +39,7 @@ abstract class GenshinService { List getElementReactions(); List getElementResonances(); + List getAllMaterials(); MaterialFileModel getMaterialByImage(String image); List getMaterials(MaterialType type); diff --git a/lib/infrastructure/genshin_service.dart b/lib/infrastructure/genshin_service.dart index 66a005f56..5d688c55d 100644 --- a/lib/infrastructure/genshin_service.dart +++ b/lib/infrastructure/genshin_service.dart @@ -447,6 +447,14 @@ class GenshinServiceImpl implements GenshinService { ).toList(); } + @override + List getAllMaterials() { + return _materialsFile.materials.map((e) { + final translation = _translationFile.materials.firstWhere((m) => m.key == e.key); + return MaterialCardModel(key: e.key, image: e.fullImagePath, rarity: e.rarity, type: e.type, name: translation.name); + }).toList(); + } + @override MaterialFileModel getMaterialByImage(String image) { return _materialsFile.materials.firstWhere((m) => m.fullImagePath == image); diff --git a/lib/main.dart b/lib/main.dart index aebb4644d..aedcfd2a2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -78,7 +78,7 @@ class MyApp extends StatelessWidget { create: (ctx) { final genshinService = getIt(); final telemetryService = getIt(); - return MaterialsBloc(genshinService, telemetryService); + return TodayMaterialsBloc(genshinService, telemetryService); }, ), BlocProvider( @@ -149,6 +149,12 @@ class MyApp extends StatelessWidget { return TierListBloc(genshinService, telemetryService, loggingService); }, ), + BlocProvider( + create: (_) { + final genshinService = getIt(); + return MaterialsBloc(genshinService); + }, + ), ], child: BlocBuilder( builder: (ctx, state) => AppWidget(), diff --git a/lib/presentation/main_tab_page.dart b/lib/presentation/main_tab_page.dart index 904906a06..8742a91c5 100644 --- a/lib/presentation/main_tab_page.dart +++ b/lib/presentation/main_tab_page.dart @@ -51,6 +51,7 @@ class _MainTabPageState extends State with SingleTickerProviderStat context.read().add(const ElementsEvent.init()); context.read().add(const SettingsEvent.init()); context.read().add(const GameCodesEvent.init()); + context.read().add(const MaterialsEvent.init()); } @override diff --git a/lib/presentation/today_materials/materials_page.dart b/lib/presentation/today_materials/today_materials_page.dart similarity index 94% rename from lib/presentation/today_materials/materials_page.dart rename to lib/presentation/today_materials/today_materials_page.dart index 2396469fe..2fb62ce82 100644 --- a/lib/presentation/today_materials/materials_page.dart +++ b/lib/presentation/today_materials/today_materials_page.dart @@ -7,12 +7,12 @@ import 'package:genshindb/presentation/shared/loading.dart'; import 'widgets/sliver_character_ascension_materials.dart'; import 'widgets/sliver_weapon_ascension_materials.dart'; -class MaterialsPage extends StatelessWidget { +class TodayMaterialsPage extends StatelessWidget { @override Widget build(BuildContext context) { final theme = Theme.of(context); final s = S.of(context); - return BlocBuilder( + return BlocBuilder( builder: (context, state) { return state.when( loading: () => const Loading(),