Skip to content

feat: Update to latest ParseCareKit and ParseSwift #110

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions OCKSample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1220,8 +1220,8 @@
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/netreconlab/ParseCareKit.git";
requirement = {
kind = exactVersion;
version = 0.11.1;
kind = upToNextMajorVersion;
minimumVersion = 0.12.0;
};
};
/* End XCRemoteSwiftPackageReference section */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/netreconlab/Parse-Swift.git",
"state" : {
"revision" : "fd285005023271e615062cfad1d92261ee55fe4b",
"version" : "5.0.0-beta.9"
"revision" : "ed55608e5d2486a5d9bca61f553313d7b21bbbb2",
"version" : "5.0.1"
}
},
{
"identity" : "parsecarekit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/netreconlab/ParseCareKit.git",
"state" : {
"revision" : "545e4ac3601e1381dafbe8073a39344919de7500",
"version" : "0.11.1"
"revision" : "f455830724244dd0077169d888f487b5b3435aae",
"version" : "0.12.0"
}
}
],
Expand Down
17 changes: 9 additions & 8 deletions OCKSample/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ class AppDelegate: UIResponder, ObservableObject {
do {
try healthKitStore.reset()
} catch {
Logger.appDelegate.error("Error deleting HealthKit Store: \(error.localizedDescription)")
Logger.appDelegate.error("Error deleting HealthKit Store: \(error)")
}
do {
try store?.delete() // Delete data in local OCKStore database
} catch {
Logger.appDelegate.error("Error deleting OCKStore: \(error.localizedDescription)")
Logger.appDelegate.error("Error deleting OCKStore: \(error)")
}
storeManager = .init(wrapping: OCKStore(name: Constants.noCareStoreName, type: .inMemory))
healthKitStore = nil
Expand All @@ -78,17 +78,17 @@ class AppDelegate: UIResponder, ObservableObject {
sessionDelegate.store = store
}

func setupRemotes(uuid: UUID? = nil) {
func setupRemotes(uuid: UUID? = nil) async throws {
do {
if isSyncingWithCloud {
guard let uuid = uuid else {
Logger.appDelegate.error("Error in setupRemotes, uuid is nil")
return
}
parseRemote = try ParseRemote(uuid: uuid,
auto: false,
subscribeToServerUpdates: true,
defaultACL: try? ParseACL.defaultACL())
parseRemote = try await ParseRemote(uuid: uuid,
auto: false,
subscribeToServerUpdates: true,
defaultACL: try? ParseACL.defaultACL())
store = OCKStore(name: Constants.iOSParseCareStoreName,
type: .onDisk(),
remote: parseRemote)
Expand Down Expand Up @@ -116,7 +116,8 @@ class AppDelegate: UIResponder, ObservableObject {
coordinator.attach(eventStore: healthKitStore)
storeManager = OCKSynchronizedStoreManager(wrapping: coordinator)
} catch {
Logger.appDelegate.error("Error setting up remote: \(error.localizedDescription)")
Logger.appDelegate.error("Error setting up remote: \(error)")
throw error
}
}
}
2 changes: 0 additions & 2 deletions OCKSample/Extensions/AppDelegate+ParseRemoteDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ extension AppDelegate: ParseRemoteDelegate {

func successfullyPushedDataToCloud() {
if isFirstTimeLogin {
// swiftlint:disable:next line_length
NotificationCenter.default.post(.init(name: Notification.Name(rawValue: Constants.completedFirstSyncAfterLogin)))
isFirstTimeLogin.toggle()
}
#if !targetEnvironment(simulator)
Expand Down
67 changes: 36 additions & 31 deletions OCKSample/Extensions/AppDelegate+UIApplicationDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,39 @@ import os.log
extension AppDelegate: UIApplicationDelegate {
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
do {
// Parse-Server setup
try PCKUtility.setupServer(fileName: Constants.parseConfigFileName) { _, completionHandler in
completionHandler(.performDefaultHandling, nil)
Task {
do {
// Parse-Server setup
try await PCKUtility.setupServer(fileName: Constants.parseConfigFileName) { _, completionHandler in
completionHandler(.performDefaultHandling, nil)
}
} catch {
Logger.appDelegate.info("Could not configure Parse Swift: \(error)")
return
}
} catch {
Logger.appDelegate.info("Could not configure Parse Swift: \(error)")
}
return true
}

func application(_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
if isSyncingWithCloud {
if User.current != nil {
Logger.appDelegate.info("User is already signed in...")
if isSyncingWithCloud {
do {
let uuid = try Utility.getRemoteClockUUID()
setupRemotes(uuid: uuid)
parseRemote.automaticallySynchronizes = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
NotificationCenter.default.post(.init(name: Notification.Name(rawValue: Constants.requestSync)))
_ = try await User.current()
Logger.appDelegate.info("User is already signed in...")
do {
let uuid = try await Utility.getRemoteClockUUID()
try? await setupRemotes(uuid: uuid)
parseRemote.automaticallySynchronizes = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
// swiftlint:disable:next line_length
NotificationCenter.default.post(.init(name: Notification.Name(rawValue: Constants.requestSync)))
}
} catch {
Logger.appDelegate.error("User is logged in, but missing remoteId: \(error)")
try await setupRemotes()
}
} catch {
Logger.appDelegate.error("User is logged in, but missing remoteId: \(error)")
setupRemotes()
Logger.appDelegate.error("User is not loggied in: \(error)")
}
}
} else {
// When syncing directly with watchOS, we do not care about login and need to setup remotes
setupRemotes()
Task {
} else {
// When syncing directly with watchOS, we do not care about login and need to setup remotes
do {
try await setupRemotes()
try await store?.populateSampleData()
try await healthKitStore.populateSampleData()
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
Expand All @@ -55,12 +54,18 @@ extension AppDelegate: UIApplicationDelegate {
}
} catch {
Logger.appDelegate.error("""
Error in SceneDelage, could not populate
data stores: \(error.localizedDescription)
""")
Error in SceneDelage, could not populate
data stores: \(error)
""")
}
}
}
return true
}

func application(_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}

Expand Down
2 changes: 1 addition & 1 deletion OCKSample/Extensions/OCKHealthKitPassthroughStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ extension OCKHealthKitPassthroughStore {
_ = try await addTasks(tasksNotInStore)
Logger.ockHealthKitPassthroughStore.info("Added tasks into HealthKitPassthroughStore!")
} catch {
Logger.ockHealthKitPassthroughStore.error("Error adding HealthKitTasks: \(error.localizedDescription)")
Logger.ockHealthKitPassthroughStore.error("Error adding HealthKitTasks: \(error)")
}
}
}
Expand Down
53 changes: 37 additions & 16 deletions OCKSample/Extensions/OCKStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ extension OCKStore {
_ = try await addTasks(tasksNotInStore)
Logger.ockStore.info("Added tasks into OCKStore!")
} catch {
Logger.ockStore.error("Error adding tasks: \(error.localizedDescription)")
Logger.ockStore.error("Error adding tasks: \(error)")
}
}
}
Expand Down Expand Up @@ -66,7 +66,7 @@ extension OCKStore {
_ = try await addContacts(contactsNotInStore)
Logger.ockStore.info("Added contacts into OCKStore!")
} catch {
Logger.ockStore.error("Error adding contacts: \(error.localizedDescription)")
Logger.ockStore.error("Error adding contacts: \(error)")
}
}
}
Expand All @@ -80,45 +80,66 @@ extension OCKStore {
let afterLunch = Calendar.current.date(byAdding: .hour, value: 14, to: aFewDaysAgo)!

let schedule = OCKSchedule(composing: [
OCKScheduleElement(start: beforeBreakfast, end: nil,
OCKScheduleElement(start: beforeBreakfast,
end: nil,
interval: DateComponents(day: 1)),

OCKScheduleElement(start: afterLunch, end: nil,
OCKScheduleElement(start: afterLunch,
end: nil,
interval: DateComponents(day: 2))
])

var doxylamine = OCKTask(id: TaskID.doxylamine, title: "Take Doxylamine",
carePlanUUID: nil, schedule: schedule)
var doxylamine = OCKTask(id: TaskID.doxylamine,
title: "Take Doxylamine",
carePlanUUID: nil,
schedule: schedule)
doxylamine.instructions = "Take 25mg of doxylamine when you experience nausea."
doxylamine.asset = "pills.fill"

let nauseaSchedule = OCKSchedule(composing: [
OCKScheduleElement(start: beforeBreakfast, end: nil, interval: DateComponents(day: 1),
text: "Anytime throughout the day", targetValues: [], duration: .allDay)
OCKScheduleElement(start: beforeBreakfast,
end: nil,
interval: DateComponents(day: 1),
text: "Anytime throughout the day",
targetValues: [], duration: .allDay)
])

var nausea = OCKTask(id: TaskID.nausea, title: "Track your nausea",
carePlanUUID: nil, schedule: nauseaSchedule)
var nausea = OCKTask(id: TaskID.nausea,
title: "Track your nausea",
carePlanUUID: nil,
schedule: nauseaSchedule)
nausea.impactsAdherence = false
nausea.instructions = "Tap the button below anytime you experience nausea."
nausea.asset = "bed.double"

let kegelElement = OCKScheduleElement(start: beforeBreakfast, end: nil, interval: DateComponents(day: 2))
let kegelElement = OCKScheduleElement(start: beforeBreakfast,
end: nil,
interval: DateComponents(day: 2))
let kegelSchedule = OCKSchedule(composing: [kegelElement])
var kegels = OCKTask(id: TaskID.kegels, title: "Kegel Exercises", carePlanUUID: nil, schedule: kegelSchedule)
var kegels = OCKTask(id: TaskID.kegels,
title: "Kegel Exercises",
carePlanUUID: nil,
schedule: kegelSchedule)
kegels.impactsAdherence = true
kegels.instructions = "Perform kegel exercies"

let stretchElement = OCKScheduleElement(start: beforeBreakfast, end: nil, interval: DateComponents(day: 1))
let stretchElement = OCKScheduleElement(start: beforeBreakfast,
end: nil,
interval: DateComponents(day: 1))
let stretchSchedule = OCKSchedule(composing: [stretchElement])
var stretch = OCKTask(id: "stretch", title: "Stretch", carePlanUUID: nil, schedule: stretchSchedule)
var stretch = OCKTask(id: TaskID.stretch,
title: "Stretch",
carePlanUUID: nil,
schedule: stretchSchedule)
stretch.impactsAdherence = true
stretch.asset = "figure.walk"

try await addTasksIfNotPresent([nausea, doxylamine, kegels, stretch])

var contact1 = OCKContact(id: "jane", givenName: "Jane",
familyName: "Daniels", carePlanUUID: nil)
var contact1 = OCKContact(id: "jane",
givenName: "Jane",
familyName: "Daniels",
carePlanUUID: nil)
contact1.asset = "JaneDaniels"
contact1.title = "Family Practice Doctor"
contact1.role = "Dr. Daniels is a family practice doctor with 8 years of experience."
Expand Down
18 changes: 14 additions & 4 deletions OCKSample/Main/Care/CareView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,32 @@ import CareKitStore
import os.log

struct CareView: UIViewControllerRepresentable {
@State var storeManager = StoreManagerKey.defaultValue
@EnvironmentObject private var appDelegate: AppDelegate

func makeUIViewController(context: Context) -> some UIViewController {
let viewController = CareViewController(storeManager: storeManager)
let viewController = createViewController()
let navigationController = UINavigationController(rootViewController: viewController)
navigationController.navigationBar.backgroundColor = UIColor { $0.userInterfaceStyle == .light ? #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1): #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1) }
return navigationController
}

func updateUIViewController(_ uiViewController: UIViewControllerType,
context: Context) {}
context: Context) {
guard let navigationController = uiViewController as? UINavigationController else {
Logger.feed.error("View should have been a UINavigationController")
return
}
navigationController.setViewControllers([createViewController()], animated: false)
}

func createViewController() -> UIViewController {
CareViewController(storeManager: appDelegate.storeManager)
}
}

struct CareView_Previews: PreviewProvider {
static var previews: some View {
CareView(storeManager: Utility.createPreviewStoreManager())
CareView()
.accentColor(Color(TintColorKey.defaultValue))
}
}
19 changes: 5 additions & 14 deletions OCKSample/Main/Care/CareViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ class CareViewController: OCKDailyPageViewController {
selector: #selector(reloadView(_:)),
name: Notification.Name(rawValue: Constants.finishedAskingForPermission),
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(reloadView(_:)),
// swiftlint:disable:next line_length
name: Notification.Name(rawValue: Constants.completedFirstSyncAfterLogin),
object: nil)
}

@objc private func updateSynchronizationProgress(_ notification: Notification) {
Expand Down Expand Up @@ -208,24 +203,20 @@ class CareViewController: OCKDailyPageViewController {
case TaskID.nausea:
var cards = [UIViewController]()
// dynamic gradient colors
let nauseaGradientStart = UIColor { traitCollection -> UIColor in
return traitCollection.userInterfaceStyle == .light ? #colorLiteral(red: 0.06253327429, green: 0.6597633362, blue: 0.8644603491, alpha: 1) : #colorLiteral(red: 0, green: 0.2858072221, blue: 0.6897063851, alpha: 1)
}
let nauseaGradientEnd = UIColor { traitCollection -> UIColor in
return traitCollection.userInterfaceStyle == .light ? #colorLiteral(red: 0, green: 0.2858072221, blue: 0.6897063851, alpha: 1) : #colorLiteral(red: 0.06253327429, green: 0.6597633362, blue: 0.8644603491, alpha: 1)
}
let nauseaGradientStart = TintColorFlipKey.defaultValue
let nauseaGradientEnd = TintColorKey.defaultValue

// Create a plot comparing nausea to medication adherence.
let nauseaDataSeries = OCKDataSeriesConfiguration(
taskID: "nausea",
taskID: task.id,
legendTitle: "Nausea",
gradientStartColor: nauseaGradientStart,
gradientEndColor: nauseaGradientEnd,
markerSize: 10,
eventAggregator: OCKEventAggregator.countOutcomeValues)

let doxylamineDataSeries = OCKDataSeriesConfiguration(
taskID: "doxylamine",
taskID: task.id,
legendTitle: "Doxylamine",
gradientStartColor: .systemGray2,
gradientEndColor: .systemGray,
Expand Down Expand Up @@ -268,7 +259,7 @@ class CareViewController: OCKDailyPageViewController {
tasks.first(where: { $0.id == orderedTaskID }) }
return orderedTasks
} catch {
Logger.feed.error("\(error.localizedDescription, privacy: .public)")
Logger.feed.error("\(error, privacy: .public)")
return []
}
}
Expand Down
Loading