Commit 1c300c8
Changed files (13)
android
ios
Runner
lib
model
screens
macos
windows
android/app/build.gradle
@@ -21,6 +21,12 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
+def keystoreProperties = new Properties()
+ def keystorePropertiesFile = rootProject.file('key.properties')
+ if (keystorePropertiesFile.exists()) {
+ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
+ }
+
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
@@ -43,21 +49,26 @@ android {
}
defaultConfig {
- // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
- applicationId "com.derdilla.blood_pressure_app"
+ applicationId "com.derdilla.bloodPressureApp"
// You can update the following values to match your application needs.
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
- minSdkVersion flutter.minSdkVersion
+ minSdkVersion 19
targetSdkVersion flutter.targetSdkVersion
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
+ signingConfigs {
+ release {
+ keyAlias keystoreProperties['keyAlias']
+ keyPassword keystoreProperties['keyPassword']
+ storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
+ storePassword keystoreProperties['storePassword']
+ }
+ }
buildTypes {
release {
- // TODO: Add your own signing config for the release build.
- // Signing with the debug keys for now, so `flutter run --release` works.
- signingConfig signingConfigs.debug
+ signingConfig signingConfigs.release
}
}
}
android/build.gradle
@@ -1,5 +1,5 @@
buildscript {
- ext.kotlin_version = '1.7.10'
+ ext.kotlin_version = '1.8.0'
repositories {
google()
mavenCentral()
ios/Runner/Info.plist
@@ -47,5 +47,9 @@
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
+ <key>LSSupportsOpeningDocumentsInPlace</key>
+ <true/>
+ <key>UIFileSharingEnabled</key>
+ <true/>
</dict>
</plist>
lib/model/blood_pressure.dart
@@ -1,13 +1,19 @@
import 'dart:collection';
+import 'dart:io';
import 'package:flutter/foundation.dart';
+import 'package:flutter/material.dart';
import 'package:path/path.dart';
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
import 'package:sqflite/sqflite.dart';
+import 'package:file_saver/file_saver.dart';
+import 'package:share_plus/share_plus.dart';
+import 'dart:convert' show utf8;
+import 'dart:typed_data';
class BloodPressureModel extends ChangeNotifier {
static const maxEntries = 2E64; // https://www.sqlite.org/limits.html Nr.13
late final Database _database;
- List<BloodPressureRecord> _allMeasurements = [];
+ List<BloodPressureRecord> _allMeasurements = []; // TODO: remove cache
var _cacheCount = 100; // how many db entries are cached on default
BloodPressureModel._create();
@@ -99,6 +105,37 @@ class BloodPressureModel extends ChangeNotifier {
}
return UnmodifiableListView(recordsInRange);
}
+
+ Future<void> save(BuildContext context) async { // TODO: passing context is not clean keep UI code out of model
+ // create csv
+ String csvData = 'timestampUnixMs, systolic, diastolic, pulse, notes\n';
+ List<Map<String, Object?>> allEntries = await _database.query('bloodPressureModel',
+ orderBy: 'timestamp DESC');
+ for (var e in allEntries) {
+ csvData += '${e['timestamp']}, ${e['systolic']}, ${e['diastolic']}, ${e['pulse']}, "${e['notes']}"\n';
+ }
+
+ // save data
+ print(csvData);
+ String path = await FileSaver.instance.saveFile(
+ name: 'blood_press_${DateTime.now().toIso8601String()}',
+ bytes: Uint8List.fromList(utf8.encode(csvData)),
+ ext: 'csv',
+ mimeType: MimeType.csv
+ );
+
+ // notify user about location
+ if (Platform.isLinux || Platform.isWindows || Platform.isMacOS) {
+ ScaffoldMessenger.of(context).showSnackBar(
+ SnackBar(content: Text('Exported to: $path')));
+ } else if (Platform.isAndroid || Platform.isIOS) {
+ Share.shareFiles([path], mimeTypes: [MimeType.csv.type]);
+ } else {
+
+ }
+
+
+ }
/* TODO:
lib/screens/home.dart
@@ -2,6 +2,8 @@ import 'package:blood_pressure_app/screens/add_measurement.dart';
import 'package:flutter/material.dart';
import 'package:blood_pressure_app/components/measurement_graph.dart';
import 'package:blood_pressure_app/components/measurement_list.dart';
+import 'package:provider/provider.dart';
+import 'package:blood_pressure_app/model/blood_pressure.dart';
class AppHome extends StatelessWidget {
const AppHome({super.key});
@@ -33,22 +35,42 @@ class AppHome extends StatelessWidget {
),
),
),
- floatingActionButton: Ink(
- decoration: ShapeDecoration(
- shape: const CircleBorder(),
- color: Theme.of(context).primaryColor
- ),
- child: IconButton(
- icon: const Icon(Icons.add),
- onPressed: () {
- Navigator.push(
- context,
- MaterialPageRoute(builder: (context) => const AddMeasurementPage()),
- );
- },
- ),
- ),
-
+ floatingActionButton:
+ Container(
+ height: 100,
+ child: Column(
+ children: [
+ Ink(
+ decoration: ShapeDecoration(
+ shape: const CircleBorder(),
+ color: Theme.of(context).unselectedWidgetColor
+ ),
+ child: IconButton(
+ icon: const Icon(Icons.save),
+ onPressed: () {
+ Provider.of<BloodPressureModel>(context, listen: false).save(context);
+ },
+ ),
+ ),
+ const SizedBox(height: 10,),
+ Ink(
+ decoration: ShapeDecoration(
+ shape: const CircleBorder(),
+ color: Theme.of(context).primaryColor
+ ),
+ child: IconButton(
+ icon: const Icon(Icons.add),
+ onPressed: () {
+ Navigator.push(
+ context,
+ MaterialPageRoute(builder: (context) => const AddMeasurementPage()),
+ );
+ },
+ ),
+ ),
+ ],
+ ),
+ )
);
}
}
\ No newline at end of file
linux/flutter/generated_plugin_registrant.cc
@@ -6,6 +6,14 @@
#include "generated_plugin_registrant.h"
+#include <file_saver/file_saver_plugin.h>
+#include <url_launcher_linux/url_launcher_plugin.h>
void fl_register_plugins(FlPluginRegistry* registry) {
+ g_autoptr(FlPluginRegistrar) file_saver_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin");
+ file_saver_plugin_register_with_registrar(file_saver_registrar);
+ g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
+ fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
+ url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
}
linux/flutter/generated_plugins.cmake
@@ -3,6 +3,8 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
+ file_saver
+ url_launcher_linux
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
macos/Flutter/GeneratedPluginRegistrant.swift
@@ -5,8 +5,16 @@
import FlutterMacOS
import Foundation
+import file_saver
+import path_provider_foundation
+import share_plus_macos
import sqflite
+import url_launcher_macos
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
+ FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin"))
+ PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
+ SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin"))
SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin"))
+ UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
}
macos/Runner/DebugProfile.entitlements
@@ -8,5 +8,7 @@
<true/>
<key>com.apple.security.network.server</key>
<true/>
+ <key>com.apple.security.files.downloads.read-write</key>
+<true/>
</dict>
</plist>
windows/flutter/generated_plugin_registrant.cc
@@ -6,6 +6,12 @@
#include "generated_plugin_registrant.h"
+#include <file_saver/file_saver_plugin.h>
+#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
+ FileSaverPluginRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("FileSaverPlugin"));
+ UrlLauncherWindowsRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}
windows/flutter/generated_plugins.cmake
@@ -3,6 +3,8 @@
#
list(APPEND FLUTTER_PLUGIN_LIST
+ file_saver
+ url_launcher_windows
)
list(APPEND FLUTTER_FFI_PLUGIN_LIST
pubspec.lock
@@ -41,6 +41,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.17.0"
+ cross_file:
+ dependency: transitive
+ description:
+ name: cross_file
+ sha256: "0b0036e8cccbfbe0555fd83c1d31a6f30b77a96b598b35a5d36dd41f718695e9"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.3.3+4"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.2"
cupertino_icons:
dependency: "direct main"
description:
@@ -73,6 +89,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.4"
+ file_saver:
+ dependency: "direct main"
+ description:
+ name: file_saver
+ sha256: "0de62b766ebbd491466b160909fce9f30d2c0b2ba9e062871dbda2e677e5b33b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.2.1"
fl_chart:
dependency: "direct main"
description:
@@ -99,6 +131,27 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.13.5"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.0.2"
intl:
dependency: "direct main"
description:
@@ -147,6 +200,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.0"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.4"
nested:
dependency: transitive
description:
@@ -163,6 +224,78 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.8.2"
+ path_provider:
+ dependency: transitive
+ description:
+ name: path_provider
+ sha256: c7edf82217d4b2952b2129a61d3ad60f1075b9299e629e149a8d2e39c2e6aad4
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.14"
+ path_provider_android:
+ dependency: transitive
+ description:
+ name: path_provider_android
+ sha256: "2cec049d282c7f13c594b4a73976b0b4f2d7a1838a6dd5aaf7bd9719196bee86"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.27"
+ path_provider_foundation:
+ dependency: transitive
+ description:
+ name: path_provider_foundation
+ sha256: ad4c4d011830462633f03eb34445a45345673dfd4faf1ab0b4735fbd93b19183
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.2.2"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ sha256: "2ae08f2216225427e64ad224a24354221c2c7907e448e6e0e8b57b1eb9f10ad1"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.10"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ sha256: "57585299a729335f1298b43245842678cb9f43a6310351b18fb577d6e33165ec"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.6"
+ path_provider_windows:
+ dependency: transitive
+ description:
+ name: path_provider_windows
+ sha256: d3f80b32e83ec208ac95253e0cd4d298e104fbc63cb29c5c69edaed43b0c69d6
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.6"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ sha256: "6a2128648c854906c53fa8e33986fc0247a1116122f9534dd20e3ab9e16a32bc"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ process:
+ dependency: transitive
+ description:
+ name: process
+ sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09"
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.2.4"
provider:
dependency: "direct main"
description:
@@ -171,6 +304,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.0.5"
+ share_plus:
+ dependency: "direct main"
+ description:
+ name: share_plus
+ sha256: f582d5741930f3ad1bf0211d358eddc0508cc346e5b4b248bd1e569c995ebb7a
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.5.3"
+ share_plus_linux:
+ dependency: transitive
+ description:
+ name: share_plus_linux
+ sha256: dc32bf9f1151b9864bb86a997c61a487967a08f2e0b4feaa9a10538712224da4
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ share_plus_macos:
+ dependency: transitive
+ description:
+ name: share_plus_macos
+ sha256: "44daa946f2845045ecd7abb3569b61cd9a55ae9cc4cbec9895b2067b270697ae"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
+ share_plus_platform_interface:
+ dependency: transitive
+ description:
+ name: share_plus_platform_interface
+ sha256: "0c6e61471bd71b04a138b8b588fa388e66d8b005e6f2deda63371c5c505a0981"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.2.1"
+ share_plus_web:
+ dependency: transitive
+ description:
+ name: share_plus_web
+ sha256: eaef05fa8548b372253e772837dd1fbe4ce3aca30ea330765c945d7d4f7c9935
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.1.0"
+ share_plus_windows:
+ dependency: transitive
+ description:
+ name: share_plus_windows
+ sha256: "3a21515ae7d46988d42130cd53294849e280a5de6ace24bae6912a1bffd757d4"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.1"
sky_engine:
dependency: transitive
description: flutter
@@ -264,6 +445,86 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.4.16"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.3.1"
+ url_launcher:
+ dependency: transitive
+ description:
+ name: url_launcher
+ sha256: "75f2846facd11168d007529d6cd8fcb2b750186bea046af9711f10b907e1587e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.10"
+ url_launcher_android:
+ dependency: transitive
+ description:
+ name: url_launcher_android
+ sha256: "22f8db4a72be26e9e3a4aa3f194b1f7afbc76d20ec141f84be1d787db2155cbd"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.0.31"
+ url_launcher_ios:
+ dependency: transitive
+ description:
+ name: url_launcher_ios
+ sha256: "9af7ea73259886b92199f9e42c116072f05ff9bea2dcb339ab935dfc957392c2"
+ url: "https://pub.dev"
+ source: hosted
+ version: "6.1.4"
+ url_launcher_linux:
+ dependency: transitive
+ description:
+ name: url_launcher_linux
+ sha256: "207f4ddda99b95b4d4868320a352d374b0b7e05eefad95a4a26f57da413443f5"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.5"
+ url_launcher_macos:
+ dependency: transitive
+ description:
+ name: url_launcher_macos
+ sha256: "91ee3e75ea9dadf38036200c5d3743518f4a5eb77a8d13fda1ee5764373f185e"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.5"
+ url_launcher_platform_interface:
+ dependency: transitive
+ description:
+ name: url_launcher_platform_interface
+ sha256: "6c9ca697a5ae218ce56cece69d46128169a58aa8653c1b01d26fcd4aad8c4370"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.2"
+ url_launcher_web:
+ dependency: transitive
+ description:
+ name: url_launcher_web
+ sha256: "81fe91b6c4f84f222d186a9d23c73157dc4c8e1c71489c4d08be1ad3b228f1aa"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.0.16"
+ url_launcher_windows:
+ dependency: transitive
+ description:
+ name: url_launcher_windows
+ sha256: "254708f17f7c20a9c8c471f67d86d76d4a3f9c1591aad1e15292008aceb82771"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.6"
+ uuid:
+ dependency: transitive
+ description:
+ name: uuid
+ sha256: "648e103079f7c64a36dc7d39369cabb358d377078a051d6ae2ad3aa539519313"
+ url: "https://pub.dev"
+ source: hosted
+ version: "3.0.7"
vector_math:
dependency: transitive
description:
@@ -272,6 +533,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
+ win32:
+ dependency: transitive
+ description:
+ name: win32
+ sha256: dd8f9344bc305ae2923e3d11a2a911d9a4e2c7dd6fe0ed10626d63211a69676e
+ url: "https://pub.dev"
+ source: hosted
+ version: "4.1.3"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ sha256: ee1505df1426458f7f60aac270645098d318a8b4766d85fde75f76f2e21807d1
+ url: "https://pub.dev"
+ source: hosted
+ version: "1.0.0"
sdks:
dart: ">=2.19.6 <3.0.0"
flutter: ">=3.3.0"
pubspec.yaml
@@ -40,6 +40,8 @@ dependencies:
cupertino_icons: ^1.0.2
intl: ^0.18.1
fl_chart: ^0.62.0
+ file_saver: ^0.2.1
+ share_plus: ^4.5.3
dev_dependencies:
flutter_test: