add delayed bolus percentage functionality, improve active profile handling (display and setting), move settings to objectbox, improve cancellation check on log bolus, add warning for already running events, implement accuracy reordering
This commit is contained in:
parent
e42ad61f44
commit
a59170940f
43 changed files with 1569 additions and 979 deletions
45
TODO
45
TODO
|
@ -1,31 +1,11 @@
|
||||||
MAIN TASKS:
|
MAIN TASKS:
|
||||||
General/Framework:
|
|
||||||
☐ find a general way to deal with duration fields
|
|
||||||
|
|
||||||
Accuracies:
|
|
||||||
☐ implement reordering
|
|
||||||
|
|
||||||
Basal/Bolus:
|
|
||||||
☐ replace active profile picking mode with simple dropdown
|
|
||||||
☐ indicate both the default rate and the currently active one (according to event)
|
|
||||||
|
|
||||||
Log Entry:
|
|
||||||
☐ check for multiple active events with temporary basal/bolus profiles (smallest covered time frame counts)
|
|
||||||
☐ provide splitting functionality for overlapping events
|
|
||||||
☐ provide percentage functionality for delayed bolus
|
|
||||||
☐ get rid of useless cancellation warnings
|
|
||||||
|
|
||||||
Events:
|
|
||||||
☐ when adding an event later on, prompt if existing boli should be recalculated
|
|
||||||
☐ show event start AND end times in list
|
|
||||||
|
|
||||||
Settings:
|
Settings:
|
||||||
☐ add objectbox class and use instead of shared preferences
|
☐ fix settings saving
|
||||||
|
|
||||||
FUTURE TASKS:
|
FUTURE TASKS:
|
||||||
General/Framework:
|
General/Framework:
|
||||||
☐ make all fields readonly if user somehow gets to a deleted record detail view
|
☐ show indicator and make all fields readonly if user somehow gets to a deleted record detail view
|
||||||
☐ add functionality to delete dead records
|
☐ add functionality to delete dead records (meaning: set deleted flag and no relations)
|
||||||
☐ clean up controllers (dispose method of each stateful widget)
|
☐ clean up controllers (dispose method of each stateful widget)
|
||||||
☐ add explanations to each section
|
☐ add explanations to each section
|
||||||
☐ account for deleted/disabled elements in dropdowns
|
☐ account for deleted/disabled elements in dropdowns
|
||||||
|
@ -33,20 +13,35 @@ FUTURE TASKS:
|
||||||
☐ add clear button to dropdown (or all text fields?)
|
☐ add clear button to dropdown (or all text fields?)
|
||||||
☐ check through all detail forms and set required fields/according messages
|
☐ check through all detail forms and set required fields/according messages
|
||||||
☐ find a better way to work with multiple measurements (or disable it?)
|
☐ find a better way to work with multiple measurements (or disable it?)
|
||||||
|
☐ evaluate if some fields should be readonly instead of completely hidden
|
||||||
|
☐ implement component for durations
|
||||||
Log Overview:
|
Log Overview:
|
||||||
☐ add pagination
|
☐ add pagination
|
||||||
☐ apply target color settings to glucose
|
☐ apply target color settings to glucose
|
||||||
|
Log Entry:
|
||||||
|
☐ check if there is still an active bolus when suggesting glucose bolus
|
||||||
Event Types:
|
Event Types:
|
||||||
|
☐ add pagination
|
||||||
☐ add colors as indicators for log entries (and later graphs in reports)
|
☐ add colors as indicators for log entries (and later graphs in reports)
|
||||||
☐ implement reminders as push notifications
|
☐ implement reminders as push notifications
|
||||||
Settings:
|
Settings:
|
||||||
☐ add fields for preferred date and time formats
|
☐ add fields for preferred date and time formats
|
||||||
☐ add fields for glucose target (as map of cutoff glucose and colors)
|
☐ add fields for glucose target (as map of cutoff glucose and colors)
|
||||||
☐ add option to hide warning dialogs on cancel or event stop
|
☐ add option to hide warning dialogs on cancel, delete or event stop
|
||||||
☐ add option to hide extra customization options (ie. changing pre calculated values)
|
☐ add option to hide extra customization options (ie. changing pre calculated values)?
|
||||||
☐ add setting for decimal places
|
☐ add setting for decimal places
|
||||||
|
☐ add field for active insulin duration
|
||||||
|
|
||||||
Archive:
|
Archive:
|
||||||
|
✔ add objectbox settings class and use instead of shared preferences @done(21-12-05 00:41) @project(MAIN TASKS.Settings)
|
||||||
|
✔ provide percentage functionality for delayed bolus @done(21-12-04 21:39) @project(MAIN TASKS.Log Entry)
|
||||||
|
✔ create two bolus entries accordingly @done(21-12-04 22:12) @project(MAIN TASKS.Log Entry)
|
||||||
|
✔ replace active profile picking mode with simple dropdown @done(21-12-04 20:10) @project(MAIN TASKS.Basal/Bolus)
|
||||||
|
✔ indicate both the default rate and the currently active one (according to event) @done(21-12-04 20:10) @project(MAIN TASKS.Basal/Bolus)
|
||||||
|
✔ get rid of excessive cancellation warnings @done(21-12-04 19:09) @project(MAIN TASKS.Log Entry)
|
||||||
|
✔ give a warning if event of same type is already running @done(21-12-04 18:50) @project(MAIN TASKS.Events)
|
||||||
|
✔ implement reordering @started(21-12-03 23:12) @done(21-12-04 17:01) @lasted(17h49m38s) @project(MAIN TASKS.Accuracies)
|
||||||
|
✔ show event start AND end times in list @done(21-12-03 22:04) @project(MAIN TASKS.Events)
|
||||||
✔ separate events from log entries @done(21-12-01 23:37) @project(MAIN TASKS.Events)
|
✔ separate events from log entries @done(21-12-01 23:37) @project(MAIN TASKS.Events)
|
||||||
✔ show total bolus and carbs per entry @done(21-12-01 19:50) @project(MAIN TASKS.Log Overview)
|
✔ show total bolus and carbs per entry @done(21-12-01 19:50) @project(MAIN TASKS.Log Overview)
|
||||||
✔ display boli correctly @done(21-11-30 04:14) @project(MAIN TASKS.Log Entry)
|
✔ display boli correctly @done(21-11-30 04:14) @project(MAIN TASKS.Log Entry)
|
||||||
|
|
|
@ -49,13 +49,15 @@ class BooleanFormField extends StatefulWidget {
|
||||||
final String label;
|
final String label;
|
||||||
final void Function(bool) onChanged;
|
final void Function(bool) onChanged;
|
||||||
final bool? enabled;
|
final bool? enabled;
|
||||||
|
final EdgeInsets? contentPadding;
|
||||||
|
|
||||||
const BooleanFormField(
|
const BooleanFormField(
|
||||||
{Key? key,
|
{Key? key,
|
||||||
required this.value,
|
required this.value,
|
||||||
required this.label,
|
required this.label,
|
||||||
required this.onChanged,
|
required this.onChanged,
|
||||||
this.enabled})
|
this.enabled,
|
||||||
|
this.contentPadding})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -67,6 +69,7 @@ class _BooleanFormFieldState extends State<BooleanFormField> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FormField<bool>(builder: (state) {
|
return FormField<bool>(builder: (state) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
|
contentPadding: widget.contentPadding,
|
||||||
onTap: () => widget.onChanged(!widget.value),
|
onTap: () => widget.onChanged(!widget.value),
|
||||||
trailing: Switch(
|
trailing: Switch(
|
||||||
value: widget.value,
|
value: widget.value,
|
||||||
|
@ -115,7 +118,8 @@ class _DateTimeFormFieldState extends State<DateTimeFormField> {
|
||||||
context: context,
|
context: context,
|
||||||
initialDate: widget.date,
|
initialDate: widget.date,
|
||||||
firstDate: widget.minDate ?? DateTime(2000, 1, 1),
|
firstDate: widget.minDate ?? DateTime(2000, 1, 1),
|
||||||
lastDate: widget.maxDate ?? DateTime.now().add(const Duration(days: 365)),
|
lastDate:
|
||||||
|
widget.maxDate ?? DateTime.now().add(const Duration(days: 365)),
|
||||||
);
|
);
|
||||||
widget.onChanged(newTime);
|
widget.onChanged(newTime);
|
||||||
},
|
},
|
||||||
|
@ -160,4 +164,3 @@ class _TimeOfDayFormFieldState extends State<TimeOfDayFormField> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
|
|
||||||
const keyApplicationId = 'DFfD2aeppmqQnVmox02kUZhYOUc7vAtGfunAP7hn';
|
|
||||||
const keyClientKey = '0ROGEVQP0Id21EMEqK05wJP3nBDuOW5DM5Cpzdt3';
|
|
||||||
const keyParseServerUrl = 'https://parseapi.back4app.com';
|
|
||||||
|
|
||||||
// settings
|
|
||||||
NutritionMeasurement nutritionMeasurement = NutritionMeasurement.grams;
|
|
||||||
GlucoseMeasurement glucoseMeasurement = GlucoseMeasurement.mgPerDl;
|
|
||||||
GlucoseDisplayMode glucoseDisplayMode = GlucoseDisplayMode.bothForList;
|
|
||||||
|
|
||||||
DateTime dummyDate = DateTime(2000);
|
|
||||||
String dateFormat = 'MM/dd/yy';
|
|
||||||
String? longDateFormat = 'MMMM dd, yyyy';
|
|
||||||
String timeFormat = 'HH:mm';
|
|
||||||
String? longTimeFormat = 'HH:mm:ss';
|
|
||||||
|
|
||||||
bool showConfirmationDialogOnCancel = true;
|
|
||||||
bool showConfirmationDialogOnDelete = true;
|
|
||||||
bool showConfirmationDialogOnStopEvent = true;
|
|
||||||
|
|
||||||
int lowGlucoseMgPerDl = 80;
|
|
||||||
int moderateGlucoseMgPerDl = 140;
|
|
||||||
int highGlucoseMgPerDl = 240;
|
|
||||||
|
|
||||||
double lowGlucoseMmolPerL = 4.44;
|
|
||||||
double moderateGlucoseMmolPerL = 7.77;
|
|
||||||
double highGlucoseMmolPerDl = 13.32;
|
|
|
@ -19,9 +19,7 @@ import 'package:diameter/screens/meal/meal_source_detail.dart';
|
||||||
import 'package:diameter/screens/meal/meal_source_list.dart';
|
import 'package:diameter/screens/meal/meal_source_list.dart';
|
||||||
import 'package:diameter/settings.dart';
|
import 'package:diameter/settings.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
|
|
||||||
import 'package:diameter/screens/accuracy_list.dart';
|
import 'package:diameter/screens/accuracy_list.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/screens/basal/basal_profile_list.dart';
|
import 'package:diameter/screens/basal/basal_profile_list.dart';
|
||||||
import 'package:diameter/screens/bolus/bolus_profile_list.dart';
|
import 'package:diameter/screens/bolus/bolus_profile_list.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
|
@ -29,17 +27,6 @@ import 'package:diameter/navigation.dart';
|
||||||
late ObjectBox objectBox;
|
late ObjectBox objectBox;
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
await Parse().initialize(
|
|
||||||
keyApplicationId,
|
|
||||||
keyParseServerUrl,
|
|
||||||
clientKey: keyClientKey,
|
|
||||||
debug: true,
|
|
||||||
coreStore: await CoreStoreSharedPrefsImp.getInstance(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Settings.loadSettingsIntoConfig();
|
|
||||||
|
|
||||||
objectBox = await ObjectBox.create();
|
objectBox = await ObjectBox.create();
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
|
|
|
@ -31,8 +31,7 @@ class Accuracy {
|
||||||
static void put(Accuracy accuracy) => box.put(accuracy);
|
static void put(Accuracy accuracy) => box.put(accuracy);
|
||||||
|
|
||||||
static List<Accuracy> getAll() {
|
static List<Accuracy> getAll() {
|
||||||
QueryBuilder<Accuracy> all = box
|
QueryBuilder<Accuracy> all = box.query(Accuracy_.deleted.equals(false))
|
||||||
.query(Accuracy_.deleted.equals(false))
|
|
||||||
..order(Accuracy_.confidenceRating);
|
..order(Accuracy_.confidenceRating);
|
||||||
return all.build().find();
|
return all.build().find();
|
||||||
}
|
}
|
||||||
|
@ -46,19 +45,30 @@ class Accuracy {
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<Accuracy> getAllForPortionSize() {
|
static List<Accuracy> getAllForPortionSize() {
|
||||||
QueryBuilder<Accuracy> allForPortionSize = box
|
QueryBuilder<Accuracy> allForPortionSize = box.query(
|
||||||
.query(Accuracy_.forPortionSize.equals(true) & Accuracy_.deleted.equals(false))
|
Accuracy_.forPortionSize.equals(true) & Accuracy_.deleted.equals(false))
|
||||||
..order(Accuracy_.confidenceRating);
|
..order(Accuracy_.confidenceRating);
|
||||||
return allForPortionSize.build().find();
|
return allForPortionSize.build().find();
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<Accuracy> getAllForCarbsRatio() {
|
static List<Accuracy> getAllForCarbsRatio() {
|
||||||
QueryBuilder<Accuracy> allForCarbsRatio = box
|
QueryBuilder<Accuracy> allForCarbsRatio = box.query(
|
||||||
.query(Accuracy_.forCarbsRatio.equals(true) & Accuracy_.deleted.equals(false))
|
Accuracy_.forCarbsRatio.equals(true) & Accuracy_.deleted.equals(false))
|
||||||
..order(Accuracy_.confidenceRating);
|
..order(Accuracy_.confidenceRating);
|
||||||
return allForCarbsRatio.build().find();
|
return allForCarbsRatio.build().find();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void reorder(Accuracy accuracy, int? newPosition) {
|
||||||
|
QueryBuilder<Accuracy> all = box.query(Accuracy_.deleted.equals(false).and(Accuracy_.id.notEquals(accuracy.id)))
|
||||||
|
..order(Accuracy_.confidenceRating);
|
||||||
|
List<Accuracy> accuracies = all.build().find();
|
||||||
|
newPosition == null || newPosition >= accuracies.length ? accuracies.add(accuracy) : accuracies.insert(newPosition, accuracy);
|
||||||
|
box.putMany(accuracies.map((item) {
|
||||||
|
item.confidenceRating = accuracies.indexOf(item);
|
||||||
|
return item;
|
||||||
|
}).toList());
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return value;
|
return value;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:diameter/main.dart';
|
import 'package:diameter/main.dart';
|
||||||
|
import 'package:diameter/models/log_event.dart';
|
||||||
import 'package:objectbox/objectbox.dart';
|
import 'package:objectbox/objectbox.dart';
|
||||||
import 'package:diameter/objectbox.g.dart' show BasalProfile_;
|
import 'package:diameter/objectbox.g.dart' show BasalProfile_;
|
||||||
|
|
||||||
|
@ -52,6 +53,31 @@ class BasalProfile {
|
||||||
}).toList());
|
}).toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BasalProfile? getActive(DateTime? dateTime) {
|
||||||
|
if (dateTime != null) {
|
||||||
|
List<LogEvent> activeEvents = LogEvent.getAllActiveForTime(dateTime)
|
||||||
|
.where((event) => event.basalProfile.target != null).toList();
|
||||||
|
if (activeEvents.length > 1) {
|
||||||
|
final now = DateTime.now();
|
||||||
|
activeEvents =
|
||||||
|
activeEvents.where((item) => !activeEvents.any((other) =>
|
||||||
|
item.time.isBefore(other.time) || (item.endTime ?? now).isAfter(other.endTime ?? now)
|
||||||
|
)).toList();
|
||||||
|
}
|
||||||
|
if (activeEvents.length == 1) {
|
||||||
|
return activeEvents.single.basalProfile.target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Query<BasalProfile> query = box
|
||||||
|
.query(BasalProfile_.active
|
||||||
|
.equals(true)
|
||||||
|
.and(BasalProfile_.deleted.equals(false)))
|
||||||
|
.build();
|
||||||
|
final result = query.find();
|
||||||
|
return result.length != 1 ? null : result.single;
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return name;
|
return name;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/main.dart';
|
import 'package:diameter/main.dart';
|
||||||
import 'package:diameter/models/bolus_profile.dart';
|
import 'package:diameter/models/bolus_profile.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/main.dart';
|
import 'package:diameter/main.dart';
|
||||||
import 'package:diameter/models/log_bolus.dart';
|
import 'package:diameter/models/log_bolus.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:objectbox/objectbox.dart';
|
import 'package:objectbox/objectbox.dart';
|
||||||
import 'package:diameter/objectbox.g.dart' show LogEntry_;
|
import 'package:diameter/objectbox.g.dart' show LogEntry_;
|
||||||
|
@ -43,8 +43,8 @@ class LogEntry {
|
||||||
|
|
||||||
static bool hasUncorrectedGlucose(int id) {
|
static bool hasUncorrectedGlucose(int id) {
|
||||||
final entry = box.get(id);
|
final entry = box.get(id);
|
||||||
if (((entry?.mgPerDl ?? 0) > moderateGlucoseMgPerDl ||
|
if (((entry?.mgPerDl ?? 0) > Settings.get().moderateGlucoseMgPerDl ||
|
||||||
(entry?.mmolPerL ?? 0) > moderateGlucoseMmolPerL)) {
|
(entry?.mmolPerL ?? 0) > Settings.get().moderateGlucoseMmolPerL)) {
|
||||||
return !LogBolus.glucoseBolusForEntryExists(id);
|
return !LogBolus.glucoseBolusForEntryExists(id);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -3,7 +3,7 @@ import 'package:diameter/models/basal_profile.dart';
|
||||||
import 'package:diameter/models/bolus_profile.dart';
|
import 'package:diameter/models/bolus_profile.dart';
|
||||||
import 'package:diameter/models/log_event_type.dart';
|
import 'package:diameter/models/log_event_type.dart';
|
||||||
import 'package:objectbox/objectbox.dart';
|
import 'package:objectbox/objectbox.dart';
|
||||||
import 'package:diameter/objectbox.g.dart' show LogEvent_;
|
import 'package:diameter/objectbox.g.dart' show LogEvent_, LogEventType_;
|
||||||
|
|
||||||
@Entity(uid: 4303325892753185970)
|
@Entity(uid: 4303325892753185970)
|
||||||
class LogEvent {
|
class LogEvent {
|
||||||
|
@ -20,6 +20,11 @@ class LogEvent {
|
||||||
int? reminderDuration;
|
int? reminderDuration;
|
||||||
String? notes;
|
String? notes;
|
||||||
|
|
||||||
|
@Transient()
|
||||||
|
String? title;
|
||||||
|
@Transient()
|
||||||
|
bool isEndEvent = false;
|
||||||
|
|
||||||
// relations
|
// relations
|
||||||
final eventType = ToOne<LogEventType>();
|
final eventType = ToOne<LogEventType>();
|
||||||
final bolusProfile = ToOne<BolusProfile>();
|
final bolusProfile = ToOne<BolusProfile>();
|
||||||
|
@ -60,7 +65,7 @@ class LogEvent {
|
||||||
if (dateTime != null) {
|
if (dateTime != null) {
|
||||||
QueryBuilder<LogEvent> builder = box.query(
|
QueryBuilder<LogEvent> builder = box.query(
|
||||||
LogEvent_.hasEndTime.equals(true) & LogEvent_.deleted.equals(false))
|
LogEvent_.hasEndTime.equals(true) & LogEvent_.deleted.equals(false))
|
||||||
..order(LogEvent_.time);
|
..order(LogEvent_.time, flags: Order.descending);
|
||||||
final eventsWithEndTime = builder.build().find();
|
final eventsWithEndTime = builder.build().find();
|
||||||
return eventsWithEndTime.where((event) {
|
return eventsWithEndTime.where((event) {
|
||||||
return (!dateTime.isBefore(event.time)) &&
|
return (!dateTime.isBefore(event.time)) &&
|
||||||
|
@ -70,21 +75,68 @@ class LogEvent {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool eventTypeExistsForTime(int id, DateTime? dateTime) {
|
||||||
|
QueryBuilder<LogEvent> builder = box.query(
|
||||||
|
LogEvent_.hasEndTime.equals(true) & LogEvent_.deleted.equals(false))
|
||||||
|
..order(LogEvent_.time, flags: Order.descending);
|
||||||
|
builder.link(LogEvent_.eventType, LogEventType_.id.equals(id));
|
||||||
|
final eventsWithEndTime = builder.build().find();
|
||||||
|
if (dateTime != null) {
|
||||||
|
return eventsWithEndTime.where((event) {
|
||||||
|
return (!dateTime.isBefore(event.time)) &&
|
||||||
|
!dateTime.isAfter(event.endTime ?? DateTime.now());
|
||||||
|
}).isNotEmpty;
|
||||||
|
}
|
||||||
|
return eventsWithEndTime.isNotEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
static Map<DateTime, List<LogEvent>> getDailyEntryMap() {
|
static Map<DateTime, List<LogEvent>> getDailyEntryMap() {
|
||||||
Map<DateTime, List<LogEvent>> dateMap = <DateTime, List<LogEvent>>{};
|
Map<DateTime, List<LogEvent>> dateMap = <DateTime, List<LogEvent>>{};
|
||||||
|
Map<DateTime, List<LogEvent>> sortedDateMap = <DateTime, List<LogEvent>>{};
|
||||||
|
|
||||||
QueryBuilder<LogEvent> allByDate = box
|
QueryBuilder<LogEvent> allByDate = box
|
||||||
.query(LogEvent_.deleted.equals(false))
|
.query(LogEvent_.deleted.equals(false))
|
||||||
..order(LogEvent_.time, flags: Order.descending);
|
..order(LogEvent_.time, flags: Order.descending);
|
||||||
List<LogEvent> events = allByDate.build().find();
|
List<LogEvent> events = allByDate.build().find();
|
||||||
|
|
||||||
DateTime? date;
|
DateTime? date;
|
||||||
|
|
||||||
for (LogEvent event in events) {
|
for (LogEvent event in events) {
|
||||||
date = DateTime.utc(event.time.year, event.time.month, event.time.day);
|
date = DateTime.utc(event.time.year, event.time.month, event.time.day);
|
||||||
dateMap.putIfAbsent(date, () => <LogEvent>[]).add(event);
|
LogEvent startEvent = event;
|
||||||
|
startEvent.title =
|
||||||
|
'${event.toString()} ${event.hasEndTime ? '(Start)' : ''}';
|
||||||
|
dateMap.putIfAbsent(date, () => <LogEvent>[]).add(startEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dateMap;
|
QueryBuilder<LogEvent> allByEndDate = box
|
||||||
|
.query(LogEvent_.deleted.equals(false).and(LogEvent_.endTime.notNull()))
|
||||||
|
..order(LogEvent_.endTime, flags: Order.descending);
|
||||||
|
List<LogEvent> endEvents = allByEndDate.build().find();
|
||||||
|
|
||||||
|
for (LogEvent event in endEvents) {
|
||||||
|
date = DateTime.utc(
|
||||||
|
event.endTime!.year, event.endTime!.month, event.endTime!.day);
|
||||||
|
LogEvent endEvent = event;
|
||||||
|
endEvent.isEndEvent = true;
|
||||||
|
endEvent.title = '${event.toString()} (End)';
|
||||||
|
dateMap.putIfAbsent(date, () => <LogEvent>[]).add(endEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
final dates = dateMap.keys.toList();
|
||||||
|
dates.sort();
|
||||||
|
for (DateTime date in dates.reversed) {
|
||||||
|
dateMap[date]!.sort((LogEvent a, LogEvent b) {
|
||||||
|
final dateA = a.isEndEvent ? a.endTime : a.time;
|
||||||
|
final dateB = b.isEndEvent ? b.endTime : b.time;
|
||||||
|
return -(dateA!.compareTo(dateB!));
|
||||||
|
});
|
||||||
|
sortedDateMap
|
||||||
|
.putIfAbsent(date, () => <LogEvent>[])
|
||||||
|
.addAll(dateMap[date]!);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sortedDateMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
95
lib/models/settings.dart
Normal file
95
lib/models/settings.dart
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
import 'package:diameter/main.dart';
|
||||||
|
import 'package:objectbox/objectbox.dart';
|
||||||
|
|
||||||
|
enum GlucoseDisplayMode { activeOnly, bothForList, bothForDetail, both }
|
||||||
|
List<String> glucoseDisplayModeLabels = [
|
||||||
|
'activeOnly',
|
||||||
|
'bothForList',
|
||||||
|
'bothForDetail',
|
||||||
|
'both',
|
||||||
|
];
|
||||||
|
|
||||||
|
enum GlucoseMeasurement {
|
||||||
|
mgPerDl,
|
||||||
|
mmolPerL,
|
||||||
|
}
|
||||||
|
List<String> glucoseMeasurementSuffixes = [
|
||||||
|
'mg/dl',
|
||||||
|
'mmol/l',
|
||||||
|
];
|
||||||
|
List<String> glucoseMeasurementLabels = [
|
||||||
|
'mgPerDl',
|
||||||
|
'mmolPerL',
|
||||||
|
];
|
||||||
|
|
||||||
|
enum NutritionMeasurement {
|
||||||
|
grams,
|
||||||
|
ounces,
|
||||||
|
lbs,
|
||||||
|
}
|
||||||
|
List<String> nutritionMeasurementSuffixes = [
|
||||||
|
'g',
|
||||||
|
'oz',
|
||||||
|
'lbs',
|
||||||
|
];
|
||||||
|
List<String> nutritionMeasurementLabels = [
|
||||||
|
'grams',
|
||||||
|
'ounces',
|
||||||
|
'lbs',
|
||||||
|
];
|
||||||
|
|
||||||
|
@Entity(uid: 3989341091218179227)
|
||||||
|
class Settings {
|
||||||
|
static final Box<Settings> box = objectBox.store.box<Settings>();
|
||||||
|
|
||||||
|
// properties
|
||||||
|
int id;
|
||||||
|
NutritionMeasurement nutritionMeasurement;
|
||||||
|
GlucoseDisplayMode glucoseDisplayMode;
|
||||||
|
GlucoseMeasurement glucoseMeasurement;
|
||||||
|
|
||||||
|
String dateFormat;
|
||||||
|
String? longDateFormat;
|
||||||
|
String timeFormat;
|
||||||
|
String? longTimeFormat;
|
||||||
|
|
||||||
|
bool showConfirmationDialogOnCancel;
|
||||||
|
bool showConfirmationDialogOnDelete;
|
||||||
|
bool showConfirmationDialogOnStopEvent;
|
||||||
|
|
||||||
|
int lowGlucoseMgPerDl;
|
||||||
|
int moderateGlucoseMgPerDl;
|
||||||
|
int highGlucoseMgPerDl;
|
||||||
|
double lowGlucoseMmolPerL;
|
||||||
|
double moderateGlucoseMmolPerL;
|
||||||
|
double highGlucoseMmolPerDl;
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Settings({
|
||||||
|
this.id = 0,
|
||||||
|
this.nutritionMeasurement = NutritionMeasurement.grams,
|
||||||
|
this.glucoseDisplayMode = GlucoseDisplayMode.bothForList,
|
||||||
|
this.glucoseMeasurement = GlucoseMeasurement.mgPerDl,
|
||||||
|
this.dateFormat = 'MM/dd/yy',
|
||||||
|
this.longDateFormat = 'MMMM dd, yyyy',
|
||||||
|
this.timeFormat = 'HH:mm',
|
||||||
|
this.longTimeFormat = 'HH:mm:ss',
|
||||||
|
this.showConfirmationDialogOnCancel = true,
|
||||||
|
this.showConfirmationDialogOnDelete = true,
|
||||||
|
this.showConfirmationDialogOnStopEvent = true,
|
||||||
|
this.lowGlucoseMgPerDl = 80,
|
||||||
|
this.moderateGlucoseMgPerDl = 140,
|
||||||
|
this.highGlucoseMgPerDl = 240,
|
||||||
|
this.lowGlucoseMmolPerL = 4.44,
|
||||||
|
this.moderateGlucoseMmolPerL = 7.77,
|
||||||
|
this.highGlucoseMmolPerDl = 13.32,
|
||||||
|
});
|
||||||
|
|
||||||
|
// methods
|
||||||
|
static Settings get() => box.getAll().single;
|
||||||
|
static void put(Settings settings) => box.put(settings);
|
||||||
|
static void reset() {
|
||||||
|
box.removeAll();
|
||||||
|
box.put(Settings());
|
||||||
|
}
|
||||||
|
}
|
|
@ -99,14 +99,6 @@ class _NavigationState extends State<Navigation> {
|
||||||
},
|
},
|
||||||
selected: widget.currentLocation == Routes.log,
|
selected: widget.currentLocation == Routes.log,
|
||||||
),
|
),
|
||||||
ListTile(
|
|
||||||
title: const Text('Log Entry'),
|
|
||||||
leading: const Icon(Icons.description),
|
|
||||||
onTap: () {
|
|
||||||
selectDestination(Routes.logEntry);
|
|
||||||
},
|
|
||||||
selected: Routes.logEntryRoutes.contains(widget.currentLocation),
|
|
||||||
),
|
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Log Events'),
|
title: const Text('Log Events'),
|
||||||
leading: const Icon(Icons.event),
|
leading: const Icon(Icons.event),
|
||||||
|
|
|
@ -791,9 +791,88 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"relations": []
|
"relations": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "16:3989341091218179227",
|
||||||
|
"lastPropertyId": "14:3282706593658092097",
|
||||||
|
"name": "Settings",
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"id": "1:7803753645747063723",
|
||||||
|
"name": "id",
|
||||||
|
"type": 6,
|
||||||
|
"flags": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "2:4703380985530623101",
|
||||||
|
"name": "dateFormat",
|
||||||
|
"type": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "3:2983395924801005937",
|
||||||
|
"name": "longDateFormat",
|
||||||
|
"type": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4:2579032794029389590",
|
||||||
|
"name": "timeFormat",
|
||||||
|
"type": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5:3970690908108519507",
|
||||||
|
"name": "longTimeFormat",
|
||||||
|
"type": 9
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "6:349893175332801783",
|
||||||
|
"name": "showConfirmationDialogOnCancel",
|
||||||
|
"type": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7:4049915860178079910",
|
||||||
|
"name": "showConfirmationDialogOnDelete",
|
||||||
|
"type": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8:3088241443557186512",
|
||||||
|
"name": "showConfirmationDialogOnStopEvent",
|
||||||
|
"type": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9:310032577683835406",
|
||||||
|
"name": "lowGlucoseMgPerDl",
|
||||||
|
"type": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "10:596980591281311896",
|
||||||
|
"name": "moderateGlucoseMgPerDl",
|
||||||
|
"type": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "11:5588897884422150510",
|
||||||
|
"name": "highGlucoseMgPerDl",
|
||||||
|
"type": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "12:7638848982383620744",
|
||||||
|
"name": "lowGlucoseMmolPerL",
|
||||||
|
"type": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "13:3633551763915044903",
|
||||||
|
"name": "moderateGlucoseMmolPerL",
|
||||||
|
"type": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "14:3282706593658092097",
|
||||||
|
"name": "highGlucoseMmolPerDl",
|
||||||
|
"type": 8
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"lastEntityId": "15:291512798403320400",
|
"relations": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"lastEntityId": "16:3989341091218179227",
|
||||||
"lastIndexId": "28:4563029809754152081",
|
"lastIndexId": "28:4563029809754152081",
|
||||||
"lastRelationId": "0:0",
|
"lastRelationId": "0:0",
|
||||||
"lastSequenceId": "0:0",
|
"lastSequenceId": "0:0",
|
||||||
|
|
|
@ -23,6 +23,7 @@ import 'models/meal.dart';
|
||||||
import 'models/meal_category.dart';
|
import 'models/meal_category.dart';
|
||||||
import 'models/meal_portion_type.dart';
|
import 'models/meal_portion_type.dart';
|
||||||
import 'models/meal_source.dart';
|
import 'models/meal_source.dart';
|
||||||
|
import 'models/settings.dart';
|
||||||
|
|
||||||
export 'package:objectbox/objectbox.dart'; // so that callers only have to import this file
|
export 'package:objectbox/objectbox.dart'; // so that callers only have to import this file
|
||||||
|
|
||||||
|
@ -789,6 +790,85 @@ final _entities = <ModelEntity>[
|
||||||
flags: 0)
|
flags: 0)
|
||||||
],
|
],
|
||||||
relations: <ModelRelation>[],
|
relations: <ModelRelation>[],
|
||||||
|
backlinks: <ModelBacklink>[]),
|
||||||
|
ModelEntity(
|
||||||
|
id: const IdUid(16, 3989341091218179227),
|
||||||
|
name: 'Settings',
|
||||||
|
lastPropertyId: const IdUid(14, 3282706593658092097),
|
||||||
|
flags: 0,
|
||||||
|
properties: <ModelProperty>[
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(1, 7803753645747063723),
|
||||||
|
name: 'id',
|
||||||
|
type: 6,
|
||||||
|
flags: 1),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(2, 4703380985530623101),
|
||||||
|
name: 'dateFormat',
|
||||||
|
type: 9,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(3, 2983395924801005937),
|
||||||
|
name: 'longDateFormat',
|
||||||
|
type: 9,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(4, 2579032794029389590),
|
||||||
|
name: 'timeFormat',
|
||||||
|
type: 9,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(5, 3970690908108519507),
|
||||||
|
name: 'longTimeFormat',
|
||||||
|
type: 9,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(6, 349893175332801783),
|
||||||
|
name: 'showConfirmationDialogOnCancel',
|
||||||
|
type: 1,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(7, 4049915860178079910),
|
||||||
|
name: 'showConfirmationDialogOnDelete',
|
||||||
|
type: 1,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(8, 3088241443557186512),
|
||||||
|
name: 'showConfirmationDialogOnStopEvent',
|
||||||
|
type: 1,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(9, 310032577683835406),
|
||||||
|
name: 'lowGlucoseMgPerDl',
|
||||||
|
type: 6,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(10, 596980591281311896),
|
||||||
|
name: 'moderateGlucoseMgPerDl',
|
||||||
|
type: 6,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(11, 5588897884422150510),
|
||||||
|
name: 'highGlucoseMgPerDl',
|
||||||
|
type: 6,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(12, 7638848982383620744),
|
||||||
|
name: 'lowGlucoseMmolPerL',
|
||||||
|
type: 8,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(13, 3633551763915044903),
|
||||||
|
name: 'moderateGlucoseMmolPerL',
|
||||||
|
type: 8,
|
||||||
|
flags: 0),
|
||||||
|
ModelProperty(
|
||||||
|
id: const IdUid(14, 3282706593658092097),
|
||||||
|
name: 'highGlucoseMmolPerDl',
|
||||||
|
type: 8,
|
||||||
|
flags: 0)
|
||||||
|
],
|
||||||
|
relations: <ModelRelation>[],
|
||||||
backlinks: <ModelBacklink>[])
|
backlinks: <ModelBacklink>[])
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -812,7 +892,7 @@ Future<Store> openStore(
|
||||||
ModelDefinition getObjectBoxModel() {
|
ModelDefinition getObjectBoxModel() {
|
||||||
final model = ModelInfo(
|
final model = ModelInfo(
|
||||||
entities: _entities,
|
entities: _entities,
|
||||||
lastEntityId: const IdUid(15, 291512798403320400),
|
lastEntityId: const IdUid(16, 3989341091218179227),
|
||||||
lastIndexId: const IdUid(28, 4563029809754152081),
|
lastIndexId: const IdUid(28, 4563029809754152081),
|
||||||
lastRelationId: const IdUid(0, 0),
|
lastRelationId: const IdUid(0, 0),
|
||||||
lastSequenceId: const IdUid(0, 0),
|
lastSequenceId: const IdUid(0, 0),
|
||||||
|
@ -1545,6 +1625,76 @@ ModelDefinition getObjectBoxModel() {
|
||||||
notes: const fb.StringReader()
|
notes: const fb.StringReader()
|
||||||
.vTableGetNullable(buffer, rootOffset, 14));
|
.vTableGetNullable(buffer, rootOffset, 14));
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}),
|
||||||
|
Settings: EntityDefinition<Settings>(
|
||||||
|
model: _entities[14],
|
||||||
|
toOneRelations: (Settings object) => [],
|
||||||
|
toManyRelations: (Settings object) => {},
|
||||||
|
getId: (Settings object) => object.id,
|
||||||
|
setId: (Settings object, int id) {
|
||||||
|
object.id = id;
|
||||||
|
},
|
||||||
|
objectToFB: (Settings object, fb.Builder fbb) {
|
||||||
|
final dateFormatOffset = fbb.writeString(object.dateFormat);
|
||||||
|
final longDateFormatOffset = object.longDateFormat == null
|
||||||
|
? null
|
||||||
|
: fbb.writeString(object.longDateFormat!);
|
||||||
|
final timeFormatOffset = fbb.writeString(object.timeFormat);
|
||||||
|
final longTimeFormatOffset = object.longTimeFormat == null
|
||||||
|
? null
|
||||||
|
: fbb.writeString(object.longTimeFormat!);
|
||||||
|
fbb.startTable(15);
|
||||||
|
fbb.addInt64(0, object.id);
|
||||||
|
fbb.addOffset(1, dateFormatOffset);
|
||||||
|
fbb.addOffset(2, longDateFormatOffset);
|
||||||
|
fbb.addOffset(3, timeFormatOffset);
|
||||||
|
fbb.addOffset(4, longTimeFormatOffset);
|
||||||
|
fbb.addBool(5, object.showConfirmationDialogOnCancel);
|
||||||
|
fbb.addBool(6, object.showConfirmationDialogOnDelete);
|
||||||
|
fbb.addBool(7, object.showConfirmationDialogOnStopEvent);
|
||||||
|
fbb.addInt64(8, object.lowGlucoseMgPerDl);
|
||||||
|
fbb.addInt64(9, object.moderateGlucoseMgPerDl);
|
||||||
|
fbb.addInt64(10, object.highGlucoseMgPerDl);
|
||||||
|
fbb.addFloat64(11, object.lowGlucoseMmolPerL);
|
||||||
|
fbb.addFloat64(12, object.moderateGlucoseMmolPerL);
|
||||||
|
fbb.addFloat64(13, object.highGlucoseMmolPerDl);
|
||||||
|
fbb.finish(fbb.endTable());
|
||||||
|
return object.id;
|
||||||
|
},
|
||||||
|
objectFromFB: (Store store, ByteData fbData) {
|
||||||
|
final buffer = fb.BufferContext(fbData);
|
||||||
|
final rootOffset = buffer.derefObject(0);
|
||||||
|
|
||||||
|
final object = Settings(
|
||||||
|
id: const fb.Int64Reader().vTableGet(buffer, rootOffset, 4, 0),
|
||||||
|
dateFormat:
|
||||||
|
const fb.StringReader().vTableGet(buffer, rootOffset, 6, ''),
|
||||||
|
longDateFormat: const fb.StringReader()
|
||||||
|
.vTableGetNullable(buffer, rootOffset, 8),
|
||||||
|
timeFormat:
|
||||||
|
const fb.StringReader().vTableGet(buffer, rootOffset, 10, ''),
|
||||||
|
longTimeFormat: const fb.StringReader()
|
||||||
|
.vTableGetNullable(buffer, rootOffset, 12),
|
||||||
|
showConfirmationDialogOnCancel: const fb.BoolReader()
|
||||||
|
.vTableGet(buffer, rootOffset, 14, false),
|
||||||
|
showConfirmationDialogOnDelete: const fb.BoolReader()
|
||||||
|
.vTableGet(buffer, rootOffset, 16, false),
|
||||||
|
showConfirmationDialogOnStopEvent: const fb.BoolReader()
|
||||||
|
.vTableGet(buffer, rootOffset, 18, false),
|
||||||
|
lowGlucoseMgPerDl:
|
||||||
|
const fb.Int64Reader().vTableGet(buffer, rootOffset, 20, 0),
|
||||||
|
moderateGlucoseMgPerDl:
|
||||||
|
const fb.Int64Reader().vTableGet(buffer, rootOffset, 22, 0),
|
||||||
|
highGlucoseMgPerDl:
|
||||||
|
const fb.Int64Reader().vTableGet(buffer, rootOffset, 24, 0),
|
||||||
|
lowGlucoseMmolPerL:
|
||||||
|
const fb.Float64Reader().vTableGet(buffer, rootOffset, 26, 0),
|
||||||
|
moderateGlucoseMmolPerL:
|
||||||
|
const fb.Float64Reader().vTableGet(buffer, rootOffset, 28, 0),
|
||||||
|
highGlucoseMmolPerDl:
|
||||||
|
const fb.Float64Reader().vTableGet(buffer, rootOffset, 30, 0));
|
||||||
|
|
||||||
return object;
|
return object;
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -2046,3 +2196,61 @@ class Accuracy_ {
|
||||||
static final deleted =
|
static final deleted =
|
||||||
QueryBooleanProperty<Accuracy>(_entities[13].properties[6]);
|
QueryBooleanProperty<Accuracy>(_entities[13].properties[6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [Settings] entity fields to define ObjectBox queries.
|
||||||
|
class Settings_ {
|
||||||
|
/// see [Settings.id]
|
||||||
|
static final id = QueryIntegerProperty<Settings>(_entities[14].properties[0]);
|
||||||
|
|
||||||
|
/// see [Settings.dateFormat]
|
||||||
|
static final dateFormat =
|
||||||
|
QueryStringProperty<Settings>(_entities[14].properties[1]);
|
||||||
|
|
||||||
|
/// see [Settings.longDateFormat]
|
||||||
|
static final longDateFormat =
|
||||||
|
QueryStringProperty<Settings>(_entities[14].properties[2]);
|
||||||
|
|
||||||
|
/// see [Settings.timeFormat]
|
||||||
|
static final timeFormat =
|
||||||
|
QueryStringProperty<Settings>(_entities[14].properties[3]);
|
||||||
|
|
||||||
|
/// see [Settings.longTimeFormat]
|
||||||
|
static final longTimeFormat =
|
||||||
|
QueryStringProperty<Settings>(_entities[14].properties[4]);
|
||||||
|
|
||||||
|
/// see [Settings.showConfirmationDialogOnCancel]
|
||||||
|
static final showConfirmationDialogOnCancel =
|
||||||
|
QueryBooleanProperty<Settings>(_entities[14].properties[5]);
|
||||||
|
|
||||||
|
/// see [Settings.showConfirmationDialogOnDelete]
|
||||||
|
static final showConfirmationDialogOnDelete =
|
||||||
|
QueryBooleanProperty<Settings>(_entities[14].properties[6]);
|
||||||
|
|
||||||
|
/// see [Settings.showConfirmationDialogOnStopEvent]
|
||||||
|
static final showConfirmationDialogOnStopEvent =
|
||||||
|
QueryBooleanProperty<Settings>(_entities[14].properties[7]);
|
||||||
|
|
||||||
|
/// see [Settings.lowGlucoseMgPerDl]
|
||||||
|
static final lowGlucoseMgPerDl =
|
||||||
|
QueryIntegerProperty<Settings>(_entities[14].properties[8]);
|
||||||
|
|
||||||
|
/// see [Settings.moderateGlucoseMgPerDl]
|
||||||
|
static final moderateGlucoseMgPerDl =
|
||||||
|
QueryIntegerProperty<Settings>(_entities[14].properties[9]);
|
||||||
|
|
||||||
|
/// see [Settings.highGlucoseMgPerDl]
|
||||||
|
static final highGlucoseMgPerDl =
|
||||||
|
QueryIntegerProperty<Settings>(_entities[14].properties[10]);
|
||||||
|
|
||||||
|
/// see [Settings.lowGlucoseMmolPerL]
|
||||||
|
static final lowGlucoseMmolPerL =
|
||||||
|
QueryDoubleProperty<Settings>(_entities[14].properties[11]);
|
||||||
|
|
||||||
|
/// see [Settings.moderateGlucoseMmolPerL]
|
||||||
|
static final moderateGlucoseMmolPerL =
|
||||||
|
QueryDoubleProperty<Settings>(_entities[14].properties[12]);
|
||||||
|
|
||||||
|
/// see [Settings.highGlucoseMmolPerDl]
|
||||||
|
static final highGlucoseMmolPerDl =
|
||||||
|
QueryDoubleProperty<Settings>(_entities[14].properties[13]);
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
|
@ -57,14 +57,16 @@ class _AccuracyDetailScreenState extends State<AccuracyDetailScreen> {
|
||||||
_isSaving = true;
|
_isSaving = true;
|
||||||
});
|
});
|
||||||
if (_accuracyForm.currentState!.validate()) {
|
if (_accuracyForm.currentState!.validate()) {
|
||||||
Accuracy.box.put(Accuracy(
|
Accuracy accuracy = Accuracy(
|
||||||
id: widget.id,
|
id: widget.id,
|
||||||
value: _valueController.text,
|
value: _valueController.text,
|
||||||
forCarbsRatio: _forCarbsRatio,
|
forCarbsRatio: _forCarbsRatio,
|
||||||
forPortionSize: _forPortionSize,
|
forPortionSize: _forPortionSize,
|
||||||
confidenceRating: int.tryParse(_confidenceRatingController.text),
|
|
||||||
notes: _notesController.text,
|
notes: _notesController.text,
|
||||||
));
|
);
|
||||||
|
Accuracy.box.put(accuracy);
|
||||||
|
Accuracy.reorder(
|
||||||
|
accuracy, int.tryParse(_confidenceRatingController.text));
|
||||||
Navigator.pop(context, '${_isNew ? 'New' : ''} Accuracy saved');
|
Navigator.pop(context, '${_isNew ? 'New' : ''} Accuracy saved');
|
||||||
}
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -73,7 +75,7 @@ class _AccuracyDetailScreenState extends State<AccuracyDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
(_isNew &&
|
(_isNew &&
|
||||||
(_forCarbsRatio ||
|
(_forCarbsRatio ||
|
||||||
_forPortionSize ||
|
_forPortionSize ||
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/accuracy_detail.dart';
|
import 'package:diameter/screens/accuracy_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -46,7 +46,7 @@ class _AccuracyListScreenState extends State<AccuracyListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(Accuracy accuracy) async {
|
void handleDeleteAction(Accuracy accuracy) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(accuracy),
|
onConfirm: () => onDelete(accuracy),
|
||||||
|
@ -83,12 +83,18 @@ class _AccuracyListScreenState extends State<AccuracyListScreen> {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _accuracies.isNotEmpty ? ListView.builder(
|
child: _accuracies.isNotEmpty
|
||||||
|
? ReorderableListView.builder(
|
||||||
padding: const EdgeInsets.only(top: 10.0),
|
padding: const EdgeInsets.only(top: 10.0),
|
||||||
itemCount: _accuracies.length,
|
itemCount: _accuracies.length,
|
||||||
|
onReorder: (oldIndex, newIndex) {
|
||||||
|
Accuracy.reorder(_accuracies[oldIndex], newIndex);
|
||||||
|
reload();
|
||||||
|
},
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final accuracy = _accuracies[index];
|
final accuracy = _accuracies[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
|
key: Key(index.toString()),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
@ -101,14 +107,8 @@ class _AccuracyListScreenState extends State<AccuracyListScreen> {
|
||||||
title: Text(accuracy.value),
|
title: Text(accuracy.value),
|
||||||
leading: Row(
|
leading: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: const [
|
||||||
IconButton(
|
Icon(Icons.reorder),
|
||||||
icon: const Icon(Icons.reorder),
|
|
||||||
onPressed: () {
|
|
||||||
// ignore: todo
|
|
||||||
// TODO: implement reordering
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
|
@ -118,30 +118,37 @@ class _AccuracyListScreenState extends State<AccuracyListScreen> {
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.square_foot,
|
Icons.square_foot,
|
||||||
color: accuracy.forPortionSize
|
color: accuracy.forPortionSize
|
||||||
? Theme.of(context).toggleableActiveColor
|
? Theme.of(context)
|
||||||
|
.toggleableActiveColor
|
||||||
: Theme.of(context).highlightColor,
|
: Theme.of(context).highlightColor,
|
||||||
),
|
),
|
||||||
onPressed: () => handleToggleForPortionSizeAction(accuracy),
|
onPressed: () =>
|
||||||
|
handleToggleForPortionSizeAction(
|
||||||
|
accuracy),
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.pie_chart,
|
Icons.pie_chart,
|
||||||
color: accuracy.forCarbsRatio
|
color: accuracy.forCarbsRatio
|
||||||
? Theme.of(context).toggleableActiveColor
|
? Theme.of(context)
|
||||||
|
.toggleableActiveColor
|
||||||
: Theme.of(context).highlightColor,
|
: Theme.of(context).highlightColor,
|
||||||
),
|
),
|
||||||
onPressed: () => handleToggleForCarbsRatioAction(accuracy),
|
onPressed: () =>
|
||||||
|
handleToggleForCarbsRatioAction(
|
||||||
|
accuracy),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 24),
|
const SizedBox(width: 24),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.delete),
|
icon: const Icon(Icons.delete),
|
||||||
onPressed: () => handleDeleteAction(accuracy),
|
onPressed: () =>
|
||||||
|
handleDeleteAction(accuracy),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
})
|
||||||
) : const Center(
|
: const Center(
|
||||||
child: Text('You have not created any Accuracies yet!'),
|
child: Text('You have not created any Accuracies yet!'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -151,7 +151,7 @@ class _BasalDetailScreenState extends State<BasalDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_startTime.hour != (widget.suggestedStartTime?.hour ?? 0) ||
|
(_startTime.hour != (widget.suggestedStartTime?.hour ?? 0) ||
|
||||||
_endTime.hour != (widget.suggestedEndTime?.hour ?? 0) ||
|
_endTime.hour != (widget.suggestedEndTime?.hour ?? 0) ||
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:diameter/models/basal.dart';
|
import 'package:diameter/models/basal.dart';
|
||||||
|
@ -57,7 +57,7 @@ class _BasalListScreenState extends State<BasalListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(Basal basal) async {
|
void handleDeleteAction(Basal basal) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(basal),
|
onConfirm: () => onDelete(basal),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/basal.dart';
|
import 'package:diameter/models/basal.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/basal/basal_detail.dart';
|
import 'package:diameter/screens/basal/basal_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -237,7 +237,7 @@ class _BasalProfileDetailScreenState extends State<BasalProfileDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
(_isNew &&
|
(_isNew &&
|
||||||
(_active != widget.active ||
|
(_active != widget.active ||
|
||||||
_nameController.text != '' ||
|
_nameController.text != '' ||
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:diameter/models/basal_profile.dart';
|
import 'package:diameter/models/basal_profile.dart';
|
||||||
|
@ -18,6 +19,8 @@ class _BasalProfileListScreenState extends State<BasalProfileListScreen> {
|
||||||
Widget banner = Container();
|
Widget banner = Container();
|
||||||
bool pickActiveProfileMode = false;
|
bool pickActiveProfileMode = false;
|
||||||
|
|
||||||
|
final BasalProfile? _activeProfile = BasalProfile.getActive(DateTime.now());
|
||||||
|
|
||||||
void refresh({String? message}) {
|
void refresh({String? message}) {
|
||||||
setState(() {
|
setState(() {
|
||||||
pickActiveProfileMode = false;
|
pickActiveProfileMode = false;
|
||||||
|
@ -77,7 +80,7 @@ class _BasalProfileListScreenState extends State<BasalProfileListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(BasalProfile basalProfile) async {
|
void handleDeleteAction(BasalProfile basalProfile) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(basalProfile),
|
onConfirm: () => onDelete(basalProfile),
|
||||||
|
@ -88,17 +91,24 @@ class _BasalProfileListScreenState extends State<BasalProfileListScreen> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onPickActive(BasalProfile basalProfile) {
|
void onPickActive(BasalProfile? basalProfile) {
|
||||||
|
if (basalProfile != null) {
|
||||||
BasalProfile.setAllInactive;
|
BasalProfile.setAllInactive;
|
||||||
basalProfile.active = true;
|
basalProfile.active = true;
|
||||||
BasalProfile.put(basalProfile);
|
BasalProfile.put(basalProfile);
|
||||||
refresh(message: '${basalProfile.name} has been set as your active Profile');
|
refresh(
|
||||||
|
message: '${basalProfile.name} has been set as your active Profile');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handlePickActiveProfileAction() {
|
void handlePickActiveProfileAction() {
|
||||||
setState(() {
|
setState(() {
|
||||||
banner = MaterialBanner(
|
banner = MaterialBanner(
|
||||||
content: const Text('Click one of the profiles to active it.'),
|
content: AutoCompleteDropdownButton(
|
||||||
|
items: _basalProfiles,
|
||||||
|
label: 'Default Basal Profile',
|
||||||
|
onChanged: onPickActive,
|
||||||
|
),
|
||||||
leading: const CircleAvatar(child: Icon(Icons.info)),
|
leading: const CircleAvatar(child: Icon(Icons.info)),
|
||||||
forceActionsBelow: true,
|
forceActionsBelow: true,
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -116,8 +126,8 @@ class _BasalProfileListScreenState extends State<BasalProfileListScreen> {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BasalProfileDetailScreen(
|
builder: (context) =>
|
||||||
id: basalProfile?.id ?? 0, active: active),
|
BasalProfileDetailScreen(id: basalProfile?.id ?? 0, active: active),
|
||||||
),
|
),
|
||||||
).then((message) => refresh(message: message));
|
).then((message) => refresh(message: message));
|
||||||
}
|
}
|
||||||
|
@ -152,24 +162,24 @@ class _BasalProfileListScreenState extends State<BasalProfileListScreen> {
|
||||||
children: [
|
children: [
|
||||||
banner,
|
banner,
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _basalProfiles.isNotEmpty ? ListView.builder(
|
child: _basalProfiles.isNotEmpty
|
||||||
|
? ListView.builder(
|
||||||
itemCount: _basalProfiles.length,
|
itemCount: _basalProfiles.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final basalProfile = _basalProfiles[index];
|
final basalProfile = _basalProfiles[index];
|
||||||
|
String activeProfileText = basalProfile.active
|
||||||
|
? 'Default Profile'
|
||||||
|
: basalProfile.id == _activeProfile?.id
|
||||||
|
? 'Current Active Profile'
|
||||||
|
: '';
|
||||||
|
if (activeProfileText != '' && (basalProfile.notes ?? '') != '') {
|
||||||
|
activeProfileText += '\n';
|
||||||
|
}
|
||||||
return ListTile(
|
return ListTile(
|
||||||
tileColor: basalProfile.active
|
selected: basalProfile.active || basalProfile.id == _activeProfile?.id,
|
||||||
? Colors.green.shade100
|
onTap: () => onEdit(basalProfile),
|
||||||
: null,
|
title: Text(basalProfile.name),
|
||||||
onTap: () {
|
subtitle: Text('$activeProfileText${basalProfile.notes ?? ''}'),
|
||||||
pickActiveProfileMode
|
|
||||||
? onPickActive(basalProfile)
|
|
||||||
: onEdit(basalProfile);
|
|
||||||
},
|
|
||||||
title: Text(
|
|
||||||
basalProfile.name,
|
|
||||||
),
|
|
||||||
subtitle: Text(basalProfile.notes!),
|
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
@ -178,14 +188,14 @@ class _BasalProfileListScreenState extends State<BasalProfileListScreen> {
|
||||||
Icons.delete,
|
Icons.delete,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
),
|
),
|
||||||
onPressed: () =>
|
onPressed: () => handleDeleteAction(basalProfile),
|
||||||
handleDeleteAction(basalProfile),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
) : const Center(
|
)
|
||||||
|
: const Center(
|
||||||
child: Text('You have not created any Basal Profiles yet!'),
|
child: Text('You have not created any Basal Profiles yet!'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:diameter/utils/utils.dart';
|
import 'package:diameter/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -166,7 +165,7 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_startTime.hour != (widget.suggestedStartTime?.hour ?? 0) ||
|
(_startTime.hour != (widget.suggestedStartTime?.hour ?? 0) ||
|
||||||
_endTime.hour != (widget.suggestedEndTime?.hour ?? 0) ||
|
_endTime.hour != (widget.suggestedEndTime?.hour ?? 0) ||
|
||||||
|
@ -297,12 +296,7 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||||
TextFormField(
|
TextFormField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'per carbs',
|
labelText: 'per carbs',
|
||||||
suffixText: nutritionMeasurement ==
|
suffixText: nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index],
|
||||||
NutritionMeasurement.grams
|
|
||||||
? 'g'
|
|
||||||
: nutritionMeasurement == NutritionMeasurement.ounces
|
|
||||||
? 'oz'
|
|
||||||
: '',
|
|
||||||
),
|
),
|
||||||
controller: _carbsController,
|
controller: _carbsController,
|
||||||
keyboardType:
|
keyboardType:
|
||||||
|
@ -316,9 +310,9 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
Settings.get().glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
Settings.get().glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? Expanded(
|
? Expanded(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
@ -343,8 +337,8 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
Settings.get().glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () => convertBetweenMgPerDlAndMmolPerL(
|
onPressed: () => convertBetweenMgPerDlAndMmolPerL(
|
||||||
|
@ -352,9 +346,9 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||||
icon: const Icon(Icons.calculate),
|
icon: const Icon(Icons.calculate),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
Settings.get().glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
Settings.get().glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? Expanded(
|
? Expanded(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
@ -380,8 +374,8 @@ class _BolusDetailScreenState extends State<BolusDetailScreen> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
Settings.get().glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () => convertBetweenMgPerDlAndMmolPerL(
|
onPressed: () => convertBetweenMgPerDlAndMmolPerL(
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:diameter/models/bolus.dart';
|
import 'package:diameter/models/bolus.dart';
|
||||||
|
@ -55,7 +54,7 @@ class _BolusListScreenState extends State<BolusListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(Bolus bolus) async {
|
void handleDeleteAction(Bolus bolus) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(bolus),
|
onConfirm: () => onDelete(bolus),
|
||||||
|
@ -128,7 +127,7 @@ class _BolusListScreenState extends State<BolusListScreen> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'${bolus.units} U per ${bolus.carbs}${nutritionMeasurement == NutritionMeasurement.grams ? ' g' : ' oz'} carbs/${glucoseMeasurement == GlucoseMeasurement.mgPerDl ? bolus.mgPerDl : bolus.mmolPerL} ${glucoseMeasurement == GlucoseMeasurement.mgPerDl ? 'mg/dl' : 'mmol/l'}'),
|
'${bolus.units} U per ${bolus.carbs}${nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index]} carbs/${Settings.get().glucoseMeasurement == GlucoseMeasurement.mgPerDl ? bolus.mgPerDl : bolus.mmolPerL} ${glucoseMeasurementSuffixes[Settings.get().glucoseMeasurement.index]}'),
|
||||||
error != null
|
error != null
|
||||||
? Text(error,
|
? Text(error,
|
||||||
style: const TextStyle(color: Colors.red))
|
style: const TextStyle(color: Colors.red))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/bolus.dart';
|
import 'package:diameter/models/bolus.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/bolus/bolus_detail.dart';
|
import 'package:diameter/screens/bolus/bolus_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -238,7 +238,7 @@ class _BolusProfileDetailScreenState extends State<BolusProfileDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
(_isNew &&
|
(_isNew &&
|
||||||
(_active != widget.active ||
|
(_active != widget.active ||
|
||||||
_nameController.text != '' ||
|
_nameController.text != '' ||
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:diameter/models/bolus_profile.dart';
|
import 'package:diameter/models/bolus_profile.dart';
|
||||||
|
@ -18,6 +19,8 @@ class _BolusProfileListScreenState extends State<BolusProfileListScreen> {
|
||||||
Widget banner = Container();
|
Widget banner = Container();
|
||||||
bool pickActiveProfileMode = false;
|
bool pickActiveProfileMode = false;
|
||||||
|
|
||||||
|
final BolusProfile? _activeProfile = BolusProfile.getActive(DateTime.now());
|
||||||
|
|
||||||
void reload({String? message}) {
|
void reload({String? message}) {
|
||||||
setState(() {
|
setState(() {
|
||||||
pickActiveProfileMode = false;
|
pickActiveProfileMode = false;
|
||||||
|
@ -80,7 +83,7 @@ class _BolusProfileListScreenState extends State<BolusProfileListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(BolusProfile bolusProfile) async {
|
void handleDeleteAction(BolusProfile bolusProfile) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(bolusProfile),
|
onConfirm: () => onDelete(bolusProfile),
|
||||||
|
@ -91,18 +94,23 @@ class _BolusProfileListScreenState extends State<BolusProfileListScreen> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onPickActive(BolusProfile bolusProfile) {
|
void onPickActive(BolusProfile? bolusProfile) {
|
||||||
|
if (bolusProfile != null) {
|
||||||
BolusProfile.setAllInactive;
|
BolusProfile.setAllInactive;
|
||||||
bolusProfile.active = true;
|
bolusProfile.active = true;
|
||||||
BolusProfile.put(bolusProfile);
|
BolusProfile.put(bolusProfile);
|
||||||
reload(
|
reload(message: '${bolusProfile.name} has been set as your active Profile');
|
||||||
message: '${bolusProfile.name} has been set as your active Profile');
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void handlePickActiveProfileAction() {
|
void handlePickActiveProfileAction() {
|
||||||
setState(() {
|
setState(() {
|
||||||
banner = MaterialBanner(
|
banner = MaterialBanner(
|
||||||
content: const Text('Click one of the profiles to active it.'),
|
content: AutoCompleteDropdownButton(
|
||||||
|
items: _bolusProfiles,
|
||||||
|
label: 'Default Basal Profile',
|
||||||
|
onChanged: onPickActive,
|
||||||
|
),
|
||||||
leading: const CircleAvatar(child: Icon(Icons.info)),
|
leading: const CircleAvatar(child: Icon(Icons.info)),
|
||||||
forceActionsBelow: true,
|
forceActionsBelow: true,
|
||||||
actions: [
|
actions: [
|
||||||
|
@ -120,8 +128,8 @@ class _BolusProfileListScreenState extends State<BolusProfileListScreen> {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => BolusProfileDetailScreen(
|
builder: (context) =>
|
||||||
id: bolusProfile?.id ?? 0, active: active),
|
BolusProfileDetailScreen(id: bolusProfile?.id ?? 0, active: active),
|
||||||
),
|
),
|
||||||
).then((message) => reload(message: message));
|
).then((message) => reload(message: message));
|
||||||
}
|
}
|
||||||
|
@ -156,23 +164,27 @@ class _BolusProfileListScreenState extends State<BolusProfileListScreen> {
|
||||||
children: [
|
children: [
|
||||||
banner,
|
banner,
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _bolusProfiles.isNotEmpty ? ListView.builder(
|
child: _bolusProfiles.isNotEmpty
|
||||||
|
? ListView.builder(
|
||||||
itemCount: _bolusProfiles.length,
|
itemCount: _bolusProfiles.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final bolusProfile = _bolusProfiles[index];
|
final bolusProfile = _bolusProfiles[index];
|
||||||
|
String activeProfileText = bolusProfile.active
|
||||||
|
? 'Default Profile'
|
||||||
|
: bolusProfile.id == _activeProfile?.id
|
||||||
|
? 'Current Active Profile'
|
||||||
|
: '';
|
||||||
|
if (activeProfileText != '' && (bolusProfile.notes ?? '') != '') {
|
||||||
|
activeProfileText += '\n';
|
||||||
|
}
|
||||||
return ListTile(
|
return ListTile(
|
||||||
tileColor: bolusProfile.active
|
selected: bolusProfile.active || bolusProfile.id == _activeProfile?.id,
|
||||||
? Colors.green.shade100
|
onTap: () => onEdit(bolusProfile),
|
||||||
: null,
|
|
||||||
onTap: () {
|
|
||||||
pickActiveProfileMode
|
|
||||||
? onPickActive(bolusProfile)
|
|
||||||
: onEdit(bolusProfile);
|
|
||||||
},
|
|
||||||
title: Text(
|
title: Text(
|
||||||
bolusProfile.name,
|
bolusProfile.name,
|
||||||
),
|
),
|
||||||
subtitle: Text(bolusProfile.notes!),
|
isThreeLine: activeProfileText != '' && (bolusProfile.notes ?? '') != '',
|
||||||
|
subtitle: Text('$activeProfileText${bolusProfile.notes ?? ''}'),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
@ -181,14 +193,14 @@ class _BolusProfileListScreenState extends State<BolusProfileListScreen> {
|
||||||
Icons.delete,
|
Icons.delete,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
),
|
),
|
||||||
onPressed: () =>
|
onPressed: () => handleDeleteAction(bolusProfile),
|
||||||
handleDeleteAction(bolusProfile),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
) : const Center(
|
)
|
||||||
|
: const Center(
|
||||||
child: Text('You have not created any Bolus Profiles yet!'),
|
child: Text('You have not created any Bolus Profiles yet!'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/log_bolus.dart';
|
import 'package:diameter/models/log_bolus.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
import 'package:diameter/models/log_entry.dart';
|
||||||
import 'package:diameter/models/log_meal.dart';
|
import 'package:diameter/models/log_meal.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
import 'package:diameter/screens/log/log_entry/log_entry.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -49,7 +48,7 @@ class _LogScreenState extends State<LogScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(LogEntry logEntry) async {
|
void handleDeleteAction(LogEntry logEntry) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(logEntry),
|
onConfirm: () => onDelete(logEntry),
|
||||||
|
@ -71,78 +70,57 @@ class _LogScreenState extends State<LogScreen> {
|
||||||
),
|
),
|
||||||
drawer: const Navigation(currentLocation: LogScreen.routeName),
|
drawer: const Navigation(currentLocation: LogScreen.routeName),
|
||||||
body: Column(
|
body: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
||||||
children: <Widget>[
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _logEntryDailyMap.isNotEmpty
|
child: _logEntryDailyMap.isNotEmpty
|
||||||
? SingleChildScrollView(
|
? ListView.builder(
|
||||||
child: ListView.builder(
|
|
||||||
shrinkWrap: true,
|
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
|
shrinkWrap: true,
|
||||||
itemCount: _logEntryDailyMap.length,
|
itemCount: _logEntryDailyMap.length,
|
||||||
itemBuilder: (context, dateIndex) {
|
itemBuilder: (context, dateIndex) {
|
||||||
List<DateTime> dateList =
|
List<DateTime> dateList = _logEntryDailyMap.keys.toList();
|
||||||
_logEntryDailyMap.keys.toList();
|
|
||||||
final date = dateList[dateIndex];
|
final date = dateList[dateIndex];
|
||||||
final entryList = _logEntryDailyMap[date];
|
final entryList = _logEntryDailyMap[date];
|
||||||
return ListBody(
|
final tiles = <Widget>[];
|
||||||
children: [
|
for (LogEntry logEntry in entryList!) {
|
||||||
Text(DateTimeUtils.displayDate(date)),
|
|
||||||
entryList != null && entryList.isNotEmpty
|
|
||||||
? ListView.builder(
|
|
||||||
shrinkWrap: true,
|
|
||||||
itemCount: entryList.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final logEntry = entryList[index];
|
|
||||||
double bolus =
|
double bolus =
|
||||||
LogBolus.getTotalBolusForEntry(
|
LogBolus.getTotalBolusForEntry(logEntry.id);
|
||||||
logEntry.id);
|
|
||||||
double carbs =
|
double carbs =
|
||||||
LogMeal.getTotalCarbsForEntry(
|
LogMeal.getTotalCarbsForEntry(logEntry.id);
|
||||||
logEntry.id);
|
tiles.add(ListTile(
|
||||||
return ListTile(
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
LogEntryScreen(
|
LogEntryScreen(id: logEntry.id),
|
||||||
id: logEntry.id),
|
|
||||||
),
|
),
|
||||||
).then((message) =>
|
).then((message) => reload(message: message));
|
||||||
reload(message: message));
|
|
||||||
},
|
},
|
||||||
title: Row(
|
title: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
DateTimeUtils.displayTime(
|
DateTimeUtils.displayTime(logEntry.time),
|
||||||
logEntry.time),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: logEntry
|
children: logEntry.mgPerDl != null &&
|
||||||
.mgPerDl !=
|
(Settings.get().glucoseMeasurement ==
|
||||||
null &&
|
GlucoseMeasurement.mgPerDl ||
|
||||||
(glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
Settings.get().glucoseDisplayMode ==
|
||||||
glucoseDisplayMode ==
|
GlucoseDisplayMode.both ||
|
||||||
GlucoseDisplayMode
|
Settings.get().glucoseDisplayMode ==
|
||||||
.both ||
|
|
||||||
glucoseDisplayMode ==
|
|
||||||
GlucoseDisplayMode
|
GlucoseDisplayMode
|
||||||
.bothForList)
|
.bothForList)
|
||||||
? [
|
? [
|
||||||
Text(logEntry
|
Text(logEntry.mgPerDl.toString()),
|
||||||
.mgPerDl
|
|
||||||
.toString()),
|
|
||||||
const Text(
|
const Text(
|
||||||
'mg/dl',
|
'mg/dl',
|
||||||
textScaleFactor:
|
textScaleFactor: 0.75,
|
||||||
0.75,
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
|
@ -150,24 +128,19 @@ class _LogScreenState extends State<LogScreen> {
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: logEntry
|
children: logEntry.mmolPerL != null &&
|
||||||
.mmolPerL !=
|
(Settings.get().glucoseMeasurement ==
|
||||||
null &&
|
GlucoseMeasurement.mmolPerL ||
|
||||||
(glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
Settings.get().glucoseDisplayMode ==
|
||||||
glucoseDisplayMode ==
|
GlucoseDisplayMode.both ||
|
||||||
GlucoseDisplayMode
|
Settings.get().glucoseDisplayMode ==
|
||||||
.both ||
|
|
||||||
glucoseDisplayMode ==
|
|
||||||
GlucoseDisplayMode
|
GlucoseDisplayMode
|
||||||
.bothForList)
|
.bothForList)
|
||||||
? [
|
? [
|
||||||
Text(logEntry
|
Text(logEntry.mmolPerL.toString()),
|
||||||
.mmolPerL
|
|
||||||
.toString()),
|
|
||||||
const Text(
|
const Text(
|
||||||
'mmol/l',
|
'mmol/l',
|
||||||
textScaleFactor:
|
textScaleFactor: 0.75,
|
||||||
0.75,
|
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
|
@ -177,12 +150,9 @@ class _LogScreenState extends State<LogScreen> {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: (bolus > 0)
|
children: (bolus > 0)
|
||||||
? [
|
? [
|
||||||
Text(bolus
|
Text(bolus.toStringAsPrecision(3)),
|
||||||
.toStringAsPrecision(
|
|
||||||
3)),
|
|
||||||
const Text('U',
|
const Text('U',
|
||||||
textScaleFactor:
|
textScaleFactor: 0.75),
|
||||||
0.75),
|
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
),
|
),
|
||||||
|
@ -191,21 +161,10 @@ class _LogScreenState extends State<LogScreen> {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: (carbs > 0)
|
children: (carbs > 0)
|
||||||
? [
|
? [
|
||||||
Text(carbs
|
Text(carbs.toStringAsPrecision(3)),
|
||||||
.toStringAsPrecision(
|
|
||||||
3)),
|
|
||||||
Text(
|
Text(
|
||||||
nutritionMeasurement ==
|
nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index],
|
||||||
NutritionMeasurement
|
textScaleFactor: 0.75),
|
||||||
.grams
|
|
||||||
? 'g carbs'
|
|
||||||
: nutritionMeasurement ==
|
|
||||||
NutritionMeasurement
|
|
||||||
.ounces
|
|
||||||
? 'oz carbs'
|
|
||||||
: '',
|
|
||||||
textScaleFactor:
|
|
||||||
0.75),
|
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
),
|
),
|
||||||
|
@ -216,20 +175,20 @@ class _LogScreenState extends State<LogScreen> {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () =>
|
onPressed: () => handleDeleteAction(logEntry),
|
||||||
handleDeleteAction(logEntry),
|
|
||||||
icon: const Icon(Icons.delete,
|
icon: const Icon(Icons.delete,
|
||||||
color: Colors.blue),
|
color: Colors.blue),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
));
|
||||||
})
|
|
||||||
: Container(),
|
}
|
||||||
],
|
return ListBody(
|
||||||
|
children: <Widget>[Text(DateTimeUtils.displayDate(date))] + tiles,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
|
||||||
)
|
)
|
||||||
: const Center(
|
: const Center(
|
||||||
child: Text('You have not created any Log Entries yet!'),
|
child: Text('You have not created any Log Entries yet!'),
|
||||||
|
|
|
@ -4,13 +4,12 @@ import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/dropdown.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/bolus.dart';
|
import 'package:diameter/models/bolus.dart';
|
||||||
import 'package:diameter/models/log_bolus.dart';
|
import 'package:diameter/models/log_bolus.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
import 'package:diameter/models/log_entry.dart';
|
||||||
import 'package:diameter/models/log_meal.dart';
|
import 'package:diameter/models/log_meal.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:diameter/utils/utils.dart';
|
import 'package:diameter/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -34,8 +33,7 @@ class LogBolusDetailScreen extends StatefulWidget {
|
||||||
final int logEntryId;
|
final int logEntryId;
|
||||||
final int id;
|
final int id;
|
||||||
|
|
||||||
const LogBolusDetailScreen(
|
const LogBolusDetailScreen({Key? key, this.logEntryId = 0, this.id = 0})
|
||||||
{Key? key, this.logEntryId = 0, this.id = 0})
|
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -62,10 +60,14 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
final _delayController = TextEditingController(text: '');
|
final _delayController = TextEditingController(text: '');
|
||||||
final _notesController = TextEditingController(text: '');
|
final _notesController = TextEditingController(text: '');
|
||||||
|
|
||||||
|
final _delayedUnitsController = TextEditingController(text: '');
|
||||||
|
final _immediateUnitsController = TextEditingController(text: '');
|
||||||
|
|
||||||
bool _setManually = false;
|
bool _setManually = false;
|
||||||
BolusType _bolusType = BolusType.meal;
|
BolusType _bolusType = BolusType.meal;
|
||||||
LogMeal? _meal;
|
LogMeal? _meal;
|
||||||
Bolus? _rate;
|
Bolus? _rate;
|
||||||
|
double _delayPercentage = 0;
|
||||||
|
|
||||||
List<LogMeal> _logMeals = [];
|
List<LogMeal> _logMeals = [];
|
||||||
|
|
||||||
|
@ -88,26 +90,45 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
|
|
||||||
_rate ??= Bolus.getRateForTime(_logEntry?.time);
|
_rate ??= Bolus.getRateForTime(_logEntry?.time);
|
||||||
|
|
||||||
_mgPerDlCurrentController.text =
|
_mgPerDlCurrentController.text = (_logBolus?.mgPerDlCurrent ??
|
||||||
(_logBolus?.mgPerDlCurrent ?? (LogEntry.hasUncorrectedGlucose(widget.logEntryId) ? _logEntry?.mgPerDl ?? 0 : 0)).toString();
|
(LogEntry.hasUncorrectedGlucose(widget.logEntryId)
|
||||||
|
? _logEntry?.mgPerDl ?? 0
|
||||||
|
: 0))
|
||||||
|
.toString();
|
||||||
_mgPerDlTargetController.text =
|
_mgPerDlTargetController.text =
|
||||||
(_logBolus?.mgPerDlTarget ?? moderateGlucoseMgPerDl).toString();
|
(_logBolus?.mgPerDlTarget ?? Settings.get().moderateGlucoseMgPerDl).toString();
|
||||||
_mgPerDlCorrectionController.text =
|
_mgPerDlCorrectionController.text = (_logBolus?.mgPerDlCorrection ??
|
||||||
(_logBolus?.mgPerDlCorrection ?? max((int.tryParse(_mgPerDlCurrentController.text) ?? 0) - (int.tryParse(_mgPerDlTargetController.text) ?? 0), 0)).toString();
|
max(
|
||||||
_mmolPerLCurrentController.text =
|
(int.tryParse(_mgPerDlCurrentController.text) ?? 0) -
|
||||||
(_logBolus?.mmolPerLCurrent ?? (LogEntry.hasUncorrectedGlucose(widget.logEntryId) ? _logEntry?.mmolPerL ?? 0 : 0)).toString();
|
(int.tryParse(_mgPerDlTargetController.text) ?? 0),
|
||||||
|
0))
|
||||||
|
.toString();
|
||||||
|
_mmolPerLCurrentController.text = (_logBolus?.mmolPerLCurrent ??
|
||||||
|
(LogEntry.hasUncorrectedGlucose(widget.logEntryId)
|
||||||
|
? _logEntry?.mmolPerL ?? 0
|
||||||
|
: 0))
|
||||||
|
.toString();
|
||||||
_mmolPerLTargetController.text =
|
_mmolPerLTargetController.text =
|
||||||
(_logBolus?.mmolPerLTarget ?? moderateGlucoseMmolPerL).toString();
|
(_logBolus?.mmolPerLTarget ?? Settings.get().moderateGlucoseMmolPerL).toString();
|
||||||
_mmolPerLCorrectionController.text =
|
_mmolPerLCorrectionController.text = (_logBolus?.mmolPerLCorrection ??
|
||||||
(_logBolus?.mmolPerLCorrection ?? max((double.tryParse(_mmolPerLCurrentController.text) ?? 0) - (double.tryParse(_mmolPerLTargetController.text) ?? 0), 0)).toString();
|
max(
|
||||||
|
(double.tryParse(_mmolPerLCurrentController.text) ?? 0) -
|
||||||
|
(double.tryParse(_mmolPerLTargetController.text) ?? 0),
|
||||||
|
0))
|
||||||
|
.toString();
|
||||||
|
|
||||||
_unitsController.text = (_logBolus?.units ??
|
_unitsController.text = (_logBolus?.units ??
|
||||||
(_rate != null && !_setManually ? ((int.tryParse(_mgPerDlCorrectionController.text) ?? 0) / ((_rate!.mgPerDl ?? 0) / _rate!.units)) : 0)
|
(_rate != null && !_setManually
|
||||||
).toString();
|
? ((int.tryParse(_mgPerDlCorrectionController.text) ?? 0) /
|
||||||
|
((_rate!.mgPerDl ?? 0) / _rate!.units))
|
||||||
|
: 0))
|
||||||
|
.toString();
|
||||||
|
|
||||||
if (widget.id == 0 && LogEntry.hasUncorrectedGlucose(widget.logEntryId)) {
|
if (widget.id == 0 && LogEntry.hasUncorrectedGlucose(widget.logEntryId)) {
|
||||||
_bolusType = BolusType.glucose;
|
_bolusType = BolusType.glucose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateDelayedRatio();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reload() {
|
void reload() {
|
||||||
|
@ -119,6 +140,23 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
_isNew = _logBolus == null;
|
_isNew = _logBolus == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateDelayedRatio() {
|
||||||
|
if (_unitsController.text != '') {
|
||||||
|
setState(() {
|
||||||
|
_delayedUnitsController.text =
|
||||||
|
((double.tryParse(_unitsController.text) ?? 0) *
|
||||||
|
_delayPercentage /
|
||||||
|
100)
|
||||||
|
.toString();
|
||||||
|
_immediateUnitsController.text =
|
||||||
|
((double.tryParse(_unitsController.text) ?? 0) *
|
||||||
|
(100 - _delayPercentage) /
|
||||||
|
100)
|
||||||
|
.toString();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onSelectMeal(LogMeal meal) {
|
void onSelectMeal(LogMeal meal) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_meal = meal;
|
_meal = meal;
|
||||||
|
@ -135,6 +173,18 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
_unitsController.text = ((double.tryParse(_carbsController.text) ?? 0) /
|
_unitsController.text = ((double.tryParse(_carbsController.text) ?? 0) /
|
||||||
(_rate!.carbs / _rate!.units))
|
(_rate!.carbs / _rate!.units))
|
||||||
.toString();
|
.toString();
|
||||||
|
if (_unitsController.text != '') {
|
||||||
|
_delayedUnitsController.text =
|
||||||
|
((double.tryParse(_unitsController.text) ?? 0) *
|
||||||
|
_delayPercentage /
|
||||||
|
100)
|
||||||
|
.toString();
|
||||||
|
_immediateUnitsController.text =
|
||||||
|
((double.tryParse(_unitsController.text) ?? 0) *
|
||||||
|
(100 - _delayPercentage) /
|
||||||
|
100)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -206,15 +256,41 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
_isSaving = true;
|
_isSaving = true;
|
||||||
});
|
});
|
||||||
if (_logBolusForm.currentState!.validate()) {
|
if (_logBolusForm.currentState!.validate()) {
|
||||||
LogBolus logBolus = LogBolus(
|
LogBolus logBolus;
|
||||||
|
LogBolus? delayedBolus;
|
||||||
|
|
||||||
|
if ((int.tryParse(_delayController.text) ?? 0) != 0 &&
|
||||||
|
_delayPercentage != 0 &&
|
||||||
|
_delayPercentage != 100) {
|
||||||
|
logBolus = LogBolus(
|
||||||
id: widget.id,
|
id: widget.id,
|
||||||
units: double.tryParse(_unitsController.text) ?? 0,
|
units: double.tryParse(_immediateUnitsController.text) ?? 0,
|
||||||
delay: int.tryParse(_delayController.text),
|
|
||||||
setManually: _setManually,
|
setManually: _setManually,
|
||||||
notes: _notesController.text,
|
notes: _notesController.text,
|
||||||
);
|
);
|
||||||
|
delayedBolus = LogBolus(
|
||||||
|
delay: int.tryParse(_delayController.text),
|
||||||
|
units: double.tryParse(_delayedUnitsController.text) ?? 0,
|
||||||
|
setManually: _setManually,
|
||||||
|
notes: _notesController.text,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
logBolus = LogBolus(
|
||||||
|
id: widget.id,
|
||||||
|
units: double.tryParse(_unitsController.text) ?? 0,
|
||||||
|
delay: _delayPercentage == 100
|
||||||
|
? int.tryParse(_delayController.text)
|
||||||
|
: null,
|
||||||
|
setManually: _setManually,
|
||||||
|
notes: _notesController.text,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (_bolusType == BolusType.meal) {
|
if (_bolusType == BolusType.meal) {
|
||||||
logBolus.carbs = double.tryParse(_carbsController.text);
|
logBolus.carbs = double.tryParse(_carbsController.text);
|
||||||
|
if (delayedBolus != null) {
|
||||||
|
delayedBolus.carbs = double.tryParse(_carbsController.text);
|
||||||
|
}
|
||||||
logBolus.mgPerDlCurrent = null;
|
logBolus.mgPerDlCurrent = null;
|
||||||
logBolus.mmolPerLCurrent = null;
|
logBolus.mmolPerLCurrent = null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -225,14 +301,37 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
logBolus.mgPerDlTarget = int.tryParse(_mgPerDlTargetController.text);
|
logBolus.mgPerDlTarget = int.tryParse(_mgPerDlTargetController.text);
|
||||||
logBolus.mmolPerLTarget =
|
logBolus.mmolPerLTarget =
|
||||||
double.tryParse(_mmolPerLTargetController.text);
|
double.tryParse(_mmolPerLTargetController.text);
|
||||||
logBolus.mgPerDlCorrection = int.tryParse(_mgPerDlCorrectionController.text);
|
logBolus.mgPerDlCorrection =
|
||||||
|
int.tryParse(_mgPerDlCorrectionController.text);
|
||||||
logBolus.mmolPerLCorrection =
|
logBolus.mmolPerLCorrection =
|
||||||
double.tryParse(_mmolPerLCorrectionController.text);
|
double.tryParse(_mmolPerLCorrectionController.text);
|
||||||
|
if (delayedBolus != null) {
|
||||||
|
delayedBolus.mgPerDlCurrent =
|
||||||
|
int.tryParse(_mgPerDlCurrentController.text);
|
||||||
|
delayedBolus.mmolPerLCurrent =
|
||||||
|
double.tryParse(_mmolPerLCurrentController.text);
|
||||||
|
delayedBolus.mgPerDlTarget =
|
||||||
|
int.tryParse(_mgPerDlTargetController.text);
|
||||||
|
delayedBolus.mmolPerLTarget =
|
||||||
|
double.tryParse(_mmolPerLTargetController.text);
|
||||||
|
delayedBolus.mgPerDlCorrection =
|
||||||
|
int.tryParse(_mgPerDlCorrectionController.text);
|
||||||
|
delayedBolus.mmolPerLCorrection =
|
||||||
|
double.tryParse(_mmolPerLCorrectionController.text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
logBolus.logEntry.target = _logEntry;
|
logBolus.logEntry.target = _logEntry;
|
||||||
logBolus.meal.target = _meal;
|
logBolus.meal.target = _meal;
|
||||||
logBolus.rate.target = _rate;
|
logBolus.rate.target = _rate;
|
||||||
LogBolus.put(logBolus);
|
LogBolus.put(logBolus);
|
||||||
|
|
||||||
|
if (delayedBolus != null) {
|
||||||
|
delayedBolus.logEntry.target = _logEntry;
|
||||||
|
delayedBolus.meal.target = _meal;
|
||||||
|
delayedBolus.rate.target = _rate;
|
||||||
|
LogBolus.put(delayedBolus);
|
||||||
|
}
|
||||||
|
|
||||||
Navigator.pop(context, '${_isNew ? 'New' : ''} Bolus Saved');
|
Navigator.pop(context, '${_isNew ? 'New' : ''} Bolus Saved');
|
||||||
}
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
|
@ -241,16 +340,18 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_unitsController.text != '' ||
|
(_carbsController.text != '' ||
|
||||||
_carbsController.text != '' ||
|
(_bolusType == BolusType.glucose &&
|
||||||
_mgPerDlCurrentController.text != '' ||
|
(_mgPerDlCurrentController.text !=
|
||||||
_mgPerDlTargetController.text != '' ||
|
(_logEntry?.mgPerDl.toString() ?? '') ||
|
||||||
_mgPerDlCorrectionController.text != '' ||
|
_mmolPerLCurrentController.text !=
|
||||||
_mmolPerLCurrentController.text != '' ||
|
(_logEntry?.mmolPerL.toString() ?? ''))) ||
|
||||||
_mmolPerLTargetController.text != '' ||
|
_mgPerDlTargetController.text !=
|
||||||
_mmolPerLCorrectionController.text != '' ||
|
Settings.get().moderateGlucoseMgPerDl.toString() ||
|
||||||
|
_mmolPerLTargetController.text !=
|
||||||
|
Settings.get().moderateGlucoseMmolPerL.toString() ||
|
||||||
_delayController.text != '' ||
|
_delayController.text != '' ||
|
||||||
_setManually ||
|
_setManually ||
|
||||||
_notesController.text != '')) ||
|
_notesController.text != '')) ||
|
||||||
|
@ -297,7 +398,10 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
FormWrapper(
|
FormWrapper(
|
||||||
formState: _logBolusForm,
|
formState: _logBolusForm,
|
||||||
fields: [
|
fields: [
|
||||||
TextFormField(
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Bolus Units',
|
labelText: 'Bolus Units',
|
||||||
suffixText: ' U',
|
suffixText: ' U',
|
||||||
|
@ -307,11 +411,16 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
setState(() {
|
setState(() {
|
||||||
_setManually = true;
|
_setManually = true;
|
||||||
});
|
});
|
||||||
|
updateDelayedRatio();
|
||||||
},
|
},
|
||||||
keyboardType:
|
keyboardType: const TextInputType.numberWithOptions(
|
||||||
const TextInputType.numberWithOptions(decimal: true),
|
decimal: true),
|
||||||
),
|
),
|
||||||
BooleanFormField(
|
),
|
||||||
|
Expanded(
|
||||||
|
child: BooleanFormField(
|
||||||
|
contentPadding: const EdgeInsets.only(
|
||||||
|
left: 10.0, right: 10.0, top: 10.0),
|
||||||
value: _setManually,
|
value: _setManually,
|
||||||
label: 'set manually',
|
label: 'set manually',
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
|
@ -320,6 +429,9 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -350,11 +462,11 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
children: _bolusType == BolusType.glucose
|
children: _bolusType == BolusType.glucose
|
||||||
? [
|
? [
|
||||||
Row(
|
Row(
|
||||||
children: glucoseMeasurement ==
|
children: Settings.get().glucoseMeasurement ==
|
||||||
GlucoseMeasurement.mgPerDl ||
|
GlucoseMeasurement.mgPerDl ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.both ||
|
GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? [
|
? [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -408,9 +520,9 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.both ||
|
GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () => onChangeGlucose(
|
onPressed: () => onChangeGlucose(
|
||||||
|
@ -424,11 +536,11 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
: [],
|
: [],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: glucoseMeasurement ==
|
children: Settings.get().glucoseMeasurement ==
|
||||||
GlucoseMeasurement.mmolPerL ||
|
GlucoseMeasurement.mmolPerL ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.both ||
|
GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? [
|
? [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -483,9 +595,9 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.both ||
|
GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () => onChangeGlucose(
|
onPressed: () => onChangeGlucose(
|
||||||
|
@ -512,13 +624,7 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
TextFormField(
|
TextFormField(
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Carbs',
|
labelText: 'Carbs',
|
||||||
suffixText: nutritionMeasurement ==
|
suffixText: nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index],
|
||||||
NutritionMeasurement.grams
|
|
||||||
? 'g'
|
|
||||||
: nutritionMeasurement ==
|
|
||||||
NutritionMeasurement.ounces
|
|
||||||
? 'oz'
|
|
||||||
: '',
|
|
||||||
),
|
),
|
||||||
controller: _carbsController,
|
controller: _carbsController,
|
||||||
onChanged: (_) => onChangeCarbs(),
|
onChanged: (_) => onChangeCarbs(),
|
||||||
|
@ -533,8 +639,64 @@ class _LogBolusDetailScreenState extends State<LogBolusDetailScreen> {
|
||||||
suffixText: ' min',
|
suffixText: ' min',
|
||||||
),
|
),
|
||||||
controller: _delayController,
|
controller: _delayController,
|
||||||
|
onChanged: (value) => setState(() {}),
|
||||||
keyboardType: const TextInputType.numberWithOptions(),
|
keyboardType: const TextInputType.numberWithOptions(),
|
||||||
),
|
),
|
||||||
|
(int.tryParse(_delayController.text) ?? 0) != 0
|
||||||
|
? Slider(
|
||||||
|
label: '${_delayPercentage.floor().toString()}%',
|
||||||
|
divisions: 100,
|
||||||
|
value: _delayPercentage,
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
onChanged: _delayController.text != ''
|
||||||
|
? (value) {
|
||||||
|
setState(() {
|
||||||
|
_delayPercentage = value;
|
||||||
|
});
|
||||||
|
updateDelayedRatio();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
)
|
||||||
|
: Container(),
|
||||||
|
Row(
|
||||||
|
children: (int.tryParse(_delayController.text) ?? 0) != 0
|
||||||
|
? [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 5.0),
|
||||||
|
child: TextFormField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Immediate Bolus',
|
||||||
|
suffixText: ' U',
|
||||||
|
),
|
||||||
|
controller: _immediateUnitsController,
|
||||||
|
readOnly: true,
|
||||||
|
enabled: (int.tryParse(_delayController.text) ??
|
||||||
|
0) !=
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 5.0),
|
||||||
|
child: TextFormField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Delayed Bolus',
|
||||||
|
suffixText: ' U',
|
||||||
|
),
|
||||||
|
controller: _delayedUnitsController,
|
||||||
|
readOnly: true,
|
||||||
|
enabled: (int.tryParse(_delayController.text) ??
|
||||||
|
0) !=
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _notesController,
|
controller: _notesController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/log_bolus.dart';
|
import 'package:diameter/models/log_bolus.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
import 'package:diameter/models/log_entry.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_bolus_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_bolus_detail.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class LogBolusListScreen extends StatefulWidget {
|
class LogBolusListScreen extends StatefulWidget {
|
||||||
|
@ -58,7 +57,7 @@ class _LogBolusListScreenState extends State<LogBolusListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(LogBolus logBolus) async {
|
void handleDeleteAction(LogBolus logBolus) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(logBolus),
|
onConfirm: () => onDelete(logBolus),
|
||||||
|
@ -92,12 +91,15 @@ class _LogBolusListScreenState extends State<LogBolusListScreen> {
|
||||||
itemCount: widget.logBoli.length,
|
itemCount: widget.logBoli.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final bolus = widget.logBoli[index];
|
final bolus = widget.logBoli[index];
|
||||||
|
String titleText = '${bolus.units} U ${(bolus.delay ?? 0) != 0
|
||||||
|
? ' (delayed by ${bolus.delay} min)'
|
||||||
|
: ''}';
|
||||||
return ListTile(
|
return ListTile(
|
||||||
onTap: () => handleEditAction(bolus),
|
onTap: () => handleEditAction(bolus),
|
||||||
title: Text('${bolus.units} U'),
|
title: Text(titleText),
|
||||||
subtitle: Text(bolus.carbs != null ?
|
subtitle: Text(bolus.carbs != null ?
|
||||||
'for ${bolus.meal.target.toString()} (${bolus.carbs}${nutritionMeasurement == NutritionMeasurement.grams ? ' g' : ' oz'} carbs)'
|
'for ${bolus.meal.target.toString()} (${bolus.carbs}${nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index]} carbs)'
|
||||||
: 'to correct ${glucoseMeasurement == GlucoseMeasurement.mgPerDl ? bolus.mgPerDlCorrection : bolus.mmolPerLCorrection} ${glucoseMeasurement == GlucoseMeasurement.mgPerDl ? 'mg/dl' : 'mmol/l'}'),
|
: 'to correct ${Settings.get().glucoseMeasurement == GlucoseMeasurement.mgPerDl ? bolus.mgPerDlCorrection : bolus.mmolPerLCorrection} ${glucoseMeasurementSuffixes[Settings.get().glucoseMeasurement.index]}'),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/log_bolus.dart';
|
import 'package:diameter/models/log_bolus.dart';
|
||||||
import 'package:diameter/models/log_entry.dart';
|
import 'package:diameter/models/log_entry.dart';
|
||||||
import 'package:diameter/models/log_meal.dart';
|
import 'package:diameter/models/log_meal.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_bolus_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_bolus_detail.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_bolus_list.dart';
|
import 'package:diameter/screens/log/log_entry/log_bolus_list.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_meal_list.dart';
|
import 'package:diameter/screens/log/log_entry/log_meal_list.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:diameter/utils/utils.dart';
|
import 'package:diameter/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -175,7 +174,7 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(int.tryParse(_mgPerDlController.text) != null ||
|
(int.tryParse(_mgPerDlController.text) != null ||
|
||||||
double.tryParse(_mmolPerLController.text) != null ||
|
double.tryParse(_mmolPerLController.text) != null ||
|
||||||
|
@ -311,10 +310,10 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
Settings.get().glucoseMeasurement == GlucoseMeasurement.mgPerDl ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.both ||
|
GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? Expanded(
|
? Expanded(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
@ -341,8 +340,8 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
Settings.get().glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
|
@ -352,10 +351,10 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||||
icon: const Icon(Icons.calculate),
|
icon: const Icon(Icons.calculate),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
Settings.get().glucoseMeasurement == GlucoseMeasurement.mmolPerL ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.both ||
|
GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? Expanded(
|
? Expanded(
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
@ -383,8 +382,8 @@ class _LogEntryScreenState extends State<LogEntryScreen> {
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Container(),
|
: Container(),
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.both ||
|
Settings.get().glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
glucoseDisplayMode ==
|
Settings.get().glucoseDisplayMode ==
|
||||||
GlucoseDisplayMode.bothForDetail
|
GlucoseDisplayMode.bothForDetail
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () =>
|
onPressed: () =>
|
||||||
|
|
|
@ -2,15 +2,14 @@ import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/dropdown.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/accuracy.dart';
|
import 'package:diameter/models/accuracy.dart';
|
||||||
import 'package:diameter/models/log_meal.dart';
|
import 'package:diameter/models/log_meal.dart';
|
||||||
import 'package:diameter/models/meal.dart';
|
import 'package:diameter/models/meal.dart';
|
||||||
import 'package:diameter/models/meal_category.dart';
|
import 'package:diameter/models/meal_category.dart';
|
||||||
import 'package:diameter/models/meal_portion_type.dart';
|
import 'package:diameter/models/meal_portion_type.dart';
|
||||||
import 'package:diameter/models/meal_source.dart';
|
import 'package:diameter/models/meal_source.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:diameter/utils/utils.dart';
|
import 'package:diameter/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -145,7 +144,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_valueController.text != '' ||
|
(_valueController.text != '' ||
|
||||||
_meal != null ||
|
_meal != null ||
|
||||||
|
@ -325,12 +324,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Portion size',
|
labelText: 'Portion size',
|
||||||
suffixText:
|
suffixText:
|
||||||
nutritionMeasurement == NutritionMeasurement.grams
|
nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index],
|
||||||
? 'g'
|
|
||||||
: nutritionMeasurement ==
|
|
||||||
NutritionMeasurement.ounces
|
|
||||||
? 'oz'
|
|
||||||
: '',
|
|
||||||
alignLabelWithHint: true,
|
alignLabelWithHint: true,
|
||||||
),
|
),
|
||||||
controller: _portionSizeController,
|
controller: _portionSizeController,
|
||||||
|
@ -366,12 +360,7 @@ class _LogMealDetailScreenState extends State<LogMealDetailScreen> {
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Carbs per portion',
|
labelText: 'Carbs per portion',
|
||||||
suffixText:
|
suffixText:
|
||||||
nutritionMeasurement == NutritionMeasurement.grams
|
nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index],
|
||||||
? 'g'
|
|
||||||
: nutritionMeasurement ==
|
|
||||||
NutritionMeasurement.ounces
|
|
||||||
? 'oz'
|
|
||||||
: '',
|
|
||||||
),
|
),
|
||||||
controller: _carbsPerPortionController,
|
controller: _carbsPerPortionController,
|
||||||
keyboardType: const TextInputType.numberWithOptions(
|
keyboardType: const TextInputType.numberWithOptions(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/log_entry.dart';
|
import 'package:diameter/models/log_entry.dart';
|
||||||
import 'package:diameter/models/log_meal.dart';
|
import 'package:diameter/models/log_meal.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
import 'package:diameter/screens/log/log_entry/log_meal_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ class _LogMealListScreenState extends State<LogMealListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(LogMeal meal) async {
|
void handleDeleteAction(LogMeal meal) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(meal),
|
onConfirm: () => onDelete(meal),
|
||||||
|
|
|
@ -2,11 +2,11 @@ import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/dropdown.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/basal_profile.dart';
|
import 'package:diameter/models/basal_profile.dart';
|
||||||
import 'package:diameter/models/bolus_profile.dart';
|
import 'package:diameter/models/bolus_profile.dart';
|
||||||
import 'package:diameter/models/log_event.dart';
|
import 'package:diameter/models/log_event.dart';
|
||||||
import 'package:diameter/models/log_event_type.dart';
|
import 'package:diameter/models/log_event_type.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -132,11 +132,42 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleSaveAction() async {
|
Future<void> checkIfActiveEventOfTypeExistsBeforeSaving() async {
|
||||||
setState(() {
|
if (_eventType != null && LogEvent.eventTypeExistsForTime(_eventType!.id, _time)) {
|
||||||
_isSaving = true;
|
await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return AlertDialog(
|
||||||
|
content: const Text(
|
||||||
|
'An Event of this type is already active within the set time frame. What would you like to do?'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context, 'DISCARD'),
|
||||||
|
child: const Text('DISCARD'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context, 'EDIT'),
|
||||||
|
child: const Text('KEEP EDITING'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () => Navigator.pop(context, 'SAVE'),
|
||||||
|
child: const Text('SAVE'),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}).then((value) async {
|
||||||
|
if (value == 'DISCARD') {
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else if (value == 'SAVE') {
|
||||||
|
onSave();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (_logEventForm.currentState!.validate()) {
|
} else {
|
||||||
|
onSave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSave() {
|
||||||
LogEvent event = LogEvent(
|
LogEvent event = LogEvent(
|
||||||
id: widget.id,
|
id: widget.id,
|
||||||
time: _time,
|
time: _time,
|
||||||
|
@ -151,13 +182,21 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||||
LogEvent.put(event);
|
LogEvent.put(event);
|
||||||
Navigator.pop(context, '${_isNew ? 'New' : ''} Event Saved');
|
Navigator.pop(context, '${_isNew ? 'New' : ''} Event Saved');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleSaveAction() async {
|
||||||
|
setState(() {
|
||||||
|
_isSaving = true;
|
||||||
|
});
|
||||||
|
if (_logEventForm.currentState!.validate()) {
|
||||||
|
await checkIfActiveEventOfTypeExistsBeforeSaving();
|
||||||
|
}
|
||||||
setState(() {
|
setState(() {
|
||||||
_isSaving = false;
|
_isSaving = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_notesController.text != '' ||
|
(_notesController.text != '' ||
|
||||||
_eventType != null ||
|
_eventType != null ||
|
||||||
|
@ -213,12 +252,8 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||||
onChanged: (newTime) {
|
onChanged: (newTime) {
|
||||||
if (newTime != null) {
|
if (newTime != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_time = DateTime(
|
_time = DateTime(newTime.year, newTime.month,
|
||||||
newTime.year,
|
newTime.day, _time.hour, _time.minute);
|
||||||
newTime.month,
|
|
||||||
newTime.day,
|
|
||||||
_time.hour,
|
|
||||||
_time.minute);
|
|
||||||
});
|
});
|
||||||
updateTime();
|
updateTime();
|
||||||
}
|
}
|
||||||
|
@ -236,12 +271,8 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||||
onChanged: (newTime) {
|
onChanged: (newTime) {
|
||||||
if (newTime != null) {
|
if (newTime != null) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_time = DateTime(
|
_time = DateTime(_time.year, _time.month,
|
||||||
_time.year,
|
_time.day, newTime.hour, newTime.minute);
|
||||||
_time.month,
|
|
||||||
_time.day,
|
|
||||||
newTime.hour,
|
|
||||||
newTime.minute);
|
|
||||||
});
|
});
|
||||||
updateTime();
|
updateTime();
|
||||||
}
|
}
|
||||||
|
@ -261,7 +292,8 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||||
label: 'has end time',
|
label: 'has end time',
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
children: _hasEndTime? [
|
children: _hasEndTime
|
||||||
|
? [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
@ -291,7 +323,8 @@ class _LogEventDetailScreenState extends State<LogEventDetailScreen> {
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 5),
|
padding: const EdgeInsets.only(left: 5),
|
||||||
child: TimeOfDayFormField(
|
child: TimeOfDayFormField(
|
||||||
time: TimeOfDay.fromDateTime(_endTime ?? now),
|
time: TimeOfDay.fromDateTime(
|
||||||
|
_endTime ?? now),
|
||||||
label: 'End Time',
|
label: 'End Time',
|
||||||
controller: _endTimeController,
|
controller: _endTimeController,
|
||||||
onChanged: (newTime) {
|
onChanged: (newTime) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/log_event.dart';
|
import 'package:diameter/models/log_event.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/screens/log/log_event/log_event_detail.dart';
|
import 'package:diameter/screens/log/log_event/log_event_detail.dart';
|
||||||
import 'package:diameter/utils/date_time_utils.dart';
|
import 'package:diameter/utils/date_time_utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -71,7 +71,7 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(LogEvent logEvent) async {
|
void handleDeleteAction(LogEvent logEvent) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(logEvent),
|
onConfirm: () => onDelete(logEvent),
|
||||||
|
@ -89,7 +89,7 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleStopAction(LogEvent event) async {
|
void handleStopAction(LogEvent event) async {
|
||||||
if (showConfirmationDialogOnStopEvent) {
|
if (Settings.get().showConfirmationDialogOnStopEvent) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onStop(event),
|
onConfirm: () => onStop(event),
|
||||||
|
@ -101,7 +101,6 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -117,65 +116,93 @@ class _LogEventListScreenState extends State<LogEventListScreen> {
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _logEventDailyMap.isNotEmpty
|
child: _logEventDailyMap.isNotEmpty
|
||||||
? SingleChildScrollView(
|
? ListView.builder(
|
||||||
child: ListView.builder(
|
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
padding: const EdgeInsets.all(10.0),
|
padding: const EdgeInsets.all(10.0),
|
||||||
itemCount: _logEventDailyMap.length,
|
itemCount: _logEventDailyMap.length,
|
||||||
itemBuilder: (context, dateIndex) {
|
itemBuilder: (context, dateIndex) {
|
||||||
List<DateTime?> dateList = <DateTime?>[null] +
|
List<DateTime?> dateList = (_activeEvents.isNotEmpty
|
||||||
|
? <DateTime?>[null]
|
||||||
|
: <DateTime?>[]) +
|
||||||
_logEventDailyMap.keys.toList();
|
_logEventDailyMap.keys.toList();
|
||||||
final date = dateList[dateIndex];
|
final date = dateList[dateIndex];
|
||||||
final eventList = date != null ? _logEventDailyMap[date] : _activeEvents;
|
final eventList = date != null
|
||||||
return ListBody(
|
? _logEventDailyMap[date]
|
||||||
children: [
|
: _activeEvents;
|
||||||
Text(DateTimeUtils.displayDate(date, fallback: 'Active Events')),
|
final tiles = <Widget>[];
|
||||||
eventList != null && eventList.isNotEmpty
|
if (eventList != null) {
|
||||||
? ListView.builder(
|
for (LogEvent event in eventList) {
|
||||||
shrinkWrap: true,
|
tiles.add(ListTile(
|
||||||
itemCount: eventList.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final event = eventList[index];
|
|
||||||
return ListTile(
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
handleEditAction(event);
|
handleEditAction(event);
|
||||||
},
|
},
|
||||||
title: Row(
|
title: Row(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.center,
|
||||||
mainAxisSize: MainAxisSize.max,
|
mainAxisSize: MainAxisSize.max,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(event.eventType.target?.value ?? '')),
|
child: Text(date == null
|
||||||
|
? DateTimeUtils
|
||||||
|
.displayDateTime(
|
||||||
|
event.time)
|
||||||
|
: DateTimeUtils.displayTime(
|
||||||
|
event.isEndEvent
|
||||||
|
? event.endTime
|
||||||
|
: event.time))),
|
||||||
|
const SizedBox(width: 24),
|
||||||
|
Expanded(
|
||||||
|
child: Text(event.title ??
|
||||||
|
event.eventType.target?.value ??
|
||||||
|
''),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
|
||||||
'${DateTimeUtils.displayDateTime(event.time)}${event.hasEndTime ? ' - ${DateTimeUtils.displayDateTime(event.endTime, fallback: '(ongoing)')}' : ''}'),
|
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
event.hasEndTime && event.endTime == null ? IconButton(
|
event.hasEndTime &&
|
||||||
|
event.endTime == null
|
||||||
|
? IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.stop,
|
Icons.stop,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
),
|
),
|
||||||
onPressed: () => handleStopAction(event),
|
onPressed: () =>
|
||||||
) : Container(),
|
handleStopAction(event),
|
||||||
const SizedBox(width: 24),
|
)
|
||||||
|
: const SizedBox(width: 50),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(
|
||||||
|
Icons.edit,
|
||||||
|
color: Colors.blue,
|
||||||
|
),
|
||||||
|
onPressed: () =>
|
||||||
|
handleEditAction(event),
|
||||||
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(
|
icon: const Icon(
|
||||||
Icons.delete,
|
Icons.delete,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
),
|
),
|
||||||
onPressed: () => handleDeleteAction(event),
|
onPressed: () =>
|
||||||
|
handleDeleteAction(event),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
));
|
||||||
}) : Container(),
|
}
|
||||||
],
|
}
|
||||||
);
|
return eventList != null && eventList.isNotEmpty ? ListBody(
|
||||||
|
children: <Widget>[
|
||||||
|
Text(DateTimeUtils.displayDate(date,
|
||||||
|
fallback: 'Active Events'))
|
||||||
|
] + tiles,
|
||||||
|
|
||||||
|
) : Container();
|
||||||
},
|
},
|
||||||
),
|
)
|
||||||
) : const Center(
|
: const Center(
|
||||||
child: Text('There are no Events!'),
|
child: Text('There are no Events!'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -2,10 +2,10 @@ import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/dropdown.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/basal_profile.dart';
|
import 'package:diameter/models/basal_profile.dart';
|
||||||
import 'package:diameter/models/bolus_profile.dart';
|
import 'package:diameter/models/bolus_profile.dart';
|
||||||
import 'package:diameter/models/log_event_type.dart';
|
import 'package:diameter/models/log_event_type.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ class _EventTypeDetailScreenState extends State<EventTypeDetailScreen> {
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
bool isNew = _logEventType == null;
|
bool isNew = _logEventType == null;
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((isNew &&
|
((isNew &&
|
||||||
(_valueController.text != '' ||
|
(_valueController.text != '' ||
|
||||||
int.tryParse(_defaultReminderDurationController.text) !=
|
int.tryParse(_defaultReminderDurationController.text) !=
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:diameter/models/meal_category.dart';
|
import 'package:diameter/models/meal_category.dart';
|
||||||
|
@ -57,7 +57,7 @@ class _MealCategoryDetailScreenState extends State<MealCategoryDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
(_isNew &&
|
(_isNew &&
|
||||||
(_valueController.text != '' || _notesController.text != '')) ||
|
(_valueController.text != '' || _notesController.text != '')) ||
|
||||||
(!_isNew &&
|
(!_isNew &&
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
// import 'package:diameter/components/progress_indicator.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/meal/meal_category_detail.dart';
|
import 'package:diameter/screens/meal/meal_category_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -47,7 +46,7 @@ class _MealCategoryListScreenState extends State<MealCategoryListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(MealCategory mealCategory) async {
|
void handleDeleteAction(MealCategory mealCategory) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(mealCategory),
|
onConfirm: () => onDelete(mealCategory),
|
||||||
|
|
|
@ -2,14 +2,13 @@ import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/dropdown.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/accuracy.dart';
|
import 'package:diameter/models/accuracy.dart';
|
||||||
import 'package:diameter/models/meal.dart';
|
import 'package:diameter/models/meal.dart';
|
||||||
import 'package:diameter/models/meal_category.dart';
|
import 'package:diameter/models/meal_category.dart';
|
||||||
import 'package:diameter/models/meal_portion_type.dart';
|
import 'package:diameter/models/meal_portion_type.dart';
|
||||||
import 'package:diameter/models/meal_source.dart';
|
import 'package:diameter/models/meal_source.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/settings.dart';
|
|
||||||
import 'package:diameter/utils/utils.dart';
|
import 'package:diameter/utils/utils.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -122,7 +121,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_valueController.text != '' ||
|
(_valueController.text != '' ||
|
||||||
_mealSource != null ||
|
_mealSource != null ||
|
||||||
|
@ -313,12 +312,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Portion size',
|
labelText: 'Portion size',
|
||||||
suffixText:
|
suffixText:
|
||||||
nutritionMeasurement == NutritionMeasurement.grams
|
nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index],
|
||||||
? 'g'
|
|
||||||
: nutritionMeasurement ==
|
|
||||||
NutritionMeasurement.ounces
|
|
||||||
? 'oz'
|
|
||||||
: '',
|
|
||||||
alignLabelWithHint: true,
|
alignLabelWithHint: true,
|
||||||
),
|
),
|
||||||
controller: _portionSizeController,
|
controller: _portionSizeController,
|
||||||
|
@ -354,12 +348,7 @@ class _MealDetailScreenState extends State<MealDetailScreen> {
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Carbs per portion',
|
labelText: 'Carbs per portion',
|
||||||
suffixText:
|
suffixText:
|
||||||
nutritionMeasurement == NutritionMeasurement.grams
|
nutritionMeasurementSuffixes[Settings.get().nutritionMeasurement.index],
|
||||||
? 'g'
|
|
||||||
: nutritionMeasurement ==
|
|
||||||
NutritionMeasurement.ounces
|
|
||||||
? 'oz'
|
|
||||||
: '',
|
|
||||||
),
|
),
|
||||||
controller: _carbsPerPortionController,
|
controller: _carbsPerPortionController,
|
||||||
keyboardType: const TextInputType.numberWithOptions(
|
keyboardType: const TextInputType.numberWithOptions(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/meal.dart';
|
import 'package:diameter/models/meal.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/meal/meal_detail.dart';
|
import 'package:diameter/screens/meal/meal_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -46,7 +46,7 @@ class _MealListScreenState extends State<MealListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(Meal meal) async {
|
void handleDeleteAction(Meal meal) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(meal),
|
onConfirm: () => onDelete(meal),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'package:diameter/components/detail.dart';
|
import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:diameter/models/meal_portion_type.dart';
|
import 'package:diameter/models/meal_portion_type.dart';
|
||||||
|
@ -60,7 +60,7 @@ class _MealPortionTypeDetailScreenState
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_valueController.text != '' || _notesController.text != '')) ||
|
(_valueController.text != '' || _notesController.text != '')) ||
|
||||||
(!_isNew &&
|
(!_isNew &&
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/meal/meal_portion_type_detail.dart';
|
import 'package:diameter/screens/meal/meal_portion_type_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -47,7 +47,7 @@ class _MealPortionTypeListScreenState extends State<MealPortionTypeListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(MealPortionType mealPortionType) async {
|
void handleDeleteAction(MealPortionType mealPortionType) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(mealPortionType),
|
onConfirm: () => onDelete(mealPortionType),
|
||||||
|
|
|
@ -2,11 +2,11 @@ import 'package:diameter/components/detail.dart';
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/dropdown.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/accuracy.dart';
|
import 'package:diameter/models/accuracy.dart';
|
||||||
import 'package:diameter/models/meal_category.dart';
|
import 'package:diameter/models/meal_category.dart';
|
||||||
import 'package:diameter/models/meal_portion_type.dart';
|
import 'package:diameter/models/meal_portion_type.dart';
|
||||||
import 'package:diameter/models/meal_source.dart';
|
import 'package:diameter/models/meal_source.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ class _MealSourceDetailScreenState extends State<MealSourceDetailScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleCancelAction() {
|
void handleCancelAction() {
|
||||||
if (showConfirmationDialogOnCancel &&
|
if (Settings.get().showConfirmationDialogOnCancel &&
|
||||||
((_isNew &&
|
((_isNew &&
|
||||||
(_valueController.text != '' ||
|
(_valueController.text != '' ||
|
||||||
_defaultCarbsRatioAccuracy != null ||
|
_defaultCarbsRatioAccuracy != null ||
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/config.dart';
|
|
||||||
import 'package:diameter/models/meal_source.dart';
|
import 'package:diameter/models/meal_source.dart';
|
||||||
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:diameter/screens/meal/meal_source_detail.dart';
|
import 'package:diameter/screens/meal/meal_source_detail.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -46,7 +46,7 @@ class _MealSourceListScreenState extends State<MealSourceListScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleDeleteAction(MealSource mealSource) async {
|
void handleDeleteAction(MealSource mealSource) async {
|
||||||
if (showConfirmationDialogOnDelete) {
|
if (Settings.get().showConfirmationDialogOnDelete) {
|
||||||
Dialogs.showConfirmationDialog(
|
Dialogs.showConfirmationDialog(
|
||||||
context: context,
|
context: context,
|
||||||
onConfirm: () => onDelete(mealSource),
|
onConfirm: () => onDelete(mealSource),
|
||||||
|
|
|
@ -1,88 +1,9 @@
|
||||||
import 'package:diameter/components/dialogs.dart';
|
import 'package:diameter/components/dialogs.dart';
|
||||||
import 'package:diameter/components/dropdown.dart';
|
import 'package:diameter/components/dropdown.dart';
|
||||||
import 'package:diameter/components/forms.dart';
|
import 'package:diameter/components/forms.dart';
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:diameter/navigation.dart';
|
import 'package:diameter/navigation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
|
||||||
|
|
||||||
enum GlucoseDisplayMode { activeOnly, bothForList, bothForDetail, both }
|
|
||||||
|
|
||||||
enum GlucoseMeasurement {
|
|
||||||
mgPerDl,
|
|
||||||
mmolPerL,
|
|
||||||
}
|
|
||||||
|
|
||||||
enum NutritionMeasurement {
|
|
||||||
grams,
|
|
||||||
ounces,
|
|
||||||
cups,
|
|
||||||
}
|
|
||||||
|
|
||||||
class Settings {
|
|
||||||
static void loadSettingsIntoConfig() async {
|
|
||||||
nutritionMeasurement = await getNutritionMeasurement();
|
|
||||||
glucoseMeasurement = await getGlucoseMeasurement();
|
|
||||||
glucoseDisplayMode = await getGlucoseDisplayMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<GlucoseDisplayMode> getGlucoseDisplayMode() async {
|
|
||||||
final settings = await SharedPreferences.getInstance();
|
|
||||||
int? index = settings.getInt('glucoseDisplayMode');
|
|
||||||
return index != null && index < GlucoseDisplayMode.values.length
|
|
||||||
? GlucoseDisplayMode.values[index]
|
|
||||||
: GlucoseDisplayMode.bothForList;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<GlucoseMeasurement> getGlucoseMeasurement() async {
|
|
||||||
final settings = await SharedPreferences.getInstance();
|
|
||||||
int? index = settings.getInt('glucoseMeasurement');
|
|
||||||
return index != null && index < GlucoseMeasurement.values.length
|
|
||||||
? GlucoseMeasurement.values[index]
|
|
||||||
: GlucoseMeasurement.mgPerDl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Future<NutritionMeasurement> getNutritionMeasurement() async {
|
|
||||||
final settings = await SharedPreferences.getInstance();
|
|
||||||
int? index = settings.getInt('nutritionMeasurement');
|
|
||||||
return index != null && index < NutritionMeasurement.values.length
|
|
||||||
? NutritionMeasurement.values[index]
|
|
||||||
: NutritionMeasurement.grams;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setGlucoseDisplayMode(
|
|
||||||
GlucoseDisplayMode? glucoseDisplayMode) async {
|
|
||||||
final settings = await SharedPreferences.getInstance();
|
|
||||||
if (glucoseDisplayMode != null) {
|
|
||||||
settings.setInt('glucoseDisplayMode', glucoseDisplayMode.index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setGlucoseMeasurement(
|
|
||||||
GlucoseMeasurement? glucoseMeasurement) async {
|
|
||||||
final settings = await SharedPreferences.getInstance();
|
|
||||||
if (glucoseMeasurement != null) {
|
|
||||||
settings.setInt('preferredGlucoseMeasurement', glucoseMeasurement.index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setNutritionMeasurement(
|
|
||||||
NutritionMeasurement? nutritionMeasurement) async {
|
|
||||||
final settings = await SharedPreferences.getInstance();
|
|
||||||
if (nutritionMeasurement != null) {
|
|
||||||
settings.setInt(
|
|
||||||
'preferredNutritionMeasurement', nutritionMeasurement.index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void resetAll() async {
|
|
||||||
final settings = await SharedPreferences.getInstance();
|
|
||||||
|
|
||||||
settings.remove('glucoseDisplayMode');
|
|
||||||
settings.remove('preferredGlucoseMeasurement');
|
|
||||||
settings.remove('preferredNutritionMeasurement');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SettingsScreen extends StatefulWidget {
|
class SettingsScreen extends StatefulWidget {
|
||||||
static const String routeName = '/settings';
|
static const String routeName = '/settings';
|
||||||
|
@ -94,12 +15,73 @@ class SettingsScreen extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SettingsScreenState extends State<SettingsScreen> {
|
class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
final GlobalKey<FormState> _settingsForm = GlobalKey<FormState>();
|
late Settings _settings;
|
||||||
|
|
||||||
|
late bool _onlyDisplayActiveGlucoseMeasurement;
|
||||||
|
late bool _displayBothGlucoseMeasurementsInDetailView;
|
||||||
|
late bool _displayBothGlucoseMeasurementsInListView;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
void onReset() {
|
void onReset() {
|
||||||
Settings.resetAll();
|
Settings.reset();
|
||||||
|
reload(message: 'Settings have been reset to default');
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveSettings() {
|
||||||
|
Settings.put(Settings(
|
||||||
|
id: _settings.id,
|
||||||
|
nutritionMeasurement: _settings.nutritionMeasurement,
|
||||||
|
glucoseDisplayMode: _settings.glucoseDisplayMode,
|
||||||
|
glucoseMeasurement: _settings.glucoseMeasurement,
|
||||||
|
dateFormat: _settings.dateFormat,
|
||||||
|
longDateFormat: _settings.longDateFormat,
|
||||||
|
timeFormat: _settings.timeFormat,
|
||||||
|
longTimeFormat: _settings.longTimeFormat,
|
||||||
|
showConfirmationDialogOnCancel: _settings.showConfirmationDialogOnCancel,
|
||||||
|
showConfirmationDialogOnDelete: _settings.showConfirmationDialogOnDelete,
|
||||||
|
showConfirmationDialogOnStopEvent:
|
||||||
|
_settings.showConfirmationDialogOnStopEvent,
|
||||||
|
lowGlucoseMgPerDl: _settings.lowGlucoseMgPerDl,
|
||||||
|
moderateGlucoseMgPerDl: _settings.moderateGlucoseMgPerDl,
|
||||||
|
highGlucoseMgPerDl: _settings.highGlucoseMgPerDl,
|
||||||
|
lowGlucoseMmolPerL: _settings.lowGlucoseMmolPerL,
|
||||||
|
moderateGlucoseMmolPerL: _settings.moderateGlucoseMmolPerL,
|
||||||
|
highGlucoseMmolPerDl: _settings.highGlucoseMmolPerDl,
|
||||||
|
));
|
||||||
|
reload(message: 'Settings updated');
|
||||||
|
}
|
||||||
|
|
||||||
|
void reload({String? message}) {
|
||||||
setState(() {
|
setState(() {
|
||||||
Settings.loadSettingsIntoConfig();
|
_settings = Settings.get();
|
||||||
|
});
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_onlyDisplayActiveGlucoseMeasurement =
|
||||||
|
_settings.glucoseDisplayMode == GlucoseDisplayMode.activeOnly;
|
||||||
|
_displayBothGlucoseMeasurementsInDetailView =
|
||||||
|
_settings.glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
|
_settings.glucoseDisplayMode == GlucoseDisplayMode.bothForDetail;
|
||||||
|
_displayBothGlucoseMeasurementsInListView =
|
||||||
|
_settings.glucoseDisplayMode == GlucoseDisplayMode.both ||
|
||||||
|
_settings.glucoseDisplayMode == GlucoseDisplayMode.bothForList;
|
||||||
|
});
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
if (message != null) {
|
||||||
|
var snackBar = SnackBar(
|
||||||
|
content: Text(message),
|
||||||
|
duration: const Duration(seconds: 2),
|
||||||
|
);
|
||||||
|
ScaffoldMessenger.of(context)
|
||||||
|
..removeCurrentSnackBar()
|
||||||
|
..showSnackBar(snackBar);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,12 +93,6 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
initState() {
|
|
||||||
super.initState();
|
|
||||||
Settings.loadSettingsIntoConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -126,91 +102,81 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
||||||
drawer: const Navigation(currentLocation: SettingsScreen.routeName),
|
drawer: const Navigation(currentLocation: SettingsScreen.routeName),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
FormWrapper(
|
AutoCompleteDropdownButton<String>(
|
||||||
formState: _settingsForm,
|
selectedItem: nutritionMeasurementLabels[
|
||||||
fields: [
|
_settings.nutritionMeasurement.index],
|
||||||
AutoCompleteDropdownButton<NutritionMeasurement>(
|
|
||||||
selectedItem: nutritionMeasurement,
|
|
||||||
label: 'Preferred Nutrition Measurement',
|
label: 'Preferred Nutrition Measurement',
|
||||||
items: NutritionMeasurement.values,
|
items: nutritionMeasurementLabels,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
Settings.setNutritionMeasurement(value);
|
_settings.nutritionMeasurement = NutritionMeasurement.values
|
||||||
setState(() {
|
.elementAt(nutritionMeasurementLabels.indexOf(value));
|
||||||
nutritionMeasurement = value;
|
saveSettings();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
AutoCompleteDropdownButton<GlucoseMeasurement>(
|
AutoCompleteDropdownButton<String>(
|
||||||
selectedItem: glucoseMeasurement,
|
selectedItem:
|
||||||
|
glucoseMeasurementLabels[_settings.glucoseMeasurement.index],
|
||||||
label: 'Preferred Glucose Measurement',
|
label: 'Preferred Glucose Measurement',
|
||||||
items: GlucoseMeasurement.values,
|
items: glucoseMeasurementLabels,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
Settings.setGlucoseMeasurement(value);
|
_settings.glucoseMeasurement = GlucoseMeasurement.values
|
||||||
setState(() {
|
.elementAt(glucoseMeasurementLabels.indexOf(value));
|
||||||
glucoseMeasurement = value;
|
saveSettings();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
BooleanFormField(
|
BooleanFormField(
|
||||||
value: glucoseDisplayMode == GlucoseDisplayMode.activeOnly,
|
value: _onlyDisplayActiveGlucoseMeasurement,
|
||||||
label: 'only display active glucose measurement',
|
label: 'only display active glucose measurement',
|
||||||
onChanged: (_) {
|
onChanged: (_) {
|
||||||
GlucoseDisplayMode mode =
|
GlucoseDisplayMode mode = _settings.glucoseDisplayMode ==
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.activeOnly
|
GlucoseDisplayMode.activeOnly
|
||||||
? GlucoseDisplayMode.both
|
? GlucoseDisplayMode.both
|
||||||
: GlucoseDisplayMode.activeOnly;
|
: GlucoseDisplayMode.activeOnly;
|
||||||
Settings.setGlucoseDisplayMode(mode);
|
_settings.glucoseDisplayMode = mode;
|
||||||
setState(() {
|
saveSettings();
|
||||||
glucoseDisplayMode = mode;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
BooleanFormField(
|
BooleanFormField(
|
||||||
value: glucoseDisplayMode == GlucoseDisplayMode.both ||
|
value: _displayBothGlucoseMeasurementsInDetailView,
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.bothForDetail,
|
enabled:
|
||||||
enabled: glucoseDisplayMode != GlucoseDisplayMode.activeOnly,
|
!_onlyDisplayActiveGlucoseMeasurement,
|
||||||
label: 'display both glucose measurements in detail view',
|
label: 'display both glucose measurements in detail view',
|
||||||
onChanged: (_) {
|
onChanged: (_) {
|
||||||
GlucoseDisplayMode mode = glucoseDisplayMode ==
|
GlucoseDisplayMode mode =
|
||||||
GlucoseDisplayMode.both
|
_settings.glucoseDisplayMode == GlucoseDisplayMode.both
|
||||||
? GlucoseDisplayMode.bothForList
|
? GlucoseDisplayMode.bothForList
|
||||||
: glucoseDisplayMode == GlucoseDisplayMode.bothForList
|
: _settings.glucoseDisplayMode ==
|
||||||
|
GlucoseDisplayMode.bothForList
|
||||||
? GlucoseDisplayMode.both
|
? GlucoseDisplayMode.both
|
||||||
: GlucoseDisplayMode.activeOnly;
|
: GlucoseDisplayMode.activeOnly;
|
||||||
Settings.setGlucoseDisplayMode(mode);
|
_settings.glucoseDisplayMode = mode;
|
||||||
setState(() {
|
saveSettings();
|
||||||
glucoseDisplayMode = mode;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
BooleanFormField(
|
BooleanFormField(
|
||||||
value: glucoseDisplayMode == GlucoseDisplayMode.both ||
|
value: _displayBothGlucoseMeasurementsInListView,
|
||||||
glucoseDisplayMode == GlucoseDisplayMode.bothForList,
|
enabled:
|
||||||
enabled: glucoseDisplayMode != GlucoseDisplayMode.activeOnly,
|
!_onlyDisplayActiveGlucoseMeasurement,
|
||||||
label: 'display both glucose measurements in list view',
|
label: 'display both glucose measurements in list view',
|
||||||
onChanged: (_) {
|
onChanged: (_) {
|
||||||
GlucoseDisplayMode mode = glucoseDisplayMode ==
|
GlucoseDisplayMode mode =
|
||||||
GlucoseDisplayMode.both
|
_settings.glucoseDisplayMode == GlucoseDisplayMode.both
|
||||||
? GlucoseDisplayMode.bothForDetail
|
? GlucoseDisplayMode.bothForDetail
|
||||||
: glucoseDisplayMode == GlucoseDisplayMode.bothForDetail
|
: _settings.glucoseDisplayMode ==
|
||||||
|
GlucoseDisplayMode.bothForDetail
|
||||||
? GlucoseDisplayMode.both
|
? GlucoseDisplayMode.both
|
||||||
: GlucoseDisplayMode.activeOnly;
|
: GlucoseDisplayMode.activeOnly;
|
||||||
Settings.setGlucoseDisplayMode(mode);
|
_settings.glucoseDisplayMode = mode;
|
||||||
setState(() {
|
saveSettings();
|
||||||
glucoseDisplayMode = mode;
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
bottomNavigationBar: BottomAppBar(
|
bottomNavigationBar: BottomAppBar(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import 'package:diameter/config.dart';
|
import 'package:diameter/models/settings.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
final DateTime dummyDate = DateTime(2000);
|
||||||
|
|
||||||
class DateTimeUtils {
|
class DateTimeUtils {
|
||||||
static String displayDateTime(DateTime? date, {String fallback = ''}) {
|
static String displayDateTime(DateTime? date, {String fallback = ''}) {
|
||||||
if (date == null) {
|
if (date == null) {
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
DateTime localDate = date.toLocal();
|
DateTime localDate = date.toLocal();
|
||||||
final DateFormat formatter = DateFormat('$dateFormat $timeFormat');
|
final DateFormat formatter = DateFormat('${Settings.get().dateFormat} ${Settings.get().timeFormat}');
|
||||||
return formatter.format(localDate);
|
return formatter.format(localDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +19,7 @@ class DateTimeUtils {
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
DateTime localDate = date.toLocal();
|
DateTime localDate = date.toLocal();
|
||||||
final DateFormat formatter = DateFormat(longDateFormat ?? dateFormat);
|
final DateFormat formatter = DateFormat(Settings.get().longDateFormat ?? Settings.get().dateFormat);
|
||||||
return formatter.format(localDate);
|
return formatter.format(localDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +30,7 @@ class DateTimeUtils {
|
||||||
}
|
}
|
||||||
DateTime localDate = date.toLocal();
|
DateTime localDate = date.toLocal();
|
||||||
final DateFormat formatter = DateFormat(
|
final DateFormat formatter = DateFormat(
|
||||||
longFormat == true ? longTimeFormat ?? timeFormat : timeFormat);
|
longFormat == true ? Settings.get().longTimeFormat ?? Settings.get().timeFormat : Settings.get().timeFormat);
|
||||||
return formatter.format(localDate);
|
return formatter.format(localDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +40,7 @@ class DateTimeUtils {
|
||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
final DateFormat formatter = DateFormat(
|
final DateFormat formatter = DateFormat(
|
||||||
longFormat == true ? longTimeFormat ?? timeFormat : timeFormat);
|
longFormat == true ? Settings.get().longTimeFormat ?? Settings.get().timeFormat : Settings.get().timeFormat);
|
||||||
return formatter.format(convertTimeOfDayToDateTime(time));
|
return formatter.format(convertTimeOfDayToDateTime(time));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
81
pubspec.lock
81
pubspec.lock
|
@ -7,14 +7,14 @@ packages:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "30.0.0"
|
version: "31.0.0"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.7.0"
|
version: "2.8.0"
|
||||||
args:
|
args:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -63,14 +63,14 @@ packages:
|
||||||
name: build_resolvers
|
name: build_resolvers
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.4"
|
version: "2.0.5"
|
||||||
build_runner:
|
build_runner:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: build_runner
|
name: build_runner
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.5"
|
||||||
build_runner_core:
|
build_runner_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -154,7 +154,7 @@ packages:
|
||||||
name: connectivity_plus_linux
|
name: connectivity_plus_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
connectivity_plus_macos:
|
connectivity_plus_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -168,7 +168,7 @@ packages:
|
||||||
name: connectivity_plus_platform_interface
|
name: connectivity_plus_platform_interface
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.1"
|
||||||
connectivity_plus_web:
|
connectivity_plus_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -203,7 +203,7 @@ packages:
|
||||||
name: cupertino_icons
|
name: cupertino_icons
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.3"
|
version: "1.0.4"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -217,14 +217,14 @@ packages:
|
||||||
name: dbus
|
name: dbus
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.6"
|
version: "0.6.6"
|
||||||
dio:
|
dio:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dio
|
name: dio
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.0.4"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -358,7 +358,7 @@ packages:
|
||||||
name: json_annotation
|
name: json_annotation
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.3.0"
|
version: "4.4.0"
|
||||||
lints:
|
lints:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -414,28 +414,28 @@ packages:
|
||||||
name: nm
|
name: nm
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.3.0"
|
version: "0.4.1"
|
||||||
objectbox:
|
objectbox:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: objectbox
|
name: objectbox
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
objectbox_flutter_libs:
|
objectbox_flutter_libs:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: objectbox_flutter_libs
|
name: objectbox_flutter_libs
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
objectbox_generator:
|
objectbox_generator:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: objectbox_generator
|
name: objectbox_generator
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.0"
|
version: "1.3.0"
|
||||||
package_config:
|
package_config:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -512,21 +512,35 @@ packages:
|
||||||
name: path_provider
|
name: path_provider
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.6"
|
version: "2.0.7"
|
||||||
|
path_provider_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_android
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.9"
|
||||||
|
path_provider_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: path_provider_ios
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.7"
|
||||||
path_provider_linux:
|
path_provider_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_linux
|
name: path_provider_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.0"
|
version: "2.1.2"
|
||||||
path_provider_macos:
|
path_provider_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_macos
|
name: path_provider_macos
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.4"
|
||||||
path_provider_platform_interface:
|
path_provider_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -540,14 +554,7 @@ packages:
|
||||||
name: path_provider_windows
|
name: path_provider_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.4"
|
||||||
pedantic:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pedantic
|
|
||||||
url: "https://pub.dartlang.org"
|
|
||||||
source: hosted
|
|
||||||
version: "1.11.1"
|
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -561,7 +568,7 @@ packages:
|
||||||
name: platform
|
name: platform
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.2"
|
version: "3.1.0"
|
||||||
plugin_platform_interface:
|
plugin_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -624,6 +631,20 @@ packages:
|
||||||
name: shared_preferences
|
name: shared_preferences
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
|
version: "2.0.9"
|
||||||
|
shared_preferences_android:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_android
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.9"
|
||||||
|
shared_preferences_ios:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: shared_preferences_ios
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
version: "2.0.8"
|
version: "2.0.8"
|
||||||
shared_preferences_linux:
|
shared_preferences_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
|
@ -631,7 +652,7 @@ packages:
|
||||||
name: shared_preferences_linux
|
name: shared_preferences_linux
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.3"
|
||||||
shared_preferences_macos:
|
shared_preferences_macos:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -659,7 +680,7 @@ packages:
|
||||||
name: shared_preferences_windows
|
name: shared_preferences_windows
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.2"
|
version: "2.0.3"
|
||||||
shelf:
|
shelf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -685,7 +706,7 @@ packages:
|
||||||
name: source_gen
|
name: source_gen
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.2.0"
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -804,7 +825,7 @@ packages:
|
||||||
name: win32
|
name: win32
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.10"
|
version: "2.3.1"
|
||||||
xdg_directories:
|
xdg_directories:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
Loading…
Add table
Reference in a new issue