Skip to content

Commit

Permalink
Exposure History Update/Remove Redundant Push (#1239)
Browse files Browse the repository at this point in the history
* Fixes.

* ExposureManagerTests.

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* Updates.

* cleanup

* Bugfixes.

* Updates per pr feedback.

* Merge develop into mb-bt-ios-tests

* wip

* wip

* wip
  • Loading branch information
Matt Buckley authored Jul 15, 2020
1 parent 8bf83a1 commit adca36a
Show file tree
Hide file tree
Showing 19 changed files with 119 additions and 60 deletions.
19 changes: 19 additions & 0 deletions app/ExposureHistoryContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface ExposureHistoryState {
userHasNewExposure: boolean;
observeExposures: () => void;
resetExposures: () => void;
getCurrentExposures: () => void;
}

const initialState = {
Expand All @@ -26,6 +27,7 @@ const initialState = {
userHasNewExposure: true,
observeExposures: () => {},
resetExposures: () => {},
getCurrentExposures: () => {},
};

const ExposureHistoryContext = createContext<ExposureHistoryState>(
Expand All @@ -42,6 +44,7 @@ export interface ExposureEventsStrategy {
exposureInfo: ExposureInfo,
calendarOptions: ExposureCalendarOptions,
) => ExposureHistory;
getCurrentExposures: (cb: (exposureInfo: ExposureInfo) => void) => void;
}

interface ExposureHistoryProps {
Expand Down Expand Up @@ -84,6 +87,10 @@ const ExposureHistoryProvider: FunctionComponent<ExposureHistoryProps> = ({
return subscription.remove;
}, [exposureInfoSubscription, toExposureHistory]);

useEffect(() => {
getCurrentExposures();
}, [toExposureHistory]);

const observeExposures = () => {
setUserHasNewExposure(false);
};
Expand All @@ -92,6 +99,17 @@ const ExposureHistoryProvider: FunctionComponent<ExposureHistoryProps> = ({
setUserHasNewExposure(true);
};

const getCurrentExposures = async () => {
const cb = (exposureInfo: ExposureInfo) => {
const exposureHistory = toExposureHistory(
exposureInfo,
blankHistoryConfig,
);
setExposureHistory(exposureHistory);
};
exposureEventsStrategy.getCurrentExposures(cb);
};

const hasBeenExposed = false;
return (
<ExposureHistoryContext.Provider
Expand All @@ -101,6 +119,7 @@ const ExposureHistoryProvider: FunctionComponent<ExposureHistoryProps> = ({
userHasNewExposure,
observeExposures,
resetExposures,
getCurrentExposures,
}}>
{children}
</ExposureHistoryContext.Provider>
Expand Down
1 change: 0 additions & 1 deletion app/bt/PermissionsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@ const PermissionsProvider = ({

const checkENPermission = () => {
const handleNativeResponse = (status: ENPermissionStatus) => {
console.log('checking ', status);
setExposureNotificationsPermission(status);
};
BTNativeModule.getCurrentENPermissionsStatus(handleNativeResponse);
Expand Down
1 change: 1 addition & 0 deletions app/bt/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ExposureEventsStrategy } from '../ExposureHistoryContext';
const btExposureEventContext: ExposureEventsStrategy = {
exposureInfoSubscription: BTNativeModule.subscribeToExposureEvents,
toExposureHistory: toExposureHistory,
getCurrentExposures: BTNativeModule.getCurrentExposures,
};

const btStrategy: TracingStrategy = {
Expand Down
11 changes: 11 additions & 0 deletions app/bt/nativeModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ export const getCurrentENPermissionsStatus = async (
});
};

// Exposure History Module
const exposureHistoryModule = NativeModules.ExposureHistoryModule;
export const getCurrentExposures = async (
cb: (exposureInfo: ExposureInfo) => void,
): Promise<void> => {
exposureHistoryModule.getCurrentExposures((rawExposure: string) => {
const rawExposures: RawExposure[] = JSON.parse(rawExposure);
cb(toExposureInfo(rawExposures));
});
};

// Exposure Key Module
const exposureKeyModule = NativeModules.ExposureKeyModule;

Expand Down
1 change: 1 addition & 0 deletions app/factories/tracingStrategy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default Factory.define<TracingStrategy>(() => ({
return { remove: () => {} };
},
toExposureHistory: () => [],
getCurrentExposures: () => {},
},
permissionsProvider: PermissionsProvider,
homeScreenComponent: HomeScreen,
Expand Down
4 changes: 4 additions & 0 deletions app/gps/exposureInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const ExposureEvents: GPSExposureHistoryEventEmitter = {
},
};

export const getCurrentExposures = async (
_cb: (exposureInfo: ExposureInfo) => void,
): Promise<void> => {};

export const subscribeToExposureEvents = (
cb: (exposureHistory: ExposureInfo) => void,
): { remove: () => void } => {
Expand Down
3 changes: 2 additions & 1 deletion app/gps/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import { TracingStrategy } from '../tracingStrategy';
import { PermissionsProvider } from './PermissionsContext';
import Home from './Home';
import ExportStack from './ExportStack';
import { subscribeToExposureEvents } from './exposureInfo';
import { subscribeToExposureEvents, getCurrentExposures } from './exposureInfo';
import { useGPSCopyContent, gpsAssets } from './content';
import { ExposureEventsStrategy } from '../ExposureHistoryContext';
import { toExposureHistory } from './intersect/exposureHistory';

const gpsExposureEventContext: ExposureEventsStrategy = {
exposureInfoSubscription: subscribeToExposureEvents,
toExposureHistory: toExposureHistory,
getCurrentExposures: getCurrentExposures,
};

const gpsStrategy: TracingStrategy = {
Expand Down
24 changes: 17 additions & 7 deletions ios/BT/API/Model/Exposure.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import RealmSwift

@objcMembers
class Exposure: Object, Codable {
var id: String!
var date: Int!
var duration: TimeInterval!
var totalRiskScore: ENRiskScore!
var transmissionRiskLevel: ENRiskLevel!
@objc dynamic var id: String = .default
@objc dynamic var date: Int = 0
@objc dynamic var duration: Double = 0.0
@objc dynamic var totalRiskScore: Int = 0
@objc dynamic var transmissionRiskLevel: Int = 0

init(id: String,
date: Int,
Expand All @@ -18,8 +18,8 @@ class Exposure: Object, Codable {
self.id = id
self.date = date
self.duration = duration
self.totalRiskScore = totalRiskScore
self.transmissionRiskLevel = transmissionRiskLevel
self.totalRiskScore = Int(totalRiskScore)
self.transmissionRiskLevel = Int(transmissionRiskLevel)
super.init()
}

Expand All @@ -31,4 +31,14 @@ class Exposure: Object, Codable {
"id"
}

var asDictionary : [String: Any] {
return [
"id": id,
"date": date,
"duration": duration,
"totalRiskScore": totalRiskScore,
"transmissionRiskLevel": transmissionRiskLevel
]
}

}
2 changes: 1 addition & 1 deletion ios/BT/API/Model/UserState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class UserState: Object {
@objc dynamic var remainingDailyFileProcessingCapacity: Int = Constants.dailyFileProcessingCapacity
@objc dynamic var exposureDetectionErrorLocalizedDescription: String = .default
@objc dynamic var urlOfMostRecentlyDetectedKeyFile: String = .default
dynamic var exposures: List<Exposure> = List<Exposure>()
let exposures: List<Exposure> = List<Exposure>()

override class func primaryKey() -> String? {
"id"
Expand Down
25 changes: 5 additions & 20 deletions ios/BT/ExposureManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,6 @@ final class ExposureManager: NSObject {
totalRiskScore: exposure.totalRiskScore,
transmissionRiskLevel: exposure.transmissionRiskLevel)
}
if !newExposures.isEmpty {
self.postNewExposureNotification()
}
self.finish(.success(newExposures),
processedFileCount: processedFileCount,
lastProcessedUrlPath: lastProcessedUrlPath,
Expand Down Expand Up @@ -345,23 +342,6 @@ final class ExposureManager: NSObject {
#endif
}

func postNewExposureNotification() {
let identifier = String.exposureDetectionErrorNotificationIdentifier

let content = UNMutableNotificationContent()
content.title = String.newExposureNotificationTitle.localized
content.body = String.newExposureNotificationBody.localized
content.sound = .default
let request = UNNotificationRequest(identifier: identifier, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request) { error in
DispatchQueue.main.async {
if let error = error {
print("Error showing error user notification: \(error)")
}
}
}
}

func urlPathsToProcess(_ urlPaths: [String]) -> [String] {
let startIdx = startIndex(for: urlPaths)
let endIdx = min(startIdx + BTSecureStorage.shared.userState.remainingDailyFileProcessingCapacity, urlPaths.count)
Expand All @@ -379,6 +359,11 @@ final class ExposureManager: NSObject {
}
}

@objc var currentExposures: String {
let exposures = Array(BTSecureStorage.shared.userState.exposures)
return exposures.jsonStringRepresentation()
}

func updateRemainingFileCapacity() {
guard let lastResetDate = BTSecureStorage.shared.userState.dateLastPerformedFileCapacityReset else {
BTSecureStorage.shared.dateLastPerformedFileCapacityReset = Date()
Expand Down
11 changes: 5 additions & 6 deletions ios/BT/Extensions/Foundation/Encodable+Extensions.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import RealmSwift

extension List where Element: Encodable {
public func encode(to coder: Encoder) throws {
var container = coder.unkeyedContainer()
try container.encode(contentsOf: self)
extension Encodable {
func jsonStringRepresentation() -> String {
let encodedValue = try! JSONEncoder().encode(self)
let string = String(data: encodedValue, encoding: .utf8)!
return string
}
}
8 changes: 8 additions & 0 deletions ios/BT/Extensions/Foundation/List+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import RealmSwift

extension List where Element: Encodable {
public func encode(to coder: Encoder) throws {
var container = coder.unkeyedContainer()
try container.encode(contentsOf: self)
}
}
1 change: 0 additions & 1 deletion ios/BT/Extensions/Other/ExposureManager+Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ extension ExposureManager {
ExposureManager.shared.postExposureDetectionErrorNotification()
callback([NSNull(), "Exposure deteaction error message: \(BTSecureStorage.shared.exposureDetectionErrorLocalizedDescription)"])
case .simulateExposure:
ExposureManager.shared.postNewExposureNotification()
let exposure = Exposure(id: UUID().uuidString,
date: Date().posixRepresentation - Int(TimeInterval.random(in: 0...13)) * 24 * 60 * 60 * 1000,
duration: TimeInterval(Int.random(in: 1...10) * 60 * 5 * 1000),
Expand Down
23 changes: 18 additions & 5 deletions ios/BT/Storage/BTSecureStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import RealmSwift

final class BTSecureStorage: SafePathsSecureStorage {

static let shared = BTSecureStorage()
static let shared = BTSecureStorage(inMemory: false)

override var keychainIdentifier: String {
"\(Bundle.main.bundleIdentifier!).realm"
Expand All @@ -17,6 +17,13 @@ final class BTSecureStorage: SafePathsSecureStorage {
return realmConfig
}()

override init(inMemory: Bool = false) {
super.init(inMemory: inMemory)
if !userStateExists {
resetUserState({ _ in })
}
}

override func getRealmConfig() -> Realm.Configuration? {
if let key = getEncryptionKey() {
if (inMemory) {
Expand All @@ -36,13 +43,17 @@ final class BTSecureStorage: SafePathsSecureStorage {
return realm.object(ofType: UserState.self, forPrimaryKey: 0) ?? UserState()
}

var userStateExists: Bool {
let realm = try! Realm(configuration: realmConfig)
return realm.object(ofType: UserState.self, forPrimaryKey: 0) != nil
}

func setUserValue<Value: Codable>(value: Value, keyPath: String, notificationName: Notification.Name) {
let realm = try! Realm(configuration: realmConfig)
try! realm.write {
realm.create(UserState.self, value: [keyPath: value], update: .modified)
let encodedValue = try JSONEncoder().encode(value)
let stringRepresentation = String(data: encodedValue, encoding: .utf8)!
NotificationCenter.default.post(name: notificationName, object: stringRepresentation)
let jsonString = value.jsonStringRepresentation()
NotificationCenter.default.post(name: notificationName, object: jsonString)
}
}

Expand All @@ -61,7 +72,9 @@ final class BTSecureStorage: SafePathsSecureStorage {
func storeExposures(_ exposures: [Exposure]) {
let realm = try! Realm(configuration: realmConfig)
try! realm.write {
exposures.forEach { userState.exposures.append($0) }
userState.exposures.append(objectsIn: exposures)
let jsonString = userState.exposures.jsonStringRepresentation()
NotificationCenter.default.post(name: .ExposuresDidChange, object: jsonString)
}
}

Expand Down
17 changes: 17 additions & 0 deletions ios/BT/bridge/ExposureHistoryModule.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#import <Foundation/Foundation.h>
#import <React/RCTLog.h>
#import <React/RCTBridgeModule.h>
#import "BT-Swift.h"

@interface ExposureHistoryModule: NSObject <RCTBridgeModule>
@end

@implementation ExposureHistoryModule

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(getCurrentExposures: (RCTResponseSenderBlock)callback) {
callback(@[[[ExposureManager shared] currentExposures]]);
}

@end
2 changes: 1 addition & 1 deletion ios/BT/bridge/ExposureKeyModule.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ @implementation ExposureKeyModule
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{
// [[ExposureManager shared] getAndPostDiagnosisKeysWithCertificate:certificate HMACKey:HMACKey com]
[[ExposureManager shared] getAndPostDiagnosisKeysWithCertificate:certificate HMACKey:HMACKey resolve:resolve reject:reject];
}


Expand Down
8 changes: 8 additions & 0 deletions ios/COVIDSafePaths.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
B576CC4324993F5200CDD9D9 /* Date+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B576CC3D24993F4C00CDD9D9 /* Date+Extensions.swift */; };
B576CC4424993F5200CDD9D9 /* Encodable+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B576CC4024993F4C00CDD9D9 /* Encodable+Extensions.swift */; };
B596C0722488127D00943B79 /* ENPermissionsModule.m in Sources */ = {isa = PBXBuildFile; fileRef = B596C0712488127D00943B79 /* ENPermissionsModule.m */; };
B59F4C3524BDF879007B09D5 /* ExposureHistoryModule.m in Sources */ = {isa = PBXBuildFile; fileRef = B59F4C3424BDF879007B09D5 /* ExposureHistoryModule.m */; };
B59F4C3724BE0658007B09D5 /* List+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B59F4C3624BE0658007B09D5 /* List+Extensions.swift */; };
B5A6FD6E24BC9E69007D328C /* ExposureManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5A6FD6A24BC9E54007D328C /* ExposureManagerTests.swift */; };
B5C9723024B8A909007F4C0B /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5C9722F24B8A909007F4C0B /* Constants.swift */; };
B5E29D54249E3BE100E686DC /* ExposureManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E29D53249E3BE100E686DC /* ExposureManager+Extensions.swift */; };
Expand Down Expand Up @@ -328,6 +330,8 @@
B576CC4024993F4C00CDD9D9 /* Encodable+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Encodable+Extensions.swift"; sourceTree = "<group>"; };
B57BA02624A3CD3F00FBAA05 /* KeySubmissionModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KeySubmissionModule.m; sourceTree = "<group>"; };
B596C0712488127D00943B79 /* ENPermissionsModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ENPermissionsModule.m; sourceTree = "<group>"; };
B59F4C3424BDF879007B09D5 /* ExposureHistoryModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExposureHistoryModule.m; sourceTree = "<group>"; };
B59F4C3624BE0658007B09D5 /* List+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "List+Extensions.swift"; sourceTree = "<group>"; };
B5A6FD6A24BC9E54007D328C /* ExposureManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExposureManagerTests.swift; sourceTree = "<group>"; };
B5C490A72498F84000588A5F /* Region.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Region.swift; sourceTree = "<group>"; };
B5C9722F24B8A909007F4C0B /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -749,6 +753,7 @@
B5E79436249E666B00BD8596 /* Array+Extensions.swift */,
B576CC3D24993F4C00CDD9D9 /* Date+Extensions.swift */,
B576CC4024993F4C00CDD9D9 /* Encodable+Extensions.swift */,
B59F4C3624BE0658007B09D5 /* List+Extensions.swift */,
B5FBB0D624916DE100433980 /* Notification+Extensions.swift */,
);
path = Foundation;
Expand Down Expand Up @@ -878,6 +883,7 @@
B596C0712488127D00943B79 /* ENPermissionsModule.m */,
C550A66524B7906F002CA7F2 /* ExposureKeyModule.m */,
B57BA02624A3CD3F00FBAA05 /* KeySubmissionModule.m */,
B59F4C3424BDF879007B09D5 /* ExposureHistoryModule.m */,
B5FB3B42248BD61A001DB1D5 /* DebugMenuModule.m */,
B5582D43249943DE001458A9 /* ExposureEventEmitter.m */,
);
Expand Down Expand Up @@ -1393,8 +1399,10 @@
B5FB3B43248BD61A001DB1D5 /* DebugMenuModule.m in Sources */,
B5582D47249943E5001458A9 /* ExposureEventEmitter.m in Sources */,
C5C850C7248014F700A494CA /* main.m in Sources */,
B59F4C3524BDF879007B09D5 /* ExposureHistoryModule.m in Sources */,
B596C0722488127D00943B79 /* ENPermissionsModule.m in Sources */,
B5FC37D8248A784F006474EB /* DiagnosisKeyRequests.swift in Sources */,
B59F4C3724BE0658007B09D5 /* List+Extensions.swift in Sources */,
B5FBB0D324916B3600433980 /* String+Extensions.swift in Sources */,
B507A9EE24A197FF00E039D5 /* DownloadedPackage.swift in Sources */,
B5FC37F6248A9968006474EB /* ENTemporaryExposureKey+Extensions.swift in Sources */,
Expand Down
Loading

0 comments on commit adca36a

Please sign in to comment.