@sency/react-native-smkit-ui 2.2.1 → 2.3.0

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.
Files changed (30) hide show
  1. package/README.md +218 -65
  2. package/android/build.gradle +3 -1
  3. package/android/src/main/java/com/smkituilibrary/SmkitUiLibraryModule.kt +238 -5
  4. package/android/src/main/java/com/smkituilibrary/mapper/SMMapper.kt +70 -10
  5. package/android/src/main/java/com/smkituilibrary/model/SMKitExercise.kt +40 -0
  6. package/android/src/main/java/com/smkituilibrary/model/SMKitWorkout.kt +8 -0
  7. package/android/src/main/java/com/smkituilibrary/model/SMKitWorkoutConfig.kt +2 -0
  8. package/android/src/main/java/com/smkituilibrary/model/SMUserData.kt +5 -1
  9. package/ios/SMKitUIManager.mm +33 -11
  10. package/ios/SMKitUIManager.swift +237 -36
  11. package/lib/commonjs/SMWorkout.js +239 -177
  12. package/lib/commonjs/SMWorkout.js.map +1 -1
  13. package/lib/commonjs/index.js +187 -5
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/module/SMWorkout.js +232 -181
  16. package/lib/module/SMWorkout.js.map +1 -1
  17. package/lib/module/index.js +165 -5
  18. package/lib/module/index.js.map +1 -1
  19. package/package.json +2 -2
  20. package/react-native-smkit-ui.podspec +2 -2
  21. package/src/SMWorkout.tsx +353 -176
  22. package/src/index.tsx +167 -8
  23. package/android/build/intermediates/compile_r_class_jar/debug/generateDebugRFile/R.jar +0 -0
  24. package/android/build/intermediates/compile_symbol_list/debug/generateDebugRFile/R.txt +0 -0
  25. package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +0 -1
  26. package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +0 -2
  27. package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +0 -2
  28. package/android/build/intermediates/local_only_symbol_list/debug/parseDebugLocalResources/R-def.txt +0 -2
  29. package/android/build/intermediates/nested_resources_validation_report/debug/generateDebugResources/nestedResourcesValidationReport.txt +0 -1
  30. package/android/build/intermediates/symbol_list_with_package_name/debug/generateDebugRFile/package-aware-r.txt +0 -1
package/README.md CHANGED
@@ -145,10 +145,10 @@ allprojects {
145
145
 
146
146
  ```gradle
147
147
  android {
148
- compileSdkVersion 35
148
+ compileSdkVersion 36
149
149
  defaultConfig {
150
150
  minSdkVersion 26
151
- targetSdkVersion 35
151
+ targetSdkVersion 36
152
152
  }
153
153
  }
154
154
  ```
@@ -217,9 +217,9 @@ if (cameraPermission === RESULTS.GRANTED) {
217
217
  ### Workout Configuration
218
218
 
219
219
  Customize workouts with:
220
- - **Body Zones**: Full Body, Upper Body, Lower Body, Core
221
- - **Difficulty**: Low, Medium, High
222
- - **Duration**: Short, Medium, Long
220
+ - **Body Zones**: Full Body, Upper Body, Lower Body
221
+ - **Difficulty**: Low, Mid, High
222
+ - **Duration**: Short, Long
223
223
  - **Week Number**: For multi-week programs
224
224
 
225
225
  ---
@@ -240,58 +240,83 @@ await configure('YOUR_API_KEY');
240
240
 
241
241
  ---
242
242
 
243
- #### `startAssessment(type: AssessmentType, options?: AssessmentOptions): Promise<AssessmentResult>`
243
+ #### `startAssessment(type, showSummary, userData, forceShowUserDataScreen, customAssessmentID, modifications): Promise<{ summary: string; didFinish: boolean }>`
244
244
 
245
245
  Start a fitness assessment.
246
246
 
247
247
  ```typescript
248
- import { startAssessment, AssessmentType } from '@sency/react-native-smkit-ui';
248
+ import { startAssessment, SMWorkoutLibrary } from '@sency/react-native-smkit-ui';
249
249
 
250
- const result = await startAssessment(AssessmentType.Fitness, {
251
- showSummary: true,
252
- customId: 'user-123'
253
- });
250
+ const userData = new SMWorkoutLibrary.UserData(
251
+ SMWorkoutLibrary.Gender.Other,
252
+ 35,
253
+ 'user@example.com'
254
+ );
255
+
256
+ const result = await startAssessment(
257
+ SMWorkoutLibrary.AssessmentTypes.Fitness,
258
+ true,
259
+ userData,
260
+ false,
261
+ '',
262
+ null
263
+ );
254
264
  ```
255
265
 
256
266
  **Parameters:**
257
- - `type` - The assessment type (Fitness, Body360, Strength, Cardio, Custom)
258
- - `options` - Optional configuration object
259
- - `showSummary` - Display summary after completion (default: true)
260
- - `customId` - Custom identifier for the assessment
267
+ - `type` - The assessment type (`Fitness`, `Body360`, `Strength`, `Cardio`, `Custom`)
268
+ - `showSummary` - Display summary after completion
269
+ - `userData` - Optional `SMWorkoutLibrary.UserData`; pass `null` when not needed
270
+ - `forceShowUserDataScreen` - Forces the user data screen even when user data is provided
271
+ - `customAssessmentID` - Custom assessment identifier, or an empty string
272
+ - `modifications` - Optional JSON string with exercise feedback parameter modifications
261
273
 
262
274
  ---
263
275
 
264
- #### `startWorkoutProgram(config: WorkoutConfig): Promise<WorkoutResult>`
276
+ #### `startWorkoutProgram(config: SMWorkoutLibrary.WorkoutConfig, modifications: string | null): Promise<{ summary: string; didFinish: boolean }>`
265
277
 
266
278
  Start a workout program with customization options.
267
279
 
268
280
  ```typescript
269
- import { startWorkoutProgram, WorkoutConfig, BodyZone, Difficulty, Duration } from '@sency/react-native-smkit-ui';
270
-
271
- const config = new WorkoutConfig(
272
- week: 1,
273
- bodyZone: BodyZone.FullBody,
274
- difficulty: Difficulty.Medium,
275
- duration: Duration.Medium,
276
- programId: 'program-123'
281
+ import { startWorkoutProgram, SMWorkoutLibrary } from '@sency/react-native-smkit-ui';
282
+
283
+ const config = new SMWorkoutLibrary.WorkoutConfig(
284
+ 1,
285
+ SMWorkoutLibrary.BodyZone.FullBody,
286
+ SMWorkoutLibrary.WorkoutDifficulty.MidDifficulty,
287
+ SMWorkoutLibrary.WorkoutDuration.Short,
288
+ SMWorkoutLibrary.Language.English,
289
+ 'program-123',
290
+ {
291
+ shortIntro: true,
292
+ phonePosition: SMWorkoutLibrary.PhonePosition.Floor,
293
+ }
277
294
  );
278
295
 
279
- const result = await startWorkoutProgram(config);
296
+ const result = await startWorkoutProgram(config, null);
280
297
  ```
281
298
 
282
299
  ---
283
300
 
284
- #### `startCustomAssessment(config: CustomAssessmentConfig): Promise<AssessmentResult>`
301
+ #### `startCustomAssessment(assessment, userData, forceShowUserDataScreen, showSummary, modifications): Promise<{ summary: string; didFinish: boolean }>`
285
302
 
286
303
  Start a custom assessment (assessment configured by Sency for your specific needs).
287
304
 
288
305
  ```typescript
289
- import { startCustomAssessment } from '@sency/react-native-smkit-ui';
306
+ import { startCustomAssessment, SMWorkoutLibrary } from '@sency/react-native-smkit-ui';
307
+
308
+ const assessment = new SMWorkoutLibrary.SMWorkout(
309
+ 'assessment-123',
310
+ 'Mobility Check',
311
+ null,
312
+ null,
313
+ [],
314
+ null,
315
+ null,
316
+ null
317
+ );
290
318
 
291
- const result = await startCustomAssessment({
292
- customId: 'assessment-123',
293
- showSummary: true
294
- });
319
+ const result = await startCustomAssessment(assessment, null, false, true, null);
295
320
  ```
296
321
 
297
322
  ---
@@ -303,12 +328,12 @@ const result = await startCustomAssessment({
303
328
  Configure which buttons appear in the pause menu during workouts and assessments.
304
329
 
305
330
  ```typescript
306
- import { setPauseTypes, PauseType } from '@sency/react-native-smkit-ui';
331
+ import { setPauseTypes, SMWorkoutLibrary } from '@sency/react-native-smkit-ui';
307
332
 
308
333
  await setPauseTypes([
309
- PauseType.Resume,
310
- PauseType.Skip,
311
- PauseType.Quit
334
+ SMWorkoutLibrary.PauseType.Resume,
335
+ SMWorkoutLibrary.PauseType.Skip,
336
+ SMWorkoutLibrary.PauseType.Quit
312
337
  ]);
313
338
  ```
314
339
 
@@ -322,11 +347,11 @@ await setPauseTypes([
322
347
  Customize the skeleton visualization style during exercises.
323
348
 
324
349
  ```typescript
325
- import { setSkeletonSettings, SkeletonPreset, SkeletonConnectionStyle } from '@sency/react-native-smkit-ui';
350
+ import { setSkeletonSettings, SMWorkoutLibrary } from '@sency/react-native-smkit-ui';
326
351
 
327
352
  await setSkeletonSettings({
328
- preset: SkeletonPreset.NeonGlow,
329
- connectionStyle: SkeletonConnectionStyle.Solid,
353
+ preset: SMWorkoutLibrary.SkeletonPreset.NeonGlow,
354
+ connectionStyle: SMWorkoutLibrary.SkeletonConnectionStyle.Solid,
330
355
  dotsOpacity: 1,
331
356
  connectionsOpacity: 0.8
332
357
  });
@@ -351,7 +376,7 @@ await setInstructionVideoConfig({
351
376
 
352
377
  #### `setAllowAudioMixing(enabled: boolean): Promise<void>`
353
378
 
354
- Allow SDK audio to mix with external app audio. **(iOS only)**
379
+ Allow SDK audio to mix with external app audio. Supported on iOS and Android native SDKs that expose the control.
355
380
 
356
381
  ```typescript
357
382
  import { setAllowAudioMixing } from '@sency/react-native-smkit-ui';
@@ -363,7 +388,7 @@ await setAllowAudioMixing(true);
363
388
 
364
389
  #### `setShowExternalAudioControl(enabled: boolean): Promise<void>`
365
390
 
366
- Show an in-session button to switch audio source. **(iOS only)**
391
+ Show an in-session button to switch audio source. Supported on iOS and Android native SDKs that expose the control.
367
392
 
368
393
  ```typescript
369
394
  import { setShowExternalAudioControl } from '@sency/react-native-smkit-ui';
@@ -385,6 +410,124 @@ await setAccuratePoseEstimation(true);
385
410
 
386
411
  ---
387
412
 
413
+ #### Advanced SDK controls
414
+
415
+ These setters are exported directly from the React Native package and return `Promise<void>` unless noted. Platform-specific methods validate their input and resolve as a no-op on unsupported platforms.
416
+
417
+ | Method | Purpose |
418
+ |--------|---------|
419
+ | `setColorTheme(theme)` | Applies a native SDK color theme. |
420
+ | `setPlayPhoneCalibrationAudio(enabled)` | Enables phone calibration audio. |
421
+ | `setPlayBodyCalibrationAudio(enabled)` | Enables body calibration audio. |
422
+ | `setStartTimerOnFirstActivity(enabled)` | Starts exercise timers on first detected activity. |
423
+ | `setWorkoutContinuationTimerDuration(seconds)` | Sets the continuation countdown duration. |
424
+ | `setPhoneMovementCountPreventionEnabled(enabled)` | Prevents counting while phone movement is detected. |
425
+ | `setVariationMismatchFeedbackEnabled(enabled)` | Enables variation mismatch feedback. |
426
+ | `setUseDefaultGuidanceMode(enabled)` | Lets native SDK defaults drive guidance mode. |
427
+ | `setGuidanceDebugLogging(enabled)` | Enables native guidance debug logging where supported. |
428
+ | `setEnableButtonTutorial(enabled)` | Shows the button tutorial overlay. |
429
+ | `setButtonTutorialCompletionAudioUri(uri)` | Sets optional tutorial completion audio. |
430
+ | `setShowRowingPhoneCalibration(enabled)` | iOS rowing phone calibration control; Android no-op. |
431
+ | `setFeedbacksUIToExclude(values)` | Hides selected native feedback types from UI. |
432
+ | `setExcludedFeedbacks(values)` | Excludes selected feedbacks where supported. |
433
+ | `setConfigString(value)` | Android native flat config string; iOS no-op. |
434
+ | `clearAdaptiveRomCache()` | Clears adaptive ROM cache where supported. |
435
+ | `quitWorkout()` | Quits the active workout where supported. |
436
+ | `pauseSDK()` / `resumeSDK()` | iOS active-workout pause and resume; Android no-op. |
437
+ | `getSupportedMovements()` | iOS supported movement names; Android returns an empty array. |
438
+ | `getExerciseType(detector)` | iOS exercise type lookup; Android returns an empty string. |
439
+ | `setPoseModelChoice(choice)` | Android pose model choice before configure; iOS no-op. |
440
+
441
+ ```typescript
442
+ import {
443
+ setColorTheme,
444
+ setPlayPhoneCalibrationAudio,
445
+ setPlayBodyCalibrationAudio,
446
+ setPhoneMovementCountPreventionEnabled,
447
+ setPoseModelChoice,
448
+ SMWorkoutLibrary,
449
+ } from '@sency/react-native-smkit-ui';
450
+
451
+ await setColorTheme(SMWorkoutLibrary.ColorTheme.Green);
452
+ await setPlayPhoneCalibrationAudio(true);
453
+ await setPlayBodyCalibrationAudio(true);
454
+ await setPhoneMovementCountPreventionEnabled(true);
455
+ await setPoseModelChoice(SMWorkoutLibrary.PoseModelChoice.AdaptiveChoice);
456
+ ```
457
+
458
+ Interactive Talk to Jinni is intentionally not exposed by this React Native SDK.
459
+
460
+ ---
461
+
462
+ #### Advanced custom workout options
463
+
464
+ `SMExercise`, `SMAssessmentExercise`, and `WorkoutConfig` keep their existing constructor arguments and accept optional trailing options objects for newer native SDK features.
465
+
466
+ ```typescript
467
+ import { startCustomWorkout, SMWorkoutLibrary } from '@sency/react-native-smkit-ui';
468
+
469
+ const exercise = new SMWorkoutLibrary.SMExercise(
470
+ 'Squat',
471
+ 45,
472
+ 'squat_instruction.mp4',
473
+ 'squat_intro.mp3',
474
+ [
475
+ SMWorkoutLibrary.UIElement.RepsCounter,
476
+ SMWorkoutLibrary.UIElement.Skeleton,
477
+ SMWorkoutLibrary.UIElement.CountdownTimer,
478
+ ],
479
+ 'SquatRegular',
480
+ null,
481
+ new SMWorkoutLibrary.SMScoringParams(
482
+ SMWorkoutLibrary.ScoringType.Reps,
483
+ null,
484
+ null,
485
+ 12,
486
+ null,
487
+ null
488
+ ),
489
+ {
490
+ shortIntro: true,
491
+ guidanceMode: true,
492
+ guidanceVideoSegments: {
493
+ introFreeze: SMWorkoutLibrary.GuidanceVideoSegment.freeze(1.2),
494
+ demoLoop: SMWorkoutLibrary.GuidanceVideoSegment.play(2.0, 6.5),
495
+ },
496
+ playPreExerciseCountdown: true,
497
+ playSoundOnEachRep: true,
498
+ playRepMilestoneVoice: true,
499
+ repMilestoneInterval: 5,
500
+ adaptiveRomFeedbackEnabled: true,
501
+ adaptiveRomWarmupReps: 3,
502
+ stretchSetConfig: new SMWorkoutLibrary.StretchSetConfig(3, 20, {
503
+ restSecondsBetweenStretches: 5,
504
+ }),
505
+ }
506
+ );
507
+
508
+ const continuation = new SMWorkoutLibrary.WorkoutContinuation(
509
+ 'continue_unlock.mp3',
510
+ [exercise],
511
+ 'continue_intro.mp3'
512
+ );
513
+
514
+ const workout = new SMWorkoutLibrary.SMWorkout(
515
+ 'workout-123',
516
+ 'Strength Builder',
517
+ null,
518
+ null,
519
+ [exercise],
520
+ null,
521
+ null,
522
+ null,
523
+ continuation
524
+ );
525
+
526
+ await startCustomWorkout(workout, null);
527
+ ```
528
+
529
+ The supported exercise options include `shortIntro`, `quickMotionParams`, `rowingFeedbackLevel`, `phonePosition`, `guidanceMode`, `useWideAngleCamera`, `playPreExerciseCountdown`, `playRepMilestoneVoice`, `repMilestoneInterval`, `playSoundOnEachRep`, `adaptiveRomFeedbackEnabled`, `adaptiveRomWarmupReps`, `guidanceVideoSegments`, `stretchSetConfig`, and `side`.
530
+
388
531
  ## Examples
389
532
 
390
533
  ### Complete Setup Example
@@ -396,11 +539,7 @@ import {
396
539
  configure,
397
540
  startAssessment,
398
541
  startWorkoutProgram,
399
- AssessmentType,
400
- BodyZone,
401
- Difficulty,
402
- Duration,
403
- WorkoutConfig
542
+ SMWorkoutLibrary
404
543
  } from '@sency/react-native-smkit-ui';
405
544
 
406
545
  export default function FitnessApp() {
@@ -421,9 +560,14 @@ export default function FitnessApp() {
421
560
 
422
561
  const handleFitnessAssessment = async () => {
423
562
  try {
424
- const result = await startAssessment(AssessmentType.Fitness, {
425
- showSummary: true
426
- });
563
+ const result = await startAssessment(
564
+ SMWorkoutLibrary.AssessmentTypes.Fitness,
565
+ true,
566
+ null,
567
+ false,
568
+ '',
569
+ null
570
+ );
427
571
  console.log('Assessment completed:', result);
428
572
  } catch (error) {
429
573
  console.error('Assessment failed:', error);
@@ -432,13 +576,15 @@ export default function FitnessApp() {
432
576
 
433
577
  const handleWorkout = async () => {
434
578
  try {
435
- const config = new WorkoutConfig(
579
+ const config = new SMWorkoutLibrary.WorkoutConfig(
436
580
  1,
437
- BodyZone.FullBody,
438
- Difficulty.Medium,
439
- Duration.Medium
581
+ SMWorkoutLibrary.BodyZone.FullBody,
582
+ SMWorkoutLibrary.WorkoutDifficulty.MidDifficulty,
583
+ SMWorkoutLibrary.WorkoutDuration.Short,
584
+ SMWorkoutLibrary.Language.English,
585
+ 'program-123'
440
586
  );
441
- const result = await startWorkoutProgram(config);
587
+ const result = await startWorkoutProgram(config, null);
442
588
  console.log('Workout completed:', result);
443
589
  } catch (error) {
444
590
  console.error('Workout failed:', error);
@@ -470,14 +616,18 @@ export default function FitnessApp() {
470
616
  ```typescript
471
617
  const startBody360Assessment = async () => {
472
618
  try {
473
- const result = await startAssessment(AssessmentType.Body360, {
474
- showSummary: true,
475
- customId: `user-${Date.now()}`
476
- });
619
+ const result = await startAssessment(
620
+ SMWorkoutLibrary.AssessmentTypes.Body360,
621
+ true,
622
+ null,
623
+ false,
624
+ `user-${Date.now()}`,
625
+ null
626
+ );
477
627
 
478
- if (result.success) {
628
+ if (result.didFinish) {
479
629
  console.log('Body360 assessment completed');
480
- console.log('Results:', result.data);
630
+ console.log('Summary:', result.summary);
481
631
  }
482
632
  } catch (error) {
483
633
  console.error('Body360 assessment error:', error);
@@ -490,14 +640,17 @@ const startBody360Assessment = async () => {
490
640
  ```typescript
491
641
  const startCustomizedWorkout = async () => {
492
642
  try {
493
- const config = new WorkoutConfig(
494
- week: 2,
495
- bodyZone: BodyZone.UpperBody,
496
- difficulty: Difficulty.High,
497
- duration: Duration.Long
643
+ const config = new SMWorkoutLibrary.WorkoutConfig(
644
+ 2,
645
+ SMWorkoutLibrary.BodyZone.UpperBody,
646
+ SMWorkoutLibrary.WorkoutDifficulty.HighDifficulty,
647
+ SMWorkoutLibrary.WorkoutDuration.Long,
648
+ SMWorkoutLibrary.Language.English,
649
+ 'program-123',
650
+ { shortIntro: true }
498
651
  );
499
652
 
500
- const result = await startWorkoutProgram(config);
653
+ const result = await startWorkoutProgram(config, null);
501
654
  console.log('Workout program completed:', result);
502
655
  } catch (error) {
503
656
  console.error('Workout error:', error);
@@ -95,11 +95,13 @@ dependencies {
95
95
  implementation "com.facebook.react:react-android"
96
96
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
97
97
 
98
- implementation("com.sency.smkitui:smkitui:1.6.3") {
98
+ implementation("com.sency.smkitui:smkitui:1.6.6") {
99
99
  exclude group: 'com.facebook.fbjni', module: 'fbjni-java-only'
100
100
  // // Don't exclude native libraries
101
101
  // exclude group: 'com.facebook.react', module: 'react-native'
102
102
  }
103
+ implementation "com.sency.smkit:smkit:1.6.6"
104
+ implementation "com.sency.smbase.nativeclient:smbase-native-client:1.6.6"
103
105
 
104
106
  // Gson
105
107
  implementation 'com.google.code.gson:gson:2.9.0'