@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.
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 +237 -3
  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/src/SMWorkout.tsx CHANGED
@@ -1,7 +1,35 @@
1
- /**
2
- * Enum representing assessment types.
3
- * @enum {string}
4
- */
1
+ type JsonPrimitive = string | number | boolean | null;
2
+ type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
3
+ type JsonObject = { [key: string]: JsonValue | undefined };
4
+
5
+ function withoutUndefined(value: JsonObject): { [key: string]: JsonValue } {
6
+ return Object.entries(value).reduce<{ [key: string]: JsonValue }>((result, [key, item]) => {
7
+ if (item !== undefined) {
8
+ result[key] = item;
9
+ }
10
+ return result;
11
+ }, {});
12
+ }
13
+
14
+ function serializeGuidanceVideoSegments(
15
+ segments: Record<string, GuidanceVideoSegment | GuidanceVideoSegmentConfig> | undefined
16
+ ): JsonObject | undefined {
17
+ if (segments === undefined) {
18
+ return undefined;
19
+ }
20
+
21
+ return Object.entries(segments).reduce<JsonObject>((result, [key, segment]) => {
22
+ result[key] = segment instanceof GuidanceVideoSegment
23
+ ? segment.toJSON()
24
+ : withoutUndefined({
25
+ kind: segment.kind,
26
+ startSeconds: segment.startSeconds,
27
+ endSeconds: segment.endSeconds ?? undefined,
28
+ });
29
+ return result;
30
+ }, {});
31
+ }
32
+
5
33
  export enum AssessmentTypes {
6
34
  Fitness = 'fitness',
7
35
  Custom = 'custom',
@@ -19,59 +47,39 @@ export enum PauseType {
19
47
  Switch = 'switchExercise',
20
48
  }
21
49
 
22
- /**
23
- * Enum representing UI elements that can be displayed during workouts.
24
- * @enum {string}
25
- */
26
50
  export enum UIElement {
27
51
  RepsCounter = 'repsCounter',
28
52
  Timer = 'timer',
29
53
  GaugeOfMotion = 'gaugeOfMotion',
54
+ Skeleton = 'skeleton',
55
+ HoldingPosition = 'holdingPosition',
56
+ CountdownTimer = 'countdownTimer',
57
+ QuickMotion = 'quickMotion',
30
58
  }
31
59
 
32
- /**
33
- * Enum representing body zones targeted in workouts.
34
- * @enum {string}
35
- */
36
60
  export enum BodyZone {
37
61
  UpperBody = 'UpperBody',
38
62
  LowerBody = 'LowerBody',
39
63
  FullBody = 'FullBody',
40
64
  }
41
65
 
42
- /**
43
- * Enum representing workout difficulty levels.
44
- * @enum {string}
45
- */
46
66
  export enum WorkoutDifficulty {
47
67
  LowDifficulty = 'LowDifficulty',
48
68
  MidDifficulty = 'MidDifficulty',
49
69
  HighDifficulty = 'HighDifficulty',
50
70
  }
51
71
 
52
- /**
53
- * Enum representing workout durations.
54
- * @enum {string}
55
- */
56
72
  export enum WorkoutDuration {
57
73
  Short = 'Short',
58
74
  Long = 'Long',
59
75
  }
60
76
 
61
- /**
62
- * Enum representing different types of scoring methods.
63
- * @enum {string}
64
- */
65
77
  export enum ScoringType {
66
78
  Rom = 'rom',
67
79
  Time = 'time',
68
80
  Reps = 'reps',
69
81
  }
70
82
 
71
- /**
72
- * Enum representing gender options for user data.
73
- * @enum {string}
74
- */
75
83
  export enum Gender {
76
84
  Female = 'Female',
77
85
  Male = 'Male',
@@ -83,22 +91,49 @@ export enum Language {
83
91
  Hebrew = 'he',
84
92
  }
85
93
 
86
- /**
87
- * Enum representing the exercise rep counter prefrence.
88
- * @enum {string}
89
- */
90
94
  export enum CounterPreferences {
91
95
  Default = 'Default',
92
96
  PerfectOnly = 'PerfectOnly',
93
97
  }
94
98
 
95
- /**
96
- * Enum representing the workout couser type.
97
- * @enum {string}
98
- */
99
99
  export enum EndExercisePreferences {
100
- Default = 'Default', //on timer end
101
- TargetBased = 'TargetBased', //on target reached
100
+ Default = 'Default',
101
+ TargetBased = 'TargetBased',
102
+ }
103
+
104
+ export enum ColorTheme {
105
+ Blue = 'blue',
106
+ Green = 'green',
107
+ Purple = 'purple',
108
+ Orange = 'orange',
109
+ Silver = 'silver',
110
+ Gold = 'gold',
111
+ Pink = 'pink',
112
+ }
113
+
114
+ export enum PoseModelChoice {
115
+ AdaptiveChoice = 'AdaptiveChoice',
116
+ Prime = 'Prime',
117
+ Pro = 'Pro',
118
+ Lite = 'Lite',
119
+ UltraLite = 'UltraLite',
120
+ Basic = 'Basic',
121
+ }
122
+
123
+ export enum PhonePosition {
124
+ Floor = 'floor',
125
+ Elevated = 'elevated',
126
+ }
127
+
128
+ export enum RowingFeedbackLevel {
129
+ Expert = 'expert',
130
+ Advanced = 'advanced',
131
+ Beginner = 'beginner',
132
+ }
133
+
134
+ export enum GuidanceVideoSegmentKind {
135
+ Freeze = 'freeze',
136
+ Play = 'play',
102
137
  }
103
138
 
104
139
  export enum SkeletonPreset {
@@ -181,77 +216,108 @@ export class SkeletonConfig {
181
216
  animationDuration?: number;
182
217
  }
183
218
 
184
- /**
185
- * Class representing a workout.
186
- */
187
- export class SMWorkout {
188
- /**
189
- * @param {string | null} id - Unique identifier for the workout.
190
- * @param {string | null} name - Name of the workout.
191
- * @param {string | null} workoutIntro - URL for workout intro sound.
192
- * @param {string | null} soundtrack - URL for soundtrack.
193
- * @param {SMExercise[]} exercises - List of exercises included in the workout.
194
- * @param {string | null} getInFrame - URL for body cal get in frame sound.
195
- * @param {string | null} bodycalFinished - URL for body cal finished sound.
196
- * @param {string | null} workoutClosure - URL for workout closure sound.
197
- */
198
- id: string | null;
199
- name: string | null;
200
- workoutIntro: string | null;
201
- soundtrack: string | null;
202
- exercises: SMExercise[];
203
- getInFrame: string | null;
204
- bodycalFinished: string | null;
205
- workoutClosure: string | null;
219
+ export type QuickMotionParams = {
220
+ validityWindow?: number;
221
+ checkInterval?: number;
222
+ };
223
+
224
+ export type GuidanceVideoSegmentConfig = {
225
+ kind: GuidanceVideoSegmentKind | 'freeze' | 'play';
226
+ startSeconds: number;
227
+ endSeconds?: number | null;
228
+ };
229
+
230
+ export class GuidanceVideoSegment {
231
+ kind: GuidanceVideoSegmentKind | 'freeze' | 'play';
232
+ startSeconds: number;
233
+ endSeconds: number | null;
206
234
 
207
235
  constructor(
208
- id: string | null,
209
- name: string | null,
210
- workoutIntro: string | null,
211
- soundtrack: string | null,
212
- exercises: SMExercise[],
213
- getInFrame: string | null,
214
- bodycalFinished: string | null,
215
- workoutClosure: string | null
236
+ kind: GuidanceVideoSegmentKind | 'freeze' | 'play',
237
+ startSeconds: number,
238
+ endSeconds: number | null = null
216
239
  ) {
217
- this.id = id || null;
218
- this.name = name || null;
219
- this.workoutIntro = workoutIntro || null;
220
- this.soundtrack = soundtrack || null;
221
- this.exercises = exercises;
222
- this.getInFrame = getInFrame || null;
223
- this.bodycalFinished = bodycalFinished || null;
224
- this.workoutClosure = workoutClosure || null;
240
+ this.kind = kind;
241
+ this.startSeconds = startSeconds;
242
+ this.endSeconds = endSeconds;
225
243
  }
226
244
 
227
- toJson(): string {
228
- return JSON.stringify({
229
- id: this.id,
230
- name: this.name,
231
- workoutIntro: this.workoutIntro,
232
- soundtrack: this.soundtrack,
233
- exercises: this.exercises,
234
- getInFrame: this.getInFrame,
235
- bodycalFinished: this.bodycalFinished,
236
- workoutClosure: this.workoutClosure,
245
+ static freeze(at: number): GuidanceVideoSegment {
246
+ return new GuidanceVideoSegment(GuidanceVideoSegmentKind.Freeze, at, at);
247
+ }
248
+
249
+ static play(from: number, to: number | null = null): GuidanceVideoSegment {
250
+ return new GuidanceVideoSegment(GuidanceVideoSegmentKind.Play, from, to);
251
+ }
252
+
253
+ toJSON(): { [key: string]: JsonValue } {
254
+ return withoutUndefined({
255
+ kind: this.kind,
256
+ startSeconds: this.startSeconds,
257
+ endSeconds: this.endSeconds ?? undefined,
237
258
  });
238
259
  }
239
260
  }
240
261
 
241
- /**
242
- * Class representing an exercise in a workout.
243
- */
262
+ export type StretchSetConfigOptions = {
263
+ enabled?: boolean;
264
+ restSecondsBetweenStretches?: number;
265
+ introSoundKey?: string | null;
266
+ positionDetectors?: string[] | null;
267
+ };
268
+
269
+ export class StretchSetConfig {
270
+ enabled: boolean;
271
+ repetitions: number;
272
+ secondsPerStretch: number;
273
+ restSecondsBetweenStretches: number;
274
+ introSoundKey: string | null;
275
+ positionDetectors: string[] | null;
276
+
277
+ constructor(
278
+ repetitions: number,
279
+ secondsPerStretch: number,
280
+ options: StretchSetConfigOptions = {}
281
+ ) {
282
+ this.enabled = options.enabled ?? true;
283
+ this.repetitions = repetitions;
284
+ this.secondsPerStretch = secondsPerStretch;
285
+ this.restSecondsBetweenStretches = options.restSecondsBetweenStretches ?? 3;
286
+ this.introSoundKey = options.introSoundKey ?? null;
287
+ this.positionDetectors = options.positionDetectors ?? null;
288
+ }
289
+
290
+ toJSON(): { [key: string]: JsonValue } {
291
+ return withoutUndefined({
292
+ enabled: this.enabled,
293
+ repetitions: this.repetitions,
294
+ secondsPerStretch: this.secondsPerStretch,
295
+ restSecondsBetweenStretches: this.restSecondsBetweenStretches,
296
+ introSoundKey: this.introSoundKey,
297
+ positionDetectors: this.positionDetectors,
298
+ });
299
+ }
300
+ }
301
+
302
+ export type ExerciseOptions = {
303
+ shortIntro?: boolean;
304
+ quickMotionParams?: QuickMotionParams | null;
305
+ rowingFeedbackLevel?: RowingFeedbackLevel | number | null;
306
+ phonePosition?: PhonePosition | null;
307
+ guidanceMode?: boolean | null;
308
+ useWideAngleCamera?: boolean | null;
309
+ playPreExerciseCountdown?: boolean;
310
+ playRepMilestoneVoice?: boolean;
311
+ repMilestoneInterval?: number;
312
+ playSoundOnEachRep?: boolean;
313
+ adaptiveRomFeedbackEnabled?: boolean;
314
+ adaptiveRomWarmupReps?: number;
315
+ guidanceVideoSegments?: Record<string, GuidanceVideoSegment | GuidanceVideoSegmentConfig> | null;
316
+ stretchSetConfig?: StretchSetConfig | null;
317
+ side?: string | null;
318
+ };
319
+
244
320
  export class SMExercise {
245
- /**
246
- * @param {string | null} prettyName - Name of the exercise.
247
- * @param {number | null} totalSeconds - Duration of the exercise in seconds.
248
- * @param {string | null} videoInstruction - Video instruction URL.
249
- * @param {string | null} exerciseIntro - URL for exercise intro sound.
250
- * @param {UIElement[] | null} uiElements - List of UI elements for this exercise.
251
- * @param {string} detector - Name of the detector for tracking exercise movement.
252
- * @param {string | null} exerciseClosure - URL for exercise closer sound.
253
- * @param {SMScoringParams | null} scoringParams - Parameters for exercise scoring.
254
- */
255
321
  detector: string;
256
322
  uiElements: UIElement[] | null;
257
323
  videoInstruction: string | null;
@@ -260,6 +326,7 @@ export class SMExercise {
260
326
  exerciseIntro: string | null;
261
327
  exerciseClosure: string | null;
262
328
  scoringParams: SMScoringParams | null;
329
+ options: ExerciseOptions;
263
330
 
264
331
  constructor(
265
332
  prettyName: string | null,
@@ -269,39 +336,55 @@ export class SMExercise {
269
336
  uiElements: UIElement[] | null,
270
337
  detector: string,
271
338
  exerciseClosure: string | null,
272
- scoringParams: SMScoringParams | null
339
+ scoringParams: SMScoringParams | null,
340
+ options: ExerciseOptions = {}
273
341
  ) {
274
- this.prettyName = prettyName || null;
275
- this.totalSeconds = totalSeconds || null;
276
- this.videoInstruction = videoInstruction || null;
277
- this.exerciseIntro = exerciseIntro || null;
278
- this.uiElements = uiElements || null;
342
+ this.prettyName = prettyName ?? null;
343
+ this.totalSeconds = totalSeconds ?? null;
344
+ this.videoInstruction = videoInstruction ?? null;
345
+ this.exerciseIntro = exerciseIntro ?? null;
346
+ this.uiElements = uiElements ?? null;
279
347
  this.detector = detector;
280
- this.exerciseClosure = exerciseClosure || null;
281
- this.scoringParams = scoringParams || null;
348
+ this.exerciseClosure = exerciseClosure ?? null;
349
+ this.scoringParams = scoringParams ?? null;
350
+ this.options = options;
351
+ }
352
+
353
+ toJSON(): { [key: string]: JsonValue } {
354
+ return withoutUndefined({
355
+ name: this.prettyName,
356
+ prettyName: this.prettyName,
357
+ totalSeconds: this.totalSeconds,
358
+ videoInstruction: this.videoInstruction,
359
+ exerciseIntro: this.exerciseIntro,
360
+ uiElements: this.uiElements,
361
+ detector: this.detector,
362
+ exerciseClosure: this.exerciseClosure,
363
+ scoringParams: this.scoringParams?.toJSON() ?? null,
364
+ shortIntro: this.options.shortIntro,
365
+ quickMotionParams: this.options.quickMotionParams ?? undefined,
366
+ rowingFeedbackLevel: this.options.rowingFeedbackLevel ?? undefined,
367
+ phonePosition: this.options.phonePosition ?? undefined,
368
+ guidanceMode: this.options.guidanceMode ?? undefined,
369
+ useWideAngleCamera: this.options.useWideAngleCamera ?? undefined,
370
+ playPreExerciseCountdown: this.options.playPreExerciseCountdown,
371
+ playRepMilestoneVoice: this.options.playRepMilestoneVoice,
372
+ repMilestoneInterval: this.options.repMilestoneInterval,
373
+ playSoundOnEachRep: this.options.playSoundOnEachRep,
374
+ adaptiveRomFeedbackEnabled: this.options.adaptiveRomFeedbackEnabled,
375
+ adaptiveRomWarmupReps: this.options.adaptiveRomWarmupReps,
376
+ guidanceVideoSegments: this.options.guidanceVideoSegments === null
377
+ ? null
378
+ : serializeGuidanceVideoSegments(this.options.guidanceVideoSegments),
379
+ stretchSetConfig: this.options.stretchSetConfig?.toJSON() ?? (this.options.stretchSetConfig === null ? null : undefined),
380
+ side: this.options.side ?? undefined,
381
+ });
282
382
  }
283
383
  }
284
384
 
285
- /**
286
- * Class representing an exercise in an assessment.
287
- */
288
- export class SMAssessmentExercise extends SMExercise {
289
- /**
290
- * @param {string | null} prettyName - Name of the exercise.
291
- * @param {number | null} totalSeconds - Duration of the exercise in seconds.
292
- * @param {string | null} videoInstruction - Video instruction URL.
293
- * @param {string | null} exerciseIntro - URL for exercise intro sound.
294
- * @param {UIElement[] | null} uiElements - List of UI elements for this exercise.
295
- * @param {string} detector - Name of the detector for tracking exercise movement.
296
- * @param {string | null} exerciseClosure - URL for exercise closer sound.
297
- * @param {SMScoringParams | null} scoringParams - Parameters for exercise scoring.
298
- * @param {string | null} closureFailedSound - Applicable only for ClouserTarget.TargetBased, URL for exercise closure sound If you did not reach clouser target.
299
- * @param {string | null} summaryTitle - Title for the exercise summary.
300
- * @param {string | null} summarySubTitle - Subtitle for the exercise summary.
301
- * @param {string | null} summaryMainMetricTitle - Main metric title in the summary.
302
- * @param {string | null} summaryMainMetricSubTitle - Main metric subtitle in the summary.
303
- */
385
+ export type AssessmentExerciseOptions = ExerciseOptions;
304
386
 
387
+ export class SMAssessmentExercise extends SMExercise {
305
388
  closureFailedSound: string | null;
306
389
  summaryTitle: string | null;
307
390
  summarySubTitle: string | null;
@@ -321,9 +404,9 @@ export class SMAssessmentExercise extends SMExercise {
321
404
  summaryTitle: string | null,
322
405
  summarySubTitle: string | null,
323
406
  summaryMainMetricTitle: string | null,
324
- summaryMainMetricSubTitle: string | null
407
+ summaryMainMetricSubTitle: string | null,
408
+ options: AssessmentExerciseOptions = {}
325
409
  ) {
326
- // Call the constructor of the parent class (SMExercise)
327
410
  super(
328
411
  prettyName,
329
412
  totalSeconds,
@@ -332,30 +415,108 @@ export class SMAssessmentExercise extends SMExercise {
332
415
  uiElements,
333
416
  detector,
334
417
  exerciseClosure,
335
- scoringParams
418
+ scoringParams,
419
+ options
336
420
  );
337
421
 
338
- // Set additional properties specific to SMAssessmentExercise
339
- this.closureFailedSound = closureFailedSound || null;
340
- this.summaryTitle = summaryTitle || null;
341
- this.summarySubTitle = summarySubTitle || null;
342
- this.summaryMainMetricTitle = summaryMainMetricTitle || null;
343
- this.summaryMainMetricSubTitle = summaryMainMetricSubTitle || null;
422
+ this.closureFailedSound = closureFailedSound ?? null;
423
+ this.summaryTitle = summaryTitle ?? null;
424
+ this.summarySubTitle = summarySubTitle ?? null;
425
+ this.summaryMainMetricTitle = summaryMainMetricTitle ?? null;
426
+ this.summaryMainMetricSubTitle = summaryMainMetricSubTitle ?? null;
427
+ }
428
+
429
+ override toJSON(): { [key: string]: JsonValue } {
430
+ return withoutUndefined({
431
+ ...super.toJSON(),
432
+ closureFailedSound: this.closureFailedSound,
433
+ summaryTitle: this.summaryTitle,
434
+ summarySubTitle: this.summarySubTitle,
435
+ summaryMainMetricTitle: this.summaryMainMetricTitle,
436
+ summaryMainMetricSubTitle: this.summaryMainMetricSubTitle,
437
+ summaryTitleMainMetric: this.summaryMainMetricTitle,
438
+ summarySubTitleMainMetric: this.summaryMainMetricSubTitle,
439
+ });
440
+ }
441
+ }
442
+
443
+ export class WorkoutContinuation {
444
+ introSoundKey: string | null;
445
+ interactionUnlockSoundKey: string;
446
+ exercises: SMExercise[];
447
+
448
+ constructor(
449
+ interactionUnlockSoundKey: string,
450
+ exercises: SMExercise[],
451
+ introSoundKey: string | null = null
452
+ ) {
453
+ this.introSoundKey = introSoundKey ?? null;
454
+ this.interactionUnlockSoundKey = interactionUnlockSoundKey;
455
+ this.exercises = exercises;
456
+ }
457
+
458
+ toJSON(): { [key: string]: JsonValue } {
459
+ return withoutUndefined({
460
+ introSoundKey: this.introSoundKey,
461
+ interactionUnlockSoundKey: this.interactionUnlockSoundKey,
462
+ exercises: this.exercises.map((exercise) => exercise.toJSON()),
463
+ });
464
+ }
465
+ }
466
+
467
+ export class SMWorkout {
468
+ id: string | null;
469
+ name: string | null;
470
+ workoutIntro: string | null;
471
+ soundtrack: string | null;
472
+ exercises: SMExercise[];
473
+ getInFrame: string | null;
474
+ bodycalFinished: string | null;
475
+ workoutClosure: string | null;
476
+ continuation: WorkoutContinuation | null;
477
+
478
+ constructor(
479
+ id: string | null,
480
+ name: string | null,
481
+ workoutIntro: string | null,
482
+ soundtrack: string | null,
483
+ exercises: SMExercise[],
484
+ getInFrame: string | null,
485
+ bodycalFinished: string | null,
486
+ workoutClosure: string | null,
487
+ continuation: WorkoutContinuation | null = null
488
+ ) {
489
+ this.id = id ?? null;
490
+ this.name = name ?? null;
491
+ this.workoutIntro = workoutIntro ?? null;
492
+ this.soundtrack = soundtrack ?? null;
493
+ this.exercises = exercises;
494
+ this.getInFrame = getInFrame ?? null;
495
+ this.bodycalFinished = bodycalFinished ?? null;
496
+ this.workoutClosure = workoutClosure ?? null;
497
+ this.continuation = continuation ?? null;
498
+ }
499
+
500
+ toJSON(): { [key: string]: JsonValue } {
501
+ return withoutUndefined({
502
+ id: this.id,
503
+ name: this.name,
504
+ workoutIntro: this.workoutIntro,
505
+ soundtrack: this.soundtrack,
506
+ exercises: this.exercises.map((exercise) => exercise.toJSON()),
507
+ getInFrame: this.getInFrame,
508
+ bodycalFinished: this.bodycalFinished,
509
+ workoutClosure: this.workoutClosure,
510
+ continuation: this.continuation?.toJSON() ?? (this.continuation === null ? null : undefined),
511
+ });
512
+ }
513
+
514
+ toJson(): string {
515
+ return JSON.stringify(this.toJSON());
344
516
  }
345
517
  }
346
518
 
347
- /**
348
- * Class representing scoring parameters for an exercise.
349
- */
350
519
  export class SMScoringParams {
351
- /**
352
- * @param {ScoringType | null} type - Type of scoring (e.g., ROM, time, reps).
353
- * @param {number | null} scoreFactor - Factor to adjust the score.
354
- * @param {number | null} targetTime - Target time for time-based scoring.
355
- * @param {number | null} targetReps - Target reps for rep-based scoring.
356
- * @param {string | null} targetRom - Range of motion target for ROM-based scoring.
357
- * @param {string[] | null} passCriteria - List of criteria required to pass.
358
- */
359
520
  type: ScoringType | null;
360
521
  scoreFactor: number | null;
361
522
  targetTime: number | null;
@@ -371,33 +532,40 @@ export class SMScoringParams {
371
532
  targetRom: string | null,
372
533
  passCriteria: string[] | null
373
534
  ) {
374
- this.type = type || null;
375
- this.scoreFactor = scoreFactor || null;
376
- this.targetTime = targetTime || null;
377
- this.targetReps = targetReps || null;
378
- this.targetRom = targetRom || null;
379
- this.passCriteria = passCriteria || null;
535
+ this.type = type ?? null;
536
+ this.scoreFactor = scoreFactor ?? null;
537
+ this.targetTime = targetTime ?? null;
538
+ this.targetReps = targetReps ?? null;
539
+ this.targetRom = targetRom ?? null;
540
+ this.passCriteria = passCriteria ?? null;
541
+ }
542
+
543
+ toJSON(): { [key: string]: JsonValue } {
544
+ return withoutUndefined({
545
+ type: this.type,
546
+ scoreFactor: this.scoreFactor,
547
+ targetTime: this.targetTime,
548
+ targetReps: this.targetReps,
549
+ targetRom: this.targetRom,
550
+ passCriteria: this.passCriteria,
551
+ });
380
552
  }
381
553
  }
382
554
 
383
- /**
384
- * Class representing the configuration for a workout program.
385
- */
555
+ export type WorkoutConfigOptions = {
556
+ phonePosition?: PhonePosition;
557
+ shortIntro?: boolean;
558
+ };
559
+
386
560
  export class WorkoutConfig {
387
- /**
388
- * @param {number} week - Week number in the program.
389
- * @param {BodyZone} bodyZone - Targeted body zone for the workout.
390
- * @param {WorkoutDifficulty} difficultyLevel - Difficulty level of the workout.
391
- * @param {WorkoutDuration} workoutDuration - Duration of the workout.
392
- * @param {Language} language - The session language
393
- * @param {string} programID - Unique identifier for the workout program.
394
- */
395
561
  week: number;
396
562
  bodyZone: BodyZone;
397
563
  difficultyLevel: WorkoutDifficulty;
398
564
  workoutDuration: WorkoutDuration;
399
565
  language: Language;
400
566
  programID: string;
567
+ phonePosition: PhonePosition;
568
+ shortIntro: boolean;
401
569
 
402
570
  constructor(
403
571
  week: number,
@@ -405,7 +573,8 @@ export class WorkoutConfig {
405
573
  difficultyLevel: WorkoutDifficulty,
406
574
  workoutDuration: WorkoutDuration,
407
575
  language: Language,
408
- programID: string
576
+ programID: string,
577
+ options: WorkoutConfigOptions = {}
409
578
  ) {
410
579
  this.week = week;
411
580
  this.bodyZone = bodyZone;
@@ -413,40 +582,48 @@ export class WorkoutConfig {
413
582
  this.workoutDuration = workoutDuration;
414
583
  this.language = language;
415
584
  this.programID = programID;
585
+ this.phonePosition = options.phonePosition ?? PhonePosition.Floor;
586
+ this.shortIntro = options.shortIntro ?? false;
416
587
  }
417
588
 
418
- toJson(): string {
419
- return JSON.stringify({
589
+ toJSON(): { [key: string]: JsonValue } {
590
+ return withoutUndefined({
420
591
  week: this.week,
421
592
  bodyZone: this.bodyZone,
422
593
  difficultyLevel: this.difficultyLevel,
423
594
  workoutDuration: this.workoutDuration,
424
595
  language: this.language,
425
596
  programID: this.programID,
597
+ phonePosition: this.phonePosition,
598
+ shortIntro: this.shortIntro,
426
599
  });
427
600
  }
601
+
602
+ toJson(): string {
603
+ return JSON.stringify(this.toJSON());
604
+ }
428
605
  }
429
606
 
430
- /**
431
- * Class representing user data.
432
- */
433
607
  export class UserData {
434
- /**
435
- * @param {Gender} gender - User's gender.
436
- * @param {number} age - User's age.
437
- */
438
608
  gender: Gender;
439
609
  age: number;
610
+ email: string | null;
440
611
 
441
- constructor(gender: Gender, age: number) {
612
+ constructor(gender: Gender, age: number, email: string | null = null) {
442
613
  this.gender = gender;
443
614
  this.age = age;
615
+ this.email = email ?? null;
444
616
  }
445
617
 
446
- toJson(): string {
447
- return JSON.stringify({
618
+ toJSON(): { [key: string]: JsonValue } {
619
+ return withoutUndefined({
448
620
  gender: this.gender,
449
621
  age: this.age,
622
+ email: this.email,
450
623
  });
451
624
  }
625
+
626
+ toJson(): string {
627
+ return JSON.stringify(this.toJSON());
628
+ }
452
629
  }