Skip to content

Commit

Permalink
Cache user history [#179].
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihail Varbanov committed Sep 23, 2020
1 parent bf62917 commit 84797f0
Showing 1 changed file with 65 additions and 14 deletions.
79 changes: 65 additions & 14 deletions lib/service/Health.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
//TMP: import 'package:flutter/services.dart' show rootBundle;
Expand All @@ -38,6 +39,8 @@ import 'package:illinois/service/Storage.dart';
import 'package:illinois/service/User.dart';
import 'package:illinois/utils/Crypt.dart';
import 'package:illinois/utils/Utils.dart';
import 'package:path/path.dart';
import 'package:path_provider/path_provider.dart';
import "package:pointycastle/export.dart";

class Health with Service implements NotificationsListener {
Expand All @@ -54,6 +57,7 @@ class Health with Service implements NotificationsListener {

static const String notifyHealthStatusChanged = "edu.illinois.rokwire.health.health_status.changed";

static const String _historyFileName = "history.json";

HealthUser _user;
PrivateKey _userPrivateKey;
Expand All @@ -62,6 +66,9 @@ class Health with Service implements NotificationsListener {
String _currentCountyId;
DateTime _pausedDateTime;

File _historyCacheFile;
List<Covid19History> _historyCache;

bool _processingCountyStatus;
bool _loadingUpdatedHistory;

Expand Down Expand Up @@ -101,6 +108,8 @@ class Health with Service implements NotificationsListener {
_user = _loadUserFromStorage();
_servicePublicKey = RsaKeyHelper.parsePublicKeyFromPem(Config().healthPublicKey);
_userPrivateKey = await _rsaUserPrivateKey;
_historyCacheFile = await _getHistoryCacheFile();
_historyCache = await _loadHistoryCache();
_refreshUser();
}

Expand Down Expand Up @@ -157,6 +166,8 @@ class Health with Service implements NotificationsListener {
_lastCovid19Status = null;
_healthUserPrivateKey = null;
_healthUser = null;

_clearHistoryCache();

NotificationService().notify(notifyStatusChanged, null);
NotificationService().notify(notifyHistoryUpdated, null);
Expand Down Expand Up @@ -211,13 +222,45 @@ class Health with Service implements NotificationsListener {

// Network API: Covid19History

Future<List<Covid19History>> loadCovid19History() async {
Future<File> _getHistoryCacheFile() async {
Directory appDocDir = await getApplicationDocumentsDirectory();
String cacheFilePath = join(appDocDir.path, _historyFileName);
return File(cacheFilePath);
}

Future<List<Covid19History>> _loadHistoryCache() async {
if (this._isLoggedIn && (_historyCacheFile != null)) {
String cachedString = await _historyCacheFile.exists() ? await _historyCacheFile.readAsString() : null;
List<dynamic> cachedJson = (cachedString != null) ? AppJson.decodeList(cachedString) : null;
return (cachedJson != null) ? await Covid19History.listFromJson(cachedJson, _decryptHistoryKeys) : null;
}
return null;
}

Future<void> _clearHistoryCache() async {
_historyCacheFile = null;
if (await _historyCacheFile.exists()) {
try { await _historyCacheFile.delete(); } catch (e) { print(e?.toString()); }
}
}

Future<List<Covid19History>> loadCovid19History({bool force}) async {
if (this._isLoggedIn) {
String url = "${Config().healthUrl}/covid19/v2/histories";
Response response = await Network().get(url, auth: NetworkAuth.User);
String responseString = (response?.statusCode == 200) ? response.body : null;
List<dynamic> responseJson = (responseString != null) ? AppJson.decodeList(responseString) : null;
return (responseJson != null) ? await Covid19History.listFromJson(responseJson, _decryptHistoryKeys) : null;
if ((_historyCache != null) && (force != true)) {
return _historyCache;
}
else {
String url = "${Config().healthUrl}/covid19/v2/histories";
Response response = await Network().get(url, auth: NetworkAuth.User);
String responseString = (response?.statusCode == 200) ? response.body : null;
List<dynamic> responseJson = (responseString != null) ? AppJson.decodeList(responseString) : null;
List<Covid19History> result = (responseJson != null) ? await Covid19History.listFromJson(responseJson, _decryptHistoryKeys) : null;
if (result != null) {
_historyCache = result;
try { await _historyCacheFile?.writeAsString(responseString, flush: true); } catch (e) { print(e?.toString()); }
return result;
}
}
}
return null;
}
Expand All @@ -236,8 +279,10 @@ class Health with Service implements NotificationsListener {
String url = "${Config().healthUrl}/covid19/v2/histories";
String post = AppJson.encode(history?.toJson());
Response response = await Network().post(url, body: post, auth: NetworkAuth.User);
String responseString = (response?.statusCode == 200) ? response.body : null;
return await Covid19History.decryptedFromJson(AppJson.decode(responseString), _decryptHistoryKeys);
if (response?.statusCode == 200) {
await _clearHistoryCache();
return await Covid19History.decryptedFromJson(AppJson.decode(response.body), _decryptHistoryKeys);
}
}
return null;
}
Expand All @@ -257,8 +302,10 @@ class Health with Service implements NotificationsListener {
String url = "${Config().healthUrl}/covid19/v2/histories/${history.id}";
String post = AppJson.encode(history?.toJson());
Response response = await Network().put(url, body: post, auth: NetworkAuth.User);
String responseString = (response?.statusCode == 200) ? response.body : null;
return await Covid19History.decryptedFromJson(AppJson.decode(responseString), _decryptHistoryKeys);
if (response?.statusCode == 200) {
await _clearHistoryCache();
return await Covid19History.decryptedFromJson(AppJson.decode(response.body), _decryptHistoryKeys);
}
}
return null;
}
Expand All @@ -267,7 +314,10 @@ class Health with Service implements NotificationsListener {
if (this._isAuthenticated) {
String url = "${Config().healthUrl}/covid19/v2/histories";
Response response = await Network().delete(url, auth: NetworkAuth.User);
return response?.statusCode == 200;
if (response?.statusCode == 200) {
await _clearHistoryCache();
return true;
}
}
return false;
}
Expand Down Expand Up @@ -655,7 +705,7 @@ class Health with Service implements NotificationsListener {
List<Covid19Event> events = await _processPendingEvents();

// 3. Load history
List<Covid19History> histories = await loadCovid19History();
List<Covid19History> histories = await loadCovid19History(force: true);

// 4. Rebuild status if we had been processed pending events
Covid19Status currentStatus;
Expand Down Expand Up @@ -725,7 +775,7 @@ class Health with Service implements NotificationsListener {
Future<Covid19Status> _statusForCounty(String countyId, { List<Covid19History> histories }) async {

if (histories == null) {
histories = await loadCovid19History();
histories = await loadCovid19History(force: true);
if (histories == null) {
return null;
}
Expand All @@ -736,7 +786,6 @@ class Health with Service implements NotificationsListener {
return null;
}


Covid19Status status;
HealthRuleStatus2 defaultStatus = rules?.defaults?.status?.eval(history: histories, historyIndex: -1, rules: rules);
if (defaultStatus != null) {
Expand Down Expand Up @@ -1492,6 +1541,8 @@ class Health with Service implements NotificationsListener {
if (await _clearUser()) {
NativeCommunicator().removeHealthRSAPrivateKey(userId: _userId);

await _clearHistoryCache();

Storage().currentHealthCountyId = _currentCountyId = null;
Storage().lastHealthProvider = null;
Storage().lastHealthCovid19Status = null;
Expand Down

0 comments on commit 84797f0

Please sign in to comment.