sonarfit-react-native 1.0.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.
- package/README.md +153 -0
- package/ios/SonarFitReactNative-Bridging-Header.h +9 -0
- package/ios/SonarFitReactNative.h +5 -0
- package/ios/SonarFitReactNative.m +14 -0
- package/ios/SonarFitReactNative.swift +148 -0
- package/lib/index.d.ts +93 -0
- package/lib/index.js +70 -0
- package/package.json +47 -0
- package/sonarfit-react-native.podspec +24 -0
package/README.md
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# sonarfit-react-native
|
|
2
|
+
|
|
3
|
+
React Native integration for SonarFit SDK - AI-powered workout rep counting for iOS
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- AI-powered rep counting for squats, deadlifts, and bench press
|
|
8
|
+
- Real-time workout tracking
|
|
9
|
+
- Support for Apple Watch and AirPods motion sensors
|
|
10
|
+
- Native iOS integration with React Native bridge
|
|
11
|
+
- TypeScript support
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install sonarfit-react-native
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### iOS Setup
|
|
20
|
+
|
|
21
|
+
1. Install CocoaPods dependencies:
|
|
22
|
+
```bash
|
|
23
|
+
cd ios && pod install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
2. The SonarFit SDK requires iOS 17.0 or higher. Make sure your `Podfile` has:
|
|
27
|
+
```ruby
|
|
28
|
+
platform :ios, '17.0'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Usage
|
|
32
|
+
|
|
33
|
+
### Initialize the SDK
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import SonarFitSDK from 'sonarfit-react-native';
|
|
37
|
+
|
|
38
|
+
// Initialize with your API key when your app starts
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const initSDK = async () => {
|
|
41
|
+
try {
|
|
42
|
+
await SonarFitSDK.initialize('your-api-key-here');
|
|
43
|
+
console.log('SonarFit SDK initialized');
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('Failed to initialize SonarFit SDK:', error);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
initSDK();
|
|
50
|
+
}, []);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Start a Workout
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import SonarFitSDK, { WorkoutConfig } from 'sonarfit-react-native';
|
|
57
|
+
|
|
58
|
+
const startWorkout = async () => {
|
|
59
|
+
const config: WorkoutConfig = {
|
|
60
|
+
workoutType: 'squat', // 'squat' | 'deadlift' | 'benchpress'
|
|
61
|
+
sets: 3,
|
|
62
|
+
reps: 10,
|
|
63
|
+
restTime: 60, // seconds
|
|
64
|
+
countdownDuration: 3, // seconds
|
|
65
|
+
autoReLift: true,
|
|
66
|
+
deviceType: 'none', // 'none' | 'watch' | 'airpods'
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const result = await SonarFitSDK.presentWorkout(config);
|
|
71
|
+
|
|
72
|
+
if (result.completed) {
|
|
73
|
+
console.log(`Completed ${result.totalRepsCompleted}/${result.totalTargetReps} reps`);
|
|
74
|
+
console.log(`Duration: ${result.totalDuration}s`);
|
|
75
|
+
console.log(`Sets:`, result.sets);
|
|
76
|
+
} else if (result.cancelled) {
|
|
77
|
+
console.log('Workout cancelled');
|
|
78
|
+
}
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error('Workout error:', error);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Reference
|
|
86
|
+
|
|
87
|
+
### `SonarFitSDK.initialize(apiKey: string): Promise<void>`
|
|
88
|
+
|
|
89
|
+
Initialize the SonarFit SDK with your API key.
|
|
90
|
+
|
|
91
|
+
**Parameters:**
|
|
92
|
+
- `apiKey`: Your SonarFit API key
|
|
93
|
+
|
|
94
|
+
### `SonarFitSDK.presentWorkout(config: WorkoutConfig): Promise<WorkoutResult>`
|
|
95
|
+
|
|
96
|
+
Present the SonarFit workout UI.
|
|
97
|
+
|
|
98
|
+
**Parameters:**
|
|
99
|
+
- `config`: Workout configuration
|
|
100
|
+
|
|
101
|
+
**Returns:**
|
|
102
|
+
- `Promise<WorkoutResult>`: Workout results when complete or cancelled
|
|
103
|
+
|
|
104
|
+
### Types
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
interface WorkoutConfig {
|
|
108
|
+
workoutType: 'squat' | 'deadlift' | 'benchpress';
|
|
109
|
+
sets: number;
|
|
110
|
+
reps: number;
|
|
111
|
+
restTime?: number; // default: 60
|
|
112
|
+
countdownDuration?: number; // default: 3
|
|
113
|
+
autoReLift?: boolean; // default: true
|
|
114
|
+
deviceType?: 'none' | 'watch' | 'airpods'; // default: 'none'
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface WorkoutResult {
|
|
118
|
+
completed: boolean;
|
|
119
|
+
cancelled?: boolean;
|
|
120
|
+
workoutType?: string;
|
|
121
|
+
deviceType?: string;
|
|
122
|
+
startTime?: number;
|
|
123
|
+
endTime?: number;
|
|
124
|
+
totalDuration?: number;
|
|
125
|
+
completionPercentage?: number;
|
|
126
|
+
targetSets?: number;
|
|
127
|
+
targetRepsPerSet?: number;
|
|
128
|
+
totalRepsCompleted?: number;
|
|
129
|
+
totalTargetReps?: number;
|
|
130
|
+
sets?: Array<{
|
|
131
|
+
setNumber: number;
|
|
132
|
+
repsCompleted: number;
|
|
133
|
+
}>;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Requirements
|
|
138
|
+
|
|
139
|
+
- React Native >= 0.60
|
|
140
|
+
- iOS >= 17.0
|
|
141
|
+
- Xcode >= 15.0
|
|
142
|
+
|
|
143
|
+
## Example
|
|
144
|
+
|
|
145
|
+
See the [example](./example) directory for a complete working example app.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT
|
|
150
|
+
|
|
151
|
+
## Support
|
|
152
|
+
|
|
153
|
+
For issues and questions, please visit [GitHub Issues](https://github.com/sonarfit/sonarfit-react-native/issues)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import "SonarFitReactNative.h"
|
|
2
|
+
#import <React/RCTBridgeModule.h>
|
|
3
|
+
|
|
4
|
+
@interface RCT_EXTERN_MODULE(SonarFitSDKModule, NSObject)
|
|
5
|
+
|
|
6
|
+
RCT_EXTERN_METHOD(initialize:(NSString *)apiKey
|
|
7
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
8
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
9
|
+
|
|
10
|
+
RCT_EXTERN_METHOD(presentWorkout:(NSDictionary *)config
|
|
11
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
12
|
+
rejecter:(RCTPromiseRejectBlock)reject)
|
|
13
|
+
|
|
14
|
+
@end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import React
|
|
3
|
+
import SonarFitKit
|
|
4
|
+
|
|
5
|
+
@objc(SonarFitSDKModule)
|
|
6
|
+
class SonarFitSDKModule: NSObject {
|
|
7
|
+
|
|
8
|
+
@objc
|
|
9
|
+
static func requiresMainQueueSetup() -> Bool {
|
|
10
|
+
return true
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@objc
|
|
14
|
+
func initialize(_ apiKey: String,
|
|
15
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
16
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
17
|
+
|
|
18
|
+
SonarFitSDK.initialize(apiKey: apiKey) { success, error in
|
|
19
|
+
if success {
|
|
20
|
+
resolve(true)
|
|
21
|
+
} else {
|
|
22
|
+
reject("E_INIT_FAILED", "Failed to initialize SonarFit SDK: \(error?.localizedDescription ?? "Unknown error")", error)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@objc
|
|
28
|
+
func presentWorkout(_ config: NSDictionary,
|
|
29
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
30
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
31
|
+
|
|
32
|
+
DispatchQueue.main.async {
|
|
33
|
+
guard let rootViewController = RCTKeyWindow()?.rootViewController else {
|
|
34
|
+
reject("E_NO_ROOT_VC", "Cannot find root view controller", nil)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Parse workout configuration
|
|
39
|
+
guard let workoutConfig = self.parseWorkoutConfig(config) else {
|
|
40
|
+
reject("E_INVALID_CONFIG", "Invalid workout configuration", nil)
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Present SonarFit workout
|
|
45
|
+
SonarFit.startWorkout(
|
|
46
|
+
config: workoutConfig,
|
|
47
|
+
from: rootViewController,
|
|
48
|
+
onCompletion: { result in
|
|
49
|
+
if let result = result {
|
|
50
|
+
// Convert WorkoutResult to dictionary
|
|
51
|
+
let resultDict: [String: Any] = [
|
|
52
|
+
"completed": result.status == .completed,
|
|
53
|
+
"workoutType": result.workoutType.rawValue,
|
|
54
|
+
"deviceType": result.deviceType.rawValue,
|
|
55
|
+
"startTime": result.startTime.timeIntervalSince1970,
|
|
56
|
+
"endTime": result.endTime.timeIntervalSince1970,
|
|
57
|
+
"totalDuration": result.totalDuration,
|
|
58
|
+
"completionPercentage": result.completionPercentage,
|
|
59
|
+
"targetSets": result.targetSets,
|
|
60
|
+
"targetRepsPerSet": result.targetRepsPerSet,
|
|
61
|
+
"totalRepsCompleted": result.totalRepsCompleted,
|
|
62
|
+
"totalTargetReps": result.totalTargetReps,
|
|
63
|
+
"sets": result.sets.map { set in
|
|
64
|
+
return [
|
|
65
|
+
"setNumber": set.setNumber,
|
|
66
|
+
"repsCompleted": set.repsCompleted
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
resolve(resultDict)
|
|
71
|
+
} else {
|
|
72
|
+
// Workout cancelled
|
|
73
|
+
resolve([
|
|
74
|
+
"completed": false,
|
|
75
|
+
"cancelled": true
|
|
76
|
+
])
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
onPermissionError: { error in
|
|
80
|
+
reject("E_PERMISSION", error.localizedDescription, error)
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private func parseWorkoutConfig(_ config: NSDictionary) -> WorkoutConfig? {
|
|
87
|
+
guard let workoutTypeString = config["workoutType"] as? String else {
|
|
88
|
+
return nil
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let workoutType: WorkoutType
|
|
92
|
+
switch workoutTypeString.lowercased() {
|
|
93
|
+
case "squat":
|
|
94
|
+
workoutType = .squat
|
|
95
|
+
case "deadlift":
|
|
96
|
+
workoutType = .deadlift
|
|
97
|
+
case "benchpress":
|
|
98
|
+
workoutType = .benchpress
|
|
99
|
+
default:
|
|
100
|
+
return nil
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
guard let sets = config["sets"] as? Int,
|
|
104
|
+
let reps = config["reps"] as? Int else {
|
|
105
|
+
return nil
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let restTime = config["restTime"] as? Int ?? 60
|
|
109
|
+
let countdownDuration = config["countdownDuration"] as? Int ?? 3
|
|
110
|
+
let autoReLift = config["autoReLift"] as? Bool ?? true
|
|
111
|
+
|
|
112
|
+
let deviceType: DeviceType
|
|
113
|
+
if let deviceTypeString = config["deviceType"] as? String {
|
|
114
|
+
switch deviceTypeString.lowercased() {
|
|
115
|
+
case "watch":
|
|
116
|
+
deviceType = .watch
|
|
117
|
+
case "airpods":
|
|
118
|
+
deviceType = .airpods
|
|
119
|
+
default:
|
|
120
|
+
deviceType = .none
|
|
121
|
+
}
|
|
122
|
+
} else {
|
|
123
|
+
deviceType = .none
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return WorkoutConfig(
|
|
127
|
+
workoutType: workoutType,
|
|
128
|
+
sets: sets,
|
|
129
|
+
reps: reps,
|
|
130
|
+
restTime: restTime,
|
|
131
|
+
countdownDuration: countdownDuration,
|
|
132
|
+
autoReLift: autoReLift,
|
|
133
|
+
deviceType: deviceType
|
|
134
|
+
)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Helper to get key window
|
|
139
|
+
func RCTKeyWindow() -> UIWindow? {
|
|
140
|
+
if #available(iOS 13.0, *) {
|
|
141
|
+
return UIApplication.shared.connectedScenes
|
|
142
|
+
.compactMap { $0 as? UIWindowScene }
|
|
143
|
+
.flatMap { $0.windows }
|
|
144
|
+
.first { $0.isKeyWindow }
|
|
145
|
+
} else {
|
|
146
|
+
return UIApplication.shared.keyWindow
|
|
147
|
+
}
|
|
148
|
+
}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export type WorkoutType = 'squat' | 'deadlift' | 'benchpress';
|
|
2
|
+
export type DeviceType = 'none' | 'watch' | 'airpods';
|
|
3
|
+
export interface WorkoutConfig {
|
|
4
|
+
/** Type of workout exercise */
|
|
5
|
+
workoutType: WorkoutType;
|
|
6
|
+
/** Number of sets to complete */
|
|
7
|
+
sets: number;
|
|
8
|
+
/** Target reps per set */
|
|
9
|
+
reps: number;
|
|
10
|
+
/** Rest time between sets in seconds (default: 60) */
|
|
11
|
+
restTime?: number;
|
|
12
|
+
/** Countdown before each set in seconds (default: 3) */
|
|
13
|
+
countdownDuration?: number;
|
|
14
|
+
/** Automatically start next set after countdown (default: true) */
|
|
15
|
+
autoReLift?: boolean;
|
|
16
|
+
/** Device type to use for motion tracking (default: 'none' for auto-detect) */
|
|
17
|
+
deviceType?: DeviceType;
|
|
18
|
+
}
|
|
19
|
+
export interface WorkoutSet {
|
|
20
|
+
/** Set number (1-indexed) */
|
|
21
|
+
setNumber: number;
|
|
22
|
+
/** Number of reps completed in this set */
|
|
23
|
+
repsCompleted: number;
|
|
24
|
+
}
|
|
25
|
+
export interface WorkoutResult {
|
|
26
|
+
/** Whether the workout was completed successfully */
|
|
27
|
+
completed: boolean;
|
|
28
|
+
/** Whether the workout was cancelled by user */
|
|
29
|
+
cancelled?: boolean;
|
|
30
|
+
/** Type of workout performed */
|
|
31
|
+
workoutType?: WorkoutType;
|
|
32
|
+
/** Device used for motion tracking */
|
|
33
|
+
deviceType?: DeviceType;
|
|
34
|
+
/** Workout start timestamp (Unix epoch) */
|
|
35
|
+
startTime?: number;
|
|
36
|
+
/** Workout end timestamp (Unix epoch) */
|
|
37
|
+
endTime?: number;
|
|
38
|
+
/** Total workout duration in seconds */
|
|
39
|
+
totalDuration?: number;
|
|
40
|
+
/** Percentage of target reps completed (0.0 to 1.0) */
|
|
41
|
+
completionPercentage?: number;
|
|
42
|
+
/** Target number of sets */
|
|
43
|
+
targetSets?: number;
|
|
44
|
+
/** Target reps per set */
|
|
45
|
+
targetRepsPerSet?: number;
|
|
46
|
+
/** Total reps completed across all sets */
|
|
47
|
+
totalRepsCompleted?: number;
|
|
48
|
+
/** Total target reps for the workout */
|
|
49
|
+
totalTargetReps?: number;
|
|
50
|
+
/** Array of completed sets with rep counts */
|
|
51
|
+
sets?: WorkoutSet[];
|
|
52
|
+
}
|
|
53
|
+
export declare class SonarFitSDK {
|
|
54
|
+
/**
|
|
55
|
+
* Initialize the SonarFit SDK with your API key
|
|
56
|
+
* @param apiKey Your SonarFit API key
|
|
57
|
+
* @returns Promise that resolves when initialization is complete
|
|
58
|
+
* @throws Error if native module is not available or initialization fails
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* await SonarFitSDK.initialize('your-api-key-here');
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
static initialize(apiKey: string): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Present the SonarFit workout UI modally
|
|
68
|
+
* @param config Workout configuration
|
|
69
|
+
* @returns Promise that resolves with workout result when workout completes or is cancelled
|
|
70
|
+
* @throws Error if native module is not available or workout fails
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* const result = await SonarFitSDK.presentWorkout({
|
|
75
|
+
* workoutType: 'squat',
|
|
76
|
+
* sets: 3,
|
|
77
|
+
* reps: 10,
|
|
78
|
+
* restTime: 60
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* if (result.completed) {
|
|
82
|
+
* console.log(`Completed ${result.totalRepsCompleted}/${result.totalTargetReps} reps`);
|
|
83
|
+
* }
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
static presentWorkout(config: WorkoutConfig): Promise<WorkoutResult>;
|
|
87
|
+
/**
|
|
88
|
+
* Check if SonarFit SDK is available on this platform
|
|
89
|
+
* @returns true if the native module is available, false otherwise
|
|
90
|
+
*/
|
|
91
|
+
static isAvailable(): boolean;
|
|
92
|
+
}
|
|
93
|
+
export default SonarFitSDK;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SonarFitSDK = void 0;
|
|
4
|
+
const react_native_1 = require("react-native");
|
|
5
|
+
const { SonarFitSDKModule } = react_native_1.NativeModules;
|
|
6
|
+
class SonarFitSDK {
|
|
7
|
+
/**
|
|
8
|
+
* Initialize the SonarFit SDK with your API key
|
|
9
|
+
* @param apiKey Your SonarFit API key
|
|
10
|
+
* @returns Promise that resolves when initialization is complete
|
|
11
|
+
* @throws Error if native module is not available or initialization fails
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* await SonarFitSDK.initialize('your-api-key-here');
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
static async initialize(apiKey) {
|
|
19
|
+
if (!SonarFitSDKModule) {
|
|
20
|
+
throw new Error('SonarFitSDK native module not found. Make sure you have installed the native dependencies.');
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
await SonarFitSDKModule.initialize(apiKey);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
throw new Error(`SonarFit initialization failed: ${(error === null || error === void 0 ? void 0 : error.message) || error}`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Present the SonarFit workout UI modally
|
|
31
|
+
* @param config Workout configuration
|
|
32
|
+
* @returns Promise that resolves with workout result when workout completes or is cancelled
|
|
33
|
+
* @throws Error if native module is not available or workout fails
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* const result = await SonarFitSDK.presentWorkout({
|
|
38
|
+
* workoutType: 'squat',
|
|
39
|
+
* sets: 3,
|
|
40
|
+
* reps: 10,
|
|
41
|
+
* restTime: 60
|
|
42
|
+
* });
|
|
43
|
+
*
|
|
44
|
+
* if (result.completed) {
|
|
45
|
+
* console.log(`Completed ${result.totalRepsCompleted}/${result.totalTargetReps} reps`);
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
static async presentWorkout(config) {
|
|
50
|
+
if (!SonarFitSDKModule) {
|
|
51
|
+
throw new Error('SonarFitSDK native module not found. Make sure you have installed the native dependencies.');
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
const result = await SonarFitSDKModule.presentWorkout(config);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
throw new Error(`SonarFit workout failed: ${(error === null || error === void 0 ? void 0 : error.message) || error}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Check if SonarFit SDK is available on this platform
|
|
63
|
+
* @returns true if the native module is available, false otherwise
|
|
64
|
+
*/
|
|
65
|
+
static isAvailable() {
|
|
66
|
+
return SonarFitSDKModule != null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.SonarFitSDK = SonarFitSDK;
|
|
70
|
+
exports.default = SonarFitSDK;
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sonarfit-react-native",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "React Native integration for SonarFit SDK - AI-powered workout rep counting",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
|
+
"types": "lib/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepare": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"react-native",
|
|
13
|
+
"fitness",
|
|
14
|
+
"workout",
|
|
15
|
+
"ai",
|
|
16
|
+
"motion-tracking",
|
|
17
|
+
"rep-counting",
|
|
18
|
+
"sonarfit"
|
|
19
|
+
],
|
|
20
|
+
"author": "SonarFit",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"homepage": "https://github.com/sonarfit/sonarfit-react-native",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/sonarfit/sonarfit-react-native.git"
|
|
26
|
+
},
|
|
27
|
+
"bugs": {
|
|
28
|
+
"url": "https://github.com/sonarfit/sonarfit-react-native/issues"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": ">=16.8.0",
|
|
32
|
+
"react-native": ">=0.60.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/react": "^18.0.0",
|
|
36
|
+
"@types/react-native": "^0.72.0",
|
|
37
|
+
"typescript": "^5.0.0"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"lib/",
|
|
41
|
+
"ios/",
|
|
42
|
+
"android/",
|
|
43
|
+
"sonarfit-react-native.podspec",
|
|
44
|
+
"README.md"
|
|
45
|
+
],
|
|
46
|
+
"react-native": "lib/index.js"
|
|
47
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "sonarfit-react-native"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => "17.0" }
|
|
14
|
+
s.source = { :git => "https://github.com/sonarfit/sonarfit-react-native.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
|
+
s.requires_arc = true
|
|
18
|
+
|
|
19
|
+
s.dependency "React-Core"
|
|
20
|
+
s.dependency "SonarFitKit-Vendored"
|
|
21
|
+
|
|
22
|
+
# Swift version
|
|
23
|
+
s.swift_version = "5.9"
|
|
24
|
+
end
|