@sency/react-native-smkit-ui 2.2.1 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +218 -65
- package/android/build.gradle +3 -1
- package/android/src/main/java/com/smkituilibrary/SmkitUiLibraryModule.kt +237 -3
- package/android/src/main/java/com/smkituilibrary/mapper/SMMapper.kt +70 -10
- package/android/src/main/java/com/smkituilibrary/model/SMKitExercise.kt +40 -0
- package/android/src/main/java/com/smkituilibrary/model/SMKitWorkout.kt +8 -0
- package/android/src/main/java/com/smkituilibrary/model/SMKitWorkoutConfig.kt +2 -0
- package/android/src/main/java/com/smkituilibrary/model/SMUserData.kt +5 -1
- package/ios/SMKitUIManager.mm +33 -11
- package/ios/SMKitUIManager.swift +237 -36
- package/lib/commonjs/SMWorkout.js +239 -177
- package/lib/commonjs/SMWorkout.js.map +1 -1
- package/lib/commonjs/index.js +187 -5
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/SMWorkout.js +232 -181
- package/lib/module/SMWorkout.js.map +1 -1
- package/lib/module/index.js +165 -5
- package/lib/module/index.js.map +1 -1
- package/package.json +2 -2
- package/react-native-smkit-ui.podspec +2 -2
- package/src/SMWorkout.tsx +353 -176
- package/src/index.tsx +167 -8
- package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
- package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -1
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
- package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -2
- package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
- package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
package com.smkituilibrary
|
|
2
2
|
|
|
3
|
+
import android.net.Uri
|
|
3
4
|
import android.util.Log
|
|
4
5
|
import com.facebook.react.bridge.Arguments
|
|
5
6
|
import com.facebook.react.bridge.Promise
|
|
@@ -13,6 +14,8 @@ import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
|
13
14
|
import com.google.gson.Gson
|
|
14
15
|
import com.google.gson.GsonBuilder
|
|
15
16
|
import com.google.gson.Strictness
|
|
17
|
+
import com.sency.smbase.nativeclient.model.FormFeedbackType
|
|
18
|
+
import com.sency.smkit.PoseModelChoice
|
|
16
19
|
import com.sency.smkitui.SMKitUI
|
|
17
20
|
import com.sency.smkitui.listener.SMKitUIConfigurationListener
|
|
18
21
|
import com.sency.smkitui.listener.SMKitUIWorkoutListener
|
|
@@ -70,6 +73,24 @@ class SmkitUiLibraryModule(reactContext: ReactApplicationContext) :
|
|
|
70
73
|
private val moshi: Moshi by lazy { moshi() }
|
|
71
74
|
private val gson: Gson by lazy { gson() }
|
|
72
75
|
private var compactJson = false
|
|
76
|
+
private var pendingInstructionVideoConfig = InstructionVideoConfig()
|
|
77
|
+
private var pendingPhoneMovementCountPreventionEnabled = false
|
|
78
|
+
private var pendingStartTimerOnFirstActivity = true
|
|
79
|
+
private var pendingWorkoutContinuationTimerSeconds = 10
|
|
80
|
+
private var pendingPlayPhoneCalibrationAudio = false
|
|
81
|
+
private var pendingPlayBodyCalibrationAudio = false
|
|
82
|
+
private var pendingAllowAudioMixing = false
|
|
83
|
+
private var pendingShowExternalAudioControl = false
|
|
84
|
+
private var pendingEnableButtonTutorial = false
|
|
85
|
+
private var pendingButtonTutorialCompletionAudioUri: Uri? = null
|
|
86
|
+
private var pendingUseDefaultGuidanceMode = false
|
|
87
|
+
private var pendingGuidanceDebugLogging = false
|
|
88
|
+
private var pendingVariationMismatchFeedbackEnabled = false
|
|
89
|
+
private var pendingIntelligenceRestEnabled = false
|
|
90
|
+
private var pendingColorTheme = UIColorTheme.GREEN
|
|
91
|
+
private var pendingPoseModelChoice = PoseModelChoice.AdaptiveChoice
|
|
92
|
+
private var pendingConfigString: String? = null
|
|
93
|
+
private var pendingFeedbacksUIToExclude: Set<FormFeedbackType>? = null
|
|
73
94
|
|
|
74
95
|
override fun getName(): String = "SMKitUIManager"
|
|
75
96
|
|
|
@@ -147,6 +168,26 @@ class SmkitUiLibraryModule(reactContext: ReactApplicationContext) :
|
|
|
147
168
|
}
|
|
148
169
|
}
|
|
149
170
|
|
|
171
|
+
private fun applyPendingRuntimeSettings() {
|
|
172
|
+
smKitUI?.setInstructionVideoConfig(pendingInstructionVideoConfig)
|
|
173
|
+
smKitUI?.setPhoneMovementCountPreventionEnabled(pendingPhoneMovementCountPreventionEnabled)
|
|
174
|
+
smKitUI?.setStartTimerOnFirstActivity(pendingStartTimerOnFirstActivity)
|
|
175
|
+
smKitUI?.setWorkoutContinuationTimerDuration(pendingWorkoutContinuationTimerSeconds)
|
|
176
|
+
smKitUI?.setPlayPhoneCalibrationAudio(pendingPlayPhoneCalibrationAudio)
|
|
177
|
+
smKitUI?.setPlayBodyCalibrationAudio(pendingPlayBodyCalibrationAudio)
|
|
178
|
+
smKitUI?.setAllowAudioMixing(pendingAllowAudioMixing)
|
|
179
|
+
smKitUI?.setShowExternalAudioControl(pendingShowExternalAudioControl)
|
|
180
|
+
smKitUI?.setEnableButtonTutorial(pendingEnableButtonTutorial)
|
|
181
|
+
smKitUI?.setButtonTutorialCompletionAudioUri(pendingButtonTutorialCompletionAudioUri)
|
|
182
|
+
smKitUI?.setUseDefaultGuidanceMode(pendingUseDefaultGuidanceMode)
|
|
183
|
+
smKitUI?.setGuidanceDebugLogging(pendingGuidanceDebugLogging)
|
|
184
|
+
smKitUI?.setVariationMismatchFeedbackEnabled(pendingVariationMismatchFeedbackEnabled)
|
|
185
|
+
smKitUI?.setIntelligenceRestEnabled(pendingIntelligenceRestEnabled)
|
|
186
|
+
smKitUI?.setColorTheme(pendingColorTheme)
|
|
187
|
+
smKitUI?.setConfigString(pendingConfigString)
|
|
188
|
+
pendingFeedbacksUIToExclude?.let { smKitUI?.setFeedbacksUIToExclude(it) }
|
|
189
|
+
}
|
|
190
|
+
|
|
150
191
|
@ReactMethod
|
|
151
192
|
fun configure(key: String, promise: Promise) {
|
|
152
193
|
// If already configured, reuse the existing instance.
|
|
@@ -161,8 +202,24 @@ class SmkitUiLibraryModule(reactContext: ReactApplicationContext) :
|
|
|
161
202
|
}
|
|
162
203
|
smKitUI = SMKitUI.Configuration(reactApplicationContext)
|
|
163
204
|
.setUIKey(key)
|
|
205
|
+
.setInstructionVideoConfig(pendingInstructionVideoConfig)
|
|
206
|
+
.setPhoneMovementCountPreventionEnabled(pendingPhoneMovementCountPreventionEnabled)
|
|
207
|
+
.setStartTimerOnFirstActivity(pendingStartTimerOnFirstActivity)
|
|
208
|
+
.setWorkoutContinuationTimerDuration(pendingWorkoutContinuationTimerSeconds)
|
|
209
|
+
.setPlayPhoneCalibrationAudio(pendingPlayPhoneCalibrationAudio)
|
|
210
|
+
.setPlayBodyCalibrationAudio(pendingPlayBodyCalibrationAudio)
|
|
211
|
+
.setAllowAudioMixing(pendingAllowAudioMixing)
|
|
212
|
+
.setShowExternalAudioControl(pendingShowExternalAudioControl)
|
|
213
|
+
.setEnableButtonTutorial(pendingEnableButtonTutorial)
|
|
214
|
+
.setButtonTutorialCompletionAudioUri(pendingButtonTutorialCompletionAudioUri)
|
|
215
|
+
.setUseDefaultGuidanceMode(pendingUseDefaultGuidanceMode)
|
|
216
|
+
.setGuidanceDebugLogging(pendingGuidanceDebugLogging)
|
|
217
|
+
.setVariationMismatchFeedbackEnabled(pendingVariationMismatchFeedbackEnabled)
|
|
218
|
+
.setColorTheme(pendingColorTheme)
|
|
219
|
+
.setPoseModelChoice(pendingPoseModelChoice)
|
|
164
220
|
.configure(object : SMKitUIConfigurationListener {
|
|
165
221
|
override fun onSuccess() {
|
|
222
|
+
applyPendingRuntimeSettings()
|
|
166
223
|
promise.resolve("")
|
|
167
224
|
}
|
|
168
225
|
|
|
@@ -234,6 +291,7 @@ class SmkitUiLibraryModule(reactContext: ReactApplicationContext) :
|
|
|
234
291
|
val mediumSizeCycles = (configMap["mediumSizeCycles"] as? Number)?.toInt() ?: 2
|
|
235
292
|
|
|
236
293
|
val config = InstructionVideoConfig(displayMode = displayMode, mediumSizeCycles = mediumSizeCycles)
|
|
294
|
+
pendingInstructionVideoConfig = config
|
|
237
295
|
smKitUI?.setInstructionVideoConfig(config)
|
|
238
296
|
promise.resolve("")
|
|
239
297
|
} catch (e: Exception) {
|
|
@@ -245,6 +303,7 @@ class SmkitUiLibraryModule(reactContext: ReactApplicationContext) :
|
|
|
245
303
|
@ReactMethod
|
|
246
304
|
fun setIntelligenceRestEnabled(enabled: Boolean, promise: Promise) {
|
|
247
305
|
try {
|
|
306
|
+
pendingIntelligenceRestEnabled = enabled
|
|
248
307
|
smKitUI?.setIntelligenceRestEnabled(enabled)
|
|
249
308
|
promise.resolve(null)
|
|
250
309
|
} catch (e: Exception) {
|
|
@@ -320,11 +379,175 @@ class SmkitUiLibraryModule(reactContext: ReactApplicationContext) :
|
|
|
320
379
|
}
|
|
321
380
|
}
|
|
322
381
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
382
|
+
@ReactMethod
|
|
383
|
+
fun setAllowAudioMixing(enabled: Boolean, promise: Promise) {
|
|
384
|
+
pendingAllowAudioMixing = enabled
|
|
385
|
+
smKitUI?.setAllowAudioMixing(enabled)
|
|
386
|
+
promise.resolve(null)
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
@ReactMethod
|
|
390
|
+
fun setShowExternalAudioControl(enabled: Boolean, promise: Promise) {
|
|
391
|
+
pendingShowExternalAudioControl = enabled
|
|
392
|
+
smKitUI?.setShowExternalAudioControl(enabled)
|
|
393
|
+
promise.resolve(null)
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
// iOS-only. Resolve immediately for API parity.
|
|
326
397
|
@ReactMethod fun setAccuratePoseEstimation(enabled: Boolean, promise: Promise) { promise.resolve(null) }
|
|
327
398
|
|
|
399
|
+
@ReactMethod
|
|
400
|
+
fun setColorTheme(theme: String, promise: Promise) {
|
|
401
|
+
val colorTheme = mapColorToTheme(theme)
|
|
402
|
+
pendingColorTheme = colorTheme
|
|
403
|
+
smKitUI?.setColorTheme(colorTheme)
|
|
404
|
+
promise.resolve(null)
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
@ReactMethod
|
|
408
|
+
fun setPlayPhoneCalibrationAudio(enabled: Boolean, promise: Promise) {
|
|
409
|
+
pendingPlayPhoneCalibrationAudio = enabled
|
|
410
|
+
smKitUI?.setPlayPhoneCalibrationAudio(enabled)
|
|
411
|
+
promise.resolve(null)
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@ReactMethod
|
|
415
|
+
fun setPlayBodyCalibrationAudio(enabled: Boolean, promise: Promise) {
|
|
416
|
+
pendingPlayBodyCalibrationAudio = enabled
|
|
417
|
+
smKitUI?.setPlayBodyCalibrationAudio(enabled)
|
|
418
|
+
promise.resolve(null)
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
@ReactMethod
|
|
422
|
+
fun setStartTimerOnFirstActivity(enabled: Boolean, promise: Promise) {
|
|
423
|
+
pendingStartTimerOnFirstActivity = enabled
|
|
424
|
+
smKitUI?.setStartTimerOnFirstActivity(enabled)
|
|
425
|
+
promise.resolve(null)
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
@ReactMethod
|
|
429
|
+
fun setWorkoutContinuationTimerDuration(seconds: Int, promise: Promise) {
|
|
430
|
+
pendingWorkoutContinuationTimerSeconds = seconds.coerceAtLeast(1)
|
|
431
|
+
smKitUI?.setWorkoutContinuationTimerDuration(pendingWorkoutContinuationTimerSeconds)
|
|
432
|
+
promise.resolve(null)
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
@ReactMethod
|
|
436
|
+
fun setPhoneMovementCountPreventionEnabled(enabled: Boolean, promise: Promise) {
|
|
437
|
+
pendingPhoneMovementCountPreventionEnabled = enabled
|
|
438
|
+
smKitUI?.setPhoneMovementCountPreventionEnabled(enabled)
|
|
439
|
+
promise.resolve(null)
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
@ReactMethod
|
|
443
|
+
fun setVariationMismatchFeedbackEnabled(enabled: Boolean, promise: Promise) {
|
|
444
|
+
pendingVariationMismatchFeedbackEnabled = enabled
|
|
445
|
+
smKitUI?.setVariationMismatchFeedbackEnabled(enabled)
|
|
446
|
+
promise.resolve(null)
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
@ReactMethod
|
|
450
|
+
fun setUseDefaultGuidanceMode(enabled: Boolean, promise: Promise) {
|
|
451
|
+
pendingUseDefaultGuidanceMode = enabled
|
|
452
|
+
smKitUI?.setUseDefaultGuidanceMode(enabled)
|
|
453
|
+
promise.resolve(null)
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
@ReactMethod
|
|
457
|
+
fun setGuidanceDebugLogging(enabled: Boolean, promise: Promise) {
|
|
458
|
+
pendingGuidanceDebugLogging = enabled
|
|
459
|
+
smKitUI?.setGuidanceDebugLogging(enabled)
|
|
460
|
+
promise.resolve(null)
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
@ReactMethod
|
|
464
|
+
fun setEnableButtonTutorial(enabled: Boolean, promise: Promise) {
|
|
465
|
+
pendingEnableButtonTutorial = enabled
|
|
466
|
+
smKitUI?.setEnableButtonTutorial(enabled)
|
|
467
|
+
promise.resolve(null)
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
@ReactMethod
|
|
471
|
+
fun setButtonTutorialCompletionAudioUri(uri: String?, promise: Promise) {
|
|
472
|
+
pendingButtonTutorialCompletionAudioUri = uri
|
|
473
|
+
?.takeIf { it.isNotBlank() }
|
|
474
|
+
?.let(Uri::parse)
|
|
475
|
+
smKitUI?.setButtonTutorialCompletionAudioUri(pendingButtonTutorialCompletionAudioUri)
|
|
476
|
+
promise.resolve(null)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// iOS-only rowing calibration switch. Resolve immediately for API parity.
|
|
480
|
+
@ReactMethod
|
|
481
|
+
fun setShowRowingPhoneCalibration(enabled: Boolean, promise: Promise) {
|
|
482
|
+
promise.resolve(null)
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
@ReactMethod
|
|
486
|
+
fun setFeedbacksUIToExclude(feedbacksJson: String, promise: Promise) {
|
|
487
|
+
try {
|
|
488
|
+
val feedbacks = feedbackTypesFromJson(feedbacksJson)
|
|
489
|
+
pendingFeedbacksUIToExclude = feedbacks
|
|
490
|
+
smKitUI?.setFeedbacksUIToExclude(feedbacks)
|
|
491
|
+
promise.resolve(null)
|
|
492
|
+
} catch (e: Exception) {
|
|
493
|
+
promise.reject("setFeedbacksUIToExclude Failed", e.message, e)
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// Android SMKitUI currently exposes UI-only feedback exclusion.
|
|
498
|
+
@ReactMethod
|
|
499
|
+
fun setExcludedFeedbacks(feedbacksJson: String, promise: Promise) {
|
|
500
|
+
try {
|
|
501
|
+
feedbackTypesFromJson(feedbacksJson)
|
|
502
|
+
promise.resolve(null)
|
|
503
|
+
} catch (e: Exception) {
|
|
504
|
+
promise.reject("setExcludedFeedbacks Failed", e.message, e)
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
@ReactMethod
|
|
509
|
+
fun setConfigString(configString: String?, promise: Promise) {
|
|
510
|
+
pendingConfigString = configString
|
|
511
|
+
smKitUI?.setConfigString(configString)
|
|
512
|
+
promise.resolve(null)
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
@ReactMethod
|
|
516
|
+
fun clearAdaptiveRomCache(promise: Promise) {
|
|
517
|
+
smKitUI?.clearAdaptiveRomCache()
|
|
518
|
+
promise.resolve(null)
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
@ReactMethod
|
|
522
|
+
fun quitWorkout(promise: Promise) {
|
|
523
|
+
smKitUI?.quitWorkout()
|
|
524
|
+
promise.resolve(null)
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// iOS-only active-session controls. Resolve immediately for API parity.
|
|
528
|
+
@ReactMethod fun pauseSDK(promise: Promise) { promise.resolve(null) }
|
|
529
|
+
@ReactMethod fun resumeSDK(promise: Promise) { promise.resolve(null) }
|
|
530
|
+
|
|
531
|
+
@ReactMethod
|
|
532
|
+
fun getSupportedMovements(promise: Promise) {
|
|
533
|
+
promise.resolve(Arguments.createArray())
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
@ReactMethod
|
|
537
|
+
fun getExerciseType(detector: String, promise: Promise) {
|
|
538
|
+
promise.resolve("")
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
@ReactMethod
|
|
542
|
+
fun setPoseModelChoice(choice: String, promise: Promise) {
|
|
543
|
+
try {
|
|
544
|
+
pendingPoseModelChoice = PoseModelChoice.valueOf(choice)
|
|
545
|
+
promise.resolve(null)
|
|
546
|
+
} catch (e: Exception) {
|
|
547
|
+
promise.reject("setPoseModelChoice Failed", "Invalid pose model choice: $choice", e)
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
328
551
|
private fun skeletonPresetFromString(s: String): SkeletonPreset? = when (s) {
|
|
329
552
|
"defaultPreset" -> SkeletonPreset.DEFAULT
|
|
330
553
|
"minimalDots" -> SkeletonPreset.MINIMAL_DOTS
|
|
@@ -428,6 +651,17 @@ class SmkitUiLibraryModule(reactContext: ReactApplicationContext) :
|
|
|
428
651
|
}
|
|
429
652
|
}
|
|
430
653
|
|
|
654
|
+
private fun feedbackTypesFromJson(feedbacksJson: String): Set<FormFeedbackType> {
|
|
655
|
+
val arr = org.json.JSONArray(feedbacksJson)
|
|
656
|
+
return (0 until arr.length())
|
|
657
|
+
.map { index ->
|
|
658
|
+
val name = arr.getString(index)
|
|
659
|
+
FormFeedbackType.fromString(name)
|
|
660
|
+
?: throw IllegalArgumentException("Invalid feedback type: $name")
|
|
661
|
+
}
|
|
662
|
+
.toSet()
|
|
663
|
+
}
|
|
664
|
+
|
|
431
665
|
private fun processModifications(modificationsJson: String?): Pair<String?, Boolean> {
|
|
432
666
|
if (modificationsJson.isNullOrEmpty()) {
|
|
433
667
|
return Pair(null, true) // Default: show phone calibration
|
|
@@ -2,8 +2,11 @@ package com.smkituilibrary.mapper
|
|
|
2
2
|
|
|
3
3
|
import com.sency.smkitui.data.entity.ScoringParams
|
|
4
4
|
import com.sency.smkitui.model.ExerciseData
|
|
5
|
+
import com.sency.smkitui.model.GuidanceVideoSegment
|
|
5
6
|
import com.sency.smkitui.model.SMExercise
|
|
7
|
+
import com.sency.smkitui.model.SMStretchSetConfig
|
|
6
8
|
import com.sency.smkitui.model.SMWorkout
|
|
9
|
+
import com.sency.smkitui.model.SMWorkoutContinuation
|
|
7
10
|
import com.sency.smkitui.model.WorkoutSummaryData
|
|
8
11
|
import com.sency.smkitui.model.workoutConfig.BodyZone
|
|
9
12
|
import com.sency.smkitui.model.workoutConfig.DifficultyLevel
|
|
@@ -11,9 +14,12 @@ import com.sency.smkitui.model.workoutConfig.SMLanguage
|
|
|
11
14
|
import com.sency.smkitui.model.workoutConfig.WorkoutConfig
|
|
12
15
|
import com.sency.smkitui.model.workoutConfig.WorkoutDuration
|
|
13
16
|
import com.smkituilibrary.model.SMKitExercise
|
|
17
|
+
import com.smkituilibrary.model.SMKitGuidanceVideoSegment
|
|
14
18
|
import com.smkituilibrary.model.SMKitScoringParams
|
|
19
|
+
import com.smkituilibrary.model.SMKitStretchSetConfig
|
|
15
20
|
import com.smkituilibrary.model.SMKitWorkout
|
|
16
21
|
import com.smkituilibrary.model.SMKitWorkoutConfig
|
|
22
|
+
import com.smkituilibrary.model.SMKitWorkoutContinuation
|
|
17
23
|
import com.smkituilibrary.model.WFPExerciseData
|
|
18
24
|
import com.smkituilibrary.model.WFPSummary
|
|
19
25
|
|
|
@@ -27,6 +33,7 @@ internal fun SMKitWorkoutConfig.toWorkoutConfig(): WorkoutConfig = WorkoutConfig
|
|
|
27
33
|
"he" -> SMLanguage.Hebrew
|
|
28
34
|
else -> SMLanguage.English
|
|
29
35
|
} ,
|
|
36
|
+
shortIntro = shortIntro,
|
|
30
37
|
)
|
|
31
38
|
|
|
32
39
|
internal fun SMKitWorkout.toSMWorkout(): SMWorkout = SMWorkout(
|
|
@@ -37,7 +44,8 @@ internal fun SMKitWorkout.toSMWorkout(): SMWorkout = SMWorkout(
|
|
|
37
44
|
exercises = exercises.map(SMKitExercise::toSMExercise),
|
|
38
45
|
workoutClosure = workoutClosure ?: "",
|
|
39
46
|
getInFrame = getInFrame ?: "",
|
|
40
|
-
bodycalFinished = bodycalFinished ?: ""
|
|
47
|
+
bodycalFinished = bodycalFinished ?: "",
|
|
48
|
+
continuation = continuation?.toSMWorkoutContinuation()
|
|
41
49
|
)
|
|
42
50
|
|
|
43
51
|
internal fun SMKitWorkout.toSMWorkoutWithoutScoringParams(): SMWorkout = SMWorkout(
|
|
@@ -48,11 +56,12 @@ internal fun SMKitWorkout.toSMWorkoutWithoutScoringParams(): SMWorkout = SMWorko
|
|
|
48
56
|
exercises = exercises.map(SMKitExercise::toSMExerciseWithoutScoringParams),
|
|
49
57
|
workoutClosure = workoutClosure ?: "",
|
|
50
58
|
getInFrame = getInFrame ?: "",
|
|
51
|
-
bodycalFinished = bodycalFinished ?: ""
|
|
59
|
+
bodycalFinished = bodycalFinished ?: "",
|
|
60
|
+
continuation = continuation?.toSMWorkoutContinuationWithoutScoringParams()
|
|
52
61
|
)
|
|
53
62
|
|
|
54
63
|
private fun SMKitExercise.toSMExercise(): SMExercise = SMExercise(
|
|
55
|
-
prettyName = prettyName ?: "",
|
|
64
|
+
prettyName = prettyName ?: name ?: "",
|
|
56
65
|
exerciseIntro = exerciseIntro ?: "",
|
|
57
66
|
totalSeconds = totalSeconds ?: 0,
|
|
58
67
|
videoInstruction = videoInstruction ?: "",
|
|
@@ -63,13 +72,23 @@ private fun SMKitExercise.toSMExercise(): SMExercise = SMExercise(
|
|
|
63
72
|
scoringParams = scoringParams?.toParams(),
|
|
64
73
|
summaryTitle = summaryTitle ?: "",
|
|
65
74
|
summarySubTitle = summarySubTitle ?: "",
|
|
66
|
-
summaryMainMetricTitle = summaryTitleMainMetric ?: "",
|
|
67
|
-
summaryMainMetricSubTitle = summarySubTitleMainMetric ?: "",
|
|
68
|
-
side = side
|
|
75
|
+
summaryMainMetricTitle = summaryMainMetricTitle ?: summaryTitleMainMetric ?: "",
|
|
76
|
+
summaryMainMetricSubTitle = summaryMainMetricSubTitle ?: summarySubTitleMainMetric ?: "",
|
|
77
|
+
side = side,
|
|
78
|
+
shortIntro = shortIntro,
|
|
79
|
+
playPreExerciseCountdown = playPreExerciseCountdown,
|
|
80
|
+
playSoundOnEachRep = playSoundOnEachRep,
|
|
81
|
+
playRepMilestoneVoice = playRepMilestoneVoice,
|
|
82
|
+
repMilestoneInterval = repMilestoneInterval,
|
|
83
|
+
guidanceMode = guidanceMode,
|
|
84
|
+
guidanceVideoSegments = guidanceVideoSegments?.mapValues { it.value.toGuidanceVideoSegment() },
|
|
85
|
+
adaptiveRomFeedbackEnabled = adaptiveRomFeedbackEnabled,
|
|
86
|
+
adaptiveRomWarmupReps = adaptiveRomWarmupReps.coerceAtLeast(1),
|
|
87
|
+
stretchSetConfig = stretchSetConfig?.toStretchSetConfig()
|
|
69
88
|
)
|
|
70
89
|
|
|
71
90
|
private fun SMKitExercise.toSMExerciseWithoutScoringParams(): SMExercise = SMExercise(
|
|
72
|
-
prettyName = prettyName ?: "",
|
|
91
|
+
prettyName = prettyName ?: name ?: "",
|
|
73
92
|
exerciseIntro = exerciseIntro ?: "",
|
|
74
93
|
totalSeconds = totalSeconds ?: 0,
|
|
75
94
|
videoInstruction = videoInstruction ?: "",
|
|
@@ -80,9 +99,50 @@ private fun SMKitExercise.toSMExerciseWithoutScoringParams(): SMExercise = SMExe
|
|
|
80
99
|
scoringParams = null, // Exclude scoring params for workouts
|
|
81
100
|
summaryTitle = summaryTitle ?: "",
|
|
82
101
|
summarySubTitle = summarySubTitle ?: "",
|
|
83
|
-
summaryMainMetricTitle = summaryTitleMainMetric ?: "",
|
|
84
|
-
summaryMainMetricSubTitle = summarySubTitleMainMetric ?: "",
|
|
85
|
-
side = side
|
|
102
|
+
summaryMainMetricTitle = summaryMainMetricTitle ?: summaryTitleMainMetric ?: "",
|
|
103
|
+
summaryMainMetricSubTitle = summaryMainMetricSubTitle ?: summarySubTitleMainMetric ?: "",
|
|
104
|
+
side = side,
|
|
105
|
+
shortIntro = shortIntro,
|
|
106
|
+
playPreExerciseCountdown = playPreExerciseCountdown,
|
|
107
|
+
playSoundOnEachRep = playSoundOnEachRep,
|
|
108
|
+
playRepMilestoneVoice = playRepMilestoneVoice,
|
|
109
|
+
repMilestoneInterval = repMilestoneInterval,
|
|
110
|
+
guidanceMode = guidanceMode,
|
|
111
|
+
guidanceVideoSegments = guidanceVideoSegments?.mapValues { it.value.toGuidanceVideoSegment() },
|
|
112
|
+
adaptiveRomFeedbackEnabled = adaptiveRomFeedbackEnabled,
|
|
113
|
+
adaptiveRomWarmupReps = adaptiveRomWarmupReps.coerceAtLeast(1),
|
|
114
|
+
stretchSetConfig = stretchSetConfig?.toStretchSetConfig()
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
private fun SMKitWorkoutContinuation.toSMWorkoutContinuation(): SMWorkoutContinuation = SMWorkoutContinuation(
|
|
118
|
+
introSoundKey = introSoundKey,
|
|
119
|
+
interactionUnlockSoundKey = interactionUnlockSoundKey,
|
|
120
|
+
exercises = exercises.map(SMKitExercise::toSMExercise)
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
private fun SMKitWorkoutContinuation.toSMWorkoutContinuationWithoutScoringParams(): SMWorkoutContinuation = SMWorkoutContinuation(
|
|
124
|
+
introSoundKey = introSoundKey,
|
|
125
|
+
interactionUnlockSoundKey = interactionUnlockSoundKey,
|
|
126
|
+
exercises = exercises.map(SMKitExercise::toSMExerciseWithoutScoringParams)
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
private fun SMKitGuidanceVideoSegment.toGuidanceVideoSegment(): GuidanceVideoSegment = GuidanceVideoSegment(
|
|
130
|
+
kind = if (kind.equals("freeze", ignoreCase = true)) {
|
|
131
|
+
GuidanceVideoSegment.Kind.FREEZE
|
|
132
|
+
} else {
|
|
133
|
+
GuidanceVideoSegment.Kind.PLAY
|
|
134
|
+
},
|
|
135
|
+
startSeconds = startSeconds,
|
|
136
|
+
endSeconds = endSeconds
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
private fun SMKitStretchSetConfig.toStretchSetConfig(): SMStretchSetConfig = SMStretchSetConfig(
|
|
140
|
+
enabled = enabled,
|
|
141
|
+
repetitions = repetitions,
|
|
142
|
+
secondsPerStretch = secondsPerStretch,
|
|
143
|
+
restSecondsBetweenStretches = restSecondsBetweenStretches,
|
|
144
|
+
introSoundKey = introSoundKey,
|
|
145
|
+
positionDetectors = positionDetectors
|
|
86
146
|
)
|
|
87
147
|
|
|
88
148
|
private fun SMKitScoringParams.toParams(): ScoringParams {
|
|
@@ -12,15 +12,32 @@ internal data class SMKitExercise(
|
|
|
12
12
|
val introSeconds: Int? = null,
|
|
13
13
|
val totalSeconds: Int? = null,
|
|
14
14
|
val scoringParams: SMKitScoringParams? = null,
|
|
15
|
+
val name: String? = null,
|
|
15
16
|
val prettyName: String? = null,
|
|
16
17
|
val exerciseIntro: String? = null,
|
|
17
18
|
val exerciseClosure: String? = null,
|
|
18
19
|
val closureFailedSound: String? = null,
|
|
19
20
|
val summaryTitle: String? = null,
|
|
20
21
|
val summarySubTitle: String? = null,
|
|
22
|
+
val summaryMainMetricTitle: String? = null,
|
|
23
|
+
val summaryMainMetricSubTitle: String? = null,
|
|
21
24
|
val summaryTitleMainMetric: String? = null,
|
|
22
25
|
val summarySubTitleMainMetric: String? = null,
|
|
23
26
|
val side: String? = null,
|
|
27
|
+
val shortIntro: Boolean = false,
|
|
28
|
+
val quickMotionParams: SMKitQuickMotionParams? = null,
|
|
29
|
+
val rowingFeedbackLevel: String? = null,
|
|
30
|
+
val phonePosition: String? = null,
|
|
31
|
+
val guidanceMode: Boolean? = null,
|
|
32
|
+
val useWideAngleCamera: Boolean? = null,
|
|
33
|
+
val playPreExerciseCountdown: Boolean = false,
|
|
34
|
+
val playSoundOnEachRep: Boolean = false,
|
|
35
|
+
val playRepMilestoneVoice: Boolean = false,
|
|
36
|
+
val repMilestoneInterval: Int = 10,
|
|
37
|
+
val guidanceVideoSegments: Map<String, SMKitGuidanceVideoSegment>? = null,
|
|
38
|
+
val adaptiveRomFeedbackEnabled: Boolean = false,
|
|
39
|
+
val adaptiveRomWarmupReps: Int = 2,
|
|
40
|
+
val stretchSetConfig: SMKitStretchSetConfig? = null,
|
|
24
41
|
)
|
|
25
42
|
|
|
26
43
|
@Keep
|
|
@@ -32,3 +49,26 @@ internal data class SMKitScoringParams(
|
|
|
32
49
|
val targetRom: String? = null,
|
|
33
50
|
val passCriteria: List<String>? = null,
|
|
34
51
|
)
|
|
52
|
+
|
|
53
|
+
@Keep
|
|
54
|
+
internal data class SMKitQuickMotionParams(
|
|
55
|
+
val validityWindow: Double? = null,
|
|
56
|
+
val checkInterval: Double? = null,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
@Keep
|
|
60
|
+
internal data class SMKitGuidanceVideoSegment(
|
|
61
|
+
val kind: String,
|
|
62
|
+
val startSeconds: Double,
|
|
63
|
+
val endSeconds: Double? = null,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
@Keep
|
|
67
|
+
internal data class SMKitStretchSetConfig(
|
|
68
|
+
val enabled: Boolean = true,
|
|
69
|
+
val repetitions: Int = 1,
|
|
70
|
+
val secondsPerStretch: Int = 0,
|
|
71
|
+
val restSecondsBetweenStretches: Int = 3,
|
|
72
|
+
val introSoundKey: String? = null,
|
|
73
|
+
val positionDetectors: List<String>? = null,
|
|
74
|
+
)
|
|
@@ -12,4 +12,12 @@ internal data class SMKitWorkout(
|
|
|
12
12
|
val workoutClosure: String? = null,
|
|
13
13
|
val getInFrame: String? = null,
|
|
14
14
|
val bodycalFinished: String? = null,
|
|
15
|
+
val continuation: SMKitWorkoutContinuation? = null,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
@Keep
|
|
19
|
+
internal data class SMKitWorkoutContinuation(
|
|
20
|
+
val introSoundKey: String? = null,
|
|
21
|
+
val interactionUnlockSoundKey: String,
|
|
22
|
+
val exercises: List<SMKitExercise>,
|
|
15
23
|
)
|
|
@@ -6,12 +6,16 @@ import com.sency.smkitui.model.UserData
|
|
|
6
6
|
data class SMUserData(
|
|
7
7
|
val gender: String,
|
|
8
8
|
val age: Int,
|
|
9
|
+
val email: String? = null,
|
|
9
10
|
)
|
|
10
11
|
|
|
11
12
|
fun SMUserData.toUserData() : UserData {
|
|
12
13
|
val g = when(gender) {
|
|
13
14
|
"Female" -> Gender.Female
|
|
15
|
+
"Rather not say" -> Gender.Idle
|
|
16
|
+
"Other" -> Gender.Idle
|
|
17
|
+
"Idle" -> Gender.Idle
|
|
14
18
|
else -> Gender.Male
|
|
15
19
|
}
|
|
16
|
-
return UserData(age, g)
|
|
20
|
+
return UserData(age, g, email)
|
|
17
21
|
}
|
package/ios/SMKitUIManager.mm
CHANGED
|
@@ -7,17 +7,39 @@ RCT_EXTERN_METHOD(startCustomWorkout:(NSString*)rawJson modifications:(NSString*
|
|
|
7
7
|
RCT_EXTERN_METHOD(startCustomAssessment:(NSString*)rawJson userData:(NSString* _Nullable)userData forceShowUserDataScreen:(BOOL)forceShowUserDataScreen showSummary:(BOOL)showSummary modifications:(NSString* _Nullable)modifications onWorkoutDidFinish:(RCTPromiseResolveBlock)onWorkoutDidFinish onWorkoutFailed:(RCTPromiseRejectBlock)onWorkoutFailed)
|
|
8
8
|
RCT_EXTERN_METHOD(startWorkoutProgram:(NSString*)dic modifications:(NSString* _Nullable)modifications onWorkoutDidFinish:(RCTPromiseResolveBlock)onWorkoutDidFinish onWorkoutFailed:(RCTPromiseRejectBlock)onWorkoutFailed)
|
|
9
9
|
|
|
10
|
-
RCT_EXTERN_METHOD(setSessionLanguage:(NSString*)language)
|
|
11
|
-
RCT_EXTERN_METHOD(setPhoneCalibrationLanguage:(NSString*)language)
|
|
12
|
-
RCT_EXTERN_METHOD(setEndExercisePreferences:(NSString*)preferencesString)
|
|
13
|
-
RCT_EXTERN_METHOD(setCounterPreferences:(NSString*)preferencesString)
|
|
10
|
+
RCT_EXTERN_METHOD(setSessionLanguage:(NSString*)language onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
11
|
+
RCT_EXTERN_METHOD(setPhoneCalibrationLanguage:(NSString*)language onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
12
|
+
RCT_EXTERN_METHOD(setEndExercisePreferences:(NSString*)preferencesString onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
13
|
+
RCT_EXTERN_METHOD(setCounterPreferences:(NSString*)preferencesString onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
14
14
|
|
|
15
|
-
RCT_EXTERN_METHOD(setIntelligenceRestEnabled:(BOOL)enabled)
|
|
16
|
-
RCT_EXTERN_METHOD(setSkeletonSettings:(NSString*)configString)
|
|
17
|
-
RCT_EXTERN_METHOD(setPauseTypes:(NSString*)typesJson)
|
|
18
|
-
RCT_EXTERN_METHOD(setAllowAudioMixing:(BOOL)enabled)
|
|
19
|
-
RCT_EXTERN_METHOD(setShowExternalAudioControl:(BOOL)enabled)
|
|
20
|
-
RCT_EXTERN_METHOD(setAccuratePoseEstimation:(BOOL)enabled)
|
|
21
|
-
RCT_EXTERN_METHOD(setInstructionVideoConfig:(NSString*)configString)
|
|
15
|
+
RCT_EXTERN_METHOD(setIntelligenceRestEnabled:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
16
|
+
RCT_EXTERN_METHOD(setSkeletonSettings:(NSString*)configString onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
17
|
+
RCT_EXTERN_METHOD(setPauseTypes:(NSString*)typesJson onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
18
|
+
RCT_EXTERN_METHOD(setAllowAudioMixing:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
19
|
+
RCT_EXTERN_METHOD(setShowExternalAudioControl:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
20
|
+
RCT_EXTERN_METHOD(setAccuratePoseEstimation:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
21
|
+
RCT_EXTERN_METHOD(setInstructionVideoConfig:(NSString*)configString onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
22
|
+
RCT_EXTERN_METHOD(setColorTheme:(NSString*)theme onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
23
|
+
RCT_EXTERN_METHOD(setPlayPhoneCalibrationAudio:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
24
|
+
RCT_EXTERN_METHOD(setPlayBodyCalibrationAudio:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
25
|
+
RCT_EXTERN_METHOD(setStartTimerOnFirstActivity:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
26
|
+
RCT_EXTERN_METHOD(setWorkoutContinuationTimerDuration:(nonnull NSNumber*)seconds onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
27
|
+
RCT_EXTERN_METHOD(setPhoneMovementCountPreventionEnabled:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
28
|
+
RCT_EXTERN_METHOD(setVariationMismatchFeedbackEnabled:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
29
|
+
RCT_EXTERN_METHOD(setUseDefaultGuidanceMode:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
30
|
+
RCT_EXTERN_METHOD(setGuidanceDebugLogging:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
31
|
+
RCT_EXTERN_METHOD(setEnableButtonTutorial:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
32
|
+
RCT_EXTERN_METHOD(setButtonTutorialCompletionAudioUri:(NSString* _Nullable)uri onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
33
|
+
RCT_EXTERN_METHOD(setShowRowingPhoneCalibration:(BOOL)enabled onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
34
|
+
RCT_EXTERN_METHOD(setFeedbacksUIToExclude:(NSString*)feedbacksJson onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
35
|
+
RCT_EXTERN_METHOD(setExcludedFeedbacks:(NSString*)feedbacksJson onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
36
|
+
RCT_EXTERN_METHOD(setConfigString:(NSString* _Nullable)configString onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
37
|
+
RCT_EXTERN_METHOD(clearAdaptiveRomCache:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
38
|
+
RCT_EXTERN_METHOD(quitWorkout:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
39
|
+
RCT_EXTERN_METHOD(pauseSDK:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
40
|
+
RCT_EXTERN_METHOD(resumeSDK:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
41
|
+
RCT_EXTERN_METHOD(getSupportedMovements:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
42
|
+
RCT_EXTERN_METHOD(getExerciseType:(NSString*)detector onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
43
|
+
RCT_EXTERN_METHOD(setPoseModelChoice:(NSString*)choice onSuccess:(RCTPromiseResolveBlock)onSuccess onFailure:(RCTPromiseRejectBlock)onFailure)
|
|
22
44
|
|
|
23
45
|
@end
|