Git Product home page Git Product logo

mobile's People

Contributors

apollozhu avatar cheng-tan avatar daniellrgn avatar hanfeichen avatar hungngo97 avatar justinklchan avatar kgao avatar kumpera avatar samkaufman avatar scottleibrand avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mobile's Issues

[Contact Tracing] Apple x Google Exposure Notification Framework

Documentation: https://developer.apple.com/documentation/exposurenotification
Analysis: https://nshipster.com/contact-tracing/

Concerns

In the FAQ, Apple states:

In keeping with our privacy guidelines, Apple and Google will not receive identifying information about the user, location data, or information about any other devices the user has been in proximity of.

Apps will receive approval based on a specific set of criteria designed to ensure they are only
administered in conjunction with public health authorities, meet our privacy requirements, and protect user data.

looking for contacts for those rolling this solution out

This is not a technical question or issue but I'm looking for functional contacts that might be able to discuss their plans for implementing the CovidSafe solution and how it would be rolled out to the constituents. Any help is appreciated.
-Brandon

Allow user to share covidsafe

In settings, when user clicks on "Share", a bottom sheet should pop up and allow user to share through message, social media etc.

contact_log logic - need permission to submit

Attached the contact_log.swift here in case someone need to use this over weekend.

/// --------------------------------------------------------------------------------
///
///
/// CovidSafe
///
///
/// ------------------------ Coordinate <> Locationm ------------------------
import MapKit
import CoreLocation

// Draw on the map - test in playground
func drawMap(lat:Double,lon:Double,address:CLPlacemark){
//--------------------- Draw on the map -----------------
let appleParkWayCoordinates = CLLocationCoordinate2DMake(lat, lon)
// Now let's create a MKMapView
let mapView = MKMapView(frame: CGRect(x:0, y:0, width:800, height:800))
// Define a region for our map view
var mapRegion = MKCoordinateRegion()
let mapRegionSpan = 0.02
mapRegion.center = appleParkWayCoordinates
mapRegion.span.latitudeDelta = mapRegionSpan
mapRegion.span.longitudeDelta = mapRegionSpan
mapView.setRegion(mapRegion, animated: true)
// Create a map annotation
let annotation = MKPointAnnotation()
annotation.coordinate = appleParkWayCoordinates
annotation.title = address.name! //Buiness name? Google API place likelyhood.
annotation.subtitle = address.compactAddress!
mapView.addAnnotation(annotation)
// Add the created mapView to our Playground Live View
PlaygroundPage.current.liveView = mapView
//--------------------------------------
}

//Test input example:
let lat = 40.75
let lon = -73.98
var placeList: [CLPlacemark] = [] //List of CLPlacemarks

//Batch input example:
struct Geo : Codable {
let lat : Double
let lon : Double
let timestamp: Double
}

struct AddressTS : Codable {
let address : String
let timestamp: Double
}

struct AddressPeriod : Codable {
let address: String
let period: String
}

//input type 1 example
let geoList = [Geo(lat:40.75,lon:-73.98,timestamp:1587749400),
Geo(lat:40.75,lon:-73.98,timestamp:1587751200),
Geo(lat:40.76,lon:-73.99,timestamp:1587752000),
Geo(lat:40.76,lon:-73.99,timestamp:1587762000),
Geo(lat:40.77,lon:-74.00,timestamp:1587770000)]
do {
//encode: struct to json
let jsonData = try JSONEncoder().encode(geoList)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString) // [{"lat":40.75,"lon":-73.98,"timestamp":1587749400},{"lat":40.75,"lon":-73.98,"timestamp":1587751200}]
//decode: json to struct
let decodedGeos = try JSONDecoder().decode([Geo].self, from: jsonData)
print(decodedGeos) //[__lldb_expr_166.Geo(lat: 40.75, lon: -73.98, timestamp: 1587749400), __lldb_expr_166.Geo(lat: 40.75, lon: -73.98, timestamp: 1587751200)]
//decode json string to struct
let JSON = """
[{ "lat":40.75,
"lon":-73.98,
"timestamp":1587749400
},
{
"lat":40.75,
"lon":-73.98,
"timestamp":1587751200
}]
"""
//input type 2 example
let test:[Geo] = try! JSONDecoder().decode([Geo].self, from: JSON.data(using: .utf8)!)
print(test[0].timestamp)
} catch { print(error) }

//---------------------------------------------------------------------------------
// Step 1: convert JSON to geoList input, then use the method - batchReserseGeocodeLocation:
//---------------------------------------------------------------------------------
func batchReserseGeocodeLocation(geoList:[Geo], completionHandler:@escaping([AddressTS]) -> ()){ //Please specify your type as contract to use
// Fire an asynchronous callback when all your requests finish in synchronous.
let asyncGroup = DispatchGroup()
var placeList: [AddressTS] = [AddressTS](repeating: AddressTS(address:"",timestamp:0), count: geoList.count) //List of AddressTS
for (index, geo) in geoList.enumerated()
{ asyncGroup.enter()
//Reverse Geocoding With Clgeocoder
let gecoder = CLGeocoder.init()
gecoder.reverseGeocodeLocation(CLLocation.init(latitude:geo.lat,longitude: geo.lon)) { (addresses, error) in
if error == nil{
if let address = addresses{
//Async: Here you can get all the info by combining that you can make address!
print("Address (index) : (address)")
//async - availability first
//placeList.append(AddressTS(address: address[0].compactAddress!, timestamp: geo.timestamp))
//async - sequential reserved - fixed size
placeList[index] = AddressTS(address: address[0].compactAddress!, timestamp: geo.timestamp)
//TODO: connect with frontend UI.
//drawMap(lat:lat,lon:lon,address:address[0])
asyncGroup.leave()
}
}
}
}
asyncGroup.notify(queue: .main){
print("Finished the loop - find (geoList.count) addresses")
// action complete
completionHandler(placeList)
}
}

// UTC time converter
func UTC_Converter(unixtime1:Double, unixtime2:Double, timezone:String?=nil) -> String{
// Localization
var localTimeZoneAbbreviation: String { return TimeZone.current.abbreviation() ?? "" } // "UTC-4"
let date1 = Date(timeIntervalSince1970: unixtime1)
let date2 = Date(timeIntervalSince1970: unixtime2)
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: localTimeZoneAbbreviation) //Set timezone that you want: i.e. New York is "UTC-4"
// Overwrite
if (timezone != nil) {
dateFormatter.timeZone = TimeZone(abbreviation: timezone ?? "")
}
dateFormatter.locale = NSLocale.current
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" //Specify your format that you want
let strDate1 = dateFormatter.string(from: date1)
let strDate2 = dateFormatter.string(from: date2)
return (strDate1 + " ~ " + strDate2)
}

//---------------------------------------------------------------------------------
// Step2: aggregate address result - from timestamp to period
//---------------------------------------------------------------------------------
func aggregateAddressList(addressTSList:[AddressTS], completionHandler:@escaping([AddressPeriod]) -> ()){
var AddressPeriodList: [AddressPeriod] = [] //List of AddressPeriod
var start: Double = 0 // UTC start
var end: Double = 0 // UTC end
var address = "" // address pointer
for (index, address_ts) in addressTSList.enumerated(){
if index == 0 { // first one
start = address_ts.timestamp
end = address_ts.timestamp
address = address_ts.address
}
else if address_ts.address != address {
//append - dynamic size
//logic: same location + 10min
if start == end {
AddressPeriodList.append(AddressPeriod(address:address,period: UTC_Converter(unixtime1:start,unixtime2:(start+600))))
} else {
AddressPeriodList.append(AddressPeriod(address:address,period: UTC_Converter(unixtime1:start,unixtime2:end)))
}
//update
start = address_ts.timestamp
end = address_ts.timestamp
address = address_ts.address
if index == (addressTSList.count-1){ // last one - unique, add extra
//logic: same location + 10min
AddressPeriodList.append(AddressPeriod(address:address_ts.address, period: UTC_Converter(unixtime1:start,unixtime2:(start+600))))
}
} else {//move on
end = address_ts.timestamp
if index == (addressTSList.count-1){ // last one - same, add extra
//logic: same location + 10min
if start == end {
AddressPeriodList.append(AddressPeriod(address:address, period: UTC_Converter(unixtime1:start,unixtime2:(start+600))))
} else {
AddressPeriodList.append(AddressPeriod(address:address, period: UTC_Converter(unixtime1:start,unixtime2:end)))
}
}
}
}
completionHandler(AddressPeriodList)
}

//---------------------------------------------------------------------------------
//Test - Type 1 input
//---------------------------------------------------------------------------------
batchReserseGeocodeLocation(geoList: geoList, completionHandler: { addressTSList in
sleep(1)
do{
try print("-------------------\nAddressTSList: ((String(data: JSONEncoder().encode(addressTSList), encoding: .utf8)!))")
}catch{ print(error) }
aggregateAddressList(addressTSList:addressTSList, completionHandler: { addressPeriodList in
sleep(1)
do{
try print("-------------------\nFinal AddressPeriodList: ((String(data: JSONEncoder().encode(addressPeriodList), encoding: .utf8)!))")
}catch{ print(error) }
})
})

Update story

  • Enable code push
  • Ensure data stays there on update.

UI updates

  • App icon
  • Add power on/off button for broadcasting
  • Add animation for power on/off button
  • Update tab navigation icons
  • Update resources list
  • Update what to do next list

BLE

  • Rotate contact? UUID on broadcast
  • Ensure background broadcasting works
  • Test with Android
  • Test with app state changes (go foreground/background/close app/lock phone / etc)
  • Do we need CLBeacons ?
  • Surface errors to JS

Recording last query timestamp

On device, for each coarse location, we need to record query ids and timestamp, when fetching messages for the same region but different resolution of the coarse location, we can deduplicate the message id.

Retention period rework

Remove the option to change retention period.
Ensure we have a way to purge logs.

This applies to BLE and location.

Sensitive strings

We need copy for a bunch of sensitive strings.

info.plist:

  • NSBluetoothAlwaysUsageDescription: Currently Trace Defense uses bluetooth to track people that comes close to you.
  • Privacy - Bluetooth Peripheral Usage Description
  • Privacy - Location Always and When In Use Usage Description
  • Privacy - Location Always Usage Description
  • Privacy - Location When In Use Usage Description

Delay to send BLE seeds

  • Needs to clarify what's this requirement mean? After user self reporting we wait a period of time uploading the seeds? Or we are sending the seeds from the past?

Shipping

  • Analytics
  • Crash reporting
  • Test flight account

Testing

Client Side:

GPS:

  • Logs lat, lon, timestamp every 5 minutes
  • test app goes foreground/background/close app/lock phone etc logs properly
  • lat and lon are encrypted when saving on device

BLE:

  • Rotate UUID on broadcast
  • Scanning peripheral iOS devices and logging the UUID(?)
  • Scanning peripheral Android devices and logging the UUID(?)
  • Test broadcasting with app state changes (go foreground/background/close app/lock phone / etc)
  • Test scanning with app state changes (go foreground/background/close app/lock phone / etc)

Background task:

  • app fetch messages regularly

Notification:

  • Shows notifications on the homepage of the app
  • Push notifications to the user if notification is enabled

Error handling:

Network:

  • Shows messages for correct region within correct time frame

Self-reporting:

  • User can submit BLE seeds

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.