From dfc6c2898edf0204a4c19598c0df2a0b86a29abb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 16:40:30 +0100 Subject: [PATCH 01/16] rework: MapNotifier --- .../providers/section_logo_provider.dart | 2 +- .../simple_groups_groups_provider.dart | 3 +- lib/admin/ui/pages/edit_page/results.dart | 16 +- lib/admin/ui/pages/edit_page/search_user.dart | 196 +++++------ .../providers/advert_posters_provider.dart | 2 +- lib/advert/ui/components/advert_card.dart | 2 +- .../pages/form_page/add_edit_advert_page.dart | 19 +- .../delivery_order_list_provider.dart | 2 +- .../detail_delivery_page/detail_page.dart | 173 +++++----- .../session_poster_map_provider.dart | 2 +- .../pages/session_pages/add_edit_session.dart | 16 +- .../admin_history_loan_list_provider.dart | 3 +- .../providers/admin_loan_list_provider.dart | 2 +- .../providers/loaners_items_provider.dart | 2 +- lib/loan/ui/pages/admin_page/admin_page.dart | 94 +++--- .../ui/pages/admin_page/loan_history.dart | 75 ++--- lib/loan/ui/pages/admin_page/loaners_bar.dart | 11 +- .../ui/pages/admin_page/loaners_items.dart | 183 +++++----- .../ui/pages/admin_page/on_going_loan.dart | 290 ++++++++-------- .../loan_group_page/add_edit_button.dart | 2 +- .../ui/pages/loan_group_page/item_bar.dart | 314 +++++++++--------- .../providers/raffle_stats_map_provider.dart | 2 +- .../providers/tombola_logos_provider.dart | 2 +- .../creation_edit_page.dart | 18 +- .../ui/pages/main_page/ticket_card.dart | 73 ++-- .../raffle_page/buy_pack_ticket_card.dart | 107 +++--- .../raffle_page/buy_type_ticket_card.dart | 80 ++--- .../ui/pages/raffle_page/confirm_payment.dart | 95 +++--- lib/tools/providers/map_provider.dart | 140 ++------ lib/tools/ui/builders/auto_loader_child.dart | 30 +- .../providers/contender_logos_provider.dart | 2 +- .../sections_contender_provider.dart | 2 +- .../providers/sections_stats_provider.dart | 2 +- lib/vote/ui/pages/admin_page/section_bar.dart | 97 +++--- .../admin_page/section_contender_items.dart | 142 ++++---- lib/vote/ui/pages/admin_page/vote_bars.dart | 73 ++-- .../contender_pages/add_edit_contender.dart | 21 +- .../ui/pages/detail_page/detail_page.dart | 101 +++--- .../pages/main_page/list_contender_card.dart | 232 +++++++------ lib/vote/ui/pages/main_page/main_page.dart | 63 ++-- test/tools/providers/map_notifier_test.dart | 256 ++++---------- 41 files changed, 1257 insertions(+), 1690 deletions(-) diff --git a/lib/admin/providers/section_logo_provider.dart b/lib/admin/providers/section_logo_provider.dart index 024a07933..eb9ff40c3 100644 --- a/lib/admin/providers/section_logo_provider.dart +++ b/lib/admin/providers/section_logo_provider.dart @@ -10,7 +10,7 @@ class SimpleGroupLogoNotifier extends MapNotifier { } final allGroupLogosProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { SimpleGroupLogoNotifier simpleGroupLogoNotifier = SimpleGroupLogoNotifier(); tokenExpireWrapperAuth(ref, () async { ref.watch(allGroupListProvider).maybeWhen(data: (allGroup) { diff --git a/lib/admin/providers/simple_groups_groups_provider.dart b/lib/admin/providers/simple_groups_groups_provider.dart index e01cbd167..51c885b79 100644 --- a/lib/admin/providers/simple_groups_groups_provider.dart +++ b/lib/admin/providers/simple_groups_groups_provider.dart @@ -9,8 +9,7 @@ class SimpleGroupsGroupsNotifier extends MapNotifier { } final simpleGroupsGroupsProvider = StateNotifierProvider< - SimpleGroupsGroupsNotifier, - AsyncValue>?>>>((ref) { + SimpleGroupsGroupsNotifier, Map>?>>((ref) { SimpleGroupsGroupsNotifier simpleGroupsGroupsNotifier = SimpleGroupsGroupsNotifier(); tokenExpireWrapperAuth(ref, () async { diff --git a/lib/admin/ui/pages/edit_page/results.dart b/lib/admin/ui/pages/edit_page/results.dart index 66d3e8cfc..11a507493 100644 --- a/lib/admin/ui/pages/edit_page/results.dart +++ b/lib/admin/ui/pages/edit_page/results.dart @@ -57,14 +57,14 @@ class MemberResults extends HookConsumerWidget { .then((value) { if (value) { simpleGroupGroupsNotifier - .setTData(newGroup.id, - AsyncData([newGroup])) - .then((value) { - displayToastWithContext( - TypeMsg.msg, - AdminTextConstants - .addedMember); - }); + .setTData( + newGroup.id, + AsyncData([newGroup]), + ); + displayToastWithContext( + TypeMsg.msg, + AdminTextConstants + .addedMember); } else { displayToastWithContext( TypeMsg.error, diff --git a/lib/admin/ui/pages/edit_page/search_user.dart b/lib/admin/ui/pages/edit_page/search_user.dart index 9d8d83ea7..f4d7b06bf 100644 --- a/lib/admin/ui/pages/edit_page/search_user.dart +++ b/lib/admin/ui/pages/edit_page/search_user.dart @@ -36,114 +36,98 @@ class SearchUser extends HookConsumerWidget { displayToast(context, type, msg); } + final simpleGroup = simpleGroupsGroups[groupId]; + if (simpleGroup == null) { + return const Loader(); + } return AsyncChild( - value: simpleGroupsGroups, - builder: (context, value) { - final simpleGroup = value[groupId]; - if (simpleGroup == null) { - return const Loader(); - } - return AsyncChild( - value: simpleGroup, - builder: (context, g) { - return Column( - children: [ - StyledSearchBar( - label: AdminTextConstants.members, - color: ColorConstants.gradient1, - padding: const EdgeInsets.all(0), - onChanged: (value) async { - if (value.isNotEmpty) { - await usersNotifier.filterUsers(value, - excludeGroup: [group.value!.toSimpleGroup()]); - } else { - usersNotifier.clear(); - } - }, - onSuffixIconTap: (focusNode, editingController) { - add.value = !add.value; - if (!add.value) { - editingController.clear(); - usersNotifier.clear(); - focusNode.unfocus(); - } else { - focusNode.requestFocus(); - } - }, - suffixIcon: Padding( - padding: const EdgeInsets.all(7.0), - child: Container( - padding: const EdgeInsets.all(7), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [ - ColorConstants.gradient1, - ColorConstants.gradient2 - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight), - boxShadow: [ - BoxShadow( - color: - ColorConstants.gradient2.withOpacity(0.4), - offset: const Offset(2, 3), - blurRadius: 5) - ], - borderRadius: - const BorderRadius.all(Radius.circular(10)), - ), - child: HeroIcon( - !add.value ? HeroIcons.plus : HeroIcons.xMark, - size: 20, - color: Colors.white, - ), - ), - ), + value: simpleGroup, + builder: (context, g) { + return Column( + children: [ + StyledSearchBar( + label: AdminTextConstants.members, + color: ColorConstants.gradient1, + padding: const EdgeInsets.all(0), + onChanged: (value) async { + if (value.isNotEmpty) { + await usersNotifier.filterUsers(value, + excludeGroup: [group.value!.toSimpleGroup()]); + } else { + usersNotifier.clear(); + } + }, + onSuffixIconTap: (focusNode, editingController) { + add.value = !add.value; + if (!add.value) { + editingController.clear(); + usersNotifier.clear(); + focusNode.unfocus(); + } else { + focusNode.requestFocus(); + } + }, + suffixIcon: Padding( + padding: const EdgeInsets.all(7.0), + child: Container( + padding: const EdgeInsets.all(7), + decoration: BoxDecoration( + gradient: const LinearGradient(colors: [ + ColorConstants.gradient1, + ColorConstants.gradient2 + ], begin: Alignment.topLeft, end: Alignment.bottomRight), + boxShadow: [ + BoxShadow( + color: ColorConstants.gradient2.withOpacity(0.4), + offset: const Offset(2, 3), + blurRadius: 5) + ], + borderRadius: const BorderRadius.all(Radius.circular(10)), + ), + child: HeroIcon( + !add.value ? HeroIcons.plus : HeroIcons.xMark, + size: 20, + color: Colors.white, ), - if (add.value) const SizedBox(height: 10), - if (add.value) const MemberResults(), - if (!add.value) - ...g[0].members.map((x) => UserUi( - user: x, - onDelete: () { - showDialog( - context: context, - builder: (BuildContext context) => - CustomDialogBox( - descriptions: AdminTextConstants - .removeAssociationMember, - title: AdminTextConstants.deleting, - onYes: () async { - await tokenExpireWrapper(ref, - () async { - Group newGroup = g[0].copyWith( - members: g[0] - .members - .where((element) => - element.id != x.id) - .toList()); - final value = await groupNotifier - .deleteMember(newGroup, x); - if (value) { - simpleGroupGroupsNotifier - .setTData(newGroup.id, - AsyncData([newGroup])); - displayToastWithContext( - TypeMsg.msg, - AdminTextConstants - .updatedAssociation); - } else { - displayToastWithContext( - TypeMsg.msg, - AdminTextConstants - .updatingError); - } - }); - })); - })), - ], - ); - }); + ), + ), + ), + if (add.value) const SizedBox(height: 10), + if (add.value) const MemberResults(), + if (!add.value) + ...g[0].members.map((x) => UserUi( + user: x, + onDelete: () { + showDialog( + context: context, + builder: (BuildContext context) => CustomDialogBox( + descriptions: + AdminTextConstants.removeAssociationMember, + title: AdminTextConstants.deleting, + onYes: () async { + await tokenExpireWrapper(ref, () async { + Group newGroup = g[0].copyWith( + members: g[0] + .members + .where( + (element) => element.id != x.id) + .toList()); + final value = await groupNotifier + .deleteMember(newGroup, x); + if (value) { + simpleGroupGroupsNotifier.setTData( + newGroup.id, AsyncData([newGroup])); + displayToastWithContext(TypeMsg.msg, + AdminTextConstants.updatedAssociation); + } else { + displayToastWithContext(TypeMsg.msg, + AdminTextConstants.updatingError); + } + }); + })); + })), + ], + ); }); } } diff --git a/lib/advert/providers/advert_posters_provider.dart b/lib/advert/providers/advert_posters_provider.dart index e37292d59..486d98a6c 100644 --- a/lib/advert/providers/advert_posters_provider.dart +++ b/lib/advert/providers/advert_posters_provider.dart @@ -10,7 +10,7 @@ class AdvertPosterNotifier extends MapNotifier { } final advertPostersProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { AdvertPosterNotifier advertPosterNotifier = AdvertPosterNotifier(); tokenExpireWrapperAuth(ref, () async { ref.watch(advertListProvider).maybeWhen(data: (advert) { diff --git a/lib/advert/ui/components/advert_card.dart b/lib/advert/ui/components/advert_card.dart index 4c9610623..2de1c87bd 100644 --- a/lib/advert/ui/components/advert_card.dart +++ b/lib/advert/ui/components/advert_card.dart @@ -41,7 +41,7 @@ class AdvertCard extends HookConsumerWidget { value: advertPosters, notifier: advertPostersNotifier, mapKey: advert, - loader: (ref) => logoNotifier.getAdvertPoster(advert.id), + loader: (advert) => logoNotifier.getAdvertPoster(advert.id), loadingBuilder: (context) => HeroIcon( HeroIcons.photo, size: width, diff --git a/lib/advert/ui/pages/form_page/add_edit_advert_page.dart b/lib/advert/ui/pages/form_page/add_edit_advert_page.dart index 96af7082d..3ba931dde 100644 --- a/lib/advert/ui/pages/form_page/add_edit_advert_page.dart +++ b/lib/advert/ui/pages/form_page/add_edit_advert_page.dart @@ -39,21 +39,20 @@ class AdvertAddEditAdvertPage extends HookConsumerWidget { final tags = advert.tags; var textTags = tags.join(', '); final textTagsController = useTextEditingController(text: textTags); - + final advertPosters = ref.watch(advertPostersProvider); final advertListNotifier = ref.watch(advertListProvider.notifier); final posterNotifier = ref.watch(advertPosterProvider.notifier); final poster = useState(null); final posterFile = useState(null); - ref.watch(advertPostersProvider).whenData((value) { - if (value[advert] != null) { - value[advert]!.whenData((data) { - if (data.isNotEmpty) { - posterFile.value = data.first; - } - }); - } - }); + if (advertPosters[advert] != null) { + advertPosters[advert]!.whenData((data) { + if (data.isNotEmpty) { + posterFile.value = data.first; + } + }); + } + final ImagePicker picker = ImagePicker(); void displayAdvertToastWithContext(TypeMsg type, String msg) { diff --git a/lib/amap/providers/delivery_order_list_provider.dart b/lib/amap/providers/delivery_order_list_provider.dart index 71b8f6e84..a0584d71b 100644 --- a/lib/amap/providers/delivery_order_list_provider.dart +++ b/lib/amap/providers/delivery_order_list_provider.dart @@ -10,7 +10,7 @@ class AdminDeliveryOrderListNotifier extends MapNotifier { final adminDeliveryOrderListProvider = StateNotifierProvider< AdminDeliveryOrderListNotifier, - AsyncValue>?>>>((ref) { + Map>?>>((ref) { AdminDeliveryOrderListNotifier orderListNotifier = AdminDeliveryOrderListNotifier(); tokenExpireWrapperAuth(ref, () async { diff --git a/lib/amap/ui/pages/detail_delivery_page/detail_page.dart b/lib/amap/ui/pages/detail_delivery_page/detail_page.dart index db24e7039..e4d57e3c6 100644 --- a/lib/amap/ui/pages/detail_delivery_page/detail_page.dart +++ b/lib/amap/ui/pages/detail_delivery_page/detail_page.dart @@ -1,5 +1,3 @@ -// ignore_for_file: unnecessary_to_list_in_spreads - import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:myecl/amap/class/order.dart'; @@ -27,6 +25,7 @@ class DetailDeliveryPage extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final delivery = ref.watch(deliveryProvider); final deliveryOrders = ref.watch(adminDeliveryOrderListProvider); + final orders = deliveryOrders[delivery.id]; final deliveryListNotifier = ref.read(deliveryListProvider.notifier); final deliveryProductListNotifier = ref.watch(deliveryProductListProvider.notifier); @@ -58,61 +57,54 @@ class DetailDeliveryPage extends HookConsumerWidget { ], ), ), - ...sortedByCategoryDeliveryProducts - .map((key, value) { - Map productsQuantity = {}; - deliveryOrders.maybeWhen( - data: (orderMap) { - final deliveryOrderList = orderMap[delivery.id]; - if (deliveryOrderList != null) { - deliveryOrderList.maybeWhen( - data: (listOrders) { - for (Order o in listOrders) { - for (Product p in o.products) { - if (!productsQuantity.containsKey(p.id)) { - productsQuantity - .addEntries({p.id: 0}.entries); - } - productsQuantity[p.id] = - productsQuantity[p.id]! + p.quantity; - } - } - }, - orElse: () {}); + ...sortedByCategoryDeliveryProducts.map((key, value) { + Map productsQuantity = {}; + final deliveryOrderList = deliveryOrders[delivery.id]; + if (deliveryOrderList != null) { + deliveryOrderList.maybeWhen( + data: (listOrders) { + for (Order o in listOrders) { + for (Product p in o.products) { + if (!productsQuantity.containsKey(p.id)) { + productsQuantity.addEntries({p.id: 0}.entries); } - }, - orElse: () {}); - return MapEntry( - key, - Column( - children: [ - Text( - key, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 5), - Wrap( - children: value - .map((e) => Container( - padding: - const EdgeInsets.symmetric(vertical: 5), - child: ProductDetailCard( - product: e, - quantity: productsQuantity[e.id] ?? 0, - ), - )) - .toList(), - ), - const SizedBox(height: 10), - ], + productsQuantity[p.id] = + productsQuantity[p.id]! + p.quantity; + } + } + }, + orElse: () {}, + ); + } + return MapEntry( + key, + Column( + children: [ + Text( + key, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 5), + Wrap( + children: value + .map((e) => Container( + padding: + const EdgeInsets.symmetric(vertical: 5), + child: ProductDetailCard( + product: e, + quantity: productsQuantity[e.id] ?? 0, + ), + )) + .toList(), ), - ); - }) - .values - .toList(), + const SizedBox(height: 10), + ], + ), + ); + }).values, const SizedBox(height: 20), const AlignLeftText( "${AMAPTextConstants.orders} :", @@ -122,46 +114,37 @@ class DetailDeliveryPage extends HookConsumerWidget { const SizedBox(height: 30), Container( margin: const EdgeInsets.symmetric(horizontal: 10), - child: AsyncChild( - value: deliveryOrders, - loaderColor: AMAPColorConstants.greenGradient2, - builder: (context, data) { - final orders = data[delivery.id]; - if (orders == null) { - return const Loader( - color: AMAPColorConstants.greenGradient2); - } - return AsyncChild( - value: orders, - loaderColor: AMAPColorConstants.greenGradient2, - builder: (context, data) { - if (data.isEmpty) { - return Container( - margin: const EdgeInsets.only(bottom: 50), - child: const Center( - child: Text(AMAPTextConstants.noOrder))); - } - return AsyncChild( - value: cash, - loaderColor: AMAPColorConstants.greenGradient2, - builder: (context, cash) { - return Wrap( - spacing: 20, - runSpacing: 20, - children: data.map((e) { - final userCash = cash.firstWhere( - (element) => - element.user.id == e.user.id); - return DetailOrderUI( - order: e, - userCash: userCash, - deliveryId: delivery.id, - ); - }).toList(), - ); - }); - }); - }), + child: orders == null + ? const Loader(color: AMAPColorConstants.greenGradient2) + : AsyncChild( + value: orders, + loaderColor: AMAPColorConstants.greenGradient2, + builder: (context, data) { + if (data.isEmpty) { + return Container( + margin: const EdgeInsets.only(bottom: 50), + child: const Center( + child: Text(AMAPTextConstants.noOrder))); + } + return AsyncChild( + value: cash, + loaderColor: AMAPColorConstants.greenGradient2, + builder: (context, cash) { + return Wrap( + spacing: 20, + runSpacing: 20, + children: data.map((e) { + final userCash = cash.firstWhere((element) => + element.user.id == e.user.id); + return DetailOrderUI( + order: e, + userCash: userCash, + deliveryId: delivery.id, + ); + }).toList(), + ); + }); + }), ), const SizedBox(height: 20) ], diff --git a/lib/cinema/providers/session_poster_map_provider.dart b/lib/cinema/providers/session_poster_map_provider.dart index 421650a41..7a452dcde 100644 --- a/lib/cinema/providers/session_poster_map_provider.dart +++ b/lib/cinema/providers/session_poster_map_provider.dart @@ -10,7 +10,7 @@ class SessionLogoNotifier extends MapNotifier { } final sessionPosterMapProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { SessionLogoNotifier sessionLogoNotifier = SessionLogoNotifier(); tokenExpireWrapperAuth(ref, () async { ref.watch(sessionListProvider).maybeWhen(data: (session) { diff --git a/lib/cinema/ui/pages/session_pages/add_edit_session.dart b/lib/cinema/ui/pages/session_pages/add_edit_session.dart index baf95dfe6..11c0100b1 100644 --- a/lib/cinema/ui/pages/session_pages/add_edit_session.dart +++ b/lib/cinema/ui/pages/session_pages/add_edit_session.dart @@ -49,15 +49,13 @@ class AddEditSessionPage extends HookConsumerWidget { final posterUrl = useTextEditingController(); final sessionPosterNotifier = ref.watch(sessionPosterProvider.notifier); - sessionPosterMap.whenData((value) { - if (value[session] != null) { - value[session]!.whenData((data) { - if (data.isNotEmpty) { - logoFile.value = data.first; - } - }); - } - }); + if (sessionPosterMap[session] != null) { + sessionPosterMap[session]!.whenData((data) { + if (data.isNotEmpty) { + logoFile.value = data.first; + } + }); + } void displayToastWithContext(TypeMsg type, String msg) { displayToast(context, type, msg); diff --git a/lib/loan/providers/admin_history_loan_list_provider.dart b/lib/loan/providers/admin_history_loan_list_provider.dart index 8edf15783..05c6129a6 100644 --- a/lib/loan/providers/admin_history_loan_list_provider.dart +++ b/lib/loan/providers/admin_history_loan_list_provider.dart @@ -12,8 +12,7 @@ class AdminHistoryLoanListNotifier extends MapNotifier { } final adminHistoryLoanListProvider = StateNotifierProvider< - AdminHistoryLoanListNotifier, - AsyncValue>?>>>((ref) { + AdminHistoryLoanListNotifier, Map>?>>((ref) { AdminHistoryLoanListNotifier adminLoanListNotifier = AdminHistoryLoanListNotifier(); tokenExpireWrapperAuth(ref, () async { diff --git a/lib/loan/providers/admin_loan_list_provider.dart b/lib/loan/providers/admin_loan_list_provider.dart index fbbc5eccd..07be0759e 100644 --- a/lib/loan/providers/admin_loan_list_provider.dart +++ b/lib/loan/providers/admin_loan_list_provider.dart @@ -12,7 +12,7 @@ class AdminLoanListNotifier extends MapNotifier { } final adminLoanListProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { AdminLoanListNotifier adminLoanListNotifier = AdminLoanListNotifier(); tokenExpireWrapperAuth(ref, () async { final loaners = ref.watch(loanerList); diff --git a/lib/loan/providers/loaners_items_provider.dart b/lib/loan/providers/loaners_items_provider.dart index 7d939c15a..7408627e9 100644 --- a/lib/loan/providers/loaners_items_provider.dart +++ b/lib/loan/providers/loaners_items_provider.dart @@ -9,7 +9,7 @@ class LoanersItemsNotifier extends MapNotifier { } final loanersItemsProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { final loaners = ref.watch(loanerList); LoanersItemsNotifier loanerLoanListNotifier = LoanersItemsNotifier(); loanerLoanListNotifier.loadTList(loaners); diff --git a/lib/loan/ui/pages/admin_page/admin_page.dart b/lib/loan/ui/pages/admin_page/admin_page.dart index 14030ac66..3063b6f51 100644 --- a/lib/loan/ui/pages/admin_page/admin_page.dart +++ b/lib/loan/ui/pages/admin_page/admin_page.dart @@ -67,69 +67,55 @@ class AdminPage extends HookConsumerWidget { LoanersBar(onTap: (key) async { tokenExpireWrapper(ref, () async { loanerIdNotifier.setId(key.id); - loanersItems.whenData( - (value) async { - final itemListNotifier = - ref.read(itemListProvider.notifier); - final loanersItemsNotifier = - ref.read(loanersItemsProvider.notifier); - final listItems = value[key]; - if (listItems == null) { + final itemListNotifier = ref.read(itemListProvider.notifier); + final loanersItemsNotifier = + ref.read(loanersItemsProvider.notifier); + final listItems = loanersItems[key]; + if (listItems == null) { + loanersItemsNotifier.autoLoadList(ref, key, + (key) => itemListNotifier.loadItemList(key.id)); + } else { + listItems.whenData((loanersItems) async { + if (loanersItems.isEmpty) { loanersItemsNotifier.autoLoadList(ref, key, (key) => itemListNotifier.loadItemList(key.id)); - } else { - listItems.whenData((value) async { - if (value.isEmpty) { - loanersItemsNotifier.autoLoadList(ref, key, - (key) => itemListNotifier.loadItemList(key.id)); - } - }); } - }, - ); - adminLoanList.whenData( - (value) async { - final loanListNotifier = - ref.read(loanerLoanListProvider.notifier); - final adminLoanListNotifier = - ref.read(adminLoanListProvider.notifier); - final listItems = value[key]; - if (listItems == null) { + }); + } + final loanListNotifier = + ref.read(loanerLoanListProvider.notifier); + final adminLoanListNotifier = + ref.read(adminLoanListProvider.notifier); + final listAdminItems = adminLoanList[key]; + if (listAdminItems == null) { + adminLoanListNotifier.autoLoadList( + ref, key, (key) => loanListNotifier.loadLoan(key.id)); + } else { + listAdminItems.whenData((adminLoanList) async { + if (adminLoanList.isEmpty) { adminLoanListNotifier.autoLoadList(ref, key, (key) => loanListNotifier.loadLoan(key.id)); - } else { - listItems.whenData((value) async { - if (value.isEmpty) { - adminLoanListNotifier.autoLoadList(ref, key, - (key) => loanListNotifier.loadLoan(key.id)); - } - }); } - }, - ); - adminHistoryLoanList.whenData( - (value) async { - final historyLoanListNotifier = - ref.read(historyLoanerLoanListProvider.notifier); - final adminHistoryLoanListNotifier = - ref.read(adminHistoryLoanListProvider.notifier); - final listItems = value[key]; - if (listItems == null) { + }); + } + + final historyLoanListNotifier = + ref.read(historyLoanerLoanListProvider.notifier); + final adminHistoryLoanListNotifier = + ref.read(adminHistoryLoanListProvider.notifier); + final listAdminHistoryItems = adminHistoryLoanList[key]; + if (listAdminHistoryItems == null) { + adminHistoryLoanListNotifier.autoLoadList(ref, key, + (key) => historyLoanListNotifier.loadLoan(key.id)); + } else { + listAdminHistoryItems + .whenData((adminHistoryLoanList) async { + if (adminHistoryLoanList.isEmpty) { adminHistoryLoanListNotifier.autoLoadList(ref, key, (key) => historyLoanListNotifier.loadLoan(key.id)); - } else { - listItems.whenData((value) async { - if (value.isEmpty) { - adminHistoryLoanListNotifier.autoLoadList( - ref, - key, - (key) => - historyLoanListNotifier.loadLoan(key.id)); - } - }); } - }, - ); + }); + } }); }), const Column( diff --git a/lib/loan/ui/pages/admin_page/loan_history.dart b/lib/loan/ui/pages/admin_page/loan_history.dart index 79693cd2e..be19ba269 100644 --- a/lib/loan/ui/pages/admin_page/loan_history.dart +++ b/lib/loan/ui/pages/admin_page/loan_history.dart @@ -34,49 +34,44 @@ class HistoryLoan extends HookConsumerWidget { focusNode.requestFocus(); } + final loan = adminLoanList[loaner]; + if (loan == null) { + return const Loader(); + } return AsyncChild( - value: adminLoanList, - builder: (context, loans) { - final loan = loans[loaner]; - if (loan == null) { - return const Loader(); + value: loan, + builder: (context, data) { + if (data.isNotEmpty) { + data.sort((a, b) => b.end.compareTo(a.end)); } - return AsyncChild( - value: loan, - builder: (context, data) { - if (data.isNotEmpty) { - data.sort((a, b) => b.end.compareTo(a.end)); - } - return Column( - children: [ - StyledSearchBar( - label: LoanTextConstants.history, - onChanged: (value) async { - if (value.isNotEmpty) { - adminHistoryLoanListNotifier.setTData(loaner, - await historyLoanListNotifier.filterLoans(value)); - } else { - adminHistoryLoanListNotifier.setTData( - loaner, loanList); - } + return Column( + children: [ + StyledSearchBar( + label: LoanTextConstants.history, + onChanged: (value) async { + if (value.isNotEmpty) { + adminHistoryLoanListNotifier.setTData(loaner, + await historyLoanListNotifier.filterLoans(value)); + } else { + adminHistoryLoanListNotifier.setTData(loaner, loanList); + } + }, + ), + const SizedBox(height: 10), + HorizontalListView.builder( + height: 120, + items: data, + itemBuilder: (context, loan, i) => LoanCard( + loan: loan, + onInfo: () { + loanNotifier.setLoan(loan); + QR.to(LoanRouter.root + + LoanRouter.admin + + LoanRouter.detail); }, - ), - const SizedBox(height: 10), - HorizontalListView.builder( - height: 120, - items: data, - itemBuilder: (context, loan, i) => LoanCard( - loan: loan, - onInfo: () { - loanNotifier.setLoan(loan); - QR.to(LoanRouter.root + - LoanRouter.admin + - LoanRouter.detail); - }, - isHistory: true)) - ], - ); - }); + isHistory: true)) + ], + ); }); } } diff --git a/lib/loan/ui/pages/admin_page/loaners_bar.dart b/lib/loan/ui/pages/admin_page/loaners_bar.dart index 8dad8c346..bc6e09506 100644 --- a/lib/loan/ui/pages/admin_page/loaners_bar.dart +++ b/lib/loan/ui/pages/admin_page/loaners_bar.dart @@ -4,7 +4,6 @@ import 'package:myecl/loan/class/loaner.dart'; import 'package:myecl/loan/providers/admin_loan_list_provider.dart'; import 'package:myecl/loan/providers/loaner_provider.dart'; import 'package:myecl/tools/functions.dart'; -import 'package:myecl/tools/ui/builders/async_child.dart'; import 'package:myecl/tools/ui/layouts/horizontal_list_view.dart'; import 'package:myecl/tools/ui/layouts/item_chip.dart'; @@ -16,11 +15,9 @@ class LoanersBar extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final adminLoanList = ref.watch(adminLoanListProvider); final loaner = ref.watch(loanerProvider); - return AsyncChild( - value: adminLoanList, - builder: (context, loans) => HorizontalListView.builder( + return HorizontalListView.builder( height: 40, - items: loans.keys.toList(), + items: adminLoanList.keys.toList(), itemBuilder: (context, key, i) { final selected = loaner.id == key.id; return ItemChip( @@ -35,8 +32,6 @@ class LoanersBar extends HookConsumerWidget { fontWeight: FontWeight.bold), ), ); - }, - ), - ); + }); } } diff --git a/lib/loan/ui/pages/admin_page/loaners_items.dart b/lib/loan/ui/pages/admin_page/loaners_items.dart index 67fa6429c..90da688dc 100644 --- a/lib/loan/ui/pages/admin_page/loaners_items.dart +++ b/lib/loan/ui/pages/admin_page/loaners_items.dart @@ -41,104 +41,93 @@ class LoanersItems extends HookConsumerWidget { displayToast(context, type, msg); } + final item = loanersItems[loaner]; + if (item == null) { + return const Center( + child: Text(LoanTextConstants.noItems), + ); + } return AsyncChild( - value: loanersItems, - builder: (context, items) { - final item = items[loaner]; - if (item == null) { - return const Center( - child: Text(LoanTextConstants.noItems), - ); - } - return AsyncChild( - value: item, - builder: (context, data) { - if (data.isNotEmpty) { - data.sort((a, b) => a.name.compareTo(b.name)); - } - return Column( - children: [ - StyledSearchBar( - label: LoanTextConstants.itemHandling, - onChanged: (value) async { - if (value.isNotEmpty) { - loanersItemsNotifier.setTData( - loaner, await itemListNotifier.filterItems(value)); - } else { - loanersItemsNotifier.setTData(loaner, itemList); - } - }, - ), - const SizedBox(height: 10), - HorizontalListView.builder( - height: 150, - firstChild: GestureDetector( - onTap: () { - itemNotifier.setItem(Item.empty()); - QR.to(LoanRouter.root + - LoanRouter.admin + - LoanRouter.addEditItem); - }, - child: const CardLayout( - width: 100, - height: 140, - child: Center( - child: HeroIcon( - HeroIcons.plus, - size: 40.0, - color: Colors.black, - ), - ), - ), + value: item, + builder: (context, data) { + if (data.isNotEmpty) { + data.sort((a, b) => a.name.compareTo(b.name)); + } + return Column( + children: [ + StyledSearchBar( + label: LoanTextConstants.itemHandling, + onChanged: (value) async { + if (value.isNotEmpty) { + loanersItemsNotifier.setTData( + loaner, await itemListNotifier.filterItems(value)); + } else { + loanersItemsNotifier.setTData(loaner, itemList); + } + }, + ), + const SizedBox(height: 10), + HorizontalListView.builder( + height: 150, + firstChild: GestureDetector( + onTap: () { + itemNotifier.setItem(Item.empty()); + QR.to(LoanRouter.root + + LoanRouter.admin + + LoanRouter.addEditItem); + }, + child: const CardLayout( + width: 100, + height: 140, + child: Center( + child: HeroIcon( + HeroIcons.plus, + size: 40.0, + color: Colors.black, ), - items: data, - itemBuilder: (context, e, i) => ItemCard( - item: e, - showButtons: true, - onDelete: () async { - showDialog( - context: context, - builder: (BuildContext context) { - return CustomDialogBox( - descriptions: - LoanTextConstants.deletingItem, - onYes: () { - tokenExpireWrapper(ref, () async { - final value = await itemListNotifier - .deleteItem(e, loaner.id); - if (value) { - itemListNotifier - .copy() - .then((value) { - loanersItemsNotifier.setTData( - loaner, value); - }); - displayToastWithContext( - TypeMsg.msg, - LoanTextConstants - .deletedItem); - } else { - displayToastWithContext( - TypeMsg.error, - LoanTextConstants - .deletingError); - } - }); - }, - title: LoanTextConstants.delete); - }); - }, - onEdit: () { - QR.to(LoanRouter.root + - LoanRouter.admin + - LoanRouter.addEditItem); - itemNotifier.setItem(e); - }, - )), - ], - ); - }, - ); - }); + ), + ), + ), + items: data, + itemBuilder: (context, e, i) => ItemCard( + item: e, + showButtons: true, + onDelete: () async { + showDialog( + context: context, + builder: (BuildContext context) { + return CustomDialogBox( + descriptions: LoanTextConstants.deletingItem, + onYes: () { + tokenExpireWrapper(ref, () async { + final value = await itemListNotifier + .deleteItem(e, loaner.id); + if (value) { + itemListNotifier.copy().then((value) { + loanersItemsNotifier.setTData( + loaner, value); + }); + displayToastWithContext(TypeMsg.msg, + LoanTextConstants.deletedItem); + } else { + displayToastWithContext(TypeMsg.error, + LoanTextConstants.deletingError); + } + }); + }, + title: LoanTextConstants.delete); + }); + }, + onEdit: () { + QR.to(LoanRouter.root + + LoanRouter.admin + + LoanRouter.addEditItem); + itemNotifier.setItem(e); + }, + )), + ], + ); + }, + ); } } diff --git a/lib/loan/ui/pages/admin_page/on_going_loan.dart b/lib/loan/ui/pages/admin_page/on_going_loan.dart index e0f80f59d..a1d98b0e7 100644 --- a/lib/loan/ui/pages/admin_page/on_going_loan.dart +++ b/lib/loan/ui/pages/admin_page/on_going_loan.dart @@ -53,169 +53,143 @@ class OnGoingLoan extends HookConsumerWidget { displayToast(context, type, msg); } + if (adminLoanList[loaner] == null) { + return const Loader(); + } return AsyncChild( - value: adminLoanList, - builder: (context, loans) { - if (loans[loaner] == null) { - return const Loader(); + value: adminLoanList[loaner]!, + builder: (context, data) { + if (data.isNotEmpty) { + data.sort((a, b) => a.end.compareTo(b.end)); } - return AsyncChild( - value: loans[loaner]!, - builder: (context, data) { - if (data.isNotEmpty) { - data.sort((a, b) => a.end.compareTo(b.end)); - } - return Column( - children: [ - StyledSearchBar( - label: - '${data.isEmpty ? LoanTextConstants.none : data.length} ${LoanTextConstants.loan.toLowerCase()}${data.length > 1 ? 's' : ''} ${LoanTextConstants.onGoing.toLowerCase()}', - onChanged: (value) async { - if (value.isNotEmpty) { - adminLoanListNotifier.setTData(loaner, - await loanListNotifier.filterLoans(value)); - } else { - adminLoanListNotifier.setTData(loaner, loanList); - } - }, + return Column( + children: [ + StyledSearchBar( + label: + '${data.isEmpty ? LoanTextConstants.none : data.length} ${LoanTextConstants.loan.toLowerCase()}${data.length > 1 ? 's' : ''} ${LoanTextConstants.onGoing.toLowerCase()}', + onChanged: (value) async { + if (value.isNotEmpty) { + adminLoanListNotifier.setTData( + loaner, await loanListNotifier.filterLoans(value)); + } else { + adminLoanListNotifier.setTData(loaner, loanList); + } + }, + ), + const SizedBox(height: 10), + HorizontalListView.builder( + height: 170, + firstChild: GestureDetector( + onTap: () async { + await loanNotifier.setLoan(Loan.empty()); + startNotifier.setStart(processDate(DateTime.now())); + endNotifier.setEnd(""); + QR.to(LoanRouter.root + + LoanRouter.admin + + LoanRouter.addEditLoan); + loanersItemsNotifier.setTData(loaner, itemList); + }, + child: const CardLayout( + width: 100, + height: 170, + child: Center( + child: HeroIcon( + HeroIcons.plus, + size: 40.0, + color: Colors.black, + )), ), - const SizedBox(height: 10), - HorizontalListView.builder( - height: 170, - firstChild: GestureDetector( - onTap: () async { - await loanNotifier.setLoan(Loan.empty()); - startNotifier.setStart(processDate(DateTime.now())); - endNotifier.setEnd(""); - QR.to(LoanRouter.root + - LoanRouter.admin + - LoanRouter.addEditLoan); - loanersItemsNotifier.setTData(loaner, itemList); - }, - child: const CardLayout( - width: 100, - height: 170, - child: Center( - child: HeroIcon( - HeroIcons.plus, - size: 40.0, - color: Colors.black, - )), - ), - ), - items: data, - itemBuilder: (context, e, i) => LoanCard( - loan: e, - isAdmin: true, - onEdit: () async { - await loanNotifier.setLoan(e); - startNotifier.setStart(processDate(e.start)); - endNotifier.setEnd(processDate(e.end)); - QR.to(LoanRouter.root + - LoanRouter.admin + - LoanRouter.addEditLoan); - loanersItemsNotifier.setTData(loaner, itemList); - }, - onCalendar: () async { - await showDialog( - context: context, - builder: (BuildContext context) { - return DelayDialog( - onYes: (i) async { - Loan newLoan = e.copyWith( - end: - e.end.add(Duration(days: i))); - await loanNotifier.setLoan(newLoan); - tokenExpireWrapper(ref, () async { - final value = await loanListNotifier - .extendLoan(newLoan, i); - if (value) { - await adminLoanListNotifier - .setTData( - loaner, - await loanListNotifier - .copy()); - displayToastWithContext( - TypeMsg.msg, - LoanTextConstants - .extendedLoan); - } else { - displayToastWithContext( - TypeMsg.error, - LoanTextConstants - .extendingError); - } - }); + ), + items: data, + itemBuilder: (context, e, i) => LoanCard( + loan: e, + isAdmin: true, + onEdit: () async { + await loanNotifier.setLoan(e); + startNotifier.setStart(processDate(e.start)); + endNotifier.setEnd(processDate(e.end)); + QR.to(LoanRouter.root + + LoanRouter.admin + + LoanRouter.addEditLoan); + loanersItemsNotifier.setTData(loaner, itemList); + }, + onCalendar: () async { + await showDialog( + context: context, + builder: (BuildContext context) { + return DelayDialog( + onYes: (i) async { + Loan newLoan = e.copyWith( + end: e.end.add(Duration(days: i))); + await loanNotifier.setLoan(newLoan); + tokenExpireWrapper(ref, () async { + final value = await loanListNotifier + .extendLoan(newLoan, i); + if (value) { + adminLoanListNotifier.setTData(loaner, + await loanListNotifier.copy()); + displayToastWithContext(TypeMsg.msg, + LoanTextConstants.extendedLoan); + } else { + displayToastWithContext(TypeMsg.error, + LoanTextConstants.extendingError); + } + }); + }, + ); + }); + }, + onReturn: () async { + await showDialog( + context: context, + builder: (context) => CustomDialogBox( + title: LoanTextConstants.returnLoan, + descriptions: + LoanTextConstants.returnLoanDescription, + onYes: () async { + await tokenExpireWrapper(ref, () async { + final loanItemsId = e.itemsQuantity + .map((e) => e.itemSimple.id) + .toList(); + final updatedItems = loanersItems[loaner]! + .maybeWhen>( + data: (items) => items, + orElse: () => []) + .map( + (item) { + if (loanItemsId.contains(item.id)) { + return item.copyWith(); + } + return item; }, - ); + ).toList(); + final value = + await loanListNotifier.returnLoan(e); + if (value) { + QR.to( + LoanRouter.root + LoanRouter.admin); + loanersItemsNotifier.setTData( + loaner, AsyncData(updatedItems)); + adminLoanListNotifier.setTData(loaner, + await loanListNotifier.copy()); + displayToastWithContext(TypeMsg.msg, + LoanTextConstants.returnedLoan); + } else { + displayToastWithContext(TypeMsg.msg, + LoanTextConstants.returningError); + } }); - }, - onReturn: () async { - await showDialog( - context: context, - builder: (context) => CustomDialogBox( - title: LoanTextConstants.returnLoan, - descriptions: LoanTextConstants - .returnLoanDescription, - onYes: () async { - await tokenExpireWrapper(ref, - () async { - final loanItemsId = e.itemsQuantity - .map((e) => e.itemSimple.id) - .toList(); - final updatedItems = loanersItems - .maybeWhen>( - data: (items) => items[loaner]! - .maybeWhen( - data: (items) => items, - orElse: () => []), - orElse: () => [], - ) - .map( - (element) { - if (loanItemsId - .contains(element.id)) { - return element.copyWith(); - } - return element; - }, - ).toList(); - final value = await loanListNotifier - .returnLoan(e); - if (value) { - QR.to(LoanRouter.root + - LoanRouter.admin); - await loanersItemsNotifier - .setTData(loaner, - AsyncData(updatedItems)); - await adminLoanListNotifier - .setTData( - loaner, - await loanListNotifier - .copy()); - displayToastWithContext( - TypeMsg.msg, - LoanTextConstants - .returnedLoan); - } else { - displayToastWithContext( - TypeMsg.msg, - LoanTextConstants - .returningError); - } - }); - })); - }, - onInfo: () { - loanNotifier.setLoan(e); - QR.to(LoanRouter.root + - LoanRouter.admin + - LoanRouter.detail); - }, - )) - ], - ); - }); + })); + }, + onInfo: () { + loanNotifier.setLoan(e); + QR.to(LoanRouter.root + + LoanRouter.admin + + LoanRouter.detail); + }, + )) + ], + ); }); } } diff --git a/lib/loan/ui/pages/loan_group_page/add_edit_button.dart b/lib/loan/ui/pages/loan_group_page/add_edit_button.dart index 7b49b1560..d1debb6c4 100644 --- a/lib/loan/ui/pages/loan_group_page/add_edit_button.dart +++ b/lib/loan/ui/pages/loan_group_page/add_edit_button.dart @@ -93,7 +93,7 @@ class AddEditButton extends HookConsumerWidget { ? await loanListNotifier.updateLoan(newLoan) : await loanListNotifier.addLoan(newLoan); if (value) { - await adminLoanListNotifier.setTData( + adminLoanListNotifier.setTData( isEdit ? loan.loaner : loaner, await loanListNotifier.copy()); QR.back(); diff --git a/lib/loan/ui/pages/loan_group_page/item_bar.dart b/lib/loan/ui/pages/loan_group_page/item_bar.dart index 502e21415..6cc6e3b11 100644 --- a/lib/loan/ui/pages/loan_group_page/item_bar.dart +++ b/lib/loan/ui/pages/loan_group_page/item_bar.dart @@ -46,11 +46,20 @@ class ItemBar extends HookConsumerWidget { .toList() ..sort((a, b) => a.name.compareTo(b.name)); data = sortedAvailableData + sortedUnavailableData; + if (loanersItems[loaner] == null) { + return const SizedBox( + height: 180, + child: Center( + child: Text(LoanTextConstants.noItems, + style: TextStyle( + fontSize: 18, fontWeight: FontWeight.w500))), + ); + } return AsyncChild( - value: loanersItems, + value: loanersItems[loaner]!, loaderColor: ColorConstants.background2, - builder: (context, items) { - if (items[loaner] == null) { + builder: (context, itemList) { + if (itemList.isEmpty) { return const SizedBox( height: 180, child: Center( @@ -60,173 +69,148 @@ class ItemBar extends HookConsumerWidget { fontWeight: FontWeight.w500))), ); } - return AsyncChild( - value: items[loaner]!, - loaderColor: ColorConstants.background2, - builder: (context, itemList) { - if (itemList.isEmpty) { - return const SizedBox( - height: 180, - child: Center( - child: Text(LoanTextConstants.noItems, - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.w500))), - ); - } - final sortedAvailable = itemList - .where((element) => - element.loanedQuantity < - element.totalQuantity) - .toList() - ..sort((a, b) => a.name.compareTo(b.name)); - final sortedUnavailable = itemList - .where((element) => - element.loanedQuantity >= - element.totalQuantity) - .toList() - ..sort((a, b) => a.name.compareTo(b.name)); - itemList = sortedAvailable + sortedUnavailable; - return HorizontalListView.builder( - height: 180, - items: itemList, - itemBuilder: (context, e, i) { - var currentValue = - selectedItems[data.indexOf(e)]; - return Column( + final sortedAvailable = itemList + .where((element) => + element.loanedQuantity < element.totalQuantity) + .toList() + ..sort((a, b) => a.name.compareTo(b.name)); + final sortedUnavailable = itemList + .where((element) => + element.loanedQuantity >= element.totalQuantity) + .toList() + ..sort((a, b) => a.name.compareTo(b.name)); + itemList = sortedAvailable + sortedUnavailable; + return HorizontalListView.builder( + height: 180, + items: itemList, + itemBuilder: (context, e, i) { + var currentValue = selectedItems[data.indexOf(e)]; + return Column( + children: [ + CheckItemCard( + item: e, + isSelected: currentValue != 0, + ), + const SizedBox(height: 10), + SizedBox( + width: 120, + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, children: [ - CheckItemCard( - item: e, - isSelected: currentValue != 0, + Container( + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(10), + ), + child: GestureDetector( + child: HeroIcon( + HeroIcons.minus, + color: currentValue == 0 + ? Colors.grey.shade400 + : Colors.white, + ), + onTap: () { + if (currentValue > 0) { + selectedItemsNotifier.set( + data.indexOf(e), + currentValue - 1); + Map + selectedItemsWithQuantity = + Map.fromIterables( + data, selectedItems); + selectedItemsWithQuantity[e] = + currentValue - 1; + List selected = + selectedItemsWithQuantity.keys + .where((element) => + selectedItemsWithQuantity[ + element] != + 0) + .toList(); + if (selected.isNotEmpty) { + endNotifier.setEndFromSelected( + start, selected); + cautionNotifier + .setCautionFromSelected( + selectedItemsWithQuantity); + } else { + endNotifier.setEnd(""); + cautionNotifier.setCaution(""); + } + } + }, + ), ), - const SizedBox(height: 10), - SizedBox( - width: 120, - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - Container( - padding: const EdgeInsets.all(5), - decoration: BoxDecoration( - color: Colors.black, - borderRadius: - BorderRadius.circular(10), - ), - child: GestureDetector( - child: HeroIcon( - HeroIcons.minus, - color: currentValue == 0 - ? Colors.grey.shade400 - : Colors.white, - ), - onTap: () { - if (currentValue > 0) { - selectedItemsNotifier.set( - data.indexOf(e), - currentValue - 1); - Map - selectedItemsWithQuantity = - Map.fromIterables( - data, selectedItems); - selectedItemsWithQuantity[e] = - currentValue - 1; - List selected = - selectedItemsWithQuantity - .keys - .where((element) => - selectedItemsWithQuantity[ - element] != - 0) - .toList(); - if (selected.isNotEmpty) { - endNotifier - .setEndFromSelected( - start, selected); - cautionNotifier - .setCautionFromSelected( - selectedItemsWithQuantity); - } else { - endNotifier.setEnd(""); - cautionNotifier - .setCaution(""); - } - } - }, - ), - ), - Padding( - padding: const EdgeInsets.symmetric( - horizontal: 6), - child: Text( - currentValue.toString(), - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - color: currentValue == 0 - ? Colors.grey.shade400 - : Colors.black, - ), - ), - ), - Container( - padding: const EdgeInsets.all(5), - decoration: BoxDecoration( - color: Colors.black, - borderRadius: - BorderRadius.circular(10), - ), - child: GestureDetector( - child: HeroIcon( - HeroIcons.plus, - color: currentValue == - e.totalQuantity - - e.loanedQuantity - ? Colors.grey.shade400 - : Colors.white, - ), - onTap: () { - if (currentValue < - e.totalQuantity - - e.loanedQuantity) { - selectedItemsNotifier.set( - data.indexOf(e), - currentValue + 1); - Map - selectedItemsWithQuantity = - Map.fromIterables(data, - selectedItems); - selectedItemsWithQuantity[ - e] = currentValue + 1; - List selected = - selectedItemsWithQuantity - .keys - .where((element) => - selectedItemsWithQuantity[ - element] != - 0) - .toList(); - if (selected.isNotEmpty) { - endNotifier - .setEndFromSelected( - start, selected); - cautionNotifier - .setCautionFromSelected( - selectedItemsWithQuantity); - } else { - endNotifier.setEnd(""); - cautionNotifier - .setCaution(""); - } - } - }, - )) - ], + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 6), + child: Text( + currentValue.toString(), + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: currentValue == 0 + ? Colors.grey.shade400 + : Colors.black, + ), ), ), + Container( + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: Colors.black, + borderRadius: + BorderRadius.circular(10), + ), + child: GestureDetector( + child: HeroIcon( + HeroIcons.plus, + color: currentValue == + e.totalQuantity - + e.loanedQuantity + ? Colors.grey.shade400 + : Colors.white, + ), + onTap: () { + if (currentValue < + e.totalQuantity - + e.loanedQuantity) { + selectedItemsNotifier.set( + data.indexOf(e), + currentValue + 1); + Map + selectedItemsWithQuantity = + Map.fromIterables( + data, selectedItems); + selectedItemsWithQuantity[e] = + currentValue + 1; + List selected = + selectedItemsWithQuantity.keys + .where((element) => + selectedItemsWithQuantity[ + element] != + 0) + .toList(); + if (selected.isNotEmpty) { + endNotifier.setEndFromSelected( + start, selected); + cautionNotifier + .setCautionFromSelected( + selectedItemsWithQuantity); + } else { + endNotifier.setEnd(""); + cautionNotifier.setCaution(""); + } + } + }, + )) ], - ); - }); + ), + ), + ], + ); }); }); })); diff --git a/lib/raffle/providers/raffle_stats_map_provider.dart b/lib/raffle/providers/raffle_stats_map_provider.dart index 1a706ffe3..b2b946073 100644 --- a/lib/raffle/providers/raffle_stats_map_provider.dart +++ b/lib/raffle/providers/raffle_stats_map_provider.dart @@ -9,7 +9,7 @@ class RaffleStatsMapNotifier extends MapNotifier { } final raffleStatsMapProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { RaffleStatsMapNotifier notifier = RaffleStatsMapNotifier(); tokenExpireWrapperAuth(ref, () async { final raffles = ref.watch(raffleListProvider); diff --git a/lib/raffle/providers/tombola_logos_provider.dart b/lib/raffle/providers/tombola_logos_provider.dart index f2be6520f..6a0a8fe96 100644 --- a/lib/raffle/providers/tombola_logos_provider.dart +++ b/lib/raffle/providers/tombola_logos_provider.dart @@ -10,7 +10,7 @@ class RaffleLogoNotifier extends MapNotifier { } final tombolaLogosProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { RaffleLogoNotifier raffleLogoNotifier = RaffleLogoNotifier(); tokenExpireWrapperAuth(ref, () async { ref.watch(raffleListProvider).maybeWhen(data: (raffle) { diff --git a/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart b/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart index 21ab4dfa0..9f46c732d 100644 --- a/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart +++ b/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart @@ -55,15 +55,15 @@ class CreationPage extends HookConsumerWidget { final raffleLogoNotifier = ref.watch(tombolaLogoProvider.notifier); final logo = useState(null); final logoFile = useState(null); - ref.watch(tombolaLogosProvider).whenData((value) { - if (value[raffle] != null) { - value[raffle]!.whenData((data) { - if (data.isNotEmpty) { - logoFile.value = data.first; - } - }); - } - }); + final tombolaLogos = ref.watch(tombolaLogosProvider); + + if (tombolaLogos[raffle] != null) { + tombolaLogos[raffle]!.whenData((data) { + if (data.isNotEmpty) { + logoFile.value = data.first; + } + }); + } void displayRaffleToastWithContext(TypeMsg type, String msg) { displayToast(context, type, msg); diff --git a/lib/raffle/ui/pages/main_page/ticket_card.dart b/lib/raffle/ui/pages/main_page/ticket_card.dart index 49f793fb8..764ba630c 100644 --- a/lib/raffle/ui/pages/main_page/ticket_card.dart +++ b/lib/raffle/ui/pages/main_page/ticket_card.dart @@ -54,48 +54,37 @@ class TicketWidget extends HookConsumerWidget { ], borderRadius: const BorderRadius.all(Radius.circular(15))), - child: Center( - child: tombolaLogos.when( - data: (data) { - if (data[raffle] != null) { - return data[raffle]!.when( - data: (data) { - if (data.isNotEmpty) { - return data.first; - } else { - Future.delayed( - const Duration(milliseconds: 1), - () { - tombolaLogosNotifier.setTData( - raffle, const AsyncLoading()); - }); - tokenExpireWrapper(ref, () async { - tombolaLogoNotifier - .getLogo(raffle.id) - .then((value) { - tombolaLogosNotifier.setTData( - raffle, AsyncData([value])); - }); - }); - return const HeroIcon( - HeroIcons.cubeTransparent); - } - }, - loading: () => - const CircularProgressIndicator(), - error: (Object error, - StackTrace? stackTrace) => - const HeroIcon( - HeroIcons.cubeTransparent)); - } else { - return const HeroIcon( - HeroIcons.cubeTransparent); - } - }, - loading: () => const CircularProgressIndicator(), - error: (Object error, StackTrace? stackTrace) => - const HeroIcon(HeroIcons.cubeTransparent)), - ), + child: Center(child: Builder(builder: (context) { + if (tombolaLogos[raffle] != null) { + return tombolaLogos[raffle]!.when( + data: (tombolaLogos) { + if (tombolaLogos.isNotEmpty) { + return tombolaLogos.first; + } else { + Future.delayed( + const Duration(milliseconds: 1), () { + tombolaLogosNotifier.setTData( + raffle, const AsyncLoading()); + }); + tokenExpireWrapper(ref, () async { + tombolaLogoNotifier + .getLogo(raffle.id) + .then((value) { + tombolaLogosNotifier.setTData( + raffle, AsyncData([value])); + }); + }); + return const HeroIcon( + HeroIcons.cubeTransparent); + } + }, + loading: () => const CircularProgressIndicator(), + error: (Object error, StackTrace? stackTrace) => + const HeroIcon(HeroIcons.cubeTransparent)); + } else { + return const HeroIcon(HeroIcons.cubeTransparent); + } + })), ), Expanded( child: AutoSizeText( diff --git a/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart b/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart index 2930b81d0..4b7b87617 100644 --- a/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart +++ b/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart @@ -61,65 +61,54 @@ class BuyPackTicket extends HookConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( - width: 50, - height: 50, - decoration: BoxDecoration( - color: Colors.white, - boxShadow: [ - BoxShadow( - color: Colors.white.withOpacity(0.3), - blurRadius: 8, - offset: const Offset(1, 2), - ), - ], - borderRadius: - const BorderRadius.all(Radius.circular(15))), - child: Container( - child: tombolaLogos.when( - data: (data) { - if (data[raffle] != null) { - return data[raffle]!.when( - data: (data) { - if (data.isNotEmpty) { - return ClipRRect( - borderRadius: - BorderRadius.circular(15.0), - child: data.first); - } else { - Future.delayed( - const Duration(milliseconds: 1), - () { - tombolaLogosNotifier.setTData( - raffle, const AsyncLoading()); - }); - tokenExpireWrapper(ref, () async { - tombolaLogoNotifier - .getLogo(raffle.id) - .then((value) { - tombolaLogosNotifier.setTData( - raffle, AsyncData([value])); - }); - }); - return const HeroIcon( - HeroIcons.cubeTransparent); - } - }, - loading: () => - const CircularProgressIndicator(), - error: (Object error, - StackTrace? stackTrace) => - const HeroIcon( - HeroIcons.cubeTransparent)); - } else { - return const HeroIcon( - HeroIcons.cubeTransparent); - } - }, - loading: () => const CircularProgressIndicator(), - error: (Object error, StackTrace? stackTrace) => - const HeroIcon(HeroIcons.cubeTransparent)), - ), - ), + width: 50, + height: 50, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.white.withOpacity(0.3), + blurRadius: 8, + offset: const Offset(1, 2), + ), + ], + borderRadius: + const BorderRadius.all(Radius.circular(15))), + child: Builder(builder: (context) { + if (tombolaLogos[raffle] != null) { + return tombolaLogos[raffle]!.when( + data: (data) { + if (data.isNotEmpty) { + return ClipRRect( + borderRadius: + BorderRadius.circular(15.0), + child: data.first); + } else { + Future.delayed( + const Duration(milliseconds: 1), () { + tombolaLogosNotifier.setTData( + raffle, const AsyncLoading()); + }); + tokenExpireWrapper(ref, () async { + tombolaLogoNotifier + .getLogo(raffle.id) + .then((value) { + tombolaLogosNotifier.setTData( + raffle, AsyncData([value])); + }); + }); + return const HeroIcon( + HeroIcons.cubeTransparent); + } + }, + loading: () => + const CircularProgressIndicator(), + error: (Object error, StackTrace? stackTrace) => + const HeroIcon(HeroIcons.cubeTransparent)); + } else { + return const HeroIcon(HeroIcons.cubeTransparent); + } + })), Text( "${packTicket.price.toStringAsFixed(2)}€", style: const TextStyle( diff --git a/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart b/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart index 835021f51..9695dcfba 100644 --- a/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart +++ b/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart @@ -74,50 +74,42 @@ class BuyPackTicket extends HookConsumerWidget { ], borderRadius: const BorderRadius.all(Radius.circular(15))), - child: Container( - child: tombolaLogos.when( - data: (data) { - if (data[raffle] != null) { - return data[raffle]!.when( - data: (data) { - if (data.isNotEmpty) { - return ClipRRect( - borderRadius: - BorderRadius.circular(15.0), - child: data.first); - } else { - Future.delayed( - const Duration(milliseconds: 1), - () { - tombolaLogosNotifier.setTData( - raffle, const AsyncLoading()); - }); - tokenExpireWrapper(ref, () async { - tombolaLogoNotifier - .getLogo(raffle.id) - .then((value) { - tombolaLogosNotifier.setTData( - raffle, AsyncData([value])); - }); - }); - return const HeroIcon( - HeroIcons.cubeTransparent); - } - }, - loading: () => - const CircularProgressIndicator(), - error: (Object error, - StackTrace? stackTrace) => - const HeroIcon( - HeroIcons.cubeTransparent)); - } else { - return const HeroIcon( - HeroIcons.cubeTransparent); - } - }, - loading: () => const CircularProgressIndicator(), - error: (Object error, StackTrace? stackTrace) => - const HeroIcon(HeroIcons.cubeTransparent)), + child: Builder( + builder: (context) { + if (tombolaLogos[raffle] != null) { + return tombolaLogos[raffle]!.when( + data: (data) { + if (data.isNotEmpty) { + return ClipRRect( + borderRadius: + BorderRadius.circular(15.0), + child: data.first); + } else { + Future.delayed( + const Duration(milliseconds: 1), () { + tombolaLogosNotifier.setTData( + raffle, const AsyncLoading()); + }); + tokenExpireWrapper(ref, () async { + tombolaLogoNotifier + .getLogo(raffle.id) + .then((value) { + tombolaLogosNotifier.setTData( + raffle, AsyncData([value])); + }); + }); + return const HeroIcon( + HeroIcons.cubeTransparent); + } + }, + loading: () => + const CircularProgressIndicator(), + error: (Object error, StackTrace? stackTrace) => + const HeroIcon(HeroIcons.cubeTransparent)); + } else { + return const HeroIcon(HeroIcons.cubeTransparent); + } + }, ), ), Text( diff --git a/lib/raffle/ui/pages/raffle_page/confirm_payment.dart b/lib/raffle/ui/pages/raffle_page/confirm_payment.dart index 0b6ef533c..061af04bc 100644 --- a/lib/raffle/ui/pages/raffle_page/confirm_payment.dart +++ b/lib/raffle/ui/pages/raffle_page/confirm_payment.dart @@ -101,61 +101,46 @@ class ConfirmPaymentDialog extends HookConsumerWidget { ], borderRadius: const BorderRadius.all( Radius.circular(25))), - child: Center( - child: tombolaLogos.when( - data: (data) { - if (data[raffle] != null) { - return data[raffle]!.when( - data: (data) { - if (data.isNotEmpty) { - return ClipRRect( - borderRadius: - BorderRadius.circular( - 20.0), - child: data.first); - } else { - Future.delayed( - const Duration( - milliseconds: 1), () { - tombolaLogosNotifier.setTData( - raffle, - const AsyncLoading()); - }); - tokenExpireWrapper(ref, - () async { - tombolaLogoNotifier - .getLogo(raffle.id) - .then((value) { - tombolaLogosNotifier - .setTData( - raffle, - AsyncData( - [value])); - }); - }); - return const HeroIcon( - HeroIcons - .cubeTransparent); - } - }, - loading: () => - const CircularProgressIndicator(), - error: (Object error, - StackTrace? stackTrace) => - const HeroIcon(HeroIcons - .cubeTransparent)); - } else { - return const HeroIcon( - HeroIcons.cubeTransparent); - } - }, - loading: () => - const CircularProgressIndicator(), - error: (Object error, - StackTrace? stackTrace) => - const HeroIcon( - HeroIcons.cubeTransparent)), - ), + child: + Center(child: Builder(builder: (context) { + if (tombolaLogos[raffle] != null) { + return tombolaLogos[raffle]!.when( + data: (data) { + if (data.isNotEmpty) { + return ClipRRect( + borderRadius: + BorderRadius.circular(20.0), + child: data.first); + } else { + Future.delayed( + const Duration(milliseconds: 1), + () { + tombolaLogosNotifier.setTData( + raffle, const AsyncLoading()); + }); + tokenExpireWrapper(ref, () async { + tombolaLogoNotifier + .getLogo(raffle.id) + .then((value) { + tombolaLogosNotifier.setTData( + raffle, AsyncData([value])); + }); + }); + return const HeroIcon( + HeroIcons.cubeTransparent); + } + }, + loading: () => + const CircularProgressIndicator(), + error: (Object error, + StackTrace? stackTrace) => + const HeroIcon( + HeroIcons.cubeTransparent)); + } else { + return const HeroIcon( + HeroIcons.cubeTransparent); + } + })), ), Text( "${packTicket.price} €", diff --git a/lib/tools/providers/map_provider.dart b/lib/tools/providers/map_provider.dart index 644f3eeb9..d4b013af8 100644 --- a/lib/tools/providers/map_provider.dart +++ b/lib/tools/providers/map_provider.dart @@ -1,131 +1,54 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:myecl/tools/exception.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:myecl/tools/token_expire_wrapper.dart'; -class MapNotifier - extends StateNotifier>?>>> { - MapNotifier() : super(const AsyncLoading()); +class MapNotifier extends StateNotifier>?>> { + MapNotifier() : super(>?>{}); void loadTList(List tList) async { Map>?> tMap = {}; for (T l in tList) { tMap[l] = null; } - state = AsyncValue.data(tMap); + state = tMap; } - Future addT(T t) async { - state.maybeWhen( - data: (tList) async { - tList[t] = null; - state = AsyncValue.data(tList); - }, - orElse: () {}, - ); + void addT(T t) async { + state[t] = null; + state = state; } - Future addE(T t, E e) { - return state.when(data: (d) async { - try { - List eList = d[t]!.maybeWhen(data: (d) => d, orElse: () => []); - d[t] = AsyncValue.data(eList + [e]); - state = AsyncValue.data(d); - return true; - } catch (error) { - state = AsyncValue.data(d); - if (error is AppException && error.type == ErrorType.tokenExpire) { - rethrow; - } else { - return false; - } - } - }, error: (error, s) async { - if (error is AppException && error.type == ErrorType.tokenExpire) { - throw error; - } else { - state = AsyncValue.error(error, s); - return false; - } - }, loading: () async { - state = - const AsyncValue.error("Cannot add while loading", StackTrace.empty); - return false; + void addE(T t, E e) { + return state[t]!.maybeWhen(data: (eList) { + state[t] = AsyncValue.data(eList + [e]); + state = state; + }, orElse: () { + state[t] = AsyncValue.data([e]); + state = state; }); } - Future deleteT(T t) { - return state.when(data: (d) async { - if (d.containsKey(t)) { - d.remove(t); - state = AsyncValue.data(d); - } - return true; - }, error: (error, s) async { - state = AsyncValue.error(error, s); - return false; - }, loading: () async { - state = const AsyncValue.error( - "Cannot delete while loading", StackTrace.empty); - return false; - }); + void deleteT(T t) { + if (state.containsKey(t)) { + state.remove(t); + state = state; + } } - Future setTData(T t, AsyncValue> asyncEList) async { - return state.when(data: (d) async { - try { - d[t] = asyncEList; - state = AsyncValue.data(d); - return true; - } catch (error) { - state = AsyncValue.data(d); - if (error is AppException && error.type == ErrorType.tokenExpire) { - rethrow; - } else { - return false; - } - } - }, error: (error, s) { - if (error is AppException && error.type == ErrorType.tokenExpire) { - throw error; - } else { - state = AsyncValue.error(error, s); - return false; - } - }, loading: () { - state = - const AsyncValue.error("Cannot add while loading", StackTrace.empty); - return false; - }); + void setTData(T t, AsyncValue> asyncEList) async { + state[t] = asyncEList; + state = state; } - Future deleteE(T t, int index) { - return state.when(data: (d) async { - try { - List eList = d[t]!.maybeWhen(data: (d) => d, orElse: () => []); - eList.removeAt(index); - d[t] = AsyncValue.data(eList); - state = AsyncValue.data(d); - return true; - } catch (error) { - state = AsyncValue.data(d); - if (error is AppException && error.type == ErrorType.tokenExpire) { - rethrow; - } else { - return false; - } - } - }, error: (error, s) async { - if (error is AppException && error.type == ErrorType.tokenExpire) { - throw error; - } else { - state = AsyncValue.error(error, s); - return false; - } - }, loading: () async { - state = - const AsyncValue.error("Cannot add while loading", StackTrace.empty); - return false; - }); + bool deleteE(T t, int index) { + return state[t]!.maybeWhen( + data: (eList) { + eList.removeAt(index); + state[t] = AsyncValue.data(eList); + state = state; + return true; + }, + orElse: () => false); } Future autoLoad( @@ -142,6 +65,7 @@ class MapNotifier Future autoLoadList(WidgetRef ref, T t, Future>> Function(T t) loader) async { + setTData(t, const AsyncLoading()); tokenExpireWrapper(ref, () async { loader(t).then((value) { if (mounted) { diff --git a/lib/tools/ui/builders/auto_loader_child.dart b/lib/tools/ui/builders/auto_loader_child.dart index 262253610..34fdfb45e 100644 --- a/lib/tools/ui/builders/auto_loader_child.dart +++ b/lib/tools/ui/builders/auto_loader_child.dart @@ -5,7 +5,7 @@ import 'package:myecl/tools/ui/builders/async_child.dart'; import 'package:myecl/tools/ui/widgets/loader.dart'; class AutoLoaderChild extends ConsumerWidget { - final AsyncValue>?>> value; + final Map>?> value; final MapNotifier notifier; final MapKey mapKey; final Future Function(MapKey t)? loader; @@ -33,25 +33,17 @@ class AutoLoaderChild extends ConsumerWidget { assert(loader != null || listLoader != null); final nonNullLoadingBuilder = loadingBuilder ?? (context) => Loader(color: loaderColor); + final group = value[mapKey]; + if (group == null) { + loader == null + ? notifier.autoLoadList(ref, mapKey, listLoader!) + : notifier.autoLoad(ref, mapKey, loader!); + return nonNullLoadingBuilder(context); + } return AsyncChild( - value: value, - builder: (context, value) { - final group = value[mapKey]; - if (group == null) { - loader == null - ? notifier.autoLoadList(ref, mapKey, listLoader!) - : notifier.autoLoad(ref, mapKey, loader!); - return nonNullLoadingBuilder(context); - } - return AsyncChild( - value: group, - builder: (context, list) { - return dataBuilder(context, list); - }, - orElseBuilder: orElseBuilder, - errorBuilder: errorBuilder, - loadingBuilder: loadingBuilder, - loaderColor: loaderColor); + value: group, + builder: (context, list) { + return dataBuilder(context, list); }, orElseBuilder: orElseBuilder, errorBuilder: errorBuilder, diff --git a/lib/vote/providers/contender_logos_provider.dart b/lib/vote/providers/contender_logos_provider.dart index ce08258a3..e8fa65b90 100644 --- a/lib/vote/providers/contender_logos_provider.dart +++ b/lib/vote/providers/contender_logos_provider.dart @@ -10,7 +10,7 @@ class ContenderLogoNotifier extends MapNotifier { } final contenderLogosProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { ContenderLogoNotifier contenderLogoNotifier = ContenderLogoNotifier(); tokenExpireWrapperAuth(ref, () async { ref.watch(contenderListProvider).maybeWhen(data: (contender) { diff --git a/lib/vote/providers/sections_contender_provider.dart b/lib/vote/providers/sections_contender_provider.dart index ab976949e..3f8f146e9 100644 --- a/lib/vote/providers/sections_contender_provider.dart +++ b/lib/vote/providers/sections_contender_provider.dart @@ -11,7 +11,7 @@ class SectionContender extends MapNotifier { } final sectionContenderProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { SectionContender adminLoanListNotifier = SectionContender(); tokenExpireWrapperAuth(ref, () async { final loaners = ref.watch(sectionList); diff --git a/lib/vote/providers/sections_stats_provider.dart b/lib/vote/providers/sections_stats_provider.dart index 3c0295359..bafdb0aa5 100644 --- a/lib/vote/providers/sections_stats_provider.dart +++ b/lib/vote/providers/sections_stats_provider.dart @@ -9,7 +9,7 @@ class SectionsStatsNotifier extends MapNotifier { } final sectionsStatsProvider = StateNotifierProvider>?>>>((ref) { + Map>?>>((ref) { SectionsStatsNotifier sectionsStatsNotifier = SectionsStatsNotifier(); tokenExpireWrapperAuth(ref, () async { final sections = ref.watch(sectionsProvider); diff --git a/lib/vote/ui/pages/admin_page/section_bar.dart b/lib/vote/ui/pages/admin_page/section_bar.dart index 21bead0d1..bdafb4a91 100644 --- a/lib/vote/ui/pages/admin_page/section_bar.dart +++ b/lib/vote/ui/pages/admin_page/section_bar.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import 'package:heroicons/heroicons.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; -import 'package:myecl/tools/ui/builders/async_child.dart'; import 'package:myecl/tools/ui/widgets/dialog.dart'; import 'package:myecl/tools/functions.dart'; import 'package:myecl/tools/token_expire_wrapper.dart'; @@ -35,56 +34,52 @@ class SectionBar extends HookConsumerWidget { displayToast(context, type, msg); } - return AsyncChild( - value: sectionContender, - builder: (context, sections) => HorizontalListView.builder( - height: 40, - items: sections.keys.toList(), - firstChild: (status == Status.waiting) - ? ItemChip( - onTap: () { - QR.to(VoteRouter.root + - VoteRouter.admin + - VoteRouter.addSection); - }, - child: const HeroIcon( - HeroIcons.plus, - color: Colors.black, - ), - ) - : null, - itemBuilder: (context, key, i) => SectionChip( - label: key.name, - selected: section.id == key.id, - isAdmin: status == Status.waiting, - onTap: () async { - tokenExpireWrapper(ref, () async { - sectionIdNotifier.setId(key.id); - }); + return HorizontalListView.builder( + height: 40, + items: sectionContender.keys.toList(), + firstChild: (status == Status.waiting) + ? ItemChip( + onTap: () { + QR.to( + VoteRouter.root + VoteRouter.admin + VoteRouter.addSection); + }, + child: const HeroIcon( + HeroIcons.plus, + color: Colors.black, + ), + ) + : null, + itemBuilder: (context, key, i) => SectionChip( + label: key.name, + selected: section.id == key.id, + isAdmin: status == Status.waiting, + onTap: () async { + tokenExpireWrapper(ref, () async { + sectionIdNotifier.setId(key.id); + }); + }, + onDelete: () async { + tokenExpireWrapper(ref, () async { + await showDialog( + context: context, + builder: (context) => CustomDialogBox( + title: VoteTextConstants.deleteSection, + descriptions: VoteTextConstants.deleteSectionDescription, + onYes: () async { + final result = await sectionsNotifier.deleteSection(key); + if (result) { + sectionContenderListNotifier.deleteT(key); + displayVoteToastWithContext( + TypeMsg.msg, VoteTextConstants.deletedSection); + } else { + displayVoteToastWithContext( + TypeMsg.error, VoteTextConstants.deletingError); + } }, - onDelete: () async { - tokenExpireWrapper(ref, () async { - await showDialog( - context: context, - builder: (context) => CustomDialogBox( - title: VoteTextConstants.deleteSection, - descriptions: - VoteTextConstants.deleteSectionDescription, - onYes: () async { - final result = - await sectionsNotifier.deleteSection(key); - if (result) { - sectionContenderListNotifier.deleteT(key); - displayVoteToastWithContext(TypeMsg.msg, - VoteTextConstants.deletedSection); - } else { - displayVoteToastWithContext(TypeMsg.error, - VoteTextConstants.deletingError); - } - }, - )); - }); - }), - )); + ), + ); + }); + }), + ); } } diff --git a/lib/vote/ui/pages/admin_page/section_contender_items.dart b/lib/vote/ui/pages/admin_page/section_contender_items.dart index acf145312..da2124540 100644 --- a/lib/vote/ui/pages/admin_page/section_contender_items.dart +++ b/lib/vote/ui/pages/admin_page/section_contender_items.dart @@ -42,87 +42,71 @@ class SectionContenderItems extends HookConsumerWidget { } return AsyncChild( - value: sectionContender, - builder: (context, sections) { - if (sections[section] == null) { - return const SizedBox( - height: 200, - child: Center(child: Text(VoteTextConstants.noPretendanceList)), - ); - } - return AsyncChild( - value: sections[section]!, - builder: (context, data) => HorizontalListView.builder( - height: 190, - firstChild: (status == Status.waiting) - ? GestureDetector( - onTap: () { - contenderNotifier.setId(Contender.empty()); - membersNotifier.setMembers([]); - QR.to(VoteRouter.root + - VoteRouter.admin + - VoteRouter.addEditContender); - }, - child: const CardLayout( - width: 120, - height: 180, - child: Center( - child: HeroIcon( - HeroIcons.plus, - size: 40.0, - color: Colors.black, - )), - ), - ) - : null, - items: data, - itemBuilder: (context, e, i) => ContenderCard( - contender: e, - isAdmin: true, - onEdit: () { + value: sectionContender[section]!, + builder: (context, data) => HorizontalListView.builder( + height: 190, + firstChild: (status == Status.waiting) + ? GestureDetector( + onTap: () { + contenderNotifier.setId(Contender.empty()); + membersNotifier.setMembers([]); + QR.to(VoteRouter.root + + VoteRouter.admin + + VoteRouter.addEditContender); + }, + child: const CardLayout( + width: 120, + height: 180, + child: Center( + child: HeroIcon( + HeroIcons.plus, + size: 40.0, + color: Colors.black, + )), + ), + ) + : null, + items: data, + itemBuilder: (context, e, i) => ContenderCard( + contender: e, + isAdmin: true, + onEdit: () { + tokenExpireWrapper(ref, () async { + contenderNotifier.setId(e); + membersNotifier.setMembers(e.members); + QR.to(VoteRouter.root + + VoteRouter.admin + + VoteRouter.addEditContender); + }); + }, + onDelete: () async { + await showDialog( + context: context, + builder: (context) { + return CustomDialogBox( + title: VoteTextConstants.deletePretendance, + descriptions: VoteTextConstants.deletePretendanceDesc, + onYes: () { tokenExpireWrapper(ref, () async { - contenderNotifier.setId(e); - membersNotifier.setMembers(e.members); - QR.to(VoteRouter.root + - VoteRouter.admin + - VoteRouter.addEditContender); - }); - }, - onDelete: () async { - await showDialog( - context: context, - builder: (context) { - return CustomDialogBox( - title: VoteTextConstants.deletePretendance, - descriptions: - VoteTextConstants.deletePretendanceDesc, - onYes: () { - tokenExpireWrapper(ref, () async { - final value = await contenderListNotifier - .deleteContender(e); - if (value) { - displayVoteToastWithContext( - TypeMsg.msg, - VoteTextConstants - .pretendanceDeleted); - contenderListNotifier - .copy() - .then((value) { - sectionContenderListNotifier.setTData( - section, value); - }); - } else { - displayVoteToastWithContext( - TypeMsg.error, - VoteTextConstants - .pretendanceNotDeleted); - } - }); - }); + final value = + await contenderListNotifier.deleteContender(e); + if (value) { + displayVoteToastWithContext(TypeMsg.msg, + VoteTextConstants.pretendanceDeleted); + contenderListNotifier.copy().then((value) { + sectionContenderListNotifier.setTData( + section, value); }); - }, - ))); - }, + } else { + displayVoteToastWithContext(TypeMsg.error, + VoteTextConstants.pretendanceNotDeleted); + } + }); + }); + }); + }, + ), + ), ); } } diff --git a/lib/vote/ui/pages/admin_page/vote_bars.dart b/lib/vote/ui/pages/admin_page/vote_bars.dart index 299d8fb92..8733d2aee 100644 --- a/lib/vote/ui/pages/admin_page/vote_bars.dart +++ b/lib/vote/ui/pages/admin_page/vote_bars.dart @@ -35,47 +35,38 @@ class VoteBars extends HookConsumerWidget { final Map sectionIds = {}; int total = 0; - sectionsContender.maybeWhen( - data: (data) { - if (data[section] != null) { - data[section]!.maybeWhen( - data: ((data) { - sectionNames = data.map((e) => e.name).toList(); - sectionIds - .addAll({for (var e in data) data.indexOf(e): e.id}); - total = data.map((e) => voteValue[e.id]).reduce( - (value, element) => (value ?? 0) + (element ?? 0)) ?? - 0; - contenderBars = data - .map((x) => BarChartGroupData( - x: data.indexOf(x), - barRods: [ - BarChartRodData( - toY: (voteValue[sectionIds[data.indexOf(x)]] ?? - 0) - .toDouble(), - color: isTouched.value - ? Colors.grey.shade800 - : barColor, - width: 40, - borderSide: isTouched.value - ? const BorderSide( - color: Colors.white, width: 2) - : const BorderSide( - color: Colors.white, width: 0), - backDrawRodData: BackgroundBarChartRodData( - show: true, - color: barBackgroundColor, - ), - ), - ], - )) - .toList(); - }), - orElse: () {}); - } - }, - orElse: () {}); + if (sectionsContender[section] != null) { + sectionsContender[section]!.maybeWhen( + data: ((data) { + sectionNames = data.map((e) => e.name).toList(); + sectionIds.addAll({for (var e in data) data.indexOf(e): e.id}); + total = data.map((e) => voteValue[e.id]).reduce( + (value, element) => (value ?? 0) + (element ?? 0)) ?? + 0; + contenderBars = data + .map((x) => BarChartGroupData( + x: data.indexOf(x), + barRods: [ + BarChartRodData( + toY: (voteValue[sectionIds[data.indexOf(x)]] ?? 0) + .toDouble(), + color: + isTouched.value ? Colors.grey.shade800 : barColor, + width: 40, + borderSide: isTouched.value + ? const BorderSide(color: Colors.white, width: 2) + : const BorderSide(color: Colors.white, width: 0), + backDrawRodData: BackgroundBarChartRodData( + show: true, + color: barBackgroundColor, + ), + ), + ], + )) + .toList(); + }), + orElse: () {}); + } return Expanded( child: Container( diff --git a/lib/vote/ui/pages/contender_pages/add_edit_contender.dart b/lib/vote/ui/pages/contender_pages/add_edit_contender.dart index 9bd7b24e2..4f63a4905 100644 --- a/lib/vote/ui/pages/contender_pages/add_edit_contender.dart +++ b/lib/vote/ui/pages/contender_pages/add_edit_contender.dart @@ -59,15 +59,16 @@ class AddEditContenderPage extends HookConsumerWidget { final logo = useState(null); final logoFile = useState(null); final showNotifier = ref.read(displayResult.notifier); - ref.watch(contenderLogosProvider).whenData((value) { - if (value[contender] != null) { - value[contender]!.whenData((data) { - if (data.isNotEmpty) { - logoFile.value = data.first; - } - }); - } - }); + + final contenderLogos = ref.watch(contenderLogosProvider); + if (contenderLogos[contender] != null) { + contenderLogos[contender]!.whenData((data) { + if (data.isNotEmpty) { + logoFile.value = data.first; + } + }); + } + final ImagePicker picker = ImagePicker(); void displayVoteToastWithContext(TypeMsg type, String msg) { @@ -378,7 +379,7 @@ class AddEditContenderPage extends HookConsumerWidget { orElse: () {}); } membersNotifier.clearMembers(); - await sectionsNotifier.setTData(section.value, + sectionsNotifier.setTData(section.value, await contenderListNotifier.copy()); } else { displayVoteToastWithContext( diff --git a/lib/vote/ui/pages/detail_page/detail_page.dart b/lib/vote/ui/pages/detail_page/detail_page.dart index 8c8262d16..224a46ce4 100644 --- a/lib/vote/ui/pages/detail_page/detail_page.dart +++ b/lib/vote/ui/pages/detail_page/detail_page.dart @@ -53,60 +53,55 @@ class DetailPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 30), - AsyncChild( - value: contenderLogos, - builder: (context, data) { - if (data[contender] == null) { - return const SizedBox.shrink(); - } - return SizedBox( - height: 140, - width: 140, - child: AsyncChild( - value: data[contender]!, - builder: (context, data) { - if (data.isEmpty) { - logoNotifier - .getLogo(contender.id) - .then((value) { - contenderLogosNotifier.setTData( - contender, - AsyncData([value])); - }); - return const HeroIcon( - HeroIcons.userCircle, - size: 40, - ); - } - return Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: Colors.grey.shade50, - image: DecorationImage( - image: data.first.image, - fit: BoxFit.cover, - ), - boxShadow: [ - BoxShadow( - color: Colors.grey - .withOpacity(0.2), - blurRadius: 10, - spreadRadius: 5, - offset: const Offset(0, 5), - ), - ], + if (contenderLogos[contender] == null) + const SizedBox.shrink() + else + SizedBox( + height: 140, + width: 140, + child: AsyncChild( + value: contenderLogos[contender]!, + builder: (context, data) { + if (data.isEmpty) { + logoNotifier + .getLogo(contender.id) + .then((value) { + contenderLogosNotifier.setTData( + contender, AsyncData([value])); + }); + return const HeroIcon( + HeroIcons.userCircle, + size: 40, + ); + } + return Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.grey.shade50, + image: DecorationImage( + image: data.first.image, + fit: BoxFit.cover, + ), + boxShadow: [ + BoxShadow( + color: + Colors.grey.withOpacity(0.2), + blurRadius: 10, + spreadRadius: 5, + offset: const Offset(0, 5), ), - ); - }, - errorBuilder: (error, stack) => - const Center( - child: HeroIcon( - HeroIcons.exclamationCircle, - size: 40), - )), - ); - }, - ), + ], + ), + ); + }, + errorBuilder: (error, stack) => + const Center( + child: HeroIcon( + HeroIcons.exclamationCircle, + size: 40), + ), + ), + ), const SizedBox(height: 20), Text( contender.section.name, diff --git a/lib/vote/ui/pages/main_page/list_contender_card.dart b/lib/vote/ui/pages/main_page/list_contender_card.dart index 2ca18c75d..509594f4a 100644 --- a/lib/vote/ui/pages/main_page/list_contender_card.dart +++ b/lib/vote/ui/pages/main_page/list_contender_card.dart @@ -42,24 +42,23 @@ class ListContenderCard extends HookConsumerWidget { Map votesPercent = {}; double h = 0; - sectionsContender.whenData((contenders) => contenders[section]!.whenData( - (contenderList) { - h = contenderList.length * - ((s == Status.open || s == Status.published) ? 180 : 140) - - MediaQuery.of(context).size.height + - (s == Status.open ? 250 : 150); - List numberVotes = []; - for (var i = 0; i < contenderList.length; i++) { - numberVotes.add(results[contenderList[i].id] ?? 0); - } - totalVotes = - numberVotes.reduce((value, element) => value + element); - for (var i = 0; i < numberVotes.length; i++) { - votesPercent[contenderList[i].id] = - totalVotes == 0 ? 0 : numberVotes[i] / totalVotes; - } - }, - )); + sectionsContender[section]!.whenData( + (contenderList) { + h = contenderList.length * + ((s == Status.open || s == Status.published) ? 180 : 140) - + MediaQuery.of(context).size.height + + (s == Status.open ? 250 : 150); + List numberVotes = []; + for (var i = 0; i < contenderList.length; i++) { + numberVotes.add(results[contenderList[i].id] ?? 0); + } + totalVotes = numberVotes.reduce((value, element) => value + element); + for (var i = 0; i < numberVotes.length; i++) { + votesPercent[contenderList[i].id] = + totalVotes == 0 ? 0 : numberVotes[i] / totalVotes; + } + }, + ); final scrollController = ref.watch(scrollControllerProvider(hideAnimation)); final votedSection = ref.watch(votedSectionProvider); @@ -76,110 +75,105 @@ class ListContenderCard extends HookConsumerWidget { animation.forward(); pageOpened.value = true; } - return AsyncChild( - value: sectionsContender, - builder: (context, contenders) => Stack( - children: [ - SingleChildScrollView( - controller: scrollController, - physics: const BouncingScrollPhysics(), - child: contenders.isNotEmpty - ? AsyncChild( - value: contenders[section]!, - builder: (context, contenderList) => Column( - children: contenderList.map((e) { - final index = contenderList.indexOf(e); - return ContenderCard( - index: index, - contender: e, - animation: animation, - enableVote: !alreadyVotedSection - .contains(section.id), - votesPercent: - votesPercent.keys.contains(e.id) - ? votesPercent[e.id]! - : 0, - ); - }).toList(), - )) - : const SizedBox( - height: 150, - child: Center( - child: Text(VoteTextConstants.noPretendanceList), - ), - ), + return Stack( + children: [ + SingleChildScrollView( + controller: scrollController, + physics: const BouncingScrollPhysics(), + child: sectionsContender.isNotEmpty + ? AsyncChild( + value: sectionsContender[section]!, + builder: (context, contenderList) => Column( + children: contenderList.map((e) { + final index = contenderList.indexOf(e); + return ContenderCard( + index: index, + contender: e, + animation: animation, + enableVote: + !alreadyVotedSection.contains(section.id), + votesPercent: votesPercent.keys.contains(e.id) + ? votesPercent[e.id]! + : 0, + ); + }).toList(), + )) + : const SizedBox( + height: 150, + child: Center( + child: Text(VoteTextConstants.noPretendanceList), + ), ), - if (h > 0) - Positioned( - bottom: 10, - right: MediaQuery.of(context).size.width / 2 - 100, - child: FadeTransition( - opacity: hideAnimation, - child: ScaleTransition( - scale: hideAnimation, - child: GestureDetector( - onTap: (() { - hideAnimation.animateTo(0); - scrollController.animateTo(h + 25, - duration: const Duration(milliseconds: 350), - curve: Curves.decelerate); - }), - child: SlideTransition( - position: Tween( - begin: const Offset(2, 0), - end: const Offset(0, 0), - ).animate(CurvedAnimation( - parent: animation, - curve: const Interval(0.2, 0.4, - curve: Curves.easeOut))), - child: Container( - padding: const EdgeInsets.symmetric( - horizontal: 15, vertical: 8), - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - ColorConstants.background2 - .withOpacity(0.8), - Colors.black.withOpacity(0.8) - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight), - boxShadow: [ - BoxShadow( - color: ColorConstants.background2 - .withOpacity(0.4), - offset: const Offset(2, 3), - blurRadius: 5) - ], - borderRadius: const BorderRadius.all( - Radius.circular(25)), - ), - alignment: Alignment.center, - child: Row( - mainAxisAlignment: - MainAxisAlignment.spaceEvenly, - children: [ - HeroIcon( - HeroIcons.chevronDoubleDown, - size: 15, - color: Colors.grey.shade100, - ), - const SizedBox(width: 10), - Text( - VoteTextConstants.seeMore, - style: TextStyle( - fontSize: 18, - color: Colors.grey.shade100, - ), - ), - ], - ), + ), + if (h > 0) + Positioned( + bottom: 10, + right: MediaQuery.of(context).size.width / 2 - 100, + child: FadeTransition( + opacity: hideAnimation, + child: ScaleTransition( + scale: hideAnimation, + child: GestureDetector( + onTap: (() { + hideAnimation.animateTo(0); + scrollController.animateTo(h + 25, + duration: const Duration(milliseconds: 350), + curve: Curves.decelerate); + }), + child: SlideTransition( + position: Tween( + begin: const Offset(2, 0), + end: const Offset(0, 0), + ).animate(CurvedAnimation( + parent: animation, + curve: + const Interval(0.2, 0.4, curve: Curves.easeOut))), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 15, vertical: 8), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + ColorConstants.background2.withOpacity(0.8), + Colors.black.withOpacity(0.8) + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight), + boxShadow: [ + BoxShadow( + color: + ColorConstants.background2.withOpacity(0.4), + offset: const Offset(2, 3), + blurRadius: 5) + ], + borderRadius: + const BorderRadius.all(Radius.circular(25)), + ), + alignment: Alignment.center, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + HeroIcon( + HeroIcons.chevronDoubleDown, + size: 15, + color: Colors.grey.shade100, + ), + const SizedBox(width: 10), + Text( + VoteTextConstants.seeMore, + style: TextStyle( + fontSize: 18, + color: Colors.grey.shade100, ), ), - ), + ], ), - )) - ], - )); + ), + ), + ), + ), + )) + ], + ); } } diff --git a/lib/vote/ui/pages/main_page/main_page.dart b/lib/vote/ui/pages/main_page/main_page.dart index 7dae6ef50..c127fb74f 100644 --- a/lib/vote/ui/pages/main_page/main_page.dart +++ b/lib/vote/ui/pages/main_page/main_page.dart @@ -33,7 +33,6 @@ class VoteMainPage extends HookConsumerWidget { final isAdmin = ref.watch(isVoteAdminProvider); final sections = ref.watch(sectionsProvider); final sectionsNotifier = ref.watch(sectionsProvider.notifier); - final sectionsContenders = ref.watch(sectionContenderProvider); final contenders = ref.watch(contenderListProvider); final contendersNotifier = ref.watch(contenderListProvider.notifier); final sectionContenderNotifier = @@ -145,39 +144,35 @@ class VoteMainPage extends HookConsumerWidget { Expanded( child: SizedBox( width: double.infinity, - child: AsyncChild( - value: sectionsContenders, - builder: (context, contenderList) => - Column(children: [ - Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - SectionTitle( - sectionList: - sectionList), - if (isAdmin) - Container( - margin: const EdgeInsets - .only(right: 20), - child: AdminButton( - onTap: () { - QR.to(VoteRouter - .root + - VoteRouter - .admin); - }, - ), - ) - ], - ), - const SizedBox(height: 15), - Expanded( - child: ListContenderCard( - animation: animation, - )) - ])), + child: Column( + children: [ + Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + SectionTitle( + sectionList: sectionList), + if (isAdmin) + Container( + margin: const EdgeInsets.only( + right: 20), + child: AdminButton( + onTap: () { + QR.to(VoteRouter.root + + VoteRouter.admin); + }, + ), + ) + ], + ), + const SizedBox(height: 15), + Expanded( + child: ListContenderCard( + animation: animation, + ), + ) + ], + ), ), ), ], diff --git a/test/tools/providers/map_notifier_test.dart b/test/tools/providers/map_notifier_test.dart index 774a97883..d5f63446f 100644 --- a/test/tools/providers/map_notifier_test.dart +++ b/test/tools/providers/map_notifier_test.dart @@ -9,23 +9,23 @@ class MockT {} class MockMapNotifier extends MapNotifier { MockMapNotifier() : super(); - Future testLoadTlist(List tList) async { + void testLoadTlist(List tList) async { return loadTList(tList); } - Future testAddT(MockT t) async { + void testAddT(MockT t) async { return addT(t); } - Future testAddE(MockT t, MockE e) async { + void testAddE(MockT t, MockE e) { return addE(t, e); } - Future testDeleteT(MockT t) async { + void testDeleteT(MockT t) { return deleteT(t); } - Future testSetTData(MockT t, AsyncValue> asyncEList) async { + void testSetTData(MockT t, AsyncValue> asyncEList) async { return setTData(t, asyncEList); } } @@ -34,27 +34,16 @@ void main() { group('Testing MapNotifier : loadTList', () { test('Should initiate to AsyncLoading', () { final notifier = MockMapNotifier(); - expect(notifier.state, isA()); + expect(notifier.state, isA()); }); test('Should state be AsyncData when loading data', () async { final notifier = MockMapNotifier(); final data = [MockT(), MockT()]; - await notifier.testLoadTlist(data); - expect(notifier.state, - isA>?>>>()); - expect( - notifier.state.when( - data: (d) => d.keys.toList(), - error: (Object error, StackTrace stackTrace) => [], - loading: () => []), - data); - expect( - notifier.state.when( - data: (d) => d.values.first, - error: (Object error, StackTrace stackTrace) => null, - loading: () => null), - isA>?>()); + notifier.testLoadTlist(data); + expect(notifier.state, isA>?>>()); + expect(notifier.state.keys.toList(), data); + expect(notifier.state.values.first, isA>?>()); }); }); @@ -65,39 +54,19 @@ void main() { MockT(): const AsyncLoading(), MockT(): const AsyncValue.data([]), }; - notifier.state = AsyncValue.data(data); + notifier.state = data; final newData = MockT(); - await notifier.testAddT(newData); - expect(notifier.state, - isA>?>>>()); - expect( - notifier.state - .when(data: (d) => d, error: (e, s) => {}, loading: () => {}) - .keys - .contains(newData), - isTrue); - expect( - notifier.state.when( - data: (d) => d, error: (e, s) => {}, loading: () => {})[newData], - isNull); + notifier.testAddT(newData); + expect(notifier.state, isA>?>>()); + expect(notifier.state.keys.contains(newData), isTrue); }); test('Should sets state on loading when start state is AsyncLoading', () async { final notifier = MockMapNotifier(); final newData = MockT(); - await notifier.testAddT(newData); - expect(notifier.state, isA()); - }); - - test( - 'Should return false sets state on error when start state is AsyncError', - () async { - final notifier = MockMapNotifier(); - notifier.state = AsyncValue.error("test", StackTrace.current); - final newData = MockT(); - await notifier.testAddT(newData); - expect(notifier.state, isA()); + notifier.testAddT(newData); + expect(notifier.state, isA()); }); }); @@ -111,22 +80,17 @@ void main() { MockT(): const AsyncLoading(), key: const AsyncValue.data([]) }; - notifier.state = AsyncValue.data(data); + notifier.state = data; final newData = MockE(); final newDataList = [newData]; - final result = await notifier.testAddE(key, newData); - expect(result, isTrue); - expect(notifier.state, - isA>?>>>()); + notifier.testAddE(key, newData); + expect(notifier.state, isA>?>>()); expect( - notifier.state - .when>?>>( - data: (d) => d, error: (e, s) => {}, loading: () => {})[key]! - .when( - data: (d) => d, - error: (e, s) => [], - loading: () => [], - ), + notifier.state[key]!.when( + data: (d) => d, + error: (e, s) => [], + loading: () => [], + ), newDataList); }); @@ -139,22 +103,17 @@ void main() { MockT(): const AsyncLoading(), key: const AsyncLoading() }; - notifier.state = AsyncValue.data(data); + notifier.state = data; final newData = MockE(); final newDataList = [newData]; - final result = await notifier.testAddE(key, newData); - expect(result, isTrue); - expect(notifier.state, - isA>?>>>()); + notifier.testAddE(key, newData); + expect(notifier.state, isA>?>>()); expect( - notifier.state - .when>?>>( - data: (d) => d, error: (e, s) => {}, loading: () => {})[key]! - .when( - data: (d) => d, - error: (e, s) => [], - loading: () => [], - ), + notifier.state[key]!.when( + data: (d) => d, + error: (e, s) => [], + loading: () => [], + ), newDataList); }); @@ -167,49 +126,19 @@ void main() { MockT(): const AsyncLoading(), key: AsyncError("test", StackTrace.current) }; - notifier.state = AsyncValue.data(data); + notifier.state = data; final newData = MockE(); final newDataList = [newData]; - final result = await notifier.testAddE(key, newData); - expect(result, isTrue); - expect(notifier.state, - isA>?>>>()); + notifier.testAddE(key, newData); + expect(notifier.state, isA>?>>()); expect( - notifier.state - .when>?>>( - data: (d) => d, error: (e, s) => {}, loading: () => {})[key]! - .when( - data: (d) => d, - error: (e, s) => [], - loading: () => [], - ), + notifier.state[key]!.when( + data: (d) => d, + error: (e, s) => [], + loading: () => [], + ), newDataList); }); - - test( - 'Should return false sets state on error when start state is AsyncLoading', - () async { - final notifier = MockMapNotifier(); - final key = MockT(); - final newData = MockE(); - final result = await notifier.testAddE(key, newData); - expect(result, isFalse); - expect(notifier.state, isA()); - expect(notifier.state.error, "Cannot add while loading"); - }); - - test( - 'Should return false sets state on error when start state is AsyncError', - () async { - final notifier = MockMapNotifier(); - notifier.state = AsyncValue.error("test", StackTrace.current); - final newData = MockE(); - final key = MockT(); - final result = await notifier.testAddE(key, newData); - expect(result, isFalse); - expect(notifier.state, isA()); - expect(notifier.state.error, "test"); - }); }); group('Testing MapNotifier : deleteT', () { @@ -220,18 +149,10 @@ void main() { MockT(): const AsyncLoading(), key: const AsyncValue.data([]) }; - notifier.state = AsyncValue.data(data); - final result = await notifier.testDeleteT(key); - expect(result, isTrue); - expect(notifier.state, - isA>?>>>()); - expect( - notifier.state - .when>?>>( - data: (d) => d, error: (e, s) => {}, loading: () => {}) - .keys - .contains(key), - isFalse); + notifier.state = data; + notifier.testDeleteT(key); + expect(notifier.state, isA>?>>()); + expect(notifier.state.keys.contains(key), isFalse); }); test('Should returns true and does not touch state when key is not in map', @@ -242,40 +163,10 @@ void main() { MockT(): const AsyncLoading(), key: const AsyncLoading() }; - notifier.state = AsyncValue.data(data); - final result = await notifier.testDeleteT(MockT()); - expect(result, isTrue); - expect(notifier.state, - isA>?>>>()); - expect( - notifier.state - .when>?>>( - data: (d) => d, error: (e, s) => {}, loading: () => {}) - .keys, - data.keys); - }); - - test( - 'Should return false sets state on error when start state is AsyncLoading', - () async { - final notifier = MockMapNotifier(); - final key = MockT(); - final result = await notifier.testDeleteT(key); - expect(result, isFalse); - expect(notifier.state, isA()); - expect(notifier.state.error, "Cannot delete while loading"); - }); - - test( - 'Should return false sets state on error when start state is AsyncError', - () async { - final notifier = MockMapNotifier(); - notifier.state = AsyncValue.error("test", StackTrace.current); - final key = MockT(); - final result = await notifier.testDeleteT(key); - expect(result, isFalse); - expect(notifier.state, isA()); - expect(notifier.state.error, "test"); + notifier.state = data; + notifier.testDeleteT(MockT()); + expect(notifier.state, isA>?>>()); + expect(notifier.state.keys, data.keys); }); }); @@ -288,15 +179,10 @@ void main() { key: const AsyncValue.data([]) }; final newData = AsyncValue.data([MockE()]); - notifier.state = AsyncValue.data(data); - final result = await notifier.testSetTData(key, newData); - expect(result, isTrue); - expect(notifier.state, - isA>?>>>()); - expect( - notifier.state.when>?>>( - data: (d) => d, error: (e, s) => {}, loading: () => {})[key]!, - newData); + notifier.state = data; + notifier.testSetTData(key, newData); + expect(notifier.state, isA>?>>()); + expect(notifier.state[key]!, newData); }); test('Should returns true and does not touch state when key is not in map', @@ -307,40 +193,10 @@ void main() { MockT(): const AsyncLoading(), }; final newData = AsyncValue.data([MockE()]); - notifier.state = AsyncValue.data(data); - final result = await notifier.testSetTData(key, newData); - expect(result, isTrue); - expect(notifier.state, - isA>?>>>()); - expect( - notifier.state.when>?>>( - data: (d) => d, error: (e, s) => {}, loading: () => {})[key]!, - newData); - }); - - test( - 'Should return false sets state on error when start state is AsyncLoading', - () async { - final notifier = MockMapNotifier(); - final key = MockT(); - final newData = AsyncValue.data([MockE()]); - final result = await notifier.testSetTData(key, newData); - expect(result, isFalse); - expect(notifier.state, isA()); - expect(notifier.state.error, "Cannot add while loading"); - }); - - test( - 'Should return false sets state on error when start state is AsyncError', - () async { - final notifier = MockMapNotifier(); - notifier.state = const AsyncValue.error("test", StackTrace.empty); - final newData = AsyncValue.data([MockE()]); - final key = MockT(); - final result = await notifier.testSetTData(key, newData); - expect(result, isFalse); - expect(notifier.state, isA()); - expect(notifier.state.error, "test"); + notifier.state = data; + notifier.testSetTData(key, newData); + expect(notifier.state, isA>?>>()); + expect(notifier.state[key]!, newData); }); }); } From 34d32005dd81d7e875f39e56c316ab5c67e479ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 18:13:03 +0100 Subject: [PATCH 02/16] optimization: use select on providers --- lib/admin/ui/pages/edit_page/edit_page.dart | 5 +++-- lib/advert/ui/components/advert_card.dart | 5 +++-- lib/advert/ui/pages/detail_page/detail.dart | 5 +++-- lib/amap/ui/pages/admin_page/delivery_ui.dart | 5 +++-- lib/cinema/ui/pages/admin_page/admin_session_card.dart | 5 +++-- lib/cinema/ui/pages/detail_page/detail_page.dart | 5 +++-- lib/cinema/ui/pages/main_page/session_card.dart | 5 +++-- lib/raffle/ui/pages/main_page/raffle_card.dart | 5 +++-- lib/tools/providers/map_provider.dart | 8 ++++---- lib/tools/ui/builders/auto_loader_child.dart | 7 +++---- lib/vote/ui/components/contender_logo.dart | 5 +++-- lib/vote/ui/pages/admin_page/vote_count.dart | 5 +++-- 12 files changed, 37 insertions(+), 28 deletions(-) diff --git a/lib/admin/ui/pages/edit_page/edit_page.dart b/lib/admin/ui/pages/edit_page/edit_page.dart index 3babebacc..dc7129e2c 100644 --- a/lib/admin/ui/pages/edit_page/edit_page.dart +++ b/lib/admin/ui/pages/edit_page/edit_page.dart @@ -33,7 +33,8 @@ class EditAssociationPage extends HookConsumerWidget { final description = useTextEditingController(); final simpleGroupsGroupsNotifier = ref.watch(simpleGroupsGroupsProvider.notifier); - final simpleGroupsGroups = ref.watch(simpleGroupsGroupsProvider); + final simpleGroupsGroups = + ref.watch(simpleGroupsGroupsProvider.select((value) => value[groupId])); void displayToastWithContext(TypeMsg type, String msg) { displayToast(context, type, msg); @@ -45,7 +46,7 @@ class EditAssociationPage extends HookConsumerWidget { child: Padding( padding: const EdgeInsets.symmetric(horizontal: 30.0), child: AutoLoaderChild( - value: simpleGroupsGroups, + group: simpleGroupsGroups, notifier: simpleGroupsGroupsNotifier, mapKey: groupId, loader: (groupId) async => diff --git a/lib/advert/ui/components/advert_card.dart b/lib/advert/ui/components/advert_card.dart index 2de1c87bd..7a6f16fbe 100644 --- a/lib/advert/ui/components/advert_card.dart +++ b/lib/advert/ui/components/advert_card.dart @@ -24,7 +24,8 @@ class AdvertCard extends HookConsumerWidget { double height = 300; double imageHeight = 175; double maxHeight = MediaQuery.of(context).size.height - 344; - final advertPosters = ref.watch(advertPostersProvider); + final posters = ref.watch( + advertPostersProvider.select((advertPosters) => advertPosters[advert])); final advertPostersNotifier = ref.watch(advertPostersProvider.notifier); final logoNotifier = ref.watch(advertPosterProvider.notifier); final isWebFormat = ref.watch(isWebFormatProvider); @@ -38,7 +39,7 @@ class AdvertCard extends HookConsumerWidget { margin: const EdgeInsets.all(10), padding: EdgeInsets.all(isWebFormat ? 50 : 0), child: AutoLoaderChild( - value: advertPosters, + group: posters, notifier: advertPostersNotifier, mapKey: advert, loader: (advert) => logoNotifier.getAdvertPoster(advert.id), diff --git a/lib/advert/ui/pages/detail_page/detail.dart b/lib/advert/ui/pages/detail_page/detail.dart index 1302fa738..cec22d5d9 100644 --- a/lib/advert/ui/pages/detail_page/detail.dart +++ b/lib/advert/ui/pages/detail_page/detail.dart @@ -19,7 +19,8 @@ class AdvertDetailPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final advert = ref.watch(advertProvider); - final advertPosters = ref.watch(advertPostersProvider); + final posters = ref.watch( + advertPostersProvider.select((advertPosters) => advertPosters[advert])); final advertPostersNotifier = ref.watch(advertPostersProvider.notifier); final logoNotifier = ref.watch(advertPosterProvider.notifier); final filteredTagList = @@ -38,7 +39,7 @@ class AdvertDetailPage extends HookConsumerWidget { ), ]), child: AutoLoaderChild( - value: advertPosters, + group: posters, notifier: advertPostersNotifier, mapKey: advert, loader: (ref) => logoNotifier.getAdvertPoster(advert.id), diff --git a/lib/amap/ui/pages/admin_page/delivery_ui.dart b/lib/amap/ui/pages/admin_page/delivery_ui.dart index 33de2281f..bdb34c8b8 100644 --- a/lib/amap/ui/pages/admin_page/delivery_ui.dart +++ b/lib/amap/ui/pages/admin_page/delivery_ui.dart @@ -28,7 +28,8 @@ class DeliveryUi extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final deliveryIdNotifier = ref.watch(deliveryIdProvider.notifier); final deliveryListNotifier = ref.watch(deliveryListProvider.notifier); - final deliveryOrders = ref.watch(adminDeliveryOrderListProvider); + final deliveryOrders = ref.watch( + adminDeliveryOrderListProvider.select((value) => value[delivery.id])); final deliveryProductListNotifier = ref.watch(deliveryProductListProvider.notifier); final deliveryOrdersNotifier = @@ -84,7 +85,7 @@ class DeliveryUi extends HookConsumerWidget { ], ), AutoLoaderChild( - value: deliveryOrders, + group: deliveryOrders, notifier: deliveryOrdersNotifier, mapKey: delivery.id, listLoader: (deliveryId) => ordersByDeliveryListNotifier diff --git a/lib/cinema/ui/pages/admin_page/admin_session_card.dart b/lib/cinema/ui/pages/admin_page/admin_session_card.dart index e757aa88a..729efcd3a 100644 --- a/lib/cinema/ui/pages/admin_page/admin_session_card.dart +++ b/lib/cinema/ui/pages/admin_page/admin_session_card.dart @@ -22,7 +22,8 @@ class AdminSessionCard extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final sessionPosterMap = ref.watch(sessionPosterMapProvider); + final sessionPoster = + ref.watch(sessionPosterMapProvider.select((value) => value[session])); final sessionPosterMapNotifier = ref.read(sessionPosterMapProvider.notifier); final sessionPosterNotifier = ref.read(sessionPosterProvider.notifier); @@ -52,7 +53,7 @@ class AdminSessionCard extends HookConsumerWidget { height: 205, width: double.infinity, child: AutoLoaderChild( - value: sessionPosterMap, + group: sessionPoster, notifier: sessionPosterMapNotifier, mapKey: session, loader: (session) => diff --git a/lib/cinema/ui/pages/detail_page/detail_page.dart b/lib/cinema/ui/pages/detail_page/detail_page.dart index a2f3b468f..2b145e12c 100644 --- a/lib/cinema/ui/pages/detail_page/detail_page.dart +++ b/lib/cinema/ui/pages/detail_page/detail_page.dart @@ -24,7 +24,8 @@ class DetailPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final session = ref.watch(sessionProvider); - final sessionPosterMap = ref.watch(sessionPosterMapProvider); + final sessionPoster = + ref.watch(sessionPosterMapProvider.select((value) => value[session])); final sessionPosterMapNotifier = ref.watch(sessionPosterMapProvider.notifier); final sessionPosterNotifier = ref.watch(sessionPosterProvider.notifier); @@ -55,7 +56,7 @@ class DetailPage extends HookConsumerWidget { ), ]), child: AutoLoaderChild( - value: sessionPosterMap, + group: sessionPoster, notifier: sessionPosterMapNotifier, mapKey: session, loader: (session) => sessionPosterNotifier.getLogo(session.id), diff --git a/lib/cinema/ui/pages/main_page/session_card.dart b/lib/cinema/ui/pages/main_page/session_card.dart index f39326f6c..91f18abe8 100644 --- a/lib/cinema/ui/pages/main_page/session_card.dart +++ b/lib/cinema/ui/pages/main_page/session_card.dart @@ -21,7 +21,8 @@ class SessionCard extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final scroll = ref.watch(scrollProvider); - final sessionPosterMap = ref.watch(sessionPosterMapProvider); + final sessionPoster = + ref.watch(sessionPosterMapProvider.select((value) => value[session])); final sessionPosterMapNotifier = ref.watch(sessionPosterMapProvider.notifier); final sessionPosterNotifier = ref.watch(sessionPosterProvider.notifier); @@ -105,7 +106,7 @@ class SessionCard extends HookConsumerWidget { ], ), child: AutoLoaderChild( - value: sessionPosterMap, + group: sessionPoster, notifier: sessionPosterMapNotifier, mapKey: session, loader: (session) => diff --git a/lib/raffle/ui/pages/main_page/raffle_card.dart b/lib/raffle/ui/pages/main_page/raffle_card.dart index bef4cf378..e34c102db 100644 --- a/lib/raffle/ui/pages/main_page/raffle_card.dart +++ b/lib/raffle/ui/pages/main_page/raffle_card.dart @@ -26,7 +26,8 @@ class RaffleWidget extends HookConsumerWidget { final ticketListNotifier = ref.watch(ticketsListProvider.notifier); final packTicketListNotifier = ref.watch(packTicketListProvider.notifier); final singleRaffleStats = ref.watch(raffleStatsProvider.notifier); - final raffleStats = ref.watch(raffleStatsMapProvider); + final raffleStat = + ref.watch(raffleStatsMapProvider.select((value) => value[raffle.id])); final rafflesStatsNotifier = ref.watch(raffleStatsMapProvider.notifier); return RaffleTemplate( child: GestureDetector( @@ -78,7 +79,7 @@ class RaffleWidget extends HookConsumerWidget { ), const SizedBox(height: 20), AutoLoaderChild( - value: raffleStats, + group: raffleStat, notifier: rafflesStatsNotifier, mapKey: raffle.id, loader: (raffleId) async => (await singleRaffleStats diff --git a/lib/tools/providers/map_provider.dart b/lib/tools/providers/map_provider.dart index d4b013af8..57dbdede9 100644 --- a/lib/tools/providers/map_provider.dart +++ b/lib/tools/providers/map_provider.dart @@ -15,7 +15,7 @@ class MapNotifier extends StateNotifier>?>> { void addT(T t) async { state[t] = null; - state = state; + state = Map.of(state); } void addE(T t, E e) { @@ -24,20 +24,20 @@ class MapNotifier extends StateNotifier>?>> { state = state; }, orElse: () { state[t] = AsyncValue.data([e]); - state = state; + state = Map.of(state); }); } void deleteT(T t) { if (state.containsKey(t)) { state.remove(t); - state = state; + state = Map.of(state); } } void setTData(T t, AsyncValue> asyncEList) async { state[t] = asyncEList; - state = state; + state = Map.of(state); } bool deleteE(T t, int index) { diff --git a/lib/tools/ui/builders/auto_loader_child.dart b/lib/tools/ui/builders/auto_loader_child.dart index 34fdfb45e..abefeb5e2 100644 --- a/lib/tools/ui/builders/auto_loader_child.dart +++ b/lib/tools/ui/builders/auto_loader_child.dart @@ -5,7 +5,7 @@ import 'package:myecl/tools/ui/builders/async_child.dart'; import 'package:myecl/tools/ui/widgets/loader.dart'; class AutoLoaderChild extends ConsumerWidget { - final Map>?> value; + final AsyncValue>? group; final MapNotifier notifier; final MapKey mapKey; final Future Function(MapKey t)? loader; @@ -17,7 +17,7 @@ class AutoLoaderChild extends ConsumerWidget { final Color? loaderColor; const AutoLoaderChild( {super.key, - required this.value, + required this.group, required this.notifier, required this.mapKey, required this.dataBuilder, @@ -33,7 +33,6 @@ class AutoLoaderChild extends ConsumerWidget { assert(loader != null || listLoader != null); final nonNullLoadingBuilder = loadingBuilder ?? (context) => Loader(color: loaderColor); - final group = value[mapKey]; if (group == null) { loader == null ? notifier.autoLoadList(ref, mapKey, listLoader!) @@ -41,7 +40,7 @@ class AutoLoaderChild extends ConsumerWidget { return nonNullLoadingBuilder(context); } return AsyncChild( - value: group, + value: group!, builder: (context, list) { return dataBuilder(context, list); }, diff --git a/lib/vote/ui/components/contender_logo.dart b/lib/vote/ui/components/contender_logo.dart index 1f0c5a702..58e23ffd9 100644 --- a/lib/vote/ui/components/contender_logo.dart +++ b/lib/vote/ui/components/contender_logo.dart @@ -11,11 +11,12 @@ class ContenderLogo extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final contenderLogos = ref.watch(contenderLogosProvider); + final contenderLogos = + ref.watch(contenderLogosProvider.select((value) => value[contender])); final contenderLogosNotifier = ref.read(contenderLogosProvider.notifier); final logoNotifier = ref.read(contenderLogoProvider.notifier); return AutoLoaderChild( - value: contenderLogos, + group: contenderLogos, notifier: contenderLogosNotifier, mapKey: contender, loader: (contender) => logoNotifier.getLogo(contender.id), diff --git a/lib/vote/ui/pages/admin_page/vote_count.dart b/lib/vote/ui/pages/admin_page/vote_count.dart index 987fa0a18..df6e5e7ad 100644 --- a/lib/vote/ui/pages/admin_page/vote_count.dart +++ b/lib/vote/ui/pages/admin_page/vote_count.dart @@ -12,10 +12,11 @@ class VoteCount extends HookConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final section = ref.watch(sectionProvider); final sectionVoteNotifier = ref.watch(sectionVoteCountProvider.notifier); - final stats = ref.watch(sectionsStatsProvider); + final stats = + ref.watch(sectionsStatsProvider.select((value) => value[section])); final statsNotifier = ref.read(sectionsStatsProvider.notifier); return AutoLoaderChild( - value: stats, + group: stats, notifier: statsNotifier, mapKey: section, loader: (section) async => From 800effa58698064ff5769aa1b2464c2789c659c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 19:07:41 +0100 Subject: [PATCH 03/16] fix: prevent Image MapNotifier from reloading every image on each parent rebuild --- lib/admin/providers/section_logo_provider.dart | 11 ----------- lib/advert/providers/advert_posters_provider.dart | 11 ----------- lib/cinema/providers/session_poster_map_provider.dart | 11 ----------- lib/raffle/providers/tombola_logos_provider.dart | 11 ----------- lib/tools/providers/map_provider.dart | 4 +++- lib/vote/providers/contender_logos_provider.dart | 11 ----------- 6 files changed, 3 insertions(+), 56 deletions(-) diff --git a/lib/admin/providers/section_logo_provider.dart b/lib/admin/providers/section_logo_provider.dart index eb9ff40c3..9a9c615b2 100644 --- a/lib/admin/providers/section_logo_provider.dart +++ b/lib/admin/providers/section_logo_provider.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/admin/class/simple_group.dart'; -import 'package:myecl/admin/providers/group_list_provider.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -import 'package:myecl/tools/token_expire_wrapper.dart'; class SimpleGroupLogoNotifier extends MapNotifier { SimpleGroupLogoNotifier() : super(); @@ -12,14 +10,5 @@ class SimpleGroupLogoNotifier extends MapNotifier { final allGroupLogosProvider = StateNotifierProvider>?>>((ref) { SimpleGroupLogoNotifier simpleGroupLogoNotifier = SimpleGroupLogoNotifier(); - tokenExpireWrapperAuth(ref, () async { - ref.watch(allGroupListProvider).maybeWhen(data: (allGroup) { - simpleGroupLogoNotifier.loadTList(allGroup); - return simpleGroupLogoNotifier; - }, orElse: () { - simpleGroupLogoNotifier.loadTList([]); - return simpleGroupLogoNotifier; - }); - }); return simpleGroupLogoNotifier; }); diff --git a/lib/advert/providers/advert_posters_provider.dart b/lib/advert/providers/advert_posters_provider.dart index 486d98a6c..8597c3cff 100644 --- a/lib/advert/providers/advert_posters_provider.dart +++ b/lib/advert/providers/advert_posters_provider.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/advert/class/advert.dart'; -import 'package:myecl/advert/providers/advert_list_provider.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -import 'package:myecl/tools/token_expire_wrapper.dart'; class AdvertPosterNotifier extends MapNotifier { AdvertPosterNotifier() : super(); @@ -12,14 +10,5 @@ class AdvertPosterNotifier extends MapNotifier { final advertPostersProvider = StateNotifierProvider>?>>((ref) { AdvertPosterNotifier advertPosterNotifier = AdvertPosterNotifier(); - tokenExpireWrapperAuth(ref, () async { - ref.watch(advertListProvider).maybeWhen(data: (advert) { - advertPosterNotifier.loadTList(advert); - return advertPosterNotifier; - }, orElse: () { - advertPosterNotifier.loadTList([]); - return advertPosterNotifier; - }); - }); return advertPosterNotifier; }); diff --git a/lib/cinema/providers/session_poster_map_provider.dart b/lib/cinema/providers/session_poster_map_provider.dart index 7a452dcde..3a4206ec1 100644 --- a/lib/cinema/providers/session_poster_map_provider.dart +++ b/lib/cinema/providers/session_poster_map_provider.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/cinema/class/session.dart'; -import 'package:myecl/cinema/providers/session_list_provider.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -import 'package:myecl/tools/token_expire_wrapper.dart'; class SessionLogoNotifier extends MapNotifier { SessionLogoNotifier() : super(); @@ -12,14 +10,5 @@ class SessionLogoNotifier extends MapNotifier { final sessionPosterMapProvider = StateNotifierProvider>?>>((ref) { SessionLogoNotifier sessionLogoNotifier = SessionLogoNotifier(); - tokenExpireWrapperAuth(ref, () async { - ref.watch(sessionListProvider).maybeWhen(data: (session) { - sessionLogoNotifier.loadTList(session); - return sessionLogoNotifier; - }, orElse: () { - sessionLogoNotifier.loadTList([]); - return sessionLogoNotifier; - }); - }); return sessionLogoNotifier; }); diff --git a/lib/raffle/providers/tombola_logos_provider.dart b/lib/raffle/providers/tombola_logos_provider.dart index 6a0a8fe96..62c81462a 100644 --- a/lib/raffle/providers/tombola_logos_provider.dart +++ b/lib/raffle/providers/tombola_logos_provider.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -import 'package:myecl/tools/token_expire_wrapper.dart'; import 'package:myecl/raffle/class/raffle.dart'; -import 'package:myecl/raffle/providers/raffle_list_provider.dart'; class RaffleLogoNotifier extends MapNotifier { RaffleLogoNotifier() : super(); @@ -12,14 +10,5 @@ class RaffleLogoNotifier extends MapNotifier { final tombolaLogosProvider = StateNotifierProvider>?>>((ref) { RaffleLogoNotifier raffleLogoNotifier = RaffleLogoNotifier(); - tokenExpireWrapperAuth(ref, () async { - ref.watch(raffleListProvider).maybeWhen(data: (raffle) { - raffleLogoNotifier.loadTList(raffle); - return RaffleLogoNotifier; - }, orElse: () { - raffleLogoNotifier.loadTList([]); - return RaffleLogoNotifier; - }); - }); return raffleLogoNotifier; }); diff --git a/lib/tools/providers/map_provider.dart b/lib/tools/providers/map_provider.dart index 57dbdede9..562f216ac 100644 --- a/lib/tools/providers/map_provider.dart +++ b/lib/tools/providers/map_provider.dart @@ -8,7 +8,9 @@ class MapNotifier extends StateNotifier>?>> { void loadTList(List tList) async { Map>?> tMap = {}; for (T l in tList) { - tMap[l] = null; + if (!tMap.containsKey(l)) { + tMap[l] = null; + } } state = tMap; } diff --git a/lib/vote/providers/contender_logos_provider.dart b/lib/vote/providers/contender_logos_provider.dart index e8fa65b90..004e85191 100644 --- a/lib/vote/providers/contender_logos_provider.dart +++ b/lib/vote/providers/contender_logos_provider.dart @@ -1,9 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -import 'package:myecl/tools/token_expire_wrapper.dart'; import 'package:myecl/vote/class/contender.dart'; -import 'package:myecl/vote/providers/contender_list_provider.dart'; class ContenderLogoNotifier extends MapNotifier { ContenderLogoNotifier() : super(); @@ -12,14 +10,5 @@ class ContenderLogoNotifier extends MapNotifier { final contenderLogosProvider = StateNotifierProvider>?>>((ref) { ContenderLogoNotifier contenderLogoNotifier = ContenderLogoNotifier(); - tokenExpireWrapperAuth(ref, () async { - ref.watch(contenderListProvider).maybeWhen(data: (contender) { - contenderLogoNotifier.loadTList(contender); - return contenderLogoNotifier; - }, orElse: () { - contenderLogoNotifier.loadTList([]); - return contenderLogoNotifier; - }); - }); return contenderLogoNotifier; }); From 03e79e2af9a651e6cbfde6296782a56d8cfeb181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 21:13:15 +0100 Subject: [PATCH 04/16] fix(advert): Apply image changes in PostersProvider on add/edit/delete --- .../providers/advert_poster_provider.dart | 23 +++++++++++++++---- .../providers/advert_posters_provider.dart | 11 ++++----- lib/advert/ui/components/advert_card.dart | 10 ++++---- .../ui/pages/admin_page/admin_page.dart | 4 ++++ .../pages/form_page/add_edit_advert_page.dart | 4 ++-- 5 files changed, 35 insertions(+), 17 deletions(-) diff --git a/lib/advert/providers/advert_poster_provider.dart b/lib/advert/providers/advert_poster_provider.dart index 5f603b53b..f72ec0a31 100644 --- a/lib/advert/providers/advert_poster_provider.dart +++ b/lib/advert/providers/advert_poster_provider.dart @@ -2,28 +2,43 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:myecl/advert/providers/advert_posters_provider.dart'; import 'package:myecl/auth/providers/openid_provider.dart'; import 'package:myecl/advert/repositories/advert_poster_repository.dart'; import 'package:myecl/tools/providers/single_notifier.dart'; class AdvertPosterNotifier extends SingleNotifier { final advertPosterRepository = AdvertPosterRepository(); - AdvertPosterNotifier({required String token}) + final AdvertPostersNotifier advertPostersNotifier; + AdvertPosterNotifier( + {required String token, required this.advertPostersNotifier}) : super(const AsyncValue.loading()) { advertPosterRepository.setToken(token); } Future getAdvertPoster(String id) async { - return await advertPosterRepository.getAdvertPoster(id); + return await advertPosterRepository.getAdvertPoster(id).then((image) { + advertPostersNotifier.setTData(id, AsyncData([image])); + return image; + }); } Future updateAdvertPoster(String id, Uint8List bytes) async { - return await advertPosterRepository.addAdvertPoster(bytes, id); + advertPostersNotifier.setTData(id, const AsyncLoading()); + return await advertPosterRepository + .addAdvertPoster(bytes, id) + .then((image) { + advertPostersNotifier.setTData(id, AsyncData([image])); + return image; + }); } } final advertPosterProvider = StateNotifierProvider>((ref) { final token = ref.watch(tokenProvider); - return AdvertPosterNotifier(token: token); + final advertPostersNotifier = ref.watch(advertPostersProvider.notifier); + return AdvertPosterNotifier( + token: token, advertPostersNotifier: advertPostersNotifier); }); diff --git a/lib/advert/providers/advert_posters_provider.dart b/lib/advert/providers/advert_posters_provider.dart index 8597c3cff..f787dbfe5 100644 --- a/lib/advert/providers/advert_posters_provider.dart +++ b/lib/advert/providers/advert_posters_provider.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:myecl/advert/class/advert.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -class AdvertPosterNotifier extends MapNotifier { - AdvertPosterNotifier() : super(); +class AdvertPostersNotifier extends MapNotifier { + AdvertPostersNotifier() : super(); } -final advertPostersProvider = StateNotifierProvider>?>>((ref) { - AdvertPosterNotifier advertPosterNotifier = AdvertPosterNotifier(); +final advertPostersProvider = StateNotifierProvider>?>>((ref) { + AdvertPostersNotifier advertPosterNotifier = AdvertPostersNotifier(); return advertPosterNotifier; }); diff --git a/lib/advert/ui/components/advert_card.dart b/lib/advert/ui/components/advert_card.dart index 7a6f16fbe..5c89131c6 100644 --- a/lib/advert/ui/components/advert_card.dart +++ b/lib/advert/ui/components/advert_card.dart @@ -24,10 +24,10 @@ class AdvertCard extends HookConsumerWidget { double height = 300; double imageHeight = 175; double maxHeight = MediaQuery.of(context).size.height - 344; - final posters = ref.watch( - advertPostersProvider.select((advertPosters) => advertPosters[advert])); + final posters = ref.watch(advertPostersProvider + .select((advertPosters) => advertPosters[advert.id])); final advertPostersNotifier = ref.watch(advertPostersProvider.notifier); - final logoNotifier = ref.watch(advertPosterProvider.notifier); + final posterNotifier = ref.watch(advertPosterProvider.notifier); final isWebFormat = ref.watch(isWebFormatProvider); return GestureDetector( onTap: () { @@ -41,8 +41,8 @@ class AdvertCard extends HookConsumerWidget { child: AutoLoaderChild( group: posters, notifier: advertPostersNotifier, - mapKey: advert, - loader: (advert) => logoNotifier.getAdvertPoster(advert.id), + mapKey: advert.id, + loader: (advertId) => posterNotifier.getAdvertPoster(advertId), loadingBuilder: (context) => HeroIcon( HeroIcons.photo, size: width, diff --git a/lib/advert/ui/pages/admin_page/admin_page.dart b/lib/advert/ui/pages/admin_page/admin_page.dart index 1f7c6ea59..0ecb90a77 100644 --- a/lib/advert/ui/pages/admin_page/admin_page.dart +++ b/lib/advert/ui/pages/admin_page/admin_page.dart @@ -4,6 +4,7 @@ import 'package:heroicons/heroicons.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:myecl/advert/class/advert.dart'; import 'package:myecl/advert/providers/advert_list_provider.dart'; +import 'package:myecl/advert/providers/advert_posters_provider.dart'; import 'package:myecl/advert/providers/advert_provider.dart'; import 'package:myecl/advert/providers/announcer_list_provider.dart'; import 'package:myecl/advert/providers/announcer_provider.dart'; @@ -28,6 +29,7 @@ class AdvertAdminPage extends HookConsumerWidget { final userAnnouncerListNotifier = ref.watch(userAnnouncerListProvider.notifier); final userAnnouncerList = ref.watch(userAnnouncerListProvider); + final advertPostersNotifier = ref.watch(advertPostersProvider.notifier); final advertListNotifier = ref.watch(advertListProvider.notifier); final selectedAnnouncers = ref.watch(announcerProvider); final selectedAnnouncersNotifier = ref.read(announcerProvider.notifier); @@ -112,6 +114,8 @@ class AdvertAdminPage extends HookConsumerWidget { AdvertTextConstants.deleteAdvert, onYes: () { advertListNotifier.deleteAdvert(advert); + advertPostersNotifier + .deleteT(advert.id); }, ); }); diff --git a/lib/advert/ui/pages/form_page/add_edit_advert_page.dart b/lib/advert/ui/pages/form_page/add_edit_advert_page.dart index 3ba931dde..1e9cbbcbf 100644 --- a/lib/advert/ui/pages/form_page/add_edit_advert_page.dart +++ b/lib/advert/ui/pages/form_page/add_edit_advert_page.dart @@ -45,8 +45,8 @@ class AdvertAddEditAdvertPage extends HookConsumerWidget { final poster = useState(null); final posterFile = useState(null); - if (advertPosters[advert] != null) { - advertPosters[advert]!.whenData((data) { + if (advertPosters[advert.id] != null) { + advertPosters[advert.id]!.whenData((data) { if (data.isNotEmpty) { posterFile.value = data.first; } From 195a18ffc32ab5ec44788c5e30942558d64aa8b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 22:09:46 +0100 Subject: [PATCH 05/16] fix: add refresh posters --- lib/advert/ui/pages/admin_page/admin_page.dart | 5 +++-- lib/advert/ui/pages/main_page/main_page.dart | 3 +++ lib/tools/providers/map_provider.dart | 11 ++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/advert/ui/pages/admin_page/admin_page.dart b/lib/advert/ui/pages/admin_page/admin_page.dart index 0ecb90a77..94c298b8f 100644 --- a/lib/advert/ui/pages/admin_page/admin_page.dart +++ b/lib/advert/ui/pages/admin_page/admin_page.dart @@ -59,6 +59,7 @@ class AdvertAdminPage extends HookConsumerWidget { onRefresh: () async { await advertListNotifier.loadAdverts(); await userAnnouncerListNotifier.loadMyAnnouncerList(); + advertPostersNotifier.resetTData(); }, children: [ const AnnouncerBar( @@ -114,8 +115,8 @@ class AdvertAdminPage extends HookConsumerWidget { AdvertTextConstants.deleteAdvert, onYes: () { advertListNotifier.deleteAdvert(advert); - advertPostersNotifier - .deleteT(advert.id); + advertPostersNotifier.deleteE( + advert.id, 0); }, ); }); diff --git a/lib/advert/ui/pages/main_page/main_page.dart b/lib/advert/ui/pages/main_page/main_page.dart index abc22324d..5e89ee927 100644 --- a/lib/advert/ui/pages/main_page/main_page.dart +++ b/lib/advert/ui/pages/main_page/main_page.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:myecl/admin/providers/is_admin_provider.dart'; import 'package:myecl/advert/providers/advert_list_provider.dart'; +import 'package:myecl/advert/providers/advert_posters_provider.dart'; import 'package:myecl/advert/providers/advert_provider.dart'; import 'package:myecl/advert/providers/announcer_provider.dart'; import 'package:myecl/advert/providers/is_advert_admin_provider.dart'; @@ -24,6 +25,7 @@ class AdvertMainPage extends HookConsumerWidget { final advertNotifier = ref.watch(advertProvider.notifier); final advertList = ref.watch(advertListProvider); final advertListNotifier = ref.watch(advertListProvider.notifier); + final advertPostersNotifier = ref.watch(advertPostersProvider.notifier); final selected = ref.watch(announcerProvider); final selectedNotifier = ref.watch(announcerProvider.notifier); final isAdmin = ref.watch(isAdminProvider); @@ -34,6 +36,7 @@ class AdvertMainPage extends HookConsumerWidget { ColumnRefresher( onRefresh: () async { await advertListNotifier.loadAdverts(); + advertPostersNotifier.resetTData(); }, children: [ SizedBox( diff --git a/lib/tools/providers/map_provider.dart b/lib/tools/providers/map_provider.dart index 562f216ac..e0d150975 100644 --- a/lib/tools/providers/map_provider.dart +++ b/lib/tools/providers/map_provider.dart @@ -8,9 +8,7 @@ class MapNotifier extends StateNotifier>?>> { void loadTList(List tList) async { Map>?> tMap = {}; for (T l in tList) { - if (!tMap.containsKey(l)) { - tMap[l] = null; - } + tMap[l] = null; } state = tMap; } @@ -42,6 +40,13 @@ class MapNotifier extends StateNotifier>?>> { state = Map.of(state); } + void resetTData() async { + for (T l in state.keys) { + state[l] = null; + } + state = Map.of(state); + } + bool deleteE(T t, int index) { return state[t]!.maybeWhen( data: (eList) { From b5ccbe2093416272447a4240afea32d713e80dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 22:10:32 +0100 Subject: [PATCH 06/16] fix:advert detail page --- lib/advert/ui/pages/detail_page/detail.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/advert/ui/pages/detail_page/detail.dart b/lib/advert/ui/pages/detail_page/detail.dart index cec22d5d9..2eaddd660 100644 --- a/lib/advert/ui/pages/detail_page/detail.dart +++ b/lib/advert/ui/pages/detail_page/detail.dart @@ -19,8 +19,8 @@ class AdvertDetailPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final advert = ref.watch(advertProvider); - final posters = ref.watch( - advertPostersProvider.select((advertPosters) => advertPosters[advert])); + final posters = ref.watch(advertPostersProvider + .select((advertPosters) => advertPosters[advert.id])); final advertPostersNotifier = ref.watch(advertPostersProvider.notifier); final logoNotifier = ref.watch(advertPosterProvider.notifier); final filteredTagList = From dea2b65d2d3365d6c69c92852e9060f2ee12e216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 22:48:01 +0100 Subject: [PATCH 07/16] fix: update on cinema --- .../session_poster_map_provider.dart | 5 ++--- .../providers/session_poster_provider.dart | 19 +++++++++++++++---- .../pages/admin_page/admin_session_card.dart | 10 +++++----- .../ui/pages/detail_page/detail_page.dart | 8 ++++---- lib/cinema/ui/pages/main_page/main_page.dart | 4 ++++ .../ui/pages/main_page/session_card.dart | 10 +++++----- .../pages/session_pages/add_edit_session.dart | 16 ++++++++-------- 7 files changed, 43 insertions(+), 29 deletions(-) diff --git a/lib/cinema/providers/session_poster_map_provider.dart b/lib/cinema/providers/session_poster_map_provider.dart index 3a4206ec1..21fa713dd 100644 --- a/lib/cinema/providers/session_poster_map_provider.dart +++ b/lib/cinema/providers/session_poster_map_provider.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:myecl/cinema/class/session.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -class SessionLogoNotifier extends MapNotifier { +class SessionLogoNotifier extends MapNotifier { SessionLogoNotifier() : super(); } final sessionPosterMapProvider = StateNotifierProvider>?>>((ref) { + Map>?>>((ref) { SessionLogoNotifier sessionLogoNotifier = SessionLogoNotifier(); return sessionLogoNotifier; }); diff --git a/lib/cinema/providers/session_poster_provider.dart b/lib/cinema/providers/session_poster_provider.dart index 1387efe39..e9147e6c7 100644 --- a/lib/cinema/providers/session_poster_provider.dart +++ b/lib/cinema/providers/session_poster_provider.dart @@ -2,25 +2,36 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:myecl/cinema/providers/session_poster_map_provider.dart'; import 'package:myecl/cinema/repositories/session_poster_repository.dart'; import 'package:myecl/tools/providers/single_notifier.dart'; class SessionPosterProvider extends SingleNotifier { final SessionPosterRepository repository; - SessionPosterProvider({required this.repository}) + final SessionLogoNotifier sessionLogoNotifier; + SessionPosterProvider( + {required this.repository, required this.sessionLogoNotifier}) : super(const AsyncValue.loading()); Future getLogo(String id) async { - return await repository.getSessionLogo(id); + return await repository.getSessionLogo(id).then((image) { + sessionLogoNotifier.setTData(id, AsyncData([image])); + return image; + }); } Future updateLogo(String id, Uint8List bytes) async { - return await repository.addSessionLogo(bytes, id); + return await repository.addSessionLogo(bytes, id).then((image) { + sessionLogoNotifier.setTData(id, AsyncData([image])); + return image; + }); } } final sessionPosterProvider = StateNotifierProvider>((ref) { final sessionPoster = ref.watch(sessionPosterRepository); - return SessionPosterProvider(repository: sessionPoster); + final sessionPosterMapNotifier = ref.watch(sessionPosterMapProvider.notifier); + return SessionPosterProvider( + repository: sessionPoster, sessionLogoNotifier: sessionPosterMapNotifier); }); diff --git a/lib/cinema/ui/pages/admin_page/admin_session_card.dart b/lib/cinema/ui/pages/admin_page/admin_session_card.dart index 729efcd3a..b7550dade 100644 --- a/lib/cinema/ui/pages/admin_page/admin_session_card.dart +++ b/lib/cinema/ui/pages/admin_page/admin_session_card.dart @@ -22,8 +22,8 @@ class AdminSessionCard extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final sessionPoster = - ref.watch(sessionPosterMapProvider.select((value) => value[session])); + final sessionPoster = ref + .watch(sessionPosterMapProvider.select((value) => value[session.id])); final sessionPosterMapNotifier = ref.read(sessionPosterMapProvider.notifier); final sessionPosterNotifier = ref.read(sessionPosterProvider.notifier); @@ -55,9 +55,9 @@ class AdminSessionCard extends HookConsumerWidget { child: AutoLoaderChild( group: sessionPoster, notifier: sessionPosterMapNotifier, - mapKey: session, - loader: (session) => - sessionPosterNotifier.getLogo(session.id), + mapKey: session.id, + loader: (sessionId) => + sessionPosterNotifier.getLogo(sessionId), dataBuilder: (context, data) => Image( image: data.first.image, fit: BoxFit.cover, diff --git a/lib/cinema/ui/pages/detail_page/detail_page.dart b/lib/cinema/ui/pages/detail_page/detail_page.dart index 2b145e12c..ef8a9b975 100644 --- a/lib/cinema/ui/pages/detail_page/detail_page.dart +++ b/lib/cinema/ui/pages/detail_page/detail_page.dart @@ -24,8 +24,8 @@ class DetailPage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final session = ref.watch(sessionProvider); - final sessionPoster = - ref.watch(sessionPosterMapProvider.select((value) => value[session])); + final sessionPoster = ref + .watch(sessionPosterMapProvider.select((value) => value[session.id])); final sessionPosterMapNotifier = ref.watch(sessionPosterMapProvider.notifier); final sessionPosterNotifier = ref.watch(sessionPosterProvider.notifier); @@ -58,8 +58,8 @@ class DetailPage extends HookConsumerWidget { child: AutoLoaderChild( group: sessionPoster, notifier: sessionPosterMapNotifier, - mapKey: session, - loader: (session) => sessionPosterNotifier.getLogo(session.id), + mapKey: session.id, + loader: (sessionId) => sessionPosterNotifier.getLogo(sessionId), dataBuilder: (context, data) => Image( image: data.first.image, fit: BoxFit.fill, diff --git a/lib/cinema/ui/pages/main_page/main_page.dart b/lib/cinema/ui/pages/main_page/main_page.dart index bc119ae71..cd0fa23fd 100644 --- a/lib/cinema/ui/pages/main_page/main_page.dart +++ b/lib/cinema/ui/pages/main_page/main_page.dart @@ -6,6 +6,7 @@ import 'package:myecl/cinema/providers/main_page_index_provider.dart'; import 'package:myecl/cinema/providers/scroll_provider.dart'; import 'package:myecl/cinema/providers/session_list_page_provider.dart'; import 'package:myecl/cinema/providers/session_list_provider.dart'; +import 'package:myecl/cinema/providers/session_poster_map_provider.dart'; import 'package:myecl/cinema/providers/session_provider.dart'; import 'package:myecl/cinema/router.dart'; import 'package:myecl/cinema/tools/constants.dart'; @@ -25,6 +26,8 @@ class CinemaMainPage extends HookConsumerWidget { final sessionList = ref.watch(sessionListProvider); final sessionListNotifier = ref.read(sessionListProvider.notifier); final sessionNotifier = ref.watch(sessionProvider.notifier); + final sessionPosterMapNotifier = + ref.watch(sessionPosterMapProvider.notifier); final initialPageNotifier = ref.watch(mainPageIndexProvider.notifier); final initialPage = ref.watch(mainPageIndexProvider); int currentPage = initialPage; @@ -44,6 +47,7 @@ class CinemaMainPage extends HookConsumerWidget { await sessionListNotifier.loadSessions(); ref.watch(mainPageIndexProvider.notifier).reset(); ref.read(cinemaTopicsProvider.notifier).getTopics(); + sessionPosterMapNotifier.resetTData(); }, child: SizedBox( height: MediaQuery.of(context).size.height - 85, diff --git a/lib/cinema/ui/pages/main_page/session_card.dart b/lib/cinema/ui/pages/main_page/session_card.dart index 91f18abe8..8456e7ad9 100644 --- a/lib/cinema/ui/pages/main_page/session_card.dart +++ b/lib/cinema/ui/pages/main_page/session_card.dart @@ -21,8 +21,8 @@ class SessionCard extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final scroll = ref.watch(scrollProvider); - final sessionPoster = - ref.watch(sessionPosterMapProvider.select((value) => value[session])); + final sessionPoster = ref + .watch(sessionPosterMapProvider.select((value) => value[session.id])); final sessionPosterMapNotifier = ref.watch(sessionPosterMapProvider.notifier); final sessionPosterNotifier = ref.watch(sessionPosterProvider.notifier); @@ -108,9 +108,9 @@ class SessionCard extends HookConsumerWidget { child: AutoLoaderChild( group: sessionPoster, notifier: sessionPosterMapNotifier, - mapKey: session, - loader: (session) => - sessionPosterNotifier.getLogo(session.id), + mapKey: session.id, + loader: (sessionId) => + sessionPosterNotifier.getLogo(sessionId), dataBuilder: (context, data) { return isWebFormat ? Container( diff --git a/lib/cinema/ui/pages/session_pages/add_edit_session.dart b/lib/cinema/ui/pages/session_pages/add_edit_session.dart index 11c0100b1..275904450 100644 --- a/lib/cinema/ui/pages/session_pages/add_edit_session.dart +++ b/lib/cinema/ui/pages/session_pages/add_edit_session.dart @@ -49,8 +49,8 @@ class AddEditSessionPage extends HookConsumerWidget { final posterUrl = useTextEditingController(); final sessionPosterNotifier = ref.watch(sessionPosterProvider.notifier); - if (sessionPosterMap[session] != null) { - sessionPosterMap[session]!.whenData((data) { + if (sessionPosterMap[session.id] != null) { + sessionPosterMap[session.id]!.whenData((data) { if (data.isNotEmpty) { logoFile.value = data.first; } @@ -242,9 +242,9 @@ class AddEditSessionPage extends HookConsumerWidget { sessionPosterMapProvider.notifier); sessionPosterMapNotifier.autoLoad( ref, - session, - (session) => sessionPosterNotifier - .updateLogo(session.id, logoBytes)); + session.id, + (sessionId) => sessionPosterNotifier + .updateLogo(sessionId, logoBytes)); } }, orElse: () {}); @@ -260,9 +260,9 @@ class AddEditSessionPage extends HookConsumerWidget { sessionPosterMapProvider.notifier); sessionPosterMapNotifier.autoLoad( ref, - newSession, - (session) => sessionPosterNotifier - .updateLogo(session.id, logoBytes)); + newSession.id, + (sessionId) => sessionPosterNotifier + .updateLogo(sessionId, logoBytes)); } }, orElse: () {}); From 76e927a53ae1fe2c1dd31e9ff5778bb69ec7ceaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 22:52:13 +0100 Subject: [PATCH 08/16] fix: update on tombola --- .../providers/tombola_logo_provider.dart | 25 ++++++++++++++++--- .../providers/tombola_logos_provider.dart | 13 +++++----- .../admin_module_page/admin_module_page.dart | 4 ++- lib/raffle/ui/pages/main_page/main_page.dart | 3 +++ .../ui/pages/main_page/ticket_card.dart | 8 +++--- .../raffle_page/buy_pack_ticket_card.dart | 8 +++--- .../raffle_page/buy_type_ticket_card.dart | 8 +++--- .../ui/pages/raffle_page/confirm_payment.dart | 10 +++++--- 8 files changed, 51 insertions(+), 28 deletions(-) diff --git a/lib/raffle/providers/tombola_logo_provider.dart b/lib/raffle/providers/tombola_logo_provider.dart index 1dda8805e..bb18023b6 100644 --- a/lib/raffle/providers/tombola_logo_provider.dart +++ b/lib/raffle/providers/tombola_logo_provider.dart @@ -3,24 +3,39 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/auth/providers/openid_provider.dart'; +import 'package:myecl/raffle/providers/tombola_logos_provider.dart'; import 'package:myecl/tools/providers/single_notifier.dart'; import 'package:myecl/raffle/repositories/tombola_logo_repository.dart'; class TombolaLogoProvider extends SingleNotifier { final repository = TombolaLogoRepository(); - TombolaLogoProvider({required String token}) + final TombolaLogosNotifier tombolaLogosNotifier; + TombolaLogoProvider( + {required String token, required this.tombolaLogosNotifier}) : super(const AsyncValue.loading()) { repository.setToken(token); } Future getLogo(String id) async { - Image logo = await repository.getTombolaLogo(id); + Image logo = await repository.getTombolaLogo(id).then((image) { + tombolaLogosNotifier.setTData( + id, + AsyncData([image]), + ); + return image; + }); state = AsyncValue.data(logo); return logo; } Future updateLogo(String id, Uint8List bytes) async { - Image logo = await repository.addTombolaLogo(bytes, id); + Image logo = await repository.addTombolaLogo(bytes, id).then((image) { + tombolaLogosNotifier.setTData( + id, + AsyncData([image]), + ); + return image; + }); state = AsyncValue.data(logo); return logo; } @@ -29,5 +44,7 @@ class TombolaLogoProvider extends SingleNotifier { final tombolaLogoProvider = StateNotifierProvider>((ref) { final token = ref.watch(tokenProvider); - return TombolaLogoProvider(token: token); + final tombolaLogosNotifier = ref.watch(tombolaLogosProvider.notifier); + return TombolaLogoProvider( + token: token, tombolaLogosNotifier: tombolaLogosNotifier); }); diff --git a/lib/raffle/providers/tombola_logos_provider.dart b/lib/raffle/providers/tombola_logos_provider.dart index 62c81462a..79d67f0da 100644 --- a/lib/raffle/providers/tombola_logos_provider.dart +++ b/lib/raffle/providers/tombola_logos_provider.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -import 'package:myecl/raffle/class/raffle.dart'; -class RaffleLogoNotifier extends MapNotifier { - RaffleLogoNotifier() : super(); +class TombolaLogosNotifier extends MapNotifier { + TombolaLogosNotifier() : super(); } -final tombolaLogosProvider = StateNotifierProvider>?>>((ref) { - RaffleLogoNotifier raffleLogoNotifier = RaffleLogoNotifier(); - return raffleLogoNotifier; +final tombolaLogosProvider = StateNotifierProvider>?>>((ref) { + TombolaLogosNotifier tombolaLogosNotifier = TombolaLogosNotifier(); + return tombolaLogosNotifier; }); diff --git a/lib/raffle/ui/pages/admin_module_page/admin_module_page.dart b/lib/raffle/ui/pages/admin_module_page/admin_module_page.dart index 24b32d26c..538e4207a 100644 --- a/lib/raffle/ui/pages/admin_module_page/admin_module_page.dart +++ b/lib/raffle/ui/pages/admin_module_page/admin_module_page.dart @@ -1,5 +1,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:flutter/material.dart'; +import 'package:myecl/raffle/providers/tombola_logos_provider.dart'; import 'package:myecl/raffle/ui/pages/admin_module_page/account_handler.dart'; import 'package:myecl/raffle/ui/pages/admin_module_page/tombola_handler.dart'; import 'package:myecl/raffle/ui/raffle.dart'; @@ -10,10 +11,11 @@ class AdminModulePage extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final tombolaLogosNotifier = ref.watch(tombolaLogosProvider.notifier); return RaffleTemplate( child: Refresher( onRefresh: () async { - () => {}; + tombolaLogosNotifier.resetTData(); }, child: const Column( children: [ diff --git a/lib/raffle/ui/pages/main_page/main_page.dart b/lib/raffle/ui/pages/main_page/main_page.dart index 2c6481f6b..7ea0b4bca 100644 --- a/lib/raffle/ui/pages/main_page/main_page.dart +++ b/lib/raffle/ui/pages/main_page/main_page.dart @@ -6,6 +6,7 @@ import 'package:myecl/raffle/class/raffle_status_type.dart'; import 'package:myecl/raffle/class/tickets.dart'; import 'package:myecl/raffle/providers/is_raffle_admin.dart'; import 'package:myecl/raffle/providers/raffle_list_provider.dart'; +import 'package:myecl/raffle/providers/tombola_logos_provider.dart'; import 'package:myecl/raffle/providers/user_tickets_provider.dart'; import 'package:myecl/raffle/router.dart'; import 'package:myecl/raffle/tools/constants.dart'; @@ -29,6 +30,7 @@ class RaffleMainPage extends HookConsumerWidget { final userTicketList = ref.watch(userTicketListProvider); final userTicketListNotifier = ref.watch(userTicketListProvider.notifier); final isAdmin = ref.watch(isRaffleAdminProvider); + final tombolaLogosNotifier = ref.watch(tombolaLogosProvider.notifier); final rafflesStatus = {}; raffleList.whenData( @@ -44,6 +46,7 @@ class RaffleMainPage extends HookConsumerWidget { onRefresh: () async { await userTicketListNotifier.loadTicketList(); await raffleListNotifier.loadRaffleList(); + tombolaLogosNotifier.resetTData(); }, child: Column( children: [ diff --git a/lib/raffle/ui/pages/main_page/ticket_card.dart b/lib/raffle/ui/pages/main_page/ticket_card.dart index 764ba630c..3d0ecfba2 100644 --- a/lib/raffle/ui/pages/main_page/ticket_card.dart +++ b/lib/raffle/ui/pages/main_page/ticket_card.dart @@ -55,8 +55,8 @@ class TicketWidget extends HookConsumerWidget { borderRadius: const BorderRadius.all(Radius.circular(15))), child: Center(child: Builder(builder: (context) { - if (tombolaLogos[raffle] != null) { - return tombolaLogos[raffle]!.when( + if (tombolaLogos[raffle.id] != null) { + return tombolaLogos[raffle.id]!.when( data: (tombolaLogos) { if (tombolaLogos.isNotEmpty) { return tombolaLogos.first; @@ -64,14 +64,14 @@ class TicketWidget extends HookConsumerWidget { Future.delayed( const Duration(milliseconds: 1), () { tombolaLogosNotifier.setTData( - raffle, const AsyncLoading()); + raffle.id, const AsyncLoading()); }); tokenExpireWrapper(ref, () async { tombolaLogoNotifier .getLogo(raffle.id) .then((value) { tombolaLogosNotifier.setTData( - raffle, AsyncData([value])); + raffle.id, AsyncData([value])); }); }); return const HeroIcon( diff --git a/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart b/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart index 4b7b87617..c50cc614f 100644 --- a/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart +++ b/lib/raffle/ui/pages/raffle_page/buy_pack_ticket_card.dart @@ -75,8 +75,8 @@ class BuyPackTicket extends HookConsumerWidget { borderRadius: const BorderRadius.all(Radius.circular(15))), child: Builder(builder: (context) { - if (tombolaLogos[raffle] != null) { - return tombolaLogos[raffle]!.when( + if (tombolaLogos[raffle.id] != null) { + return tombolaLogos[raffle.id]!.when( data: (data) { if (data.isNotEmpty) { return ClipRRect( @@ -87,14 +87,14 @@ class BuyPackTicket extends HookConsumerWidget { Future.delayed( const Duration(milliseconds: 1), () { tombolaLogosNotifier.setTData( - raffle, const AsyncLoading()); + raffle.id, const AsyncLoading()); }); tokenExpireWrapper(ref, () async { tombolaLogoNotifier .getLogo(raffle.id) .then((value) { tombolaLogosNotifier.setTData( - raffle, AsyncData([value])); + raffle.id, AsyncData([value])); }); }); return const HeroIcon( diff --git a/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart b/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart index 9695dcfba..5a6f4f14b 100644 --- a/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart +++ b/lib/raffle/ui/pages/raffle_page/buy_type_ticket_card.dart @@ -76,8 +76,8 @@ class BuyPackTicket extends HookConsumerWidget { const BorderRadius.all(Radius.circular(15))), child: Builder( builder: (context) { - if (tombolaLogos[raffle] != null) { - return tombolaLogos[raffle]!.when( + if (tombolaLogos[raffle.id] != null) { + return tombolaLogos[raffle.id]!.when( data: (data) { if (data.isNotEmpty) { return ClipRRect( @@ -88,14 +88,14 @@ class BuyPackTicket extends HookConsumerWidget { Future.delayed( const Duration(milliseconds: 1), () { tombolaLogosNotifier.setTData( - raffle, const AsyncLoading()); + raffle.id, const AsyncLoading()); }); tokenExpireWrapper(ref, () async { tombolaLogoNotifier .getLogo(raffle.id) .then((value) { tombolaLogosNotifier.setTData( - raffle, AsyncData([value])); + raffle.id, AsyncData([value])); }); }); return const HeroIcon( diff --git a/lib/raffle/ui/pages/raffle_page/confirm_payment.dart b/lib/raffle/ui/pages/raffle_page/confirm_payment.dart index 061af04bc..13de1ca06 100644 --- a/lib/raffle/ui/pages/raffle_page/confirm_payment.dart +++ b/lib/raffle/ui/pages/raffle_page/confirm_payment.dart @@ -103,8 +103,8 @@ class ConfirmPaymentDialog extends HookConsumerWidget { Radius.circular(25))), child: Center(child: Builder(builder: (context) { - if (tombolaLogos[raffle] != null) { - return tombolaLogos[raffle]!.when( + if (tombolaLogos[raffle.id] != null) { + return tombolaLogos[raffle.id]!.when( data: (data) { if (data.isNotEmpty) { return ClipRRect( @@ -116,14 +116,16 @@ class ConfirmPaymentDialog extends HookConsumerWidget { const Duration(milliseconds: 1), () { tombolaLogosNotifier.setTData( - raffle, const AsyncLoading()); + raffle.id, + const AsyncLoading()); }); tokenExpireWrapper(ref, () async { tombolaLogoNotifier .getLogo(raffle.id) .then((value) { tombolaLogosNotifier.setTData( - raffle, AsyncData([value])); + raffle.id, + AsyncData([value])); }); }); return const HeroIcon( From 2bc8013a2496baef2f6668eff872bab9e64f7e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 22:52:37 +0100 Subject: [PATCH 09/16] fix: update on vote --- .../providers/contender_logo_provider.dart | 22 +++++++++++++++---- .../providers/contender_logos_provider.dart | 5 ++--- lib/vote/ui/components/contender_logo.dart | 8 +++---- .../contender_pages/add_edit_contender.dart | 14 +++++++----- .../ui/pages/detail_page/detail_page.dart | 6 ++--- lib/vote/ui/pages/main_page/main_page.dart | 10 +++++---- 6 files changed, 41 insertions(+), 24 deletions(-) diff --git a/lib/vote/providers/contender_logo_provider.dart b/lib/vote/providers/contender_logo_provider.dart index b84dddba0..d042810d2 100644 --- a/lib/vote/providers/contender_logo_provider.dart +++ b/lib/vote/providers/contender_logo_provider.dart @@ -3,25 +3,39 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/tools/providers/single_notifier.dart'; +import 'package:myecl/vote/providers/contender_logos_provider.dart'; import 'package:myecl/vote/repositories/contender_logo_repository.dart'; class ContenderLogoProvider extends SingleNotifier { final ContenderLogoRepository contenderLogoRepository; - ContenderLogoProvider({required this.contenderLogoRepository}) + final ContenderLogoNotifier contenderLogosNotifier; + ContenderLogoProvider( + {required this.contenderLogoRepository, + required this.contenderLogosNotifier}) : super(const AsyncValue.loading()); Future getLogo(String id) async { - return await contenderLogoRepository.getContenderLogo(id); + return await contenderLogoRepository.getContenderLogo(id).then((image) { + contenderLogosNotifier.setTData(id, AsyncData([image])); + return image; + }); } Future updateLogo(String id, Uint8List bytes) async { - return await contenderLogoRepository.addContenderLogo(bytes, id); + return await contenderLogoRepository + .addContenderLogo(bytes, id) + .then((image) { + contenderLogosNotifier.setTData(id, AsyncData([image])); + return image; + }); } } final contenderLogoProvider = StateNotifierProvider>((ref) { final contenderLogoRepository = ref.watch(contenderLogoRepositoryProvider); + final contenderLogosNotifier = ref.watch(contenderLogosProvider.notifier); return ContenderLogoProvider( - contenderLogoRepository: contenderLogoRepository); + contenderLogoRepository: contenderLogoRepository, + contenderLogosNotifier: contenderLogosNotifier); }); diff --git a/lib/vote/providers/contender_logos_provider.dart b/lib/vote/providers/contender_logos_provider.dart index 004e85191..9cd4d4fda 100644 --- a/lib/vote/providers/contender_logos_provider.dart +++ b/lib/vote/providers/contender_logos_provider.dart @@ -1,14 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:myecl/tools/providers/map_provider.dart'; -import 'package:myecl/vote/class/contender.dart'; -class ContenderLogoNotifier extends MapNotifier { +class ContenderLogoNotifier extends MapNotifier { ContenderLogoNotifier() : super(); } final contenderLogosProvider = StateNotifierProvider>?>>((ref) { + Map>?>>((ref) { ContenderLogoNotifier contenderLogoNotifier = ContenderLogoNotifier(); return contenderLogoNotifier; }); diff --git a/lib/vote/ui/components/contender_logo.dart b/lib/vote/ui/components/contender_logo.dart index 58e23ffd9..c94e8301c 100644 --- a/lib/vote/ui/components/contender_logo.dart +++ b/lib/vote/ui/components/contender_logo.dart @@ -11,15 +11,15 @@ class ContenderLogo extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final contenderLogos = - ref.watch(contenderLogosProvider.select((value) => value[contender])); + final contenderLogos = ref + .watch(contenderLogosProvider.select((value) => value[contender.id])); final contenderLogosNotifier = ref.read(contenderLogosProvider.notifier); final logoNotifier = ref.read(contenderLogoProvider.notifier); return AutoLoaderChild( group: contenderLogos, notifier: contenderLogosNotifier, - mapKey: contender, - loader: (contender) => logoNotifier.getLogo(contender.id), + mapKey: contender.id, + loader: (contenderId) => logoNotifier.getLogo(contenderId), dataBuilder: (context, logo) => Container( width: 40, height: 40, diff --git a/lib/vote/ui/pages/contender_pages/add_edit_contender.dart b/lib/vote/ui/pages/contender_pages/add_edit_contender.dart index 4f63a4905..88cd9842a 100644 --- a/lib/vote/ui/pages/contender_pages/add_edit_contender.dart +++ b/lib/vote/ui/pages/contender_pages/add_edit_contender.dart @@ -355,9 +355,10 @@ class AddEditContenderPage extends HookConsumerWidget { if (logoBytes != null) { contenderLogosNotifier.autoLoad( ref, - contender, - (contender) => logoNotifier.updateLogo( - contender.id, logoBytes)); + contender.id, + (contenderId) => + logoNotifier.updateLogo( + contenderId, logoBytes)); } }, orElse: () {}); @@ -371,9 +372,10 @@ class AddEditContenderPage extends HookConsumerWidget { if (logoBytes != null) { contenderLogosNotifier.autoLoad( ref, - newContender, - (contender) => logoNotifier.updateLogo( - contender.id, logoBytes)); + newContender.id, + (contenderId) => + logoNotifier.updateLogo( + contenderId, logoBytes)); } }, orElse: () {}); diff --git a/lib/vote/ui/pages/detail_page/detail_page.dart b/lib/vote/ui/pages/detail_page/detail_page.dart index 224a46ce4..b028b3518 100644 --- a/lib/vote/ui/pages/detail_page/detail_page.dart +++ b/lib/vote/ui/pages/detail_page/detail_page.dart @@ -53,21 +53,21 @@ class DetailPage extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.center, children: [ const SizedBox(height: 30), - if (contenderLogos[contender] == null) + if (contenderLogos[contender.id] == null) const SizedBox.shrink() else SizedBox( height: 140, width: 140, child: AsyncChild( - value: contenderLogos[contender]!, + value: contenderLogos[contender.id]!, builder: (context, data) { if (data.isEmpty) { logoNotifier .getLogo(contender.id) .then((value) { contenderLogosNotifier.setTData( - contender, AsyncData([value])); + contender.id, AsyncData([value])); }); return const HeroIcon( HeroIcons.userCircle, diff --git a/lib/vote/ui/pages/main_page/main_page.dart b/lib/vote/ui/pages/main_page/main_page.dart index c127fb74f..5dc251e56 100644 --- a/lib/vote/ui/pages/main_page/main_page.dart +++ b/lib/vote/ui/pages/main_page/main_page.dart @@ -100,7 +100,8 @@ class VoteMainPage extends HookConsumerWidget { list = contender; }); sectionContenderNotifier.loadTList(value); - contenderLogosNotifier.loadTList(list); + contenderLogosNotifier + .loadTList(list.map((contender) => contender.id).toList()); for (final l in value) { sectionContenderNotifier.setTData( l, @@ -108,9 +109,10 @@ class VoteMainPage extends HookConsumerWidget { .where((element) => element.section.id == l.id) .toList())); } - for (final l in list) { - logosNotifier.getLogo(l.id).then((value) => - contenderLogosNotifier.setTData(l, AsyncValue.data([value]))); + for (final contender in list) { + logosNotifier.getLogo(contender.id).then((value) => + contenderLogosNotifier.setTData( + contender.id, AsyncValue.data([value]))); } }); }, From e73f6c0288cc1768dcf4c2c6ac54312bc6998015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 22:52:54 +0100 Subject: [PATCH 10/16] fix: update tests --- test/cinema/session_poster_provider_test.dart | 8 +++++++- test/vote/pretendance_logo_provider_test.dart | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/test/cinema/session_poster_provider_test.dart b/test/cinema/session_poster_provider_test.dart index a0bdd0e97..8e2d09e51 100644 --- a/test/cinema/session_poster_provider_test.dart +++ b/test/cinema/session_poster_provider_test.dart @@ -3,6 +3,7 @@ import 'dart:typed_data'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:myecl/cinema/providers/session_poster_map_provider.dart'; import 'package:myecl/cinema/providers/session_poster_provider.dart'; import 'package:myecl/cinema/repositories/session_poster_repository.dart'; import 'package:mocktail/mocktail.dart'; @@ -10,14 +11,19 @@ import 'package:mocktail/mocktail.dart'; class MockSessionPosterRepository extends Mock implements SessionPosterRepository {} +class MockSessionLogoNotifier extends Mock implements SessionLogoNotifier {} + void main() { group('SessionPosterProvider', () { late SessionPosterRepository repository; late SessionPosterProvider provider; + late SessionLogoNotifier notifier; setUp(() { repository = MockSessionPosterRepository(); - provider = SessionPosterProvider(repository: repository); + notifier = MockSessionLogoNotifier(); + provider = SessionPosterProvider( + repository: repository, sessionLogoNotifier: notifier); }); test('initial state is loading', () { diff --git a/test/vote/pretendance_logo_provider_test.dart b/test/vote/pretendance_logo_provider_test.dart index ee46e97ff..0d591897c 100644 --- a/test/vote/pretendance_logo_provider_test.dart +++ b/test/vote/pretendance_logo_provider_test.dart @@ -5,18 +5,24 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:myecl/vote/providers/contender_logo_provider.dart'; +import 'package:myecl/vote/providers/contender_logos_provider.dart'; import 'package:myecl/vote/repositories/contender_logo_repository.dart'; class MockContenderLogoRepository extends Mock implements ContenderLogoRepository {} +class MockContenderLogoNotifier extends Mock implements ContenderLogoNotifier {} + void main() { late ContenderLogoRepository repository; + late ContenderLogoNotifier notifier; late ContenderLogoProvider provider; setUp(() { repository = MockContenderLogoRepository(); - provider = ContenderLogoProvider(contenderLogoRepository: repository); + notifier = MockContenderLogoNotifier(); + provider = ContenderLogoProvider( + contenderLogoRepository: repository, contenderLogosNotifier: notifier); }); group('ContenderLogoProvider', () { From 140b5b94e8c30858e966d4c40b48db5421088c84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Fri, 1 Mar 2024 22:53:52 +0100 Subject: [PATCH 11/16] fix: missing ids --- .../ui/pages/creation_edit_page/creation_edit_page.dart | 4 ++-- lib/vote/ui/pages/contender_pages/add_edit_contender.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart b/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart index 9f46c732d..88d07edbb 100644 --- a/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart +++ b/lib/raffle/ui/pages/creation_edit_page/creation_edit_page.dart @@ -57,8 +57,8 @@ class CreationPage extends HookConsumerWidget { final logoFile = useState(null); final tombolaLogos = ref.watch(tombolaLogosProvider); - if (tombolaLogos[raffle] != null) { - tombolaLogos[raffle]!.whenData((data) { + if (tombolaLogos[raffle.id] != null) { + tombolaLogos[raffle.id]!.whenData((data) { if (data.isNotEmpty) { logoFile.value = data.first; } diff --git a/lib/vote/ui/pages/contender_pages/add_edit_contender.dart b/lib/vote/ui/pages/contender_pages/add_edit_contender.dart index 88cd9842a..1925e429f 100644 --- a/lib/vote/ui/pages/contender_pages/add_edit_contender.dart +++ b/lib/vote/ui/pages/contender_pages/add_edit_contender.dart @@ -61,8 +61,8 @@ class AddEditContenderPage extends HookConsumerWidget { final showNotifier = ref.read(displayResult.notifier); final contenderLogos = ref.watch(contenderLogosProvider); - if (contenderLogos[contender] != null) { - contenderLogos[contender]!.whenData((data) { + if (contenderLogos[contender.id] != null) { + contenderLogos[contender.id]!.whenData((data) { if (data.isNotEmpty) { logoFile.value = data.first; } From 52215e12d1b592bd305b3a77912f10c18dcd9e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Sat, 2 Mar 2024 08:48:07 +0100 Subject: [PATCH 12/16] optimisation: change widgets order to benefit lazy widgets loading offer by ColumnRefresher --- lib/advert/ui/pages/main_page/main_page.dart | 123 +++++++++---------- 1 file changed, 60 insertions(+), 63 deletions(-) diff --git a/lib/advert/ui/pages/main_page/main_page.dart b/lib/advert/ui/pages/main_page/main_page.dart index 5e89ee927..dce0d07f9 100644 --- a/lib/advert/ui/pages/main_page/main_page.dart +++ b/lib/advert/ui/pages/main_page/main_page.dart @@ -33,72 +33,69 @@ class AdvertMainPage extends HookConsumerWidget { return AdvertTemplate( child: Stack( children: [ - ColumnRefresher( - onRefresh: () async { - await advertListNotifier.loadAdverts(); - advertPostersNotifier.resetTData(); - }, - children: [ - SizedBox( - width: 300, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, + AsyncChild( + value: advertList, + builder: (context, advertData) { + final sortedAdvertData = + advertData.sortedBy((element) => element.date).reversed; + final filteredSortedAdvertData = sortedAdvertData.where( + (advert) => + selected + .where((e) => advert.announcer.name == e.name) + .isNotEmpty || + selected.isEmpty); + return ColumnRefresher( + onRefresh: () async { + await advertListNotifier.loadAdverts(); + advertPostersNotifier.resetTData(); + }, children: [ - if (isAdvertAdmin) - AdminButton( - onTap: () { - selectedNotifier.clearAnnouncer(); - QR.to(AdvertRouter.root + AdvertRouter.admin); - }, - ), - if (isAdmin) - AdminButton( - onTap: () { - QR.to(AdvertRouter.root + - AdvertRouter.addRemAnnouncer); - }, - text: AdvertTextConstants.management), - ], - ), - ), - const SizedBox( - height: 20, - ), - const AnnouncerBar( - useUserAnnouncers: false, multipleSelect: true), - const SizedBox( - height: 20, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 30), - child: AsyncChild( - value: advertList, - builder: (context, advertData) { - final sortedAdvertData = advertData - .sortedBy((element) => element.date) - .reversed; - final filteredSortedAdvertData = sortedAdvertData.where( - (advert) => - selected - .where((e) => advert.announcer.name == e.name) - .isNotEmpty || - selected.isEmpty); - return Column(children: [ - ...filteredSortedAdvertData.map( - (advert) => AdvertCard( + SizedBox( + width: 300, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + if (isAdvertAdmin) + AdminButton( onTap: () { - advertNotifier.setAdvert(advert); - QR.to(AdvertRouter.root + AdvertRouter.detail); + selectedNotifier.clearAnnouncer(); + QR.to(AdvertRouter.root + AdvertRouter.admin); }, - advert: advert), - ), - ]); - }, - )), - const SizedBox( - height: 20, - ), - ], + ), + if (isAdmin) + AdminButton( + onTap: () { + QR.to(AdvertRouter.root + + AdvertRouter.addRemAnnouncer); + }, + text: AdvertTextConstants.management), + ], + ), + ), + const SizedBox( + height: 20, + ), + const AnnouncerBar( + useUserAnnouncers: false, multipleSelect: true), + const SizedBox( + height: 20, + ), + ...filteredSortedAdvertData.map( + (advert) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 30), + child: AdvertCard( + onTap: () { + advertNotifier.setAdvert(advert); + QR.to(AdvertRouter.root + AdvertRouter.detail); + }, + advert: advert), + ), + ), + ], + ); + }), + const SizedBox( + height: 20, ), ], ), From b31a1364d1af4baadb9929e4f8b97039e10976ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Sat, 2 Mar 2024 09:11:21 +0100 Subject: [PATCH 13/16] fix: shows advert card without having to load image --- lib/advert/ui/components/advert_card.dart | 428 +++++++++--------- .../ui/pages/admin_page/admin_page.dart | 184 ++++---- 2 files changed, 312 insertions(+), 300 deletions(-) diff --git a/lib/advert/ui/components/advert_card.dart b/lib/advert/ui/components/advert_card.dart index 5c89131c6..1f5ea7b10 100644 --- a/lib/advert/ui/components/advert_card.dart +++ b/lib/advert/ui/components/advert_card.dart @@ -38,103 +38,115 @@ class AdvertCard extends HookConsumerWidget { child: Container( margin: const EdgeInsets.all(10), padding: EdgeInsets.all(isWebFormat ? 50 : 0), - child: AutoLoaderChild( - group: posters, - notifier: advertPostersNotifier, - mapKey: advert.id, - loader: (advertId) => posterNotifier.getAdvertPoster(advertId), - loadingBuilder: (context) => HeroIcon( - HeroIcons.photo, - size: width, - ), - dataBuilder: (context, value) => isWebFormat - ? Container( - height: maxHeight, - width: double.infinity, - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(30), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - ClipRRect( - borderRadius: BorderRadius.circular(30), - child: AspectRatio( - aspectRatio: 2 / 3, - child: Image( + child: isWebFormat + ? Container( + height: maxHeight, + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(30), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(30), + child: AspectRatio( + aspectRatio: 2 / 3, + child: AutoLoaderChild( + group: posters, + notifier: advertPostersNotifier, + mapKey: advert.id, + loader: (advertId) => + posterNotifier.getAdvertPoster(advertId), + loadingBuilder: (context) => HeroIcon( + HeroIcons.photo, + size: width, + ), + dataBuilder: (context, value) => Image( image: value.first.image, fit: BoxFit.cover, // use this ), ), ), - const SizedBox( - width: 50, - ), - Expanded( - child: Column( - children: [ - AutoSizeText( - advert.title, - maxLines: 2, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox( - height: 10, - ), - AutoSizeText( - formatDate(advert.date), - maxLines: 1, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 16, - ), + ), + const SizedBox( + width: 50, + ), + Expanded( + child: Column( + children: [ + AutoSizeText( + advert.title, + maxLines: 2, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.bold, ), - const SizedBox( - height: 10, + ), + const SizedBox( + height: 10, + ), + AutoSizeText( + formatDate(advert.date), + maxLines: 1, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 16, ), - Expanded( - child: SingleChildScrollView( - child: TextWithHyperLink(advert.content, - textAlign: TextAlign.center, - style: const TextStyle( - fontSize: 16, - )), - ), + ), + const SizedBox( + height: 10, + ), + Expanded( + child: SingleChildScrollView( + child: TextWithHyperLink(advert.content, + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 16, + )), ), - ], - ), - ), - const SizedBox( - width: 50, + ), + ], ), - ], - ), - ) - : Container( - margin: const EdgeInsets.symmetric(vertical: 10), - width: width, - height: height, - decoration: BoxDecoration( - color: Colors.white, - boxShadow: const [ - BoxShadow( - blurRadius: 5, - color: Color(0x33000000), - offset: Offset(2, 2), - spreadRadius: 3, - ) - ], - borderRadius: BorderRadius.circular(20), - ), - child: Stack( - children: [ - Column(children: [ - Container( + ), + const SizedBox( + width: 50, + ), + ], + ), + ) + : Container( + margin: const EdgeInsets.symmetric(vertical: 10), + width: width, + height: height, + decoration: BoxDecoration( + color: Colors.white, + boxShadow: const [ + BoxShadow( + blurRadius: 5, + color: Color(0x33000000), + offset: Offset(2, 2), + spreadRadius: 3, + ) + ], + borderRadius: BorderRadius.circular(20), + ), + child: Stack( + children: [ + Column(children: [ + AutoLoaderChild( + group: posters, + notifier: advertPostersNotifier, + mapKey: advert.id, + loader: (advertId) => + posterNotifier.getAdvertPoster(advertId), + loadingBuilder: (context) => HeroIcon( + HeroIcons.photo, + size: width, + ), + dataBuilder: (context, value) => Container( width: width, height: imageHeight, decoration: BoxDecoration( @@ -147,147 +159,147 @@ class AdvertCard extends HookConsumerWidget { ), ), ), - Container( - padding: const EdgeInsets.only( - top: 20, left: 10, right: 10), - width: width, - height: height - imageHeight, - child: Column( - children: [ - Column( - children: [ - Container( - width: width, - margin: const EdgeInsets.only(bottom: 5), - child: AutoSizeText( - advert.title.trim(), - textAlign: TextAlign.left, - overflow: TextOverflow.ellipsis, - maxLines: 1, - minFontSize: 15, - style: const TextStyle( - color: Colors.black, - fontSize: 16, - fontWeight: FontWeight.bold, - ), + ), + Container( + padding: + const EdgeInsets.only(top: 20, left: 10, right: 10), + width: width, + height: height - imageHeight, + child: Column( + children: [ + Column( + children: [ + Container( + width: width, + margin: const EdgeInsets.only(bottom: 5), + child: AutoSizeText( + advert.title.trim(), + textAlign: TextAlign.left, + overflow: TextOverflow.ellipsis, + maxLines: 1, + minFontSize: 15, + style: const TextStyle( + color: Colors.black, + fontSize: 16, + fontWeight: FontWeight.bold, ), ), - ], - ), - TextWithHyperLink( - advert.content.trim(), - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.justify, - maxLines: 3, - minFontSize: 13, - maxFontSize: 15, - style: const TextStyle( - color: Colors.black, - fontSize: 15, ), + ], + ), + TextWithHyperLink( + advert.content.trim(), + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.justify, + maxLines: 3, + minFontSize: 13, + maxFontSize: 15, + style: const TextStyle( + color: Colors.black, + fontSize: 15, ), - ], - ), + ), + ], ), - ]), - Positioned( - top: imageHeight - 40, - left: 15, - child: Container( - decoration: BoxDecoration( - borderRadius: - const BorderRadius.all(Radius.circular(8)), - boxShadow: [ - BoxShadow( - blurRadius: 5, - color: Colors.black.withOpacity(0.3), - offset: const Offset(2, 2), - spreadRadius: 3, - ) - ]), - child: ClipRRect( + ), + ]), + Positioned( + top: imageHeight - 40, + left: 15, + child: Container( + decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(8)), - child: Container( - color: Colors.white, - height: 50, - width: 50, - padding: const EdgeInsets.symmetric( - horizontal: 5, vertical: 5), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - AutoSizeText( - DateFormat('dd').format(advert.date), - textAlign: TextAlign.center, - style: const TextStyle( - color: Colors.black, - fontSize: 22, - fontWeight: FontWeight.bold, - height: 1.0, - ), + boxShadow: [ + BoxShadow( + blurRadius: 5, + color: Colors.black.withOpacity(0.3), + offset: const Offset(2, 2), + spreadRadius: 3, + ) + ]), + child: ClipRRect( + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: Container( + color: Colors.white, + height: 50, + width: 50, + padding: const EdgeInsets.symmetric( + horizontal: 5, vertical: 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AutoSizeText( + DateFormat('dd').format(advert.date), + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.black, + fontSize: 22, + fontWeight: FontWeight.bold, + height: 1.0, ), - AutoSizeText( - AdvertTextConstants.months[int.parse( - DateFormat('MM') - .format(advert.date)) - - 1], - textAlign: TextAlign.center, - style: const TextStyle( - color: Colors.black, - fontSize: 11, - fontWeight: FontWeight.bold, - height: 1.0, - ), + ), + AutoSizeText( + AdvertTextConstants.months[int.parse( + DateFormat('MM') + .format(advert.date)) - + 1], + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.black, + fontSize: 11, + fontWeight: FontWeight.bold, + height: 1.0, ), - ], - ), + ), + ], ), ), ), ), - Positioned( - top: imageHeight - 20, - right: 15, - child: Container( - decoration: BoxDecoration( - borderRadius: - const BorderRadius.all(Radius.circular(8)), - boxShadow: [ - BoxShadow( - blurRadius: 5, - color: Colors.black.withOpacity(0.3), - offset: const Offset(2, 2), - spreadRadius: 3, - ) - ]), - child: ClipRRect( + ), + Positioned( + top: imageHeight - 20, + right: 15, + child: Container( + decoration: BoxDecoration( borderRadius: const BorderRadius.all(Radius.circular(8)), - child: Container( - color: Colors.white, - height: 30, - padding: const EdgeInsets.symmetric( - vertical: 5, horizontal: 10), - alignment: Alignment.center, - child: AutoSizeText( - advert.announcer.name, - textAlign: TextAlign.center, - style: const TextStyle( - color: Colors.black, - fontSize: 14, - fontWeight: FontWeight.bold, - ), + boxShadow: [ + BoxShadow( + blurRadius: 5, + color: Colors.black.withOpacity(0.3), + offset: const Offset(2, 2), + spreadRadius: 3, + ) + ]), + child: ClipRRect( + borderRadius: + const BorderRadius.all(Radius.circular(8)), + child: Container( + color: Colors.white, + height: 30, + padding: const EdgeInsets.symmetric( + vertical: 5, horizontal: 10), + alignment: Alignment.center, + child: AutoSizeText( + advert.announcer.name, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.black, + fontSize: 14, + fontWeight: FontWeight.bold, ), ), ), ), ), - ], - ), + ), + ], ), - ), + ), ), ); } diff --git a/lib/advert/ui/pages/admin_page/admin_page.dart b/lib/advert/ui/pages/admin_page/admin_page.dart index 94c298b8f..537bd6f4d 100644 --- a/lib/advert/ui/pages/admin_page/admin_page.dart +++ b/lib/advert/ui/pages/admin_page/admin_page.dart @@ -35,98 +35,98 @@ class AdvertAdminPage extends HookConsumerWidget { final selectedAnnouncersNotifier = ref.read(announcerProvider.notifier); return AdvertTemplate( child: AsyncChild( - value: advertList, - builder: (context, advertData) => AsyncChild( - value: userAnnouncerList, - builder: (context, userAnnouncerData) { - final userAnnouncerAdvert = advertData.where((advert) => - userAnnouncerData - .where((element) => advert.announcer.id == element.id) - .isNotEmpty); - final sortedUserAnnouncerAdverts = userAnnouncerAdvert - .toList() - .sortedBy((element) => element.date) - .reversed; - final filteredSortedUserAnnouncerAdverts = - sortedUserAnnouncerAdverts - .where((advert) => - selectedAnnouncers - .where((e) => advert.announcer.id == e.id) - .isNotEmpty || - selectedAnnouncers.isEmpty) - .toList(); - return ColumnRefresher( - onRefresh: () async { - await advertListNotifier.loadAdverts(); - await userAnnouncerListNotifier.loadMyAnnouncerList(); - advertPostersNotifier.resetTData(); - }, - children: [ - const AnnouncerBar( - useUserAnnouncers: true, - multipleSelect: true, - ), - GestureDetector( - onTap: () { - advertNotifier.setAdvert(Advert.empty()); - QR.to(AdvertRouter.root + - AdvertRouter.admin + - AdvertRouter.addEditAdvert); - }, - child: CardLayout( - margin: const EdgeInsets.only( - bottom: 10, top: 20, left: 30, right: 30), - width: 300, - height: 100, - colors: [ - Colors.white, - Colors.grey.shade100, - ], - shadowColor: Colors.grey.withOpacity(0.2), - child: Center( - child: HeroIcon( - HeroIcons.plus, - size: 40, - color: Colors.grey.shade500, - ))), - ), - ...filteredSortedUserAnnouncerAdverts.map( - (advert) => AdminAdvertCard( - onTap: () { - advertNotifier.setAdvert(advert); - QR.to(AdvertRouter.root + AdvertRouter.detail); - }, - onEdit: () { - QR.to(AdvertRouter.root + - AdvertRouter.admin + - AdvertRouter.addEditAdvert); - advertNotifier.setAdvert(advert); - selectedAnnouncersNotifier.clearAnnouncer(); - selectedAnnouncersNotifier - .addAnnouncer(advert.announcer); - }, - onDelete: () async { - await showDialog( - context: context, - builder: (context) { - return CustomDialogBox( - title: AdvertTextConstants.deleting, - descriptions: - AdvertTextConstants.deleteAdvert, - onYes: () { - advertListNotifier.deleteAdvert(advert); - advertPostersNotifier.deleteE( - advert.id, 0); - }, - ); - }); - }, - advert: advert), - ), - ], - ); - }, - )), + value: advertList, + builder: (context, advertData) => AsyncChild( + value: userAnnouncerList, + builder: (context, userAnnouncerData) { + final userAnnouncerAdvert = advertData.where((advert) => + userAnnouncerData + .where((element) => advert.announcer.id == element.id) + .isNotEmpty); + final sortedUserAnnouncerAdverts = userAnnouncerAdvert + .toList() + .sortedBy((element) => element.date) + .reversed; + final filteredSortedUserAnnouncerAdverts = + sortedUserAnnouncerAdverts + .where((advert) => + selectedAnnouncers + .where((e) => advert.announcer.id == e.id) + .isNotEmpty || + selectedAnnouncers.isEmpty) + .toList(); + return ColumnRefresher( + onRefresh: () async { + await advertListNotifier.loadAdverts(); + await userAnnouncerListNotifier.loadMyAnnouncerList(); + advertPostersNotifier.resetTData(); + }, + children: [ + const AnnouncerBar( + useUserAnnouncers: true, + multipleSelect: true, + ), + GestureDetector( + onTap: () { + advertNotifier.setAdvert(Advert.empty()); + QR.to(AdvertRouter.root + + AdvertRouter.admin + + AdvertRouter.addEditAdvert); + }, + child: CardLayout( + margin: const EdgeInsets.only( + bottom: 10, top: 20, left: 30, right: 30), + width: 300, + height: 100, + colors: [ + Colors.white, + Colors.grey.shade100, + ], + shadowColor: Colors.grey.withOpacity(0.2), + child: Center( + child: HeroIcon( + HeroIcons.plus, + size: 40, + color: Colors.grey.shade500, + ))), + ), + ...filteredSortedUserAnnouncerAdverts.map( + (advert) => AdminAdvertCard( + onTap: () { + advertNotifier.setAdvert(advert); + QR.to(AdvertRouter.root + AdvertRouter.detail); + }, + onEdit: () { + QR.to(AdvertRouter.root + + AdvertRouter.admin + + AdvertRouter.addEditAdvert); + advertNotifier.setAdvert(advert); + selectedAnnouncersNotifier.clearAnnouncer(); + selectedAnnouncersNotifier + .addAnnouncer(advert.announcer); + }, + onDelete: () async { + await showDialog( + context: context, + builder: (context) { + return CustomDialogBox( + title: AdvertTextConstants.deleting, + descriptions: AdvertTextConstants.deleteAdvert, + onYes: () { + advertListNotifier.deleteAdvert(advert); + advertPostersNotifier.deleteE(advert.id, 0); + }, + ); + }, + ); + }, + advert: advert), + ), + ], + ); + }, + ), + ), ); } } From 7bfc92c16c9a05a4c61c84d5666f30df87f9e031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Sat, 2 Mar 2024 10:13:32 +0100 Subject: [PATCH 14/16] advert: improve code quality --- lib/advert/providers/advert_poster_provider.dart | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/advert/providers/advert_poster_provider.dart b/lib/advert/providers/advert_poster_provider.dart index f72ec0a31..99c04855d 100644 --- a/lib/advert/providers/advert_poster_provider.dart +++ b/lib/advert/providers/advert_poster_provider.dart @@ -18,20 +18,16 @@ class AdvertPosterNotifier extends SingleNotifier { } Future getAdvertPoster(String id) async { - return await advertPosterRepository.getAdvertPoster(id).then((image) { - advertPostersNotifier.setTData(id, AsyncData([image])); - return image; - }); + final image = await advertPosterRepository.getAdvertPoster(id); + advertPostersNotifier.setTData(id, AsyncData([image])); + return image; } Future updateAdvertPoster(String id, Uint8List bytes) async { advertPostersNotifier.setTData(id, const AsyncLoading()); - return await advertPosterRepository - .addAdvertPoster(bytes, id) - .then((image) { - advertPostersNotifier.setTData(id, AsyncData([image])); - return image; - }); + final image = await advertPosterRepository.addAdvertPoster(bytes, id); + advertPostersNotifier.setTData(id, AsyncData([image])); + return image; } } From 6ad395d5e57fa0e9345ba38d6981ba7dce925268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Sat, 2 Mar 2024 10:20:33 +0100 Subject: [PATCH 15/16] optimization: Improve code quality cinema/tombola/vote --- .../providers/session_poster_provider.dart | 14 +++++------ .../providers/tombola_logo_provider.dart | 24 ++++++++----------- .../providers/contender_logo_provider.dart | 9 +++---- 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/lib/cinema/providers/session_poster_provider.dart b/lib/cinema/providers/session_poster_provider.dart index e9147e6c7..38c4d3fcb 100644 --- a/lib/cinema/providers/session_poster_provider.dart +++ b/lib/cinema/providers/session_poster_provider.dart @@ -14,17 +14,15 @@ class SessionPosterProvider extends SingleNotifier { : super(const AsyncValue.loading()); Future getLogo(String id) async { - return await repository.getSessionLogo(id).then((image) { - sessionLogoNotifier.setTData(id, AsyncData([image])); - return image; - }); + final image = await repository.getSessionLogo(id); + sessionLogoNotifier.setTData(id, AsyncData([image])); + return image; } Future updateLogo(String id, Uint8List bytes) async { - return await repository.addSessionLogo(bytes, id).then((image) { - sessionLogoNotifier.setTData(id, AsyncData([image])); - return image; - }); + final image = await repository.addSessionLogo(bytes, id); + sessionLogoNotifier.setTData(id, AsyncData([image])); + return image; } } diff --git a/lib/raffle/providers/tombola_logo_provider.dart b/lib/raffle/providers/tombola_logo_provider.dart index bb18023b6..33300379e 100644 --- a/lib/raffle/providers/tombola_logo_provider.dart +++ b/lib/raffle/providers/tombola_logo_provider.dart @@ -17,25 +17,21 @@ class TombolaLogoProvider extends SingleNotifier { } Future getLogo(String id) async { - Image logo = await repository.getTombolaLogo(id).then((image) { - tombolaLogosNotifier.setTData( - id, - AsyncData([image]), - ); - return image; - }); + Image logo = await repository.getTombolaLogo(id); + tombolaLogosNotifier.setTData( + id, + AsyncData([logo]), + ); state = AsyncValue.data(logo); return logo; } Future updateLogo(String id, Uint8List bytes) async { - Image logo = await repository.addTombolaLogo(bytes, id).then((image) { - tombolaLogosNotifier.setTData( - id, - AsyncData([image]), - ); - return image; - }); + Image logo = await repository.addTombolaLogo(bytes, id); + tombolaLogosNotifier.setTData( + id, + AsyncData([logo]), + ); state = AsyncValue.data(logo); return logo; } diff --git a/lib/vote/providers/contender_logo_provider.dart b/lib/vote/providers/contender_logo_provider.dart index d042810d2..43a95f638 100644 --- a/lib/vote/providers/contender_logo_provider.dart +++ b/lib/vote/providers/contender_logo_provider.dart @@ -22,12 +22,9 @@ class ContenderLogoProvider extends SingleNotifier { } Future updateLogo(String id, Uint8List bytes) async { - return await contenderLogoRepository - .addContenderLogo(bytes, id) - .then((image) { - contenderLogosNotifier.setTData(id, AsyncData([image])); - return image; - }); + final image = await contenderLogoRepository.addContenderLogo(bytes, id); + contenderLogosNotifier.setTData(id, AsyncData([image])); + return image; } } From 59446d3f54be2b36e7b5a667ee2de6659e96f154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sha=C3=AEhh?= Date: Sat, 2 Mar 2024 10:59:01 +0100 Subject: [PATCH 16/16] fix(advert): cards layout while image loading --- lib/advert/ui/components/advert_card.dart | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/advert/ui/components/advert_card.dart b/lib/advert/ui/components/advert_card.dart index 1f5ea7b10..fbeaaf50d 100644 --- a/lib/advert/ui/components/advert_card.dart +++ b/lib/advert/ui/components/advert_card.dart @@ -142,9 +142,17 @@ class AdvertCard extends HookConsumerWidget { mapKey: advert.id, loader: (advertId) => posterNotifier.getAdvertPoster(advertId), - loadingBuilder: (context) => HeroIcon( - HeroIcons.photo, - size: width, + loadingBuilder: (context) => Container( + width: width, + height: imageHeight, + decoration: const BoxDecoration( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20))), + child: HeroIcon( + HeroIcons.photo, + size: width, + ), ), dataBuilder: (context, value) => Container( width: width,