Compare commits
1 Commits
swipeable-
...
master
Author | SHA1 | Date | |
---|---|---|---|
ce373404ad |
@ -4,61 +4,96 @@ 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, PageState> {
|
class FoodEntryBloc extends Bloc<FoodEvent, GlobalEntryState> {
|
||||||
final PageState initialState;
|
final GlobalEntryState initialState;
|
||||||
final FoodStorage storage;
|
final FoodStorage storage;
|
||||||
final DateTime forDate;
|
|
||||||
|
|
||||||
FoodEntryBloc(
|
FoodEntryBloc({required this.initialState, required this.storage})
|
||||||
{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<PageState> emit) async {
|
FoodEntryEvent event, Emitter<GlobalEntryState> emit) async {
|
||||||
PageState newState = PageState.from(state);
|
var entriesForDate = state.foodEntries[event.forDate];
|
||||||
newState.addEntry(event.entry);
|
entriesForDate ??= [];
|
||||||
|
|
||||||
await storage.writeEntriesForDate(forDate, newState.foodEntries);
|
entriesForDate.add(event.entry);
|
||||||
|
|
||||||
|
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
||||||
storage.addFoodEntryToLookupDatabase(event.entry);
|
storage.addFoodEntryToLookupDatabase(event.entry);
|
||||||
|
|
||||||
emit(newState);
|
// 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 handleFoodChangedEvent(
|
void handleFoodChangedEvent(
|
||||||
FoodChangedEvent event, Emitter<PageState> emit) async {
|
FoodChangedEvent event, Emitter<GlobalEntryState> emit) async {
|
||||||
var entries = state.foodEntries;
|
var entriesForDate = state.foodEntries[event.forDate];
|
||||||
var index = entries.indexWhere((entry) {
|
if (entriesForDate == null) return;
|
||||||
|
|
||||||
|
var index = entriesForDate.indexWhere((entry) {
|
||||||
return entry.id == event.newEntry.id;
|
return entry.id == event.newEntry.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
entries.removeAt(index);
|
entriesForDate.removeAt(index);
|
||||||
entries.insert(index, event.newEntry);
|
entriesForDate.insert(index, event.newEntry);
|
||||||
|
|
||||||
await storage.writeEntriesForDate(forDate, entries);
|
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
||||||
storage.addFoodEntryToLookupDatabase(event.newEntry);
|
storage.addFoodEntryToLookupDatabase(event.newEntry);
|
||||||
|
|
||||||
emit(PageState(foodEntries: entries));
|
// 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 handleDeleteFoodEvent(
|
void handleDeleteFoodEvent(
|
||||||
FoodDeletionEvent event, Emitter<PageState> emit) async {
|
FoodDeletionEvent event, Emitter<GlobalEntryState> emit) async {
|
||||||
state.foodEntries.removeWhere((entry) => entry.id == event.entryID);
|
var entriesForDate = state.foodEntries[event.forDate];
|
||||||
|
if (entriesForDate == null) return;
|
||||||
|
|
||||||
await storage.writeEntriesForDate(forDate, state.foodEntries);
|
entriesForDate.removeWhere((entry) => entry.id == event.entryID);
|
||||||
|
|
||||||
emit(PageState.from(state));
|
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
||||||
|
|
||||||
|
// 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<PageState> emit) async {
|
BarcodeScanned event, Emitter<GlobalEntryState> 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;
|
||||||
|
|
||||||
@ -66,14 +101,13 @@ class FoodEntryBloc extends Bloc<FoodEvent, PageState> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (scanResult.type == ResultType.Error) {
|
if (scanResult.type == ResultType.Error) {
|
||||||
emit(PageState(
|
emit(GlobalEntryState(
|
||||||
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: "",
|
||||||
@ -81,11 +115,13 @@ class FoodEntryBloc extends Bloc<FoodEvent, PageState> {
|
|||||||
waitingForNetwork: true,
|
waitingForNetwork: true,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
);
|
);
|
||||||
newList.add(newEntryWaiting);
|
entriesForDate.add(newEntryWaiting);
|
||||||
emit(PageState(foodEntries: newList));
|
var newFoodEntries = state.foodEntries;
|
||||||
|
newFoodEntries.addAll({event.forDate: entriesForDate});
|
||||||
|
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
||||||
|
|
||||||
await responseFuture.then((response) async {
|
await responseFuture.then((response) async {
|
||||||
var index = newList
|
var index = entriesForDate
|
||||||
.indexWhere((entryState) => entryState.id == newEntryWaiting.id);
|
.indexWhere((entryState) => entryState.id == newEntryWaiting.id);
|
||||||
|
|
||||||
// element not found (was deleted previously)
|
// element not found (was deleted previously)
|
||||||
@ -94,25 +130,23 @@ class FoodEntryBloc extends Bloc<FoodEvent, PageState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (response.status == FoodFactResponseStatus.barcodeNotFound) {
|
if (response.status == FoodFactResponseStatus.barcodeNotFound) {
|
||||||
List<FoodEntryState> listWithEntryRemoved =
|
entriesForDate.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
||||||
List.from(state.foodEntries);
|
var newFoodEntries = state.foodEntries;
|
||||||
listWithEntryRemoved
|
newFoodEntries.addAll({event.forDate: entriesForDate});
|
||||||
.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
|
||||||
|
|
||||||
emit(PageState(
|
emit(GlobalEntryState(
|
||||||
foodEntries: listWithEntryRemoved,
|
foodEntries: newFoodEntries,
|
||||||
errorString: "Barcode konnte nicht gefunden werden."));
|
errorString: "Barcode konnte nicht gefunden werden."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (response.status ==
|
if (response.status ==
|
||||||
FoodFactResponseStatus.foodFactServerNotReachable) {
|
FoodFactResponseStatus.foodFactServerNotReachable) {
|
||||||
List<FoodEntryState> listWithEntryRemoved =
|
entriesForDate.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
||||||
List.from(state.foodEntries);
|
var newFoodEntries = state.foodEntries;
|
||||||
listWithEntryRemoved
|
newFoodEntries.addAll({event.forDate: entriesForDate});
|
||||||
.removeWhere((entry) => entry.id == newEntryWaiting.id);
|
|
||||||
|
|
||||||
emit(PageState(
|
emit(GlobalEntryState(
|
||||||
foodEntries: listWithEntryRemoved,
|
foodEntries: newFoodEntries,
|
||||||
errorString: "OpenFoodFacts-Server konnte nicht erreicht werden."));
|
errorString: "OpenFoodFacts-Server konnte nicht erreicht werden."));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -125,91 +159,114 @@ class FoodEntryBloc extends Bloc<FoodEvent, PageState> {
|
|||||||
isSelected: false,
|
isSelected: false,
|
||||||
);
|
);
|
||||||
|
|
||||||
newList.removeAt(index);
|
entriesForDate.removeAt(index);
|
||||||
newList.insert(index, newEntryFinishedWaiting);
|
entriesForDate.insert(index, newEntryFinishedWaiting);
|
||||||
|
|
||||||
await storage.writeEntriesForDate(forDate, newList);
|
await storage.writeEntriesForDate(event.forDate, entriesForDate);
|
||||||
storage.addFoodEntryToLookupDatabase(newEntryFinishedWaiting);
|
storage.addFoodEntryToLookupDatabase(newEntryFinishedWaiting);
|
||||||
|
|
||||||
emit(PageState(foodEntries: newList));
|
var entriesFromStorage = await storage.getEntriesForDate(event.forDate);
|
||||||
|
var newFoodEntries = state.foodEntries;
|
||||||
|
newFoodEntries.addAll({event.forDate: entriesFromStorage});
|
||||||
|
|
||||||
|
emit(GlobalEntryState(foodEntries: newFoodEntries));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleFoodEntryTapped(
|
void handleFoodEntryTapped(
|
||||||
FoodEntryTapped event, Emitter<PageState> emit) async {
|
FoodEntryTapped event, Emitter<GlobalEntryState> 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 state.foodEntries) {
|
for (var entry in entriesForDate) {
|
||||||
entry.isSelected = false;
|
entry.isSelected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selectedEntry = state.foodEntries.firstWhere((entry) {
|
var selectedEntry = entriesForDate.firstWhere((entry) {
|
||||||
return entry.id == event.entry.id;
|
return entry.id == event.entry.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
selectedEntry.isSelected = !oldStateOfTappedEntry;
|
selectedEntry.isSelected = !oldStateOfTappedEntry;
|
||||||
|
|
||||||
emit(PageState(foodEntries: state.foodEntries));
|
emit(GlobalEntryState(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});
|
FoodEntryEvent({required this.entry, required super.forDate});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodChangedEvent extends FoodEvent {
|
class FoodChangedEvent extends FoodEvent {
|
||||||
final FoodEntryState newEntry;
|
final FoodEntryState newEntry;
|
||||||
|
|
||||||
FoodChangedEvent({required this.newEntry});
|
FoodChangedEvent({required this.newEntry, required super.forDate});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodDeletionEvent extends FoodEvent {
|
class FoodDeletionEvent extends FoodEvent {
|
||||||
final String entryID;
|
final String entryID;
|
||||||
|
|
||||||
FoodDeletionEvent({required this.entryID});
|
FoodDeletionEvent({required this.entryID, required super.forDate});
|
||||||
}
|
}
|
||||||
|
|
||||||
class BarcodeScanned extends FoodEvent {
|
class BarcodeScanned extends FoodEvent {
|
||||||
final Future<ScanResult> scanResultFuture;
|
final Future<ScanResult> scanResultFuture;
|
||||||
|
|
||||||
BarcodeScanned({required this.scanResultFuture});
|
BarcodeScanned({required this.scanResultFuture, required super.forDate});
|
||||||
}
|
}
|
||||||
|
|
||||||
class FoodEntryTapped extends FoodEvent {
|
class FoodEntryTapped extends FoodEvent {
|
||||||
final FoodEntryState entry;
|
final FoodEntryState entry;
|
||||||
|
|
||||||
FoodEntryTapped({required this.entry});
|
FoodEntryTapped({required this.entry, required super.forDate});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is the state for one date/page
|
/// This is the state for one date/page
|
||||||
class PageState {
|
class GlobalEntryState {
|
||||||
final List<FoodEntryState> foodEntries;
|
final Map<DateTime, List<FoodEntryState>> foodEntries;
|
||||||
final String? errorString;
|
final String? errorString;
|
||||||
|
|
||||||
PageState({required this.foodEntries, this.errorString});
|
GlobalEntryState({required this.foodEntries, this.errorString});
|
||||||
|
|
||||||
factory PageState.init() {
|
factory GlobalEntryState.init() {
|
||||||
return PageState(foodEntries: []);
|
return GlobalEntryState(foodEntries: {});
|
||||||
}
|
}
|
||||||
|
|
||||||
static from(PageState state) {
|
static from(GlobalEntryState state) {
|
||||||
return PageState(foodEntries: state.foodEntries);
|
return GlobalEntryState(foodEntries: state.foodEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void addEntry(FoodEntryState entry) {
|
bool addEntry(FoodEntryState entry, DateTime date) {
|
||||||
foodEntries.add(entry);
|
var list = foodEntries[date];
|
||||||
|
|
||||||
|
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,3 +1,4 @@
|
|||||||
|
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';
|
||||||
@ -7,6 +8,9 @@ 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();
|
||||||
|
|
||||||
@ -14,6 +18,16 @@ 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();
|
||||||
|
|
||||||
@ -42,6 +56,13 @@ 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,9 +6,11 @@ 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,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -25,7 +27,7 @@ class FoodEntryList extends StatelessWidget {
|
|||||||
onAdd: (context, entry) {
|
onAdd: (context, entry) {
|
||||||
context
|
context
|
||||||
.read<FoodEntryBloc>()
|
.read<FoodEntryBloc>()
|
||||||
.add(FoodEntryEvent(entry: entry));
|
.add(FoodEntryEvent(entry: entry, forDate: date));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 75),
|
const SizedBox(height: 75),
|
||||||
@ -40,19 +42,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.read<FoodEntryBloc>().add(FoodDeletionEvent(
|
context
|
||||||
entryID: id,
|
.read<FoodEntryBloc>()
|
||||||
));
|
.add(FoodDeletionEvent(entryID: id, forDate: date));
|
||||||
},
|
},
|
||||||
onChange: (_, changedEntry) {
|
onChange: (_, changedEntry) {
|
||||||
context
|
context.read<FoodEntryBloc>().add(
|
||||||
.read<FoodEntryBloc>()
|
FoodChangedEvent(newEntry: changedEntry, forDate: date),
|
||||||
.add(FoodChangedEvent(newEntry: changedEntry));
|
);
|
||||||
},
|
},
|
||||||
onTap: (_, tappedEntry) {
|
onTap: (_, tappedEntry) {
|
||||||
context
|
context.read<FoodEntryBloc>().add(
|
||||||
.read<FoodEntryBloc>()
|
FoodEntryTapped(entry: tappedEntry, forDate: date),
|
||||||
.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,
|
date: dateToBuildWidgetFor.copyWith(isUtc: true),
|
||||||
onDateSelected: (dateSelected) {
|
onDateSelected: (dateSelected) {
|
||||||
if (dateSelected == null) return;
|
if (dateSelected == null) return;
|
||||||
|
|
||||||
|
@ -11,7 +11,6 @@ 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;
|
||||||
@ -26,16 +25,13 @@ 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() {
|
||||||
storage = FoodStorage.getInstance();
|
context
|
||||||
entriesFuture = storage.getEntriesForDate(widget.date);
|
.read<FoodEntryBloc>()
|
||||||
entriesFuture.then((val) {
|
.add(PageBeingInitialized(forDate: widget.date));
|
||||||
entries = val;
|
|
||||||
});
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,47 +44,37 @@ class _PerDateWidgetState extends State<PerDateWidget>
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
super.build(context);
|
super.build(context);
|
||||||
|
|
||||||
return FutureBuilder(
|
return BlocConsumer<FoodEntryBloc, GlobalEntryState>(
|
||||||
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, pageState) {
|
builder: (context, globalState) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(
|
title: Text(DateFormat.yMMMMd('de').format(widget.date)),
|
||||||
DateFormat.yMMMMd('de').format(widget.date)),
|
|
||||||
actions: const [ThemeSwitcherButton()],
|
actions: const [ThemeSwitcherButton()],
|
||||||
),
|
),
|
||||||
body: FoodEntryList(entries: pageState.foodEntries),
|
body: FoodEntryList(
|
||||||
|
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: pageState.foodEntries)),
|
foodEntries: globalState.foodEntries[widget.date] ?? [])),
|
||||||
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(scanResultFuture: result));
|
BarcodeScanned(
|
||||||
|
scanResultFuture: result,
|
||||||
|
forDate: widget.date,
|
||||||
|
),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
@ -102,9 +88,7 @@ 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