Change behavior of global state
Until now, FoodEntryBloc (which is holding the global state for every day) would cause a change in every widget in the tree. For example, when an entry for one day gets added, all other entries in opened days would also be rebuilt. Now, the GlobalState will be emitted with an additional date, which signals, which date caused the state change. With this information, I selectively only build the EntryLists that needs to be rebuilt. Additionally, the calendar FAB will push a new route instead of navigating to a new day by utilizing the pageController.
This commit is contained in:
parent
7126b1b593
commit
7728ec3b66
@ -27,7 +27,8 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
var newList = await storage.getEntriesForDate(event.forDate);
|
var newList = await storage.getEntriesForDate(event.forDate);
|
||||||
state.foodEntries.addAll({event.forDate: newList});
|
state.foodEntries.addAll({event.forDate: newList});
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: state.foodEntries));
|
emit(GlobalEntryState(
|
||||||
|
foodEntries: state.foodEntries, stateChangedForDate: event.forDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFoodEntryEvent(
|
void handleFoodEntryEvent(
|
||||||
@ -43,7 +44,8 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
var newFoodEntries = state.foodEntries;
|
var newFoodEntries = state.foodEntries;
|
||||||
newFoodEntries.addAll({event.forDate: entriesForDate});
|
newFoodEntries.addAll({event.forDate: entriesForDate});
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
emit(GlobalEntryState(
|
||||||
|
foodEntries: newFoodEntries, stateChangedForDate: event.forDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFoodChangedEvent(
|
void handleFoodChangedEvent(
|
||||||
@ -64,7 +66,8 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
var newFoodEntries = state.foodEntries;
|
var newFoodEntries = state.foodEntries;
|
||||||
newFoodEntries.addAll({event.forDate: entriesForDate});
|
newFoodEntries.addAll({event.forDate: entriesForDate});
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
emit(GlobalEntryState(
|
||||||
|
foodEntries: newFoodEntries, stateChangedForDate: event.forDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteFoodEvent(
|
void handleDeleteFoodEvent(
|
||||||
@ -79,7 +82,8 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
var newFoodEntries = state.foodEntries;
|
var newFoodEntries = state.foodEntries;
|
||||||
newFoodEntries.addAll({event.forDate: entriesForDate});
|
newFoodEntries.addAll({event.forDate: entriesForDate});
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
emit(GlobalEntryState(
|
||||||
|
foodEntries: newFoodEntries, stateChangedForDate: event.forDate));
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleBarcodeScannedEvent(
|
void handleBarcodeScannedEvent(
|
||||||
@ -91,6 +95,7 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
if (e.code == BarcodeScanner.cameraAccessDenied) {
|
if (e.code == BarcodeScanner.cameraAccessDenied) {
|
||||||
emit(GlobalEntryState(
|
emit(GlobalEntryState(
|
||||||
foodEntries: state.foodEntries,
|
foodEntries: state.foodEntries,
|
||||||
|
stateChangedForDate: event.forDate,
|
||||||
appError:
|
appError:
|
||||||
GlobalAppError(GlobalAppErrorType.errCameraPermissionDenied)));
|
GlobalAppError(GlobalAppErrorType.errCameraPermissionDenied)));
|
||||||
}
|
}
|
||||||
@ -107,6 +112,7 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
if (scanResult.type == ResultType.Error) {
|
if (scanResult.type == ResultType.Error) {
|
||||||
emit(GlobalEntryState(
|
emit(GlobalEntryState(
|
||||||
foodEntries: state.foodEntries,
|
foodEntries: state.foodEntries,
|
||||||
|
stateChangedForDate: event.forDate,
|
||||||
appError: GlobalAppError(GlobalAppErrorType.errGeneralError)));
|
appError: GlobalAppError(GlobalAppErrorType.errGeneralError)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -122,7 +128,10 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
|
|
||||||
entriesForDate.add(newEntryWaiting);
|
entriesForDate.add(newEntryWaiting);
|
||||||
state.foodEntries.addAll({event.forDate: entriesForDate});
|
state.foodEntries.addAll({event.forDate: entriesForDate});
|
||||||
emit(GlobalEntryState(foodEntries: state.foodEntries));
|
emit(GlobalEntryState(
|
||||||
|
foodEntries: state.foodEntries,
|
||||||
|
stateChangedForDate: event.forDate,
|
||||||
|
));
|
||||||
|
|
||||||
await responseFuture.then((response) async {
|
await responseFuture.then((response) async {
|
||||||
var index = entriesForDate
|
var index = entriesForDate
|
||||||
@ -140,6 +149,7 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
|
|
||||||
emit(GlobalEntryState(
|
emit(GlobalEntryState(
|
||||||
foodEntries: newFoodEntries,
|
foodEntries: newFoodEntries,
|
||||||
|
stateChangedForDate: event.forDate,
|
||||||
appError: GlobalAppError(GlobalAppErrorType.errbarcodeNotFound)));
|
appError: GlobalAppError(GlobalAppErrorType.errbarcodeNotFound)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -151,6 +161,7 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
|
|
||||||
emit(GlobalEntryState(
|
emit(GlobalEntryState(
|
||||||
foodEntries: newFoodEntries,
|
foodEntries: newFoodEntries,
|
||||||
|
stateChangedForDate: event.forDate,
|
||||||
appError:
|
appError:
|
||||||
GlobalAppError(GlobalAppErrorType.errServerNotReachable)));
|
GlobalAppError(GlobalAppErrorType.errServerNotReachable)));
|
||||||
return;
|
return;
|
||||||
@ -173,7 +184,8 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
var newFoodEntries = state.foodEntries;
|
var newFoodEntries = state.foodEntries;
|
||||||
newFoodEntries.addAll({event.forDate: entriesForDate});
|
newFoodEntries.addAll({event.forDate: entriesForDate});
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
emit(GlobalEntryState(
|
||||||
|
foodEntries: newFoodEntries, stateChangedForDate: event.forDate));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +206,8 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
|
|
||||||
selectedEntry.isSelected = !oldStateOfTappedEntry;
|
selectedEntry.isSelected = !oldStateOfTappedEntry;
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: state.foodEntries));
|
emit(GlobalEntryState(
|
||||||
|
foodEntries: state.foodEntries, stateChangedForDate: event.forDate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,12 +253,17 @@ class PermissionException extends FoodEvent {
|
|||||||
PermissionException({required super.forDate});
|
PermissionException({required super.forDate});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the state for one date/page
|
class PageEntryState {}
|
||||||
|
|
||||||
class GlobalEntryState {
|
class GlobalEntryState {
|
||||||
final Map<DateTime, List<FoodEntryState>> foodEntries;
|
final Map<DateTime, List<FoodEntryState>> foodEntries;
|
||||||
final GlobalAppError? appError;
|
final GlobalAppError? appError;
|
||||||
|
|
||||||
GlobalEntryState({required this.foodEntries, this.appError});
|
//we use this to only redraw pages whose entries changed
|
||||||
|
final DateTime? stateChangedForDate;
|
||||||
|
|
||||||
|
GlobalEntryState(
|
||||||
|
{required this.foodEntries, this.stateChangedForDate, this.appError});
|
||||||
|
|
||||||
factory GlobalEntryState.init() {
|
factory GlobalEntryState.init() {
|
||||||
return GlobalEntryState(foodEntries: {});
|
return GlobalEntryState(foodEntries: {});
|
||||||
|
@ -92,10 +92,9 @@ class PerDatePageViewController extends StatelessWidget {
|
|||||||
onDateSelected: (dateSelected) {
|
onDateSelected: (dateSelected) {
|
||||||
if (dateSelected == null) return;
|
if (dateSelected == null) return;
|
||||||
|
|
||||||
var dateDiff = dateSelected.difference(initialDate).inDays;
|
Navigator.of(context).push(MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
log("dateDiff = $dateDiff");
|
PerDatePageViewController(initialDate: dateSelected)));
|
||||||
pageController.jumpToPage(initialOffset - dateDiff);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -33,6 +33,11 @@ class _PerDateWidgetState extends State<PerDateWidget>
|
|||||||
showNewSnackbarWith(context, pageState.appError!);
|
showNewSnackbarWith(context, pageState.appError!);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
buildWhen: (previous, current) {
|
||||||
|
if (current.stateChangedForDate == null) return true;
|
||||||
|
if (current.stateChangedForDate == widget.date) return true;
|
||||||
|
return false;
|
||||||
|
},
|
||||||
builder: (context, pageState) {
|
builder: (context, pageState) {
|
||||||
return FoodEntryList(
|
return FoodEntryList(
|
||||||
entries: pageState.foodEntries[widget.date] ?? [],
|
entries: pageState.foodEntries[widget.date] ?? [],
|
||||||
|
Loading…
Reference in New Issue
Block a user