Compare commits
No commits in common. "master" and "swipeable-pages" have entirely different histories.
master
...
swipeable-
@ -4,96 +4,61 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:calorimeter/storage/storage.dart';
|
import 'package:calorimeter/storage/storage.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
class FoodEntryBloc extends Bloc<FoodEvent, PageState> {
|
||||||
final GlobalEntryState initialState;
|
final PageState initialState;
|
||||||
final FoodStorage storage;
|
final FoodStorage storage;
|
||||||
|
final DateTime forDate;
|
||||||
|
|
||||||
FoodEntryBloc({required this.initialState, required this.storage})
|
FoodEntryBloc(
|
||||||
|
{required this.initialState,
|
||||||
|
required this.forDate,
|
||||||
|
required this.storage})
|
||||||
: super(initialState) {
|
: super(initialState) {
|
||||||
on<PageBeingInitialized>(handlePageBeingInitialized);
|
|
||||||
on<FoodEntryEvent>(handleFoodEntryEvent);
|
on<FoodEntryEvent>(handleFoodEntryEvent);
|
||||||
on<FoodChangedEvent>(handleFoodChangedEvent);
|
on<FoodChangedEvent>(handleFoodChangedEvent);
|
||||||
on<FoodDeletionEvent>(handleDeleteFoodEvent);
|
on<FoodDeletionEvent>(handleDeleteFoodEvent);
|
||||||
on<BarcodeScanned>(handleBarcodeScannedEvent);
|
on<BarcodeScanned>(handleBarcodeScannedEvent);
|
||||||
on<FoodEntryTapped>(handleFoodEntryTapped);
|
on<FoodEntryTapped>(handleFoodEntryTapped);
|
||||||
}
|
}
|
||||||
void handlePageBeingInitialized(
|
|
||||||
PageBeingInitialized event, Emitter<GlobalEntryState> emit) async {
|
|
||||||
var newList = await storage.getEntriesForDate(event.forDate);
|
|
||||||
state.foodEntries.addAll({event.forDate: newList});
|
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: state.foodEntries));
|
|
||||||
}
|
|
||||||
|
|
||||||
void handleFoodEntryEvent(
|
void handleFoodEntryEvent(
|
||||||
FoodEntryEvent event, Emitter<GlobalEntryState> emit) async {
|
FoodEntryEvent event, Emitter<PageState> emit) async {
|
||||||
var entriesForDate = state.foodEntries[event.forDate];
|
PageState newState = PageState.from(state);
|
||||||
entriesForDate ??= [];
|
newState.addEntry(event.entry);
|
||||||
|
|
||||||
entriesForDate.add(event.entry);
|
await storage.writeEntriesForDate(forDate, newState.foodEntries);
|
||||||
|
|
||||||
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
|
||||||
storage.addFoodEntryToLookupDatabase(event.entry);
|
storage.addFoodEntryToLookupDatabase(event.entry);
|
||||||
|
|
||||||
// this is just checking if writing to the database worked
|
emit(newState);
|
||||||
// can be optimized out by just emitting newState
|
|
||||||
var newList = await storage.getEntriesForDate(event.forDate);
|
|
||||||
|
|
||||||
var newFoodEntries = state.foodEntries;
|
|
||||||
newFoodEntries.addAll({event.forDate: newList});
|
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFoodChangedEvent(
|
void handleFoodChangedEvent(
|
||||||
FoodChangedEvent event, Emitter<GlobalEntryState> emit) async {
|
FoodChangedEvent event, Emitter<PageState> emit) async {
|
||||||
var entriesForDate = state.foodEntries[event.forDate];
|
var entries = state.foodEntries;
|
||||||
if (entriesForDate == null) return;
|
var index = entries.indexWhere((entry) {
|
||||||
|
|
||||||
var index = entriesForDate.indexWhere((entry) {
|
|
||||||
return entry.id == event.newEntry.id;
|
return entry.id == event.newEntry.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
entriesForDate.removeAt(index);
|
entries.removeAt(index);
|
||||||
entriesForDate.insert(index, event.newEntry);
|
entries.insert(index, event.newEntry);
|
||||||
|
|
||||||
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
await storage.writeEntriesForDate(forDate, entries);
|
||||||
storage.addFoodEntryToLookupDatabase(event.newEntry);
|
storage.addFoodEntryToLookupDatabase(event.newEntry);
|
||||||
|
|
||||||
// this is just checking if writing to the database worked
|
emit(PageState(foodEntries: entries));
|
||||||
// can be optimized out by just emitting newState
|
|
||||||
var newList = await storage.getEntriesForDate(event.forDate);
|
|
||||||
|
|
||||||
var newFoodEntries = state.foodEntries;
|
|
||||||
newFoodEntries.addAll({event.forDate: newList});
|
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteFoodEvent(
|
void handleDeleteFoodEvent(
|
||||||
FoodDeletionEvent event, Emitter<GlobalEntryState> emit) async {
|
FoodDeletionEvent event, Emitter<PageState> emit) async {
|
||||||
var entriesForDate = state.foodEntries[event.forDate];
|
state.foodEntries.removeWhere((entry) => entry.id == event.entryID);
|
||||||
if (entriesForDate == null) return;
|
|
||||||
|
|
||||||
entriesForDate.removeWhere((entry) => entry.id == event.entryID);
|
await storage.writeEntriesForDate(forDate, state.foodEntries);
|
||||||
|
|
||||||
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
emit(PageState.from(state));
|
||||||
|
|
||||||
// this is just checking if writing to the database worked
|
|
||||||
// can be optimized out by just emitting newState
|
|
||||||
var newList = await storage.getEntriesForDate(event.forDate);
|
|
||||||
|
|
||||||
var newFoodEntries = state.foodEntries;
|
|
||||||
newFoodEntries.addAll({event.forDate: newList});
|
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleBarcodeScannedEvent(
|
void handleBarcodeScannedEvent(
|
||||||
BarcodeScanned event, Emitter<GlobalEntryState> emit) async {
|
BarcodeScanned event, Emitter<PageState> emit) async {
|
||||||
var entriesForDate = state.foodEntries[event.forDate];
|
|
||||||
if (entriesForDate == null) return;
|
|
||||||
|
|
||||||
var client = FoodFactLookupClient();
|
var client = FoodFactLookupClient();
|
||||||
var scanResult = await event.scanResultFuture;
|
var scanResult = await event.scanResultFuture;
|
||||||
|
|
||||||
@ -101,13 +66,14 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (scanResult.type == ResultType.Error) {
|
if (scanResult.type == ResultType.Error) {
|
||||||
emit(GlobalEntryState(
|
emit(PageState(
|
||||||
foodEntries: state.foodEntries,
|
foodEntries: state.foodEntries,
|
||||||
errorString: "Fehler beim Scannen des Barcodes"));
|
errorString: "Fehler beim Scannen des Barcodes"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var responseFuture = client.retrieveFoodInfo(scanResult.rawContent);
|
var responseFuture = client.retrieveFoodInfo(scanResult.rawContent);
|
||||||
|
|
||||||
|
List<FoodEntryState> newList = List.from(state.foodEntries);
|
||||||
var newEntryWaiting = FoodEntryState(
|
var newEntryWaiting = FoodEntryState(
|
||||||
kcalPer100: 0,
|
kcalPer100: 0,
|
||||||
name: "",
|
name: "",
|
||||||
@ -115,13 +81,11 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
waitingForNetwork: true,
|
waitingForNetwork: true,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
);
|
);
|
||||||
entriesForDate.add(newEntryWaiting);
|
newList.add(newEntryWaiting);
|
||||||
var newFoodEntries = state.foodEntries;
|
emit(PageState(foodEntries: newList));
|
||||||
newFoodEntries.addAll({event.forDate: entriesForDate});
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
|
||||||
|
|
||||||
await responseFuture.then((response) async {
|
await responseFuture.then((response) async {
|
||||||
var index = entriesForDate
|
var index = newList
|
||||||
.indexWhere((entryState) => entryState.id == newEntryWaiting.id);
|
.indexWhere((entryState) => entryState.id == newEntryWaiting.id);
|
||||||
|
|
||||||
// element not found (was deleted previously)
|
// element not found (was deleted previously)
|
||||||
@ -130,23 +94,25 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (response.status == FoodFactResponseStatus.barcodeNotFound) {
|
if (response.status == FoodFactResponseStatus.barcodeNotFound) {
|
||||||
entriesForDate.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
List<FoodEntryState> listWithEntryRemoved =
|
||||||
var newFoodEntries = state.foodEntries;
|
List.from(state.foodEntries);
|
||||||
newFoodEntries.addAll({event.forDate: entriesForDate});
|
listWithEntryRemoved
|
||||||
|
.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
||||||
|
|
||||||
emit(GlobalEntryState(
|
emit(PageState(
|
||||||
foodEntries: newFoodEntries,
|
foodEntries: listWithEntryRemoved,
|
||||||
errorString: "Barcode konnte nicht gefunden werden."));
|
errorString: "Barcode konnte nicht gefunden werden."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (response.status ==
|
if (response.status ==
|
||||||
FoodFactResponseStatus.foodFactServerNotReachable) {
|
FoodFactResponseStatus.foodFactServerNotReachable) {
|
||||||
entriesForDate.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
List<FoodEntryState> listWithEntryRemoved =
|
||||||
var newFoodEntries = state.foodEntries;
|
List.from(state.foodEntries);
|
||||||
newFoodEntries.addAll({event.forDate: entriesForDate});
|
listWithEntryRemoved
|
||||||
|
.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
||||||
|
|
||||||
emit(GlobalEntryState(
|
emit(PageState(
|
||||||
foodEntries: newFoodEntries,
|
foodEntries: listWithEntryRemoved,
|
||||||
errorString: "OpenFoodFacts-Server konnte nicht erreicht werden."));
|
errorString: "OpenFoodFacts-Server konnte nicht erreicht werden."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -159,114 +125,91 @@ class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
|||||||
isSelected: false,
|
isSelected: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
entriesForDate.removeAt(index);
|
newList.removeAt(index);
|
||||||
entriesForDate.insert(index, newEntryFinishedWaiting);
|
newList.insert(index, newEntryFinishedWaiting);
|
||||||
|
|
||||||
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
await storage.writeEntriesForDate(forDate, newList);
|
||||||
storage.addFoodEntryToLookupDatabase(newEntryFinishedWaiting);
|
storage.addFoodEntryToLookupDatabase(newEntryFinishedWaiting);
|
||||||
|
|
||||||
var entriesFromStorage = await storage.getEntriesForDate(event.forDate);
|
emit(PageState(foodEntries: newList));
|
||||||
var newFoodEntries = state.foodEntries;
|
|
||||||
newFoodEntries.addAll({event.forDate: entriesFromStorage});
|
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFoodEntryTapped(
|
void handleFoodEntryTapped(
|
||||||
FoodEntryTapped event, Emitter<GlobalEntryState> emit) async {
|
FoodEntryTapped event, Emitter<PageState> emit) async {
|
||||||
var entriesForDate = state.foodEntries[event.forDate];
|
|
||||||
if (entriesForDate == null) return;
|
|
||||||
|
|
||||||
var oldStateOfTappedEntry = event.entry.isSelected;
|
var oldStateOfTappedEntry = event.entry.isSelected;
|
||||||
|
|
||||||
for (var entry in entriesForDate) {
|
for (var entry in state.foodEntries) {
|
||||||
entry.isSelected = false;
|
entry.isSelected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedEntry = entriesForDate.firstWhere((entry) {
|
var selectedEntry = state.foodEntries.firstWhere((entry) {
|
||||||
return entry.id == event.entry.id;
|
return entry.id == event.entry.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
selectedEntry.isSelected = !oldStateOfTappedEntry;
|
selectedEntry.isSelected = !oldStateOfTappedEntry;
|
||||||
|
|
||||||
emit(GlobalEntryState(foodEntries: state.foodEntries));
|
emit(PageState(foodEntries: state.foodEntries));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodEvent {
|
class FoodEvent {}
|
||||||
final DateTime forDate;
|
|
||||||
|
|
||||||
FoodEvent({required this.forDate});
|
|
||||||
}
|
|
||||||
|
|
||||||
class PageBeingInitialized extends FoodEvent {
|
|
||||||
PageBeingInitialized({required super.forDate});
|
|
||||||
}
|
|
||||||
|
|
||||||
class FoodEntryEvent extends FoodEvent {
|
class FoodEntryEvent extends FoodEvent {
|
||||||
final FoodEntryState entry;
|
final FoodEntryState entry;
|
||||||
|
|
||||||
FoodEntryEvent({required this.entry, required super.forDate});
|
FoodEntryEvent({required this.entry});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodChangedEvent extends FoodEvent {
|
class FoodChangedEvent extends FoodEvent {
|
||||||
final FoodEntryState newEntry;
|
final FoodEntryState newEntry;
|
||||||
|
|
||||||
FoodChangedEvent({required this.newEntry, required super.forDate});
|
FoodChangedEvent({required this.newEntry});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodDeletionEvent extends FoodEvent {
|
class FoodDeletionEvent extends FoodEvent {
|
||||||
final String entryID;
|
final String entryID;
|
||||||
|
|
||||||
FoodDeletionEvent({required this.entryID, required super.forDate});
|
FoodDeletionEvent({required this.entryID});
|
||||||
}
|
}
|
||||||
|
|
||||||
class BarcodeScanned extends FoodEvent {
|
class BarcodeScanned extends FoodEvent {
|
||||||
final Future<ScanResult> scanResultFuture;
|
final Future<ScanResult> scanResultFuture;
|
||||||
|
|
||||||
BarcodeScanned({required this.scanResultFuture, required super.forDate});
|
BarcodeScanned({required this.scanResultFuture});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodEntryTapped extends FoodEvent {
|
class FoodEntryTapped extends FoodEvent {
|
||||||
final FoodEntryState entry;
|
final FoodEntryState entry;
|
||||||
|
|
||||||
FoodEntryTapped({required this.entry, required super.forDate});
|
FoodEntryTapped({required this.entry});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the state for one date/page
|
/// This is the state for one date/page
|
||||||
class GlobalEntryState {
|
class PageState {
|
||||||
final Map<DateTime, List<FoodEntryState>> foodEntries;
|
final List<FoodEntryState> foodEntries;
|
||||||
final String? errorString;
|
final String? errorString;
|
||||||
|
|
||||||
GlobalEntryState({required this.foodEntries, this.errorString});
|
PageState({required this.foodEntries, this.errorString});
|
||||||
|
|
||||||
factory GlobalEntryState.init() {
|
factory PageState.init() {
|
||||||
return GlobalEntryState(foodEntries: {});
|
return PageState(foodEntries: []);
|
||||||
}
|
}
|
||||||
|
|
||||||
static from(GlobalEntryState state) {
|
static from(PageState state) {
|
||||||
return GlobalEntryState(foodEntries: state.foodEntries);
|
return PageState(foodEntries: state.foodEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool addEntry(FoodEntryState entry, DateTime date) {
|
void addEntry(FoodEntryState entry) {
|
||||||
var list = foodEntries[date];
|
foodEntries.add(entry);
|
||||||
|
|
||||||
if (list == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
list.add(entry);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodEntryState {
|
class FoodEntryState {
|
||||||
final String id;
|
|
||||||
final String name;
|
final String name;
|
||||||
final int mass;
|
final int mass;
|
||||||
final int kcalPer100;
|
final int kcalPer100;
|
||||||
|
final String id;
|
||||||
final bool waitingForNetwork;
|
final bool waitingForNetwork;
|
||||||
bool isSelected;
|
bool isSelected;
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import 'package:calorimeter/food_entry/food_entry_bloc.dart';
|
|
||||||
import 'package:calorimeter/perdate/perdate_pageview.dart';
|
import 'package:calorimeter/perdate/perdate_pageview.dart';
|
||||||
import 'package:calorimeter/storage/storage.dart';
|
import 'package:calorimeter/storage/storage.dart';
|
||||||
import 'package:calorimeter/utils/settings_bloc.dart';
|
import 'package:calorimeter/utils/settings_bloc.dart';
|
||||||
@ -8,9 +7,6 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
List<FoodEntryState> entriesForToday = [];
|
|
||||||
DateTime timeNow = DateTime.now();
|
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
@ -18,16 +14,6 @@ void main() async {
|
|||||||
|
|
||||||
var storage = await FoodStorage.create();
|
var storage = await FoodStorage.create();
|
||||||
await storage.buildFoodLookupDatabase();
|
await storage.buildFoodLookupDatabase();
|
||||||
timeNow = DateTime.now().copyWith(
|
|
||||||
hour: 0,
|
|
||||||
isUtc: true,
|
|
||||||
minute: 0,
|
|
||||||
second: 0,
|
|
||||||
millisecond: 0,
|
|
||||||
microsecond: 0);
|
|
||||||
|
|
||||||
entriesForToday = await storage.getEntriesForDate(timeNow);
|
|
||||||
|
|
||||||
var kcalLimit = await storage.readLimit();
|
var kcalLimit = await storage.readLimit();
|
||||||
var brightness = await storage.readBrightness();
|
var brightness = await storage.readBrightness();
|
||||||
|
|
||||||
@ -56,13 +42,6 @@ class MainApp extends StatelessWidget {
|
|||||||
return SafeArea(
|
return SafeArea(
|
||||||
child: MultiBlocProvider(
|
child: MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider(
|
|
||||||
create: (context) => FoodEntryBloc(
|
|
||||||
storage: storage,
|
|
||||||
initialState:
|
|
||||||
GlobalEntryState(foodEntries: {timeNow: entriesForToday}),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (context) => SettingsDataBloc(
|
create: (context) => SettingsDataBloc(
|
||||||
SettingsState(kcalLimit: kcalLimit),
|
SettingsState(kcalLimit: kcalLimit),
|
||||||
|
@ -6,11 +6,9 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
|
|
||||||
class FoodEntryList extends StatelessWidget {
|
class FoodEntryList extends StatelessWidget {
|
||||||
final List<FoodEntryState> entries;
|
final List<FoodEntryState> entries;
|
||||||
final DateTime date;
|
|
||||||
|
|
||||||
const FoodEntryList({
|
const FoodEntryList({
|
||||||
required this.entries,
|
required this.entries,
|
||||||
required this.date,
|
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -27,7 +25,7 @@ class FoodEntryList extends StatelessWidget {
|
|||||||
onAdd: (context, entry) {
|
onAdd: (context, entry) {
|
||||||
context
|
context
|
||||||
.read<FoodEntryBloc>()
|
.read<FoodEntryBloc>()
|
||||||
.add(FoodEntryEvent(entry: entry, forDate: date));
|
.add(FoodEntryEvent(entry: entry));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 75),
|
const SizedBox(height: 75),
|
||||||
@ -42,19 +40,19 @@ class FoodEntryList extends StatelessWidget {
|
|||||||
key: ValueKey(entries[entryIndex].id),
|
key: ValueKey(entries[entryIndex].id),
|
||||||
entry: entries[entryIndex],
|
entry: entries[entryIndex],
|
||||||
onDelete: (_, id) {
|
onDelete: (_, id) {
|
||||||
context
|
context.read<FoodEntryBloc>().add(FoodDeletionEvent(
|
||||||
.read<FoodEntryBloc>()
|
entryID: id,
|
||||||
.add(FoodDeletionEvent(entryID: id, forDate: date));
|
));
|
||||||
},
|
},
|
||||||
onChange: (_, changedEntry) {
|
onChange: (_, changedEntry) {
|
||||||
context.read<FoodEntryBloc>().add(
|
context
|
||||||
FoodChangedEvent(newEntry: changedEntry, forDate: date),
|
.read<FoodEntryBloc>()
|
||||||
);
|
.add(FoodChangedEvent(newEntry: changedEntry));
|
||||||
},
|
},
|
||||||
onTap: (_, tappedEntry) {
|
onTap: (_, tappedEntry) {
|
||||||
context.read<FoodEntryBloc>().add(
|
context
|
||||||
FoodEntryTapped(entry: tappedEntry, forDate: date),
|
.read<FoodEntryBloc>()
|
||||||
);
|
.add(FoodEntryTapped(entry: tappedEntry));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
|
@ -61,7 +61,7 @@ class _PerDatePageviewState extends State<PerDatePageview> {
|
|||||||
|
|
||||||
return PerDateWidget(
|
return PerDateWidget(
|
||||||
key: ValueKey(dateToBuildWidgetFor.toString()),
|
key: ValueKey(dateToBuildWidgetFor.toString()),
|
||||||
date: dateToBuildWidgetFor.copyWith(isUtc: true),
|
date: dateToBuildWidgetFor,
|
||||||
onDateSelected: (dateSelected) {
|
onDateSelected: (dateSelected) {
|
||||||
if (dateSelected == null) return;
|
if (dateSelected == null) return;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import 'package:calorimeter/utils/theme_switcher_button.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class PerDateWidget extends StatefulWidget {
|
class PerDateWidget extends StatefulWidget {
|
||||||
final DateTime date;
|
final DateTime date;
|
||||||
@ -25,13 +26,16 @@ class PerDateWidget extends StatefulWidget {
|
|||||||
class _PerDateWidgetState extends State<PerDateWidget>
|
class _PerDateWidgetState extends State<PerDateWidget>
|
||||||
with AutomaticKeepAliveClientMixin<PerDateWidget> {
|
with AutomaticKeepAliveClientMixin<PerDateWidget> {
|
||||||
late FoodStorage storage;
|
late FoodStorage storage;
|
||||||
|
late Future<List<FoodEntryState>> entriesFuture;
|
||||||
List<FoodEntryState> entries = [];
|
List<FoodEntryState> entries = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
context
|
storage = FoodStorage.getInstance();
|
||||||
.read<FoodEntryBloc>()
|
entriesFuture = storage.getEntriesForDate(widget.date);
|
||||||
.add(PageBeingInitialized(forDate: widget.date));
|
entriesFuture.then((val) {
|
||||||
|
entries = val;
|
||||||
|
});
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,37 +48,47 @@ class _PerDateWidgetState extends State<PerDateWidget>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
|
|
||||||
return BlocConsumer<FoodEntryBloc, GlobalEntryState>(
|
return FutureBuilder(
|
||||||
|
future: entriesFuture,
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
return snapshot.connectionState != ConnectionState.done
|
||||||
|
? const Center(child: CircularProgressIndicator())
|
||||||
|
: MultiProvider(
|
||||||
|
providers: [
|
||||||
|
BlocProvider(
|
||||||
|
create: (context) => FoodEntryBloc(
|
||||||
|
initialState: PageState(foodEntries: entries),
|
||||||
|
storage: storage,
|
||||||
|
forDate: widget.date,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: BlocConsumer<FoodEntryBloc, PageState>(
|
||||||
listener: (context, pageState) {
|
listener: (context, pageState) {
|
||||||
if (pageState.errorString != null) {
|
if (pageState.errorString != null) {
|
||||||
showNewSnackbarWith(context, pageState.errorString!);
|
showNewSnackbarWith(context, pageState.errorString!);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
builder: (context, globalState) {
|
builder: (context, pageState) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(DateFormat.yMMMMd('de').format(widget.date)),
|
title: Text(
|
||||||
|
DateFormat.yMMMMd('de').format(widget.date)),
|
||||||
actions: const [ThemeSwitcherButton()],
|
actions: const [ThemeSwitcherButton()],
|
||||||
),
|
),
|
||||||
body: FoodEntryList(
|
body: FoodEntryList(entries: pageState.foodEntries),
|
||||||
entries: globalState.foodEntries[widget.date] ?? [],
|
|
||||||
date: widget.date),
|
|
||||||
bottomNavigationBar: BottomAppBar(
|
bottomNavigationBar: BottomAppBar(
|
||||||
shape: const RectangularNotchShape(),
|
shape: const RectangularNotchShape(),
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
child: SumWidget(
|
child: SumWidget(
|
||||||
foodEntries: globalState.foodEntries[widget.date] ?? [])),
|
foodEntries: pageState.foodEntries)),
|
||||||
drawer: const AppDrawer(),
|
drawer: const AppDrawer(),
|
||||||
floatingActionButton: OverflowBar(children: [
|
floatingActionButton: OverflowBar(children: [
|
||||||
ScanFoodFloatingButton(
|
ScanFoodFloatingButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
var result = BarcodeScanner.scan();
|
var result = BarcodeScanner.scan();
|
||||||
context.read<FoodEntryBloc>().add(
|
context.read<FoodEntryBloc>().add(
|
||||||
BarcodeScanned(
|
BarcodeScanned(scanResultFuture: result));
|
||||||
scanResultFuture: result,
|
|
||||||
forDate: widget.date,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@ -88,7 +102,9 @@ class _PerDateWidgetState extends State<PerDateWidget>
|
|||||||
floatingActionButtonLocation:
|
floatingActionButtonLocation:
|
||||||
FloatingActionButtonLocation.endDocked);
|
FloatingActionButtonLocation.endDocked);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void showNewSnackbarWith(BuildContext context, String text) {
|
void showNewSnackbarWith(BuildContext context, String text) {
|
||||||
|
Loading…
Reference in New Issue
Block a user