Skip to content

Commit e6f8147

Browse files
committed
readme and fixes
1 parent 6b72a78 commit e6f8147

File tree

5 files changed

+127
-71
lines changed

5 files changed

+127
-71
lines changed

FitCount/Workout/QuickPoseBasicView.swift

Lines changed: 43 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -30,25 +30,23 @@ enum ViewState: Equatable {
3030
return "Stand so that your whole body is inside the bounding box"
3131
case .introExercise(let exercise):
3232
return "Now let's start the \(exercise.name) exercise"
33-
case .exercise(let results, _):
34-
return "\(results.count)"
3533
default:
3634
return nil
3735
}
3836
}
39-
37+
4038
var features: [QuickPose.Feature]? {
4139
switch self {
4240
case .introBoundingBox, .boundingBox:
43-
return [.inside(edgeInsets: QuickPose.RelativeCameraEdgeInsets(top: 0.1, left: 0.2, bottom: 0.01, right: 0.2))]
44-
default:
45-
return nil
41+
return [.inside(QuickPose.RelativeCameraEdgeInsets(top: 0.1, left: 0.2, bottom: 0.01, right: 0.2))]
42+
default:
43+
return nil
4644
}
4745
}
4846
}
4947

5048
struct QuickPoseBasicView: View {
51-
private var quickPose = QuickPose(sdkKey: "01H122Z3J6NY33V548V2D55K3J") // register for your free key at https://dev.quickpose.ai
49+
private var quickPose = QuickPose(sdkKey: "YOUR SDK KEY") // register for your free key at https://dev.quickpose.ai
5250
@EnvironmentObject var viewModel: ViewModel
5351
@EnvironmentObject var sessionConfig: SessionConfig
5452

@@ -63,6 +61,8 @@ struct QuickPoseBasicView: View {
6361
@State private var countScale = 1.0
6462
@State private var boundingBoxMaskWidth = 0.0
6563

64+
static let synthesizer = AVSpeechSynthesizer()
65+
6666
var body: some View {
6767
GeometryReader { geometry in
6868
VStack {
@@ -74,62 +74,41 @@ struct QuickPoseBasicView: View {
7474
.edgesIgnoringSafeArea(.all)
7575
.overlay() {
7676
switch state {
77-
case .startVolume:
78-
VolumeChangeView()
79-
.overlay(alignment: .bottom) {
80-
Button (action: {
81-
state = .instructions
82-
}) {
83-
Text("Continue").foregroundColor(.white)
84-
.padding()
85-
.background(Color("AccentColor"))
86-
.cornerRadius(8)
77+
case .startVolume:
78+
VolumeChangeView()
79+
.overlay(alignment: .bottom) {
80+
Button (action: {
81+
state = .instructions
82+
}) {
83+
Text("Continue").foregroundColor(.white)
84+
.padding()
85+
.background(Color("AccentColor"))
86+
.cornerRadius(8)
8787
}
8888
}
89-
case .instructions:
90-
InstructionsView()
89+
case .instructions:
90+
InstructionsView()
9191
.overlay(alignment: .bottom) {
9292
Button (action: {
9393
state = .introBoundingBox
94+
Text2Speech(text: state.speechPrompt!).say()
9495
}) {
9596
Text("Start Workout").foregroundColor(.white)
9697
.padding()
9798
.background(Color("AccentColor"))
9899
.cornerRadius(8)
99-
}
100-
}
101-
case .introBoundingBox:
102-
ZStack {
103-
RoundedRectangle(cornerRadius: 15)
104-
.stroke(.red, lineWidth: 5)
105-
}
106-
.frame(width: geometry.size.width * 0.6, height: geometry.size.height * 0.8)
107-
.padding(.horizontal, (geometry.size.width * 1 - 0.6)/2)
108-
109-
case .boundingBox:
110-
ZStack {
111-
RoundedRectangle(cornerRadius: 15)
112-
.stroke(boundingBoxVisibility == 1 ? .green : .red, lineWidth: 5)
113-
114-
RoundedRectangle(cornerRadius: 15)
115-
.fill(.green.opacity(0.5))
116-
.mask(alignment: .leading) {
117-
Rectangle()
118-
.frame(width: geometry.size.width * 0.6 * boundingBoxMaskWidth)
119100
}
120-
}
121-
.frame(width: geometry.size.width * 0.6, height: geometry.size.height * 0.8)
122-
.padding(.horizontal, (geometry.size.width * 1 - 0.6)/2)
123-
124-
case .results(let results):
125-
WorkoutResultsView(sessionData: results)
126-
.environmentObject(viewModel)
127-
128-
default:
129-
EmptyView()
101+
}
102+
103+
case .results(let results):
104+
WorkoutResultsView(sessionData: results)
105+
.environmentObject(viewModel)
106+
107+
default:
108+
EmptyView()
130109
}
131110
}
132-
111+
133112
.overlay(alignment: .topTrailing) {
134113
Button(action: {
135114
if case .results = state {
@@ -144,15 +123,15 @@ struct QuickPoseBasicView: View {
144123
}
145124
.padding()
146125
}
147-
126+
148127
.overlay(alignment: .bottom) {
149128
if case .exercise(let results, let enterTime) = state {
150129
HStack {
151130
Text(String(results.count) + (sessionConfig.useReps ? " \\ " + String(sessionConfig.nReps) : "") + " reps")
152131
.font(.system(size: 30, weight: .semibold))
153132
.padding(16)
154133
.scaleEffect(countScale)
155-
134+
156135
Text(String(format: "%.0f",-enterTime.timeIntervalSinceNow) + (!sessionConfig.useReps ? " \\ " + String(sessionConfig.nSeconds + sessionConfig.nMinutes * 60) : "") + " sec")
157136
.font(.system(size: 30, weight: .semibold))
158137
.padding(16)
@@ -171,14 +150,8 @@ struct QuickPoseBasicView: View {
171150
}
172151
}
173152
}
174-
153+
175154
.onChange(of: state) { _ in
176-
177-
if let speechPrompt = state.speechPrompt {
178-
let utterance = AVSpeechUtterance(string: speechPrompt)
179-
AVSpeechSynthesizer().speak(utterance)
180-
}
181-
182155
if case .results(let result) = state {
183156
let sessionDataDump = SessionDataModel(exercise: sessionConfig.exercise.name, count: result.count, seconds: result.seconds, date: Date())
184157
appendToJson(sessionData: sessionDataDump)
@@ -191,7 +164,7 @@ struct QuickPoseBasicView: View {
191164
quickPose.start(features: state.features ?? sessionConfig.exercise.features, onFrame: { status, image, features, feedback, landmarks in
192165
overlayImage = image
193166
if case .success(_,_) = status {
194-
167+
195168
switch state {
196169
case .introBoundingBox:
197170

@@ -211,28 +184,30 @@ struct QuickPoseBasicView: View {
211184
}
212185
DispatchQueue.main.asyncAfter(deadline: .now()+1) {
213186
state = .introExercise(sessionConfig.exercise)
187+
Text2Speech(text: state.speechPrompt!).say()
214188
}
215189
} else {
216190
state = .introBoundingBox
217191
}
218192
}
219193
}
220-
194+
221195
case .introExercise(_):
222196
DispatchQueue.main.asyncAfter(deadline: .now()+0.5) {
223197
state = .exercise(SessionData(count: 0, seconds: 0), enterTime: Date())
224198
}
225199
case .exercise(_, let enterDate):
226200
let secondsElapsed = Int(-enterDate.timeIntervalSinceNow)
227-
201+
228202
if let feedback = feedback[.fitness(.bicepCurls)] {
229203
feedbackText = feedback.displayString
230204
} else {
231205
feedbackText = nil
232-
206+
233207
if case .fitness = sessionConfig.exercise.features.first, let result = features[sessionConfig.exercise.features.first!] {
234208
_ = counter.count(result.value) { newState in
235209
if !newState.isEntered {
210+
Text2Speech(text: "\(counter.state.count)").say()
236211
DispatchQueue.main.asyncAfter(deadline: .now()+0.1) {
237212
withAnimation(.easeInOut(duration: 0.1)) {
238213
countScale = 2.0
@@ -247,7 +222,7 @@ struct QuickPoseBasicView: View {
247222
}
248223
}
249224
}
250-
225+
251226
let newResults = SessionData(count: counter.state.count, seconds: secondsElapsed)
252227
state = .exercise(newResults, enterTime: enterDate) // refresh view for every updated second
253228
var hasFinished = false
@@ -256,9 +231,10 @@ struct QuickPoseBasicView: View {
256231
} else {
257232
hasFinished = secondsElapsed >= sessionConfig.nSeconds + sessionConfig.nMinutes * 60
258233
}
259-
234+
260235
if hasFinished {
261236
state = .results(newResults)
237+
quickPose.stop()
262238
}
263239
default:
264240
break
@@ -269,12 +245,11 @@ struct QuickPoseBasicView: View {
269245
})
270246
}
271247
.onDisappear {
272-
quickPose.stop()
273248
UIApplication.shared.isIdleTimerDisabled = false
274249
}
275250
}
276-
.navigationBarBackButtonHidden(true)
277-
.toolbar(.hidden, for: .tabBar)
251+
.navigationBarBackButtonHidden(true)
252+
.toolbar(.hidden, for: .tabBar)
278253
}
279254
}
280255
}

FitCounter by QuickPose.ai.xcodeproj/project.pbxproj

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
924D6E222A264B3600227183 /* JsonWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D6E212A264B3600227183 /* JsonWriter.swift */; };
1515
924D6E252A289ED700227183 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D6E242A289ED700227183 /* AboutView.swift */; };
1616
924D6E282A29F90400227183 /* VolumeChangeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 924D6E272A29F90400227183 /* VolumeChangeView.swift */; };
17+
925DB1D62A40B35800CCA87E /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 925DB1D52A40B35800CCA87E /* README.md */; };
1718
927261A42A24EF0B00C3B390 /* HistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927261A32A24EF0B00C3B390 /* HistoryView.swift */; };
19+
927BFE642A4095F500C001AC /* QuickPoseCamera in Frameworks */ = {isa = PBXBuildFile; productRef = 927BFE632A4095F500C001AC /* QuickPoseCamera */; };
20+
927BFE662A4095F500C001AC /* QuickPoseCore in Frameworks */ = {isa = PBXBuildFile; productRef = 927BFE652A4095F500C001AC /* QuickPoseCore */; };
21+
927BFE682A4095F500C001AC /* QuickPoseMP in Frameworks */ = {isa = PBXBuildFile; productRef = 927BFE672A4095F500C001AC /* QuickPoseMP */; };
22+
927BFE6A2A4095F500C001AC /* QuickPoseSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = 927BFE692A4095F500C001AC /* QuickPoseSwiftUI */; };
1823
92C702F92A1BC705002ECC0B /* QuickPoseBasicView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92C702F82A1BC705002ECC0B /* QuickPoseBasicView.swift */; };
1924
92CACFD12A1B7DD100DA2B40 /* FitCountApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92CACFD02A1B7DD100DA2B40 /* FitCountApp.swift */; };
2025
92CACFD32A1B7DD100DA2B40 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92CACFD22A1B7DD100DA2B40 /* ContentView.swift */; };
@@ -35,6 +40,7 @@
3540
924D6E212A264B3600227183 /* JsonWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JsonWriter.swift; sourceTree = "<group>"; };
3641
924D6E242A289ED700227183 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
3742
924D6E272A29F90400227183 /* VolumeChangeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VolumeChangeView.swift; sourceTree = "<group>"; };
43+
925DB1D52A40B35800CCA87E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
3844
927261A32A24EF0B00C3B390 /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = "<group>"; };
3945
92C702F82A1BC705002ECC0B /* QuickPoseBasicView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickPoseBasicView.swift; sourceTree = "<group>"; };
4046
92CACFCD2A1B7DD100DA2B40 /* FitCounter.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FitCounter.app; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -53,7 +59,11 @@
5359
buildActionMask = 2147483647;
5460
files = (
5561
D06C7CDE2A373D18001B4508 /* QuickPoseSwiftUI in Frameworks */,
62+
927BFE6A2A4095F500C001AC /* QuickPoseSwiftUI in Frameworks */,
63+
927BFE662A4095F500C001AC /* QuickPoseCore in Frameworks */,
5664
D06C7CDC2A373D18001B4508 /* QuickPoseMP in Frameworks */,
65+
927BFE642A4095F500C001AC /* QuickPoseCamera in Frameworks */,
66+
927BFE682A4095F500C001AC /* QuickPoseMP in Frameworks */,
5767
D06C7CD82A373D18001B4508 /* QuickPoseCamera in Frameworks */,
5868
920A3EF62A20B14100EC6FC9 /* PagerTabStripView in Frameworks */,
5969
D06C7CDA2A373D18001B4508 /* QuickPoseCore in Frameworks */,
@@ -95,6 +105,7 @@
95105
92CACFC42A1B7DD000DA2B40 = {
96106
isa = PBXGroup;
97107
children = (
108+
925DB1D52A40B35800CCA87E /* README.md */,
98109
D06C7CD42A373CFA001B4508 /* Packages */,
99110
92CACFCF2A1B7DD100DA2B40 /* FitCount */,
100111
92CACFCE2A1B7DD100DA2B40 /* Products */,
@@ -163,6 +174,10 @@
163174
D06C7CD92A373D18001B4508 /* QuickPoseCore */,
164175
D06C7CDB2A373D18001B4508 /* QuickPoseMP */,
165176
D06C7CDD2A373D18001B4508 /* QuickPoseSwiftUI */,
177+
927BFE632A4095F500C001AC /* QuickPoseCamera */,
178+
927BFE652A4095F500C001AC /* QuickPoseCore */,
179+
927BFE672A4095F500C001AC /* QuickPoseMP */,
180+
927BFE692A4095F500C001AC /* QuickPoseSwiftUI */,
166181
);
167182
productName = FitCount;
168183
productReference = 92CACFCD2A1B7DD100DA2B40 /* FitCounter.app */;
@@ -194,6 +209,7 @@
194209
mainGroup = 92CACFC42A1B7DD000DA2B40;
195210
packageReferences = (
196211
920A3EF42A20B14000EC6FC9 /* XCRemoteSwiftPackageReference "PagerTabStripView" */,
212+
927BFE622A4095F500C001AC /* XCRemoteSwiftPackageReference "quickpose-ios-sdk" */,
197213
);
198214
productRefGroup = 92CACFCE2A1B7DD100DA2B40 /* Products */;
199215
projectDirPath = "";
@@ -209,6 +225,7 @@
209225
isa = PBXResourcesBuildPhase;
210226
buildActionMask = 2147483647;
211227
files = (
228+
925DB1D62A40B35800CCA87E /* README.md in Resources */,
212229
92CACFD52A1B7DD100DA2B40 /* Assets.xcassets in Resources */,
213230
);
214231
runOnlyForDeploymentPostprocessing = 0;
@@ -453,6 +470,14 @@
453470
minimumVersion = 4.0.0;
454471
};
455472
};
473+
927BFE622A4095F500C001AC /* XCRemoteSwiftPackageReference "quickpose-ios-sdk" */ = {
474+
isa = XCRemoteSwiftPackageReference;
475+
repositoryURL = "https://github.com/quickpose/quickpose-ios-sdk";
476+
requirement = {
477+
branch = feature/1.1.2;
478+
kind = branch;
479+
};
480+
};
456481
/* End XCRemoteSwiftPackageReference section */
457482

458483
/* Begin XCSwiftPackageProductDependency section */
@@ -461,6 +486,26 @@
461486
package = 920A3EF42A20B14000EC6FC9 /* XCRemoteSwiftPackageReference "PagerTabStripView" */;
462487
productName = PagerTabStripView;
463488
};
489+
927BFE632A4095F500C001AC /* QuickPoseCamera */ = {
490+
isa = XCSwiftPackageProductDependency;
491+
package = 927BFE622A4095F500C001AC /* XCRemoteSwiftPackageReference "quickpose-ios-sdk" */;
492+
productName = QuickPoseCamera;
493+
};
494+
927BFE652A4095F500C001AC /* QuickPoseCore */ = {
495+
isa = XCSwiftPackageProductDependency;
496+
package = 927BFE622A4095F500C001AC /* XCRemoteSwiftPackageReference "quickpose-ios-sdk" */;
497+
productName = QuickPoseCore;
498+
};
499+
927BFE672A4095F500C001AC /* QuickPoseMP */ = {
500+
isa = XCSwiftPackageProductDependency;
501+
package = 927BFE622A4095F500C001AC /* XCRemoteSwiftPackageReference "quickpose-ios-sdk" */;
502+
productName = QuickPoseMP;
503+
};
504+
927BFE692A4095F500C001AC /* QuickPoseSwiftUI */ = {
505+
isa = XCSwiftPackageProductDependency;
506+
package = 927BFE622A4095F500C001AC /* XCRemoteSwiftPackageReference "quickpose-ios-sdk" */;
507+
productName = QuickPoseSwiftUI;
508+
};
464509
D06C7CD72A373D18001B4508 /* QuickPoseCamera */ = {
465510
isa = XCSwiftPackageProductDependency;
466511
productName = QuickPoseCamera;

FitCounter by QuickPose.ai.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

FitCounter by QuickPose.ai.xcodeproj/xcshareddata/xcschemes/FitCounter.xcscheme

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
33
LastUpgradeVersion = "1430"
4-
version = "1.8">
4+
version = "1.7">
55
<BuildAction
66
parallelizeBuildables = "YES"
77
buildImplicitDependencies = "YES">
@@ -28,8 +28,6 @@
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
2929
shouldUseLaunchSchemeArgsEnv = "YES"
3030
shouldAutocreateTestPlan = "YES">
31-
<Testables>
32-
</Testables>
3331
</TestAction>
3432
<LaunchAction
3533
buildConfiguration = "Debug"

0 commit comments

Comments
 (0)