Commit 9fe979c
Changed files (7)
lib
macos
lib/components/measurement_list.dart
@@ -2,9 +2,21 @@ import 'package:blood_pressure_app/model/blood_pressure.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:intl/intl.dart';
+import 'dart:io' show Platform;
class MeasurementList extends StatelessWidget {
- const MeasurementList({super.key});
+ late final _tableElementsSizes;
+ late final _sideFlex;
+
+ MeasurementList(BuildContext context, {super.key}) {
+ if (MediaQuery.of(context).size.width < 1000) {
+ _tableElementsSizes = [30,10,10,10,30];
+ _sideFlex = 1;
+ } else {
+ _tableElementsSizes = [9,7,7,7,60];
+ _sideFlex = 5;
+ }
+ }
@override
Widget build(BuildContext context) {
@@ -38,37 +50,37 @@ class MeasurementList extends StatelessWidget {
}
Widget buildListItem(BloodPressureRecord record) {
- final DateFormat formater = DateFormat('yyyy-MM-dd H:mm:s');
+ final DateFormat formater = DateFormat('yy-MM-dd H:mm:s');
return Container(
margin: EdgeInsets.only(bottom: 5),
child: Row(
children: [
- const Expanded(
- flex: 5,
+ Expanded(
+ flex: _sideFlex,
child: SizedBox(),
),
Expanded(
- flex: 9,
+ flex: _tableElementsSizes[0],
child: Text(formater.format(record.creationTime))
),
Expanded(
- flex: 7,
+ flex: _tableElementsSizes[1],
child: Text(record.systolic.toString())
),
Expanded(
- flex: 7,
+ flex: _tableElementsSizes[2],
child: Text(record.diastolic.toString())
),
Expanded(
- flex: 7,
+ flex: _tableElementsSizes[3],
child: Text(record.pulse.toString())
),
Expanded(
- flex: 60,
+ flex: _tableElementsSizes[4],
child: Text(record.notes)
),
- const Expanded(
- flex: 5,
+ Expanded(
+ flex: _sideFlex,
child: SizedBox(),
),
]
@@ -82,33 +94,33 @@ class MeasurementList extends StatelessWidget {
child: Column (
children: [
Row(
- children: const [
+ children: [
Expanded(
- flex: 5,
+ flex: _sideFlex,
child: SizedBox(),
),
Expanded(
- flex: 9,
- child: Text("timestamp", style: TextStyle(fontWeight: FontWeight.bold))
+ flex: _tableElementsSizes[0],
+ child: Text("time", style: TextStyle(fontWeight: FontWeight.bold))
),
Expanded(
- flex: 7,
- child: Text("systolic", style: TextStyle(fontWeight: FontWeight.bold))
+ flex: _tableElementsSizes[1],
+ child: Text("sys", style: TextStyle(fontWeight: FontWeight.bold))
),
Expanded(
- flex: 7,
- child: Text("diastolic", style: TextStyle(fontWeight: FontWeight.bold))
+ flex: _tableElementsSizes[2],
+ child: Text("dia", style: TextStyle(fontWeight: FontWeight.bold))
),
Expanded(
- flex: 7,
- child: Text("pulse", style: TextStyle(fontWeight: FontWeight.bold))
+ flex: _tableElementsSizes[3],
+ child: Text("pul", style: TextStyle(fontWeight: FontWeight.bold))
),
Expanded(
- flex: 60,
+ flex: _tableElementsSizes[4],
child: Text("notes", style: TextStyle(fontWeight: FontWeight.bold))
),
Expanded(
- flex: 5,
+ flex: _sideFlex,
child: SizedBox(),
),
],
lib/model/blood_pressure.dart
@@ -1,9 +1,31 @@
import 'dart:collection';
-
import 'package:flutter/foundation.dart';
+import 'package:path/path.dart';
+import 'package:sqflite_common_ffi/sqflite_ffi.dart';
+import 'package:sqflite/sqflite.dart';
class BloodPressureModel extends ChangeNotifier {
final List<BloodPressureRecord> _allMeasurements = [];
+ late final Database _database;
+
+ BloodPressureModel._create();
+ Future<void> _asyncInit() async {
+ _database = await openDatabase(
+ join(await getDatabasesPath(), 'blood_pressure.db'),
+ // runs when the database is first created
+ onCreate: (db, version) {
+ return db.execute('CREATE TABLE bloodPressureModel(timestamp INTEGER(14) PRIMARY KEY, systolic INTEGER, diastolic INTEGER, pulse INTEGER, notes STRING)',
+ );
+ },
+ version: 1,
+ );
+ }
+ // factory method, to allow for async contructor
+ static Future<BloodPressureModel> create() async{
+ final component = BloodPressureModel._create();
+ await component._asyncInit();
+ return component;
+ }
// All measurements (might get slow after some time)
UnmodifiableListView<BloodPressureRecord> get allMeasurements => UnmodifiableListView(_allMeasurements);
@@ -11,7 +33,14 @@ class BloodPressureModel extends ChangeNotifier {
/// Adds a new measurement at the correct chronological position in the List.
/// If the measurement was taken at exactly the same time as an existing
/// measurement, the existing measurement gets replaced.
- void add(BloodPressureRecord measurement) {
+ Future<void> add(BloodPressureRecord measurement) async {
+ assert(_database.isOpen);
+ final existingMeasurements = await _database.query('bloodPressureModel',
+ columns: ['timestamp'],
+ orderBy: 'timestamp'
+ );
+ print(existingMeasurements);
+
if (_allMeasurements.isNotEmpty &&
_allMeasurements.last.compareTo(measurement) >= 0) {
// naive approach; change algorithm
@@ -24,6 +53,12 @@ class BloodPressureModel extends ChangeNotifier {
}
} else {
_allMeasurements.add(measurement);
+ _database.rawInsert('INSERT INTO bloodPressureModel(timestamp, systolic, diastolic, pulse, notes) VALUES (?, ?, ?, ?, ?)', [
+ measurement.creationTime.millisecondsSinceEpoch,
+ measurement.systolic,
+ measurement.diastolic,
+ measurement.pulse,
+ measurement.notes]);
}
notifyListeners();
}
@@ -38,8 +73,8 @@ class BloodPressureModel extends ChangeNotifier {
}
return UnmodifiableListView(lastMeasurements);
}
-
- /* TODO:
+
+/* TODO:
- bool deleteFromTime (timestamp)
- bool changeAtTime (newRecord)
*/
lib/screens/home.dart
@@ -8,19 +8,26 @@ class AppHome extends StatelessWidget {
@override
Widget build(BuildContext context) {
+ double _padding;
+ if (MediaQuery.of(context).size.width < 1000) {
+ _padding = 10;
+ } else {
+ _padding = 80;
+ }
+
return Scaffold(
body: Center(
child: Container(
- padding: const EdgeInsets.all(80),
+ padding: EdgeInsets.all(_padding),
child: Column(
- children: const [
- Expanded(
+ children: [
+ const Expanded(
flex: 40,
child: MeasurementGraph()
),
Expanded(
flex: 60,
- child: MeasurementList()
+ child: MeasurementList(context)
),
]
),
lib/main.dart
@@ -2,11 +2,25 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:blood_pressure_app/model/blood_pressure.dart';
import 'package:blood_pressure_app/screens/home.dart';
+import 'dart:io' show Platform;
+import 'package:sqflite_common_ffi/sqflite_ffi.dart';
+import 'package:sqflite/sqflite.dart';
+
+void main() async {
+ WidgetsFlutterBinding.ensureInitialized();
+
+ if (Platform.isWindows || Platform.isLinux) {
+ // Initialize FFI
+ sqfliteFfiInit();
+ // Change the default factory
+ databaseFactory = databaseFactoryFfi;
+ }
+
+ final dataModel = await BloodPressureModel.create();
-void main() {
runApp(
ChangeNotifierProvider(
- create: (context) => BloodPressureModel(),
+ create: (context) => dataModel,
child: const AppRoot(),
),
);
macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,6 +5,8 @@
import FlutterMacOS
import Foundation
+import sqflite
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
}
pubspec.lock
@@ -57,6 +57,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.1"
+ ffi:
+ dependency: transitive
+ description:
+ name: ffi
+ sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.1"
flutter:
dependency: "direct main"
description: flutter
@@ -132,7 +140,7 @@ packages:
source: hosted
version: "1.0.0"
path:
- dependency: transitive
+ dependency: "direct main"
description:
name: path
sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b
@@ -160,6 +168,38 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.9.1"
+ sqflite:
+ dependency: "direct main"
+ description:
+ name: sqflite
+ sha256: "8453780d1f703ead201a39673deb93decf85d543f359f750e2afc4908b55533f"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.8"
+ sqflite_common:
+ dependency: transitive
+ description:
+ name: sqflite_common
+ sha256: e77abf6ff961d69dfef41daccbb66b51e9983cdd5cb35bf30733598057401555
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.4.5"
+ sqflite_common_ffi:
+ dependency: "direct dev"
+ description:
+ name: sqflite_common_ffi
+ sha256: f86de82d37403af491b21920a696b19f01465b596f545d1acd4d29a0a72418ad
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.5"
+ sqlite3:
+ dependency: transitive
+ description:
+ name: sqlite3
+ sha256: a3ba4b66a7ab170ce7aa3f5ac43c19ee8d6637afbe7b7c95c94112b4f4d91566
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.11.0"
stack_trace:
dependency: transitive
description:
@@ -184,6 +224,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.0"
+ synchronized:
+ dependency: transitive
+ description:
+ name: synchronized
+ sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0"
term_glyph:
dependency: transitive
description:
@@ -210,4 +258,4 @@ packages:
version: "2.1.4"
sdks:
dart: ">=2.19.6 <3.0.0"
- flutter: ">=1.16.0"
+ flutter: ">=3.3.0"
pubspec.yaml
@@ -31,6 +31,8 @@ dependencies:
flutter:
sdk: flutter
provider: ^6.0.0
+ sqflite:
+ path:
# The following adds the Cupertino Icons font to your application.
@@ -41,6 +43,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
+ sqflite_common_ffi:
# The "flutter_lints" package below contains a set of recommended lints to
# encourage good coding practices. The lint set provided by the package is