Update dependency
This commit is contained in:
parent
08825f84a1
commit
5dcaf0b3d7
@ -47,8 +47,8 @@
|
|||||||
E2E5528E2BA21C5900BF5E9B /* FileManager+Directory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5528D2BA21C5900BF5E9B /* FileManager+Directory.swift */; };
|
E2E5528E2BA21C5900BF5E9B /* FileManager+Directory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5528D2BA21C5900BF5E9B /* FileManager+Directory.swift */; };
|
||||||
E2E552902BA236A000BF5E9B /* DatabaseList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5528F2BA236A000BF5E9B /* DatabaseList.swift */; };
|
E2E552902BA236A000BF5E9B /* DatabaseList.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5528F2BA236A000BF5E9B /* DatabaseList.swift */; };
|
||||||
E2E552922BA236D000BF5E9B /* DatabaseFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E552912BA236D000BF5E9B /* DatabaseFile.swift */; };
|
E2E552922BA236D000BF5E9B /* DatabaseFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E552912BA236D000BF5E9B /* DatabaseFile.swift */; };
|
||||||
E2E552992BA3748500BF5E9B /* HKDatabase in Frameworks */ = {isa = PBXBuildFile; productRef = E2E552982BA3748500BF5E9B /* HKDatabase */; };
|
|
||||||
E2E5529B2BA3935600BF5E9B /* HKWorkout+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5529A2BA3935600BF5E9B /* HKWorkout+Extensions.swift */; };
|
E2E5529B2BA3935600BF5E9B /* HKWorkout+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E5529A2BA3935600BF5E9B /* HKWorkout+Extensions.swift */; };
|
||||||
|
E2E5529E2BA47BA600BF5E9B /* HealthDB in Frameworks */ = {isa = PBXBuildFile; productRef = E2E5529D2BA47BA600BF5E9B /* HealthDB */; };
|
||||||
E2FDFF202B6BE34C0080A7B3 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */; };
|
E2FDFF202B6BE34C0080A7B3 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */; };
|
||||||
E2FDFF292B6D10D60080A7B3 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FDFF282B6D10D60080A7B3 /* String+Extensions.swift */; };
|
E2FDFF292B6D10D60080A7B3 /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2FDFF282B6D10D60080A7B3 /* String+Extensions.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
@ -102,9 +102,9 @@
|
|||||||
files = (
|
files = (
|
||||||
885002A62B5D296700E7D4DB /* Collections in Frameworks */,
|
885002A62B5D296700E7D4DB /* Collections in Frameworks */,
|
||||||
E20881D32B76912000D41D95 /* HealthKitExtensions in Frameworks */,
|
E20881D32B76912000D41D95 /* HealthKitExtensions in Frameworks */,
|
||||||
E2E552992BA3748500BF5E9B /* HKDatabase in Frameworks */,
|
|
||||||
885002772B5C2FC400E7D4DB /* SQLite in Frameworks */,
|
885002772B5C2FC400E7D4DB /* SQLite in Frameworks */,
|
||||||
885002AA2B5D296700E7D4DB /* OrderedCollections in Frameworks */,
|
885002AA2B5D296700E7D4DB /* OrderedCollections in Frameworks */,
|
||||||
|
E2E5529E2BA47BA600BF5E9B /* HealthDB in Frameworks */,
|
||||||
885002A82B5D296700E7D4DB /* DequeModule in Frameworks */,
|
885002A82B5D296700E7D4DB /* DequeModule in Frameworks */,
|
||||||
E2A38EA82B9C6EE800BAD02E /* SFSafeSymbols in Frameworks */,
|
E2A38EA82B9C6EE800BAD02E /* SFSafeSymbols in Frameworks */,
|
||||||
E2FDFF202B6BE34C0080A7B3 /* SwiftProtobuf in Frameworks */,
|
E2FDFF202B6BE34C0080A7B3 /* SwiftProtobuf in Frameworks */,
|
||||||
@ -119,6 +119,7 @@
|
|||||||
children = (
|
children = (
|
||||||
885002592B5C273C00E7D4DB /* HealthImport */,
|
885002592B5C273C00E7D4DB /* HealthImport */,
|
||||||
885002582B5C273C00E7D4DB /* Products */,
|
885002582B5C273C00E7D4DB /* Products */,
|
||||||
|
E2E5529C2BA47BA600BF5E9B /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@ -215,6 +216,13 @@
|
|||||||
path = Model;
|
path = Model;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
E2E5529C2BA47BA600BF5E9B /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
@ -239,7 +247,7 @@
|
|||||||
E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */,
|
E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */,
|
||||||
E20881D22B76912000D41D95 /* HealthKitExtensions */,
|
E20881D22B76912000D41D95 /* HealthKitExtensions */,
|
||||||
E2A38EA72B9C6EE800BAD02E /* SFSafeSymbols */,
|
E2A38EA72B9C6EE800BAD02E /* SFSafeSymbols */,
|
||||||
E2E552982BA3748500BF5E9B /* HKDatabase */,
|
E2E5529D2BA47BA600BF5E9B /* HealthDB */,
|
||||||
);
|
);
|
||||||
productName = HealthImport;
|
productName = HealthImport;
|
||||||
productReference = 885002572B5C273C00E7D4DB /* HealthImport.app */;
|
productReference = 885002572B5C273C00E7D4DB /* HealthImport.app */;
|
||||||
@ -576,8 +584,8 @@
|
|||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/christophhagen/HealthKitExtensions";
|
repositoryURL = "https://github.com/christophhagen/HealthKitExtensions";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
branch = main;
|
||||||
minimumVersion = 0.3.3;
|
kind = branch;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
E2A38EA62B9C6EE800BAD02E /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = {
|
E2A38EA62B9C6EE800BAD02E /* XCRemoteSwiftPackageReference "SFSafeSymbols" */ = {
|
||||||
@ -592,8 +600,8 @@
|
|||||||
isa = XCRemoteSwiftPackageReference;
|
isa = XCRemoteSwiftPackageReference;
|
||||||
repositoryURL = "https://github.com/christophhagen/HealthDB";
|
repositoryURL = "https://github.com/christophhagen/HealthDB";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = upToNextMajorVersion;
|
branch = main;
|
||||||
minimumVersion = 0.2.0;
|
kind = branch;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
E2FDFF1E2B6BE34C0080A7B3 /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
E2FDFF1E2B6BE34C0080A7B3 /* XCRemoteSwiftPackageReference "swift-protobuf" */ = {
|
||||||
@ -637,10 +645,10 @@
|
|||||||
package = E2A38EA62B9C6EE800BAD02E /* XCRemoteSwiftPackageReference "SFSafeSymbols" */;
|
package = E2A38EA62B9C6EE800BAD02E /* XCRemoteSwiftPackageReference "SFSafeSymbols" */;
|
||||||
productName = SFSafeSymbols;
|
productName = SFSafeSymbols;
|
||||||
};
|
};
|
||||||
E2E552982BA3748500BF5E9B /* HKDatabase */ = {
|
E2E5529D2BA47BA600BF5E9B /* HealthDB */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = E2E552972BA3748500BF5E9B /* XCRemoteSwiftPackageReference "HealthDB" */;
|
package = E2E552972BA3748500BF5E9B /* XCRemoteSwiftPackageReference "HealthDB" */;
|
||||||
productName = HKDatabase;
|
productName = HealthDB;
|
||||||
};
|
};
|
||||||
E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */ = {
|
E2FDFF1F2B6BE34C0080A7B3 /* SwiftProtobuf */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/christophhagen/HealthDB",
|
"location" : "https://github.com/christophhagen/HealthDB",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "b1f45d1abf47a13696fba9670db24fe6ca7fab53",
|
"branch" : "main",
|
||||||
"version" : "0.2.1"
|
"revision" : "90b616517861733c1f52ef6f0aaf42849b44e09f"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -15,8 +15,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/christophhagen/HealthKitExtensions",
|
"location" : "https://github.com/christophhagen/HealthKitExtensions",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "18ee575892e6cc429c74c7bc3f156cc6791b220f",
|
"branch" : "main",
|
||||||
"version" : "0.3.3"
|
"revision" : "a7f6612e959a76f211d8526adfd9b5bf88442bb8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import HealthKit
|
import HealthKit
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import CoreLocation
|
import CoreLocation
|
||||||
|
|
||||||
struct ActivityDetailView: View {
|
struct ActivityDetailView: View {
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
var database: HealthDatabase
|
var database: Database
|
||||||
|
|
||||||
let workout: Workout
|
let workout: Workout
|
||||||
|
|
||||||
@ -91,6 +91,6 @@ struct ActivityDetailView: View {
|
|||||||
#Preview {
|
#Preview {
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
ActivityDetailView(workout: .mock1, activity: .mock1)
|
ActivityDetailView(workout: .mock1, activity: .mock1)
|
||||||
.environmentObject(HealthDatabase.mock)
|
.environmentObject(Database.mock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import OrderedCollections
|
import OrderedCollections
|
||||||
import HealthKit
|
import HealthKit
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
|
|
||||||
struct ActivitySamplesView: View {
|
struct ActivitySamplesView: View {
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import SFSafeSymbols
|
import SFSafeSymbols
|
||||||
|
|
||||||
private enum TabSelection: Int {
|
private enum TabSelection: Int {
|
||||||
@ -12,7 +12,7 @@ private enum TabSelection: Int {
|
|||||||
struct HealthImportApp: App {
|
struct HealthImportApp: App {
|
||||||
|
|
||||||
@State
|
@State
|
||||||
var database = HealthDatabase()
|
var database = Database()
|
||||||
|
|
||||||
@State
|
@State
|
||||||
private var selection: TabSelection = .databases
|
private var selection: TabSelection = .databases
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
|
|
||||||
final class HealthDatabase: ObservableObject {
|
final class Database: ObservableObject {
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
var store: HKDatabaseStoreWrapper? = nil
|
var store: HealthDatabase? = nil
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
var file: DatabaseFile? = nil
|
var file: DatabaseFile? = nil
|
||||||
|
|
||||||
init(store: HKDatabaseStoreWrapper? = nil) {
|
init(store: HealthDatabase? = nil) {
|
||||||
self.store = store
|
self.store = store
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ final class HealthDatabase: ObservableObject {
|
|||||||
}
|
}
|
||||||
close()
|
close()
|
||||||
do {
|
do {
|
||||||
let store = try HKDatabaseStoreWrapper(fileUrl: database.url)
|
let store = try HealthDatabase(fileUrl: database.url)
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.store = store
|
self.store = store
|
||||||
self.file = database
|
self.file = database
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import SQLite
|
import SQLite
|
||||||
import HealthKit
|
import HealthKit
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
|
|
||||||
extension HealthDatabase {
|
extension Database {
|
||||||
|
|
||||||
private static let databaseFileUrl = Bundle.main.url(forResource: "healthdb_secure", withExtension: "sqlite")
|
private static let databaseFileUrl = Bundle.main.url(forResource: "healthdb_secure", withExtension: "sqlite")
|
||||||
|
|
||||||
static var mock: HealthDatabase {
|
static var mock: Database {
|
||||||
let bundleUrl = HealthDatabase.databaseFileUrl!
|
let bundleUrl = Database.databaseFileUrl!
|
||||||
let local = FileManager.default.documentDirectory.appendingPathComponent("db.sqlite")
|
let local = FileManager.default.documentDirectory.appendingPathComponent("db.sqlite")
|
||||||
if !FileManager.default.fileExists(atPath: local.path) {
|
if !FileManager.default.fileExists(atPath: local.path) {
|
||||||
try! FileManager.default.copyItem(at: bundleUrl, to: local)
|
try! FileManager.default.copyItem(at: bundleUrl, to: local)
|
||||||
}
|
}
|
||||||
let store = try! HKDatabaseStoreWrapper(fileUrl: local)
|
let store = try! HealthDatabase(fileUrl: local)
|
||||||
return .init(store: store)
|
return .init(store: store)
|
||||||
}
|
}
|
||||||
|
|
||||||
static var empty: HealthDatabase {
|
static var empty: Database {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let connection = try Connection(.inMemory)
|
let connection = try Connection(.inMemory)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import HealthKitExtensions
|
import HealthKitExtensions
|
||||||
import HealthKit
|
import HealthKit
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import HealthKit
|
import HealthKit
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import HealthKitExtensions
|
import HealthKitExtensions
|
||||||
|
|
||||||
extension Workout {
|
extension Workout {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import HealthKit
|
import HealthKit
|
||||||
|
|
||||||
private let df: DateFormatter = {
|
private let df: DateFormatter = {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import SFSafeSymbols
|
import SFSafeSymbols
|
||||||
|
|
||||||
struct DatabasesTab: View {
|
struct DatabasesTab: View {
|
||||||
|
|
||||||
@ObservedObject
|
@ObservedObject
|
||||||
var database: HealthDatabase
|
var database: Database
|
||||||
|
|
||||||
@ObservedObject
|
@ObservedObject
|
||||||
var databases: DatabaseList
|
var databases: DatabaseList
|
||||||
@ -160,5 +160,5 @@ struct DatabasesTab: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
DatabasesTab(database: HealthDatabase(), databases: .init())
|
DatabasesTab(database: Database(), databases: .init())
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import HealthKit
|
import HealthKit
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import SFSafeSymbols
|
import SFSafeSymbols
|
||||||
|
|
||||||
struct WorkoutTab: View {
|
struct WorkoutTab: View {
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
var database: HealthDatabase
|
var database: Database
|
||||||
|
|
||||||
@State var navigationPath: NavigationPath = .init()
|
@State var navigationPath: NavigationPath = .init()
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ struct WorkoutTab: View {
|
|||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
WorkoutTab()
|
WorkoutTab()
|
||||||
.environmentObject(HealthDatabase.mock)
|
.environmentObject(Database.mock)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4,7 +4,7 @@ import HealthKitExtensions
|
|||||||
|
|
||||||
func insertExamplesOfAllTypes() async throws {
|
func insertExamplesOfAllTypes() async throws {
|
||||||
|
|
||||||
let store = HKHealthStore()
|
let store = HealthStore()
|
||||||
|
|
||||||
guard try await requestAllPermissions(in: store) else {
|
guard try await requestAllPermissions(in: store) else {
|
||||||
return
|
return
|
||||||
@ -16,7 +16,7 @@ func insertExamplesOfAllTypes() async throws {
|
|||||||
try await insertQuantityTypes(in: store, startDate: &startDate)
|
try await insertQuantityTypes(in: store, startDate: &startDate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestAllPermissions(in store: HKHealthStore) async throws -> Bool {
|
func requestAllPermissions(in store: HealthStore) async throws -> Bool {
|
||||||
|
|
||||||
let writable: [HKSampleContainer.Type] = HKQuantityType.writableTypes + HKCorrelationType.writableTypes + HKCategoryType.writableTypes
|
let writable: [HKSampleContainer.Type] = HKQuantityType.writableTypes + HKCorrelationType.writableTypes + HKCategoryType.writableTypes
|
||||||
let readable: [HKObjectContainer.Type] = HKQuantityType.readableTypes + HKCorrelationType.readableTypes + HKCategoryType.readableTypes
|
let readable: [HKObjectContainer.Type] = HKQuantityType.readableTypes + HKCorrelationType.readableTypes + HKCategoryType.readableTypes
|
||||||
@ -25,7 +25,7 @@ func requestAllPermissions(in store: HKHealthStore) async throws -> Bool {
|
|||||||
|
|
||||||
var hasAllPermissions = true
|
var hasAllPermissions = true
|
||||||
writable.forEach {
|
writable.forEach {
|
||||||
if store.authorizationStatus(for: $0.objectType) != .sharingAuthorized {
|
if store.authorizationStatus(for: $0) != .sharingAuthorized {
|
||||||
print("Missing permission for \($0.objectType)")
|
print("Missing permission for \($0.objectType)")
|
||||||
hasAllPermissions = false
|
hasAllPermissions = false
|
||||||
}
|
}
|
||||||
@ -33,7 +33,7 @@ func requestAllPermissions(in store: HKHealthStore) async throws -> Bool {
|
|||||||
return hasAllPermissions
|
return hasAllPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
private func insertCategoryTypes(in store: HKHealthStore, startDate: inout Date) async throws {
|
private func insertCategoryTypes(in store: HealthStore, startDate: inout Date) async throws {
|
||||||
|
|
||||||
func make<T>(convert: (Date, Date) -> T) -> T where T: HKObjectContainer {
|
func make<T>(convert: (Date, Date) -> T) -> T where T: HKObjectContainer {
|
||||||
let result = convert(startDate, startDate.addingTimeInterval(1))
|
let result = convert(startDate, startDate.addingTimeInterval(1))
|
||||||
@ -101,7 +101,7 @@ private func insertCategoryTypes(in store: HKHealthStore, startDate: inout Date)
|
|||||||
print("Done.")
|
print("Done.")
|
||||||
}
|
}
|
||||||
|
|
||||||
private func insertQuantityTypes(in store: HKHealthStore, startDate: inout Date) async throws {
|
private func insertQuantityTypes(in store: HealthStore, startDate: inout Date) async throws {
|
||||||
|
|
||||||
func make<T>(convert: (Date, Date) -> T) -> T where T: HKObjectContainer {
|
func make<T>(convert: (Date, Date) -> T) -> T where T: HKObjectContainer {
|
||||||
let result = convert(startDate, startDate.addingTimeInterval(1))
|
let result = convert(startDate, startDate.addingTimeInterval(1))
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import Collections
|
import Collections
|
||||||
import HealthKit
|
import HealthKit
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import HealthKitExtensions
|
import HealthKitExtensions
|
||||||
import CoreLocation
|
import CoreLocation
|
||||||
|
|
||||||
struct WorkoutDetailView: View {
|
struct WorkoutDetailView: View {
|
||||||
|
|
||||||
@EnvironmentObject
|
@EnvironmentObject
|
||||||
var database: HealthDatabase
|
var database: Database
|
||||||
|
|
||||||
private let store = HKHealthStore()
|
private let store = HealthStore()
|
||||||
|
|
||||||
let workout: Workout
|
let workout: Workout
|
||||||
|
|
||||||
@ -119,15 +119,15 @@ struct WorkoutDetailView: View {
|
|||||||
|
|
||||||
private func checkPermissionsAndFindWorkout() async throws {
|
private func checkPermissionsAndFindWorkout() async throws {
|
||||||
|
|
||||||
switch store.authorizationStatus(for: .workoutType()) {
|
switch store.authorizationStatus(for: HKWorkout.self) {
|
||||||
case .notDetermined:
|
case .notDetermined:
|
||||||
try await requestWorkoutPermission()
|
try await requestWorkoutPermission()
|
||||||
try await checkPermissionsAndFindWorkout()
|
try await checkPermissionsAndFindWorkout()
|
||||||
case .sharingAuthorized:
|
case .sharingAuthorized:
|
||||||
findWorkoutInHealth()
|
await findWorkoutInHealth()
|
||||||
case .sharingDenied:
|
case .sharingDenied:
|
||||||
print("No permission to write workouts")
|
print("No permission to write workouts")
|
||||||
findWorkoutInHealth()
|
await findWorkoutInHealth()
|
||||||
return
|
return
|
||||||
@unknown default:
|
@unknown default:
|
||||||
print("Unknown permission for workouts")
|
print("Unknown permission for workouts")
|
||||||
@ -139,76 +139,33 @@ struct WorkoutDetailView: View {
|
|||||||
try await store.requestAuthorization(read: HKWorkout.self)
|
try await store.requestAuthorization(read: HKWorkout.self)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func findWorkoutInHealth() {
|
private func findWorkoutInHealth() async {
|
||||||
guard let activityType = workout.workoutActivities.first?.workoutConfiguration.activityType else {
|
guard let activityType = workout.workoutActivities.first?.workoutConfiguration.activityType else {
|
||||||
print("No activity type to find workout")
|
print("No activity type to find workout")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let start = workout.startDate.addingTimeInterval(-60)
|
let start = workout.startDate.addingTimeInterval(-60)
|
||||||
let end = workout.endDate.addingTimeInterval(60)
|
let end = workout.endDate.addingTimeInterval(60)
|
||||||
let workoutPredicate = HKQuery.predicateForWorkouts(with: activityType)
|
guard let workout = try? await store.workouts(activityType: activityType, from: start, to: end)
|
||||||
let timePredicate = HKQuery.predicateForSamples(withStart: start, end: end)
|
.first else {
|
||||||
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [workoutPredicate, timePredicate])
|
print("No workout found or error")
|
||||||
let sortDescriptor = NSSortDescriptor(
|
return
|
||||||
key: HKSampleSortIdentifierEndDate,
|
}
|
||||||
ascending: true)
|
|
||||||
|
|
||||||
let query = HKSampleQuery(
|
|
||||||
sampleType: .workoutType(),
|
|
||||||
predicate: predicate,
|
|
||||||
limit: 0,
|
|
||||||
sortDescriptors: [sortDescriptor]) { _, samples, error in
|
|
||||||
if let error {
|
|
||||||
print("Failed to search for workout: \(error)")
|
|
||||||
}
|
|
||||||
guard let workout = samples?.first as? HKWorkout else {
|
|
||||||
print("No suitable workout found: \(samples?.count ?? 0)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
foundHealthStore(workout: workout)
|
|
||||||
}
|
|
||||||
|
|
||||||
store.execute(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func foundHealthStore(workout: HKWorkout) {
|
|
||||||
print("Found matching workout in health")
|
print("Found matching workout in health")
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.healthWorkout = workout
|
self.healthWorkout = workout
|
||||||
}
|
}
|
||||||
findHealthStoreHeartRates(for: workout)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func findHealthStoreHeartRates(for workout: HKWorkout) {
|
do {
|
||||||
let forWorkout = HKQuery.predicateForObjects(from: workout)
|
let heartRates: [HeartRate] = try await store.samples(associatedWith: workout)
|
||||||
let heartRate = HKQuantityType(.heartRate)
|
print("Found \(heartRates.count) heart rate samples in Health")
|
||||||
|
DispatchQueue.main.async {
|
||||||
let heartRateDescriptor = HKQueryDescriptor(
|
self.heartRateSamplesInHealth = heartRates
|
||||||
sampleType: heartRate,
|
|
||||||
predicate: forWorkout)
|
|
||||||
|
|
||||||
let heartRateQuery = HKSampleQuery(
|
|
||||||
queryDescriptors: [heartRateDescriptor],
|
|
||||||
limit: HKObjectQueryNoLimit)
|
|
||||||
{ query, samples, error in
|
|
||||||
if let error {
|
|
||||||
print("Failed to search for heart rates: \(error)")
|
|
||||||
}
|
}
|
||||||
guard let samples else {
|
} catch {
|
||||||
print("No heart rate samples found in Health")
|
print("Failed to get heart rates for workout: \(error)")
|
||||||
return
|
|
||||||
}
|
|
||||||
let heartRates = samples.map { HeartRate(sample: $0) }
|
|
||||||
processHealthStore(heartRateSamples: heartRates)
|
|
||||||
}
|
|
||||||
|
|
||||||
store.execute(heartRateQuery)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func processHealthStore(heartRateSamples: [HeartRate]) {
|
|
||||||
print("Found \(heartRateSamples.count) heart rate samples in Health")
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.heartRateSamplesInHealth = heartRateSamples
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -216,7 +173,7 @@ struct WorkoutDetailView: View {
|
|||||||
#Preview {
|
#Preview {
|
||||||
return NavigationStack {
|
return NavigationStack {
|
||||||
WorkoutDetailView(workout: .mock1)
|
WorkoutDetailView(workout: .mock1)
|
||||||
.environmentObject(HealthDatabase.mock)
|
.environmentObject(Database.mock)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
import HealthKit
|
import HealthKit
|
||||||
|
|
||||||
struct WorkoutEventsView: View {
|
struct WorkoutEventsView: View {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import HKDatabase
|
import HealthDB
|
||||||
|
|
||||||
struct WorkoutMetadataView: View {
|
struct WorkoutMetadataView: View {
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user