react-native-mytatva-rn-sdk 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.
Files changed (35) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +31 -0
  3. package/android/build.gradle +112 -0
  4. package/android/gradle.properties +5 -0
  5. package/android/src/main/AndroidManifest.xml +3 -0
  6. package/android/src/main/AndroidManifestNew.xml +2 -0
  7. package/android/src/main/java/com/visitrnsdk/VisitRnSdkPackage.kt +17 -0
  8. package/android/src/main/java/com/visitrnsdk/VisitRnSdkViewManager.kt +20 -0
  9. package/ios/VisitRnSdk.xcodeproj/project.pbxproj +274 -0
  10. package/ios/VisitRnSdkViewManager.h +20 -0
  11. package/ios/VisitRnSdkViewManager.m +1240 -0
  12. package/lib/commonjs/Services.js +35 -0
  13. package/lib/commonjs/Services.js.map +1 -0
  14. package/lib/commonjs/constants.js +11 -0
  15. package/lib/commonjs/constants.js.map +1 -0
  16. package/lib/commonjs/index.android.js +518 -0
  17. package/lib/commonjs/index.android.js.map +1 -0
  18. package/lib/commonjs/index.ios.js +313 -0
  19. package/lib/commonjs/index.ios.js.map +1 -0
  20. package/lib/module/Services.js +27 -0
  21. package/lib/module/Services.js.map +1 -0
  22. package/lib/module/constants.js +5 -0
  23. package/lib/module/constants.js.map +1 -0
  24. package/lib/module/index.android.js +508 -0
  25. package/lib/module/index.android.js.map +1 -0
  26. package/lib/module/index.ios.js +304 -0
  27. package/lib/module/index.ios.js.map +1 -0
  28. package/lib/typescript/index.test.d.ts +1 -0
  29. package/lib/typescript/index.test.d.ts.map +1 -0
  30. package/package.json +177 -0
  31. package/react-native-visit-rn-sdk.podspec +42 -0
  32. package/src/Services.js +37 -0
  33. package/src/constants.js +4 -0
  34. package/src/index.android.js +714 -0
  35. package/src/index.ios.js +376 -0
@@ -0,0 +1,1240 @@
1
+ #import "MyTatvaRnSdkViewManager.h"
2
+
3
+ @implementation MyTatvaRnSdkViewManager
4
+
5
+ RCT_EXPORT_MODULE(MyTatvaRnSdkViewManager)
6
+
7
+ // Example method
8
+ // See // https://reactnative.dev/docs/native-modules-ios
9
+ RCT_REMAP_METHOD(multiply,
10
+ multiplyWithA:(nonnull NSNumber*)a withB:(nonnull NSNumber*)b
11
+ withResolver:(RCTPromiseResolveBlock)resolve
12
+ withRejecter:(RCTPromiseRejectBlock)reject)
13
+ {
14
+ NSNumber *result = @([a floatValue] * [b floatValue]);
15
+
16
+ resolve(result);
17
+ }
18
+
19
+ - (instancetype)init
20
+ {
21
+ self = [super init];
22
+ self->calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierISO8601];
23
+ self->calendar.timeZone = [NSTimeZone timeZoneWithName:@"IST"];
24
+ NSLog(@"Do some stuff here");
25
+ return self;
26
+ }
27
+
28
+ + (BOOL)requiresMainQueueSetup{
29
+ return YES;
30
+ }
31
+
32
+ + (HKHealthStore *)sharedManager {
33
+ __strong static HKHealthStore *store = nil;
34
+ static dispatch_once_t onceToken;
35
+ dispatch_once(&onceToken, ^{
36
+ store = [[HKHealthStore alloc] init];
37
+ });
38
+
39
+ return store;
40
+ }
41
+
42
+ - (NSArray<NSString *> *)supportedEvents
43
+ {
44
+ return @[@"EventReminder"];
45
+ }
46
+
47
+ - (NSString *)readGender
48
+ {
49
+ NSError *error;
50
+ HKBiologicalSexObject *gen=[[MyTatvaRnSdkViewManager sharedManager] biologicalSexWithError:&error];
51
+ if (gen.biologicalSex==HKBiologicalSexMale)
52
+ {
53
+ return(@"Male");
54
+ }
55
+ else if (gen.biologicalSex==HKBiologicalSexFemale)
56
+ {
57
+ return (@"Female");
58
+ }
59
+ else if (gen.biologicalSex==HKBiologicalSexOther)
60
+ {
61
+ return (@"Other");
62
+ }
63
+ else{
64
+ return (@"Not Set");
65
+ }
66
+ }
67
+
68
+ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
69
+ unit:(HKUnit *)unit
70
+ predicate:(NSPredicate *)predicate
71
+ ascending:(BOOL)asc
72
+ limit:(NSUInteger)lim
73
+ completion:(void (^)(NSArray *, NSError *))completion {
74
+
75
+ NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate
76
+ ascending:asc];
77
+ __block NSTimeInterval totalActivityDuration = 0;
78
+ // declare the block
79
+ void (^handlerBlock)(HKSampleQuery *query, NSArray *results, NSError *error);
80
+ // create and assign the block
81
+ handlerBlock = ^(HKSampleQuery *query, NSArray *results, NSError *error) {
82
+ if (!results) {
83
+ if (completion) {
84
+ completion(nil, error);
85
+ }
86
+ return;
87
+ }
88
+
89
+ if (completion) {
90
+ NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
91
+ NSMutableArray *dataByFrequency = [NSMutableArray new];
92
+ dispatch_async(dispatch_get_main_queue(), ^{
93
+ for (HKQuantitySample *sample in results) {
94
+ HKQuantity *quantity = sample.quantity;
95
+ double value = [quantity doubleValueForUnit:unit];
96
+ if(value){
97
+ NSLog(@"startDate and endDate for fetchQuantitySamplesOfType is %@ & %@", sample.startDate,sample.endDate);
98
+ NSNumber* val = [NSNumber numberWithDouble:[sample.endDate timeIntervalSinceDate:sample.startDate]/60];
99
+ NSDictionary *element = @{
100
+ @"date" : sample.endDate,
101
+ @"value" : val,
102
+ };
103
+ NSMutableDictionary *dict =[NSMutableDictionary dictionaryWithDictionary:element];
104
+
105
+ if([dataByFrequency count]>0){
106
+ NSMutableDictionary* ele = [dataByFrequency objectAtIndex:[dataByFrequency count]-1];
107
+ if([[NSCalendar currentCalendar] isDate:sample.endDate inSameDayAsDate:[ele valueForKey:@"date"]]){
108
+ double myValue = [[ele valueForKey:@"value"] doubleValue];
109
+ myValue+=[val doubleValue];
110
+ [ele setObject:sample.endDate forKey:@"date" ];
111
+ [ele setObject: [NSNumber numberWithDouble:myValue] forKey:@"value" ];
112
+ }else{
113
+ [dataByFrequency addObject:dict];
114
+ }
115
+ }
116
+ else{
117
+ [dataByFrequency addObject:dict];
118
+ }
119
+
120
+ NSTimeInterval duration = [sample.endDate timeIntervalSinceDate:sample.startDate];
121
+ totalActivityDuration+=duration;
122
+ NSLog(@"fetchQuantitySamplesOfType dict is %@",dict);
123
+ }
124
+ }
125
+ NSLog(@"fetchQuantitySamplesOfType dataByFrequency %@ ",dataByFrequency);
126
+ [data addObject:[NSString stringWithFormat:@"%f",totalActivityDuration/60]];
127
+ [data addObject:dataByFrequency];
128
+ completion(data, error);
129
+ });
130
+ }
131
+ };
132
+
133
+ HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:quantityType
134
+ predicate:predicate
135
+ limit:lim
136
+ sortDescriptors:@[timeSortDescriptor]
137
+ resultsHandler:handlerBlock];
138
+
139
+ [[MyTatvaRnSdkViewManager sharedManager] executeQuery:query];
140
+ }
141
+
142
+
143
+ - (void) getActivityTime:(NSDate*) endDate frequency:(NSString*) frequency days:(NSInteger) days callback:(void(^)(NSMutableArray*))callback{
144
+ HKQuantityType *stepCountType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
145
+ NSDate *startDate;
146
+ NSDate *endDatePeriod;
147
+ if([frequency isEqualToString:@"day"]){
148
+ NSTimeInterval interval;
149
+ [self->calendar rangeOfUnit:NSCalendarUnitDay
150
+ startDate:&startDate
151
+ interval:&interval
152
+ forDate:endDate];
153
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
154
+ }else if ([frequency isEqualToString:@"week"]){
155
+ NSTimeInterval interval;
156
+ [self->calendar rangeOfUnit:NSCalendarUnitWeekOfYear
157
+ startDate:&startDate
158
+ interval:&interval
159
+ forDate:endDate];
160
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
161
+ }else if ([frequency isEqualToString:@"month"]){
162
+ NSTimeInterval interval;
163
+ [self->calendar rangeOfUnit:NSCalendarUnitMonth
164
+ startDate:&startDate
165
+ interval:&interval
166
+ forDate:endDate];
167
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
168
+ }else if([frequency isEqualToString:@"custom"]){
169
+ endDatePeriod = endDate;
170
+ startDate = [self->calendar dateByAddingUnit:NSCalendarUnitDay
171
+ value:1-days
172
+ toDate:endDatePeriod
173
+ options:0];
174
+ }
175
+ NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDatePeriod options:HKQueryOptionStrictStartDate];
176
+ NSPredicate *userEnteredValuePredicate = [HKQuery predicateForObjectsWithMetadataKey:HKMetadataKeyWasUserEntered operatorType: NSNotEqualToPredicateOperatorType value: @YES];
177
+
178
+ NSCompoundPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate, userEnteredValuePredicate]];
179
+ [self fetchQuantitySamplesOfType:stepCountType unit:[HKUnit countUnit] predicate:compoundPredicate ascending:true limit:HKObjectQueryNoLimit completion:^(NSArray *results, NSError *error) {
180
+ if (results) {
181
+ NSLog(@"the results of getActivityTime %@",results);
182
+ callback([NSMutableArray arrayWithArray:results]);
183
+ return;
184
+ } else {
185
+ NSLog(@"error getting step count samples: %@", error);
186
+ return;
187
+ }
188
+ }];
189
+ }
190
+
191
+ - (void)fetchHourlySteps:(NSDate*) endDate callback:(void(^)(NSArray*))callback{
192
+ HKQuantityType *stepCountType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
193
+ NSCalendar *calendar = [NSCalendar currentCalendar];
194
+ HKUnit *stepsUnit = [HKUnit countUnit];
195
+ NSDateComponents *interval = [[NSDateComponents alloc] init];
196
+ interval.hour = 1;
197
+ NSDate *startDate = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601] startOfDayForDate:endDate];
198
+ NSDateComponents *dayInteval = [[NSDateComponents alloc] init];
199
+ dayInteval.day = 1;
200
+ dayInteval.second = -1;
201
+ NSDate* endOfDay = [calendar dateByAddingComponents:dayInteval toDate:startDate options:0];
202
+ NSLog(@"endOfDay is, %@",endOfDay);
203
+ NSDate *anchorDate = [calendar startOfDayForDate:startDate];
204
+ NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endOfDay options:HKQueryOptionStrictStartDate];
205
+ NSPredicate *userEnteredValuePredicate = [HKQuery predicateForObjectsWithMetadataKey:HKMetadataKeyWasUserEntered operatorType: NSNotEqualToPredicateOperatorType value: @YES];
206
+
207
+ NSCompoundPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate, userEnteredValuePredicate]];
208
+
209
+ HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:stepCountType quantitySamplePredicate:compoundPredicate options:HKStatisticsOptionCumulativeSum anchorDate:anchorDate intervalComponents:interval];
210
+
211
+ query.initialResultsHandler = ^(HKStatisticsCollectionQuery * _Nonnull query, HKStatisticsCollection * _Nullable result, NSError * _Nullable error) {
212
+ if (error) {
213
+ NSLog(@"*** An error occurred while calculating the statistics: %@ ***",
214
+ error.localizedDescription);
215
+ return;
216
+ }
217
+
218
+ NSMutableArray *data = [NSMutableArray arrayWithCapacity:24];
219
+ NSMutableArray *stepsData = [NSMutableArray arrayWithCapacity:24];
220
+ NSMutableArray *calorieData = [NSMutableArray arrayWithCapacity:24];
221
+ NSLog(@"the startDate is %@ while endOfDay is %@",startDate,endOfDay);
222
+ [result enumerateStatisticsFromDate:startDate toDate:endOfDay withBlock:^(HKStatistics * _Nonnull result, BOOL * _Nonnull stop) {
223
+ HKQuantity *quantity = result.sumQuantity;
224
+
225
+ if (quantity) {
226
+ int value = (int)[quantity doubleValueForUnit:stepsUnit];
227
+ [data addObject:[NSNumber numberWithInt:value]];
228
+ int calories = value/21;
229
+ calories+=self->bmrCaloriesPerHour;
230
+ [calorieData addObject:[NSNumber numberWithInt:calories]];
231
+ } else {
232
+ [data addObject:[NSNumber numberWithInt:0]];
233
+ [calorieData addObject:[NSNumber numberWithInt:0]];
234
+ }
235
+ }];
236
+ int count = 0;
237
+ for (NSNumber* steps in data) {
238
+ [stepsData insertObject:steps atIndex:count];
239
+ count++;
240
+ }
241
+ NSArray* finalData = @[stepsData, calorieData];
242
+ callback(finalData);
243
+ };
244
+
245
+ [[MyTatvaRnSdkViewManager sharedManager] executeQuery:query];
246
+ }
247
+
248
+ -(void) fetchSteps:(NSString*) frequency endDate:(NSDate*) endDate days:(NSInteger) days callback:(void(^)(NSArray*))callback{
249
+ NSDateComponents *interval = [[NSDateComponents alloc] init];
250
+ NSDate *startDate;
251
+ interval.day = 1;
252
+ NSDate *endDatePeriod;
253
+ if([frequency isEqualToString:@"day"]){
254
+ endDatePeriod = endDate;
255
+ startDate = [self->calendar dateByAddingUnit:NSCalendarUnitDay
256
+ value:0
257
+ toDate:endDatePeriod
258
+ options:0];
259
+ }else if ([frequency isEqualToString:@"week"]){
260
+ NSTimeInterval interval;
261
+ [self->calendar rangeOfUnit:NSCalendarUnitWeekOfYear
262
+ startDate:&startDate
263
+ interval:&interval
264
+ forDate:endDate];
265
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
266
+ }else if ([frequency isEqualToString:@"month"]){
267
+ NSTimeInterval interval;
268
+ [self->calendar rangeOfUnit:NSCalendarUnitMonth
269
+ startDate:&startDate
270
+ interval:&interval
271
+ forDate:endDate];
272
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
273
+ }else if([frequency isEqualToString:@"custom"]){
274
+ endDatePeriod = endDate;
275
+ startDate = [self->calendar dateByAddingUnit:NSCalendarUnitDay
276
+ value:1-days
277
+ toDate:endDatePeriod
278
+ options:0];
279
+ NSLog(@"startDate and endDate in custom fetchSteps is, %@, %@",startDate,endDatePeriod);
280
+ }
281
+ NSLog(@"startDate and endDate in fetchSteps is, %@, %@",startDate,endDatePeriod);
282
+ NSDateComponents *anchorComponents = [self->calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear
283
+ fromDate:[NSDate date]];
284
+ anchorComponents.hour = 0;
285
+ NSLog(@"anchorComponents in fetchSteps are, %@",anchorComponents);
286
+ NSDate *anchorDate = [self->calendar dateFromComponents:anchorComponents];
287
+ NSLog(@"anchorDate in fetchSteps are, %@",anchorDate);
288
+ HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
289
+ // Create the query
290
+ HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType
291
+ quantitySamplePredicate:nil
292
+ options:HKStatisticsOptionCumulativeSum
293
+ anchorDate:anchorDate
294
+ intervalComponents:interval];
295
+
296
+ // Set the results handler
297
+ query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) {
298
+ if (error) {
299
+ // Perform proper error handling here
300
+ NSLog(@"*** An error occurred while calculating the statistics: %@ ***",error.localizedDescription);
301
+ }
302
+ NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
303
+ NSMutableArray *calorieData = [NSMutableArray arrayWithCapacity:1];
304
+ [results enumerateStatisticsFromDate:startDate
305
+ toDate:endDatePeriod
306
+ withBlock:^(HKStatistics *result, BOOL *stop) {
307
+
308
+ HKQuantity *quantity = result.sumQuantity;
309
+ if (quantity) {
310
+ int value = [[NSNumber numberWithInt:[quantity doubleValueForUnit:[HKUnit countUnit]]] intValue];
311
+ int calories = value/21;
312
+ calories+=self->bmrCaloriesPerHour;
313
+ [calorieData addObject:[NSNumber numberWithInt:calories]];
314
+ [data addObject:[NSNumber numberWithInt:value]];
315
+ }else{
316
+ [data addObject:[NSNumber numberWithInt:0]];
317
+ [calorieData addObject:[NSNumber numberWithInt:0]];
318
+ }
319
+ }];
320
+ NSLog(@"in stepsData and calorieData is %@,%@", data, calorieData);
321
+ NSArray* finalData = @[data, calorieData];
322
+ callback(finalData);
323
+ };
324
+
325
+ [[MyTatvaRnSdkViewManager sharedManager] executeQuery:query];
326
+ }
327
+
328
+ -(void) fetchHourlyDistanceWalkingRunning:(NSDate*) endDate callback:(void(^)(NSArray*))callback{
329
+ HKQuantityType *distanceType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
330
+ NSCalendar *calendar = [NSCalendar currentCalendar];
331
+ NSDate *startDate = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601] startOfDayForDate:endDate];
332
+ HKUnit *distanceUnit = [HKUnit meterUnit];
333
+ NSDateComponents *interval = [[NSDateComponents alloc] init];
334
+ interval.hour = 1;
335
+
336
+ NSDateComponents *dayInteval = [[NSDateComponents alloc] init];
337
+ dayInteval.day = 1;
338
+ dayInteval.second = -1;
339
+ NSDate* endOfDay = [calendar dateByAddingComponents:dayInteval toDate:startDate options:0];
340
+
341
+ NSDate *anchorDate = [calendar startOfDayForDate:startDate];
342
+ NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endOfDay options:HKQueryOptionStrictStartDate];
343
+ NSPredicate *userEnteredValuePredicate = [HKQuery predicateForObjectsWithMetadataKey:HKMetadataKeyWasUserEntered operatorType: NSNotEqualToPredicateOperatorType value: @YES];
344
+
345
+ NSCompoundPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate, userEnteredValuePredicate]];
346
+
347
+ HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:distanceType quantitySamplePredicate:compoundPredicate options:HKStatisticsOptionCumulativeSum anchorDate:anchorDate intervalComponents:interval];
348
+
349
+ query.initialResultsHandler = ^(HKStatisticsCollectionQuery * _Nonnull query, HKStatisticsCollection * _Nullable result, NSError * _Nullable error) {
350
+ if (error) {
351
+ NSLog(@"*** An error occurred while calculating the statistics: %@ ***",
352
+ error.localizedDescription);
353
+ return;
354
+ }
355
+
356
+ NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
357
+ [result enumerateStatisticsFromDate:startDate toDate:endOfDay withBlock:^(HKStatistics * _Nonnull result, BOOL * _Nonnull stop) {
358
+ HKQuantity *quantity = result.sumQuantity;
359
+ if (quantity) {
360
+ int value =(int) [quantity doubleValueForUnit:distanceUnit];
361
+ [data addObject:[NSNumber numberWithInt:value]];
362
+ } else {
363
+ [data addObject:[NSNumber numberWithInt:0]];
364
+ }
365
+ }];
366
+ callback(data);
367
+ NSLog(@"fetchDistanceWalkingRunning is,%@",data);
368
+ };
369
+
370
+ [[MyTatvaRnSdkViewManager sharedManager] executeQuery:query];
371
+ }
372
+
373
+ -(void) fetchDistanceWalkingRunning:(NSString*) frequency endDate:(NSDate*) endDate days:(NSInteger) days callback:(void(^)(NSArray*))callback{
374
+ NSDateComponents *interval = [[NSDateComponents alloc] init];
375
+ NSDate *startDate;
376
+ interval.day = 1;
377
+ NSDate *endDatePeriod;
378
+ HKUnit *distanceUnit = [HKUnit meterUnit];
379
+ if([frequency isEqualToString:@"day"]){
380
+ endDatePeriod = endDate;
381
+ startDate = [self->calendar dateByAddingUnit:NSCalendarUnitDay
382
+ value:0
383
+ toDate:endDatePeriod
384
+ options:0];
385
+ }else if ([frequency isEqualToString:@"week"]){
386
+ NSTimeInterval interval;
387
+ [self->calendar rangeOfUnit:NSCalendarUnitWeekOfYear
388
+ startDate:&startDate
389
+ interval:&interval
390
+ forDate:endDate];
391
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
392
+ }else if ([frequency isEqualToString:@"month"]){
393
+ NSTimeInterval interval;
394
+ [self->calendar rangeOfUnit:NSCalendarUnitMonth
395
+ startDate:&startDate
396
+ interval:&interval
397
+ forDate:endDate];
398
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
399
+ }else if([frequency isEqualToString:@"custom"]){
400
+ endDatePeriod = endDate;
401
+ startDate = [self->calendar dateByAddingUnit:NSCalendarUnitDay
402
+ value:1-days
403
+ toDate:endDatePeriod
404
+ options:0];
405
+ NSLog(@"startDate and endDate in custom fetchDistanceWalkingRunning is, %@, %@",startDate,endDatePeriod);
406
+ }
407
+ NSLog(@"startDate and endDate in fetchDistanceWalkingRunning is, %@, %@",startDate,endDatePeriod);
408
+ NSDateComponents *anchorComponents = [self->calendar components:NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear
409
+ fromDate:[NSDate date]];
410
+ anchorComponents.hour = 0;
411
+ NSDate *anchorDate = [self->calendar dateFromComponents:anchorComponents];
412
+ HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
413
+ // Create the query
414
+ HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType
415
+ quantitySamplePredicate:nil
416
+ options:HKStatisticsOptionCumulativeSum
417
+ anchorDate:anchorDate
418
+ intervalComponents:interval];
419
+
420
+ // Set the results handler
421
+ query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) {
422
+ if (error) {
423
+ // Perform proper error handling here
424
+ NSLog(@"*** An error occurred while calculating the statistics: %@ ***",error.localizedDescription);
425
+ }
426
+ NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
427
+
428
+ [results enumerateStatisticsFromDate:startDate
429
+ toDate:endDatePeriod
430
+ withBlock:^(HKStatistics *result, BOOL *stop) {
431
+
432
+ HKQuantity *quantity = result.sumQuantity;
433
+ if (quantity) {
434
+ int value = [[NSNumber numberWithInt:[quantity doubleValueForUnit:distanceUnit]] intValue];
435
+ NSLog(@"in fetchDistanceWalkingRunning %d", value);
436
+
437
+ [data addObject:[NSNumber numberWithInt:value]];
438
+ }else{
439
+ [data addObject:[NSNumber numberWithInt:0]];
440
+ }
441
+ }];
442
+ callback(data);
443
+ };
444
+
445
+ [[MyTatvaRnSdkViewManager sharedManager] executeQuery:query];
446
+ }
447
+
448
+ - (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate
449
+ limit:(NSUInteger)lim
450
+ completion:(void (^)(NSArray *, NSError *))completion {
451
+
452
+
453
+ NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate
454
+ ascending:true];
455
+
456
+
457
+ // declare the block
458
+ void (^handlerBlock)(HKSampleQuery *query, NSArray *results, NSError *error);
459
+ // create and assign the block
460
+ handlerBlock = ^(HKSampleQuery *query, NSArray *results, NSError *error) {
461
+ if (!results) {
462
+ if (completion) {
463
+ completion(nil, error);
464
+ }
465
+ return;
466
+ }
467
+ NSLog(@"the results of sleep is, %@", results);
468
+
469
+ if (completion) {
470
+ NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
471
+
472
+ dispatch_async(dispatch_get_main_queue(), ^{
473
+ for (HKCategorySample *sample in results) {
474
+
475
+ NSInteger val = sample.value;
476
+
477
+ NSString *valueString;
478
+
479
+ switch (val) {
480
+ case HKCategoryValueSleepAnalysisInBed:
481
+ valueString = @"INBED";
482
+ break;
483
+ case HKCategoryValueSleepAnalysisAsleep:
484
+ valueString = @"ASLEEP";
485
+ break;
486
+ default:
487
+ valueString = @"UNKNOWN";
488
+ break;
489
+ }
490
+
491
+ NSDictionary *elem = @{
492
+ @"value" : valueString,
493
+ @"startDate" : sample.startDate,
494
+ @"endDate" : sample.endDate,
495
+ };
496
+
497
+ [data addObject:elem];
498
+ }
499
+
500
+ completion(data, error);
501
+ });
502
+ }
503
+ };
504
+
505
+ HKCategoryType *categoryType = [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis];
506
+ HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:categoryType
507
+ predicate:predicate
508
+ limit:lim
509
+ sortDescriptors:@[timeSortDescriptor]
510
+ resultsHandler:handlerBlock];
511
+
512
+ [[MyTatvaRnSdkViewManager sharedManager] executeQuery:query];
513
+ }
514
+
515
+ - (void)requestAuthorization:(void(^)(NSDictionary*))callback {
516
+
517
+ if ([HKHealthStore isHealthDataAvailable] == NO) {
518
+ // If our device doesn't support HealthKit -> return.
519
+ return;
520
+ }
521
+ NSArray *writeTypes = @[[HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount]];
522
+ NSArray *readTypes = @[[HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount],
523
+ [HKSampleType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis],
524
+ [HKSampleType characteristicTypeForIdentifier:HKCharacteristicTypeIdentifierBiologicalSex],
525
+ [HKSampleType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning]];
526
+
527
+ [[MyTatvaRnSdkViewManager sharedManager] requestAuthorizationToShareTypes:[NSSet setWithArray:writeTypes] readTypes:[NSSet setWithArray:readTypes]
528
+ completion:^(BOOL success, NSError *error) {
529
+ NSLog(@"requestAuthorizationToShareTypes executed");
530
+ [self canAccessHealthKit:^(BOOL value){
531
+ if(value){
532
+ NSLog(@"the health kit permission granted");
533
+ [self onHealthKitPermissionGranted:^(NSDictionary * data) {
534
+ callback(data);
535
+ }];
536
+ }else{
537
+ NSLog(@"the health kit permission not granted");
538
+ }
539
+ }];
540
+ }];
541
+ }
542
+
543
+ -(void) onHealthKitPermissionGranted:(void(^)(NSDictionary*))callback{
544
+ dispatch_group_t loadDetailsGroup=dispatch_group_create();
545
+ __block NSString* numberOfSteps = 0;
546
+ __block NSTimeInterval totalSleepTime = 0;
547
+ NSLog(@"gender is, %@",gender);
548
+ for (int i = 0; i<2; i++) {
549
+
550
+ dispatch_group_enter(loadDetailsGroup);
551
+ if(i==0){
552
+ // getting steps for current day
553
+ [self fetchSteps:@"day" endDate:[NSDate date] days:0 callback:^(NSArray * result) {
554
+ if([[result objectAtIndex:0] count]>0){
555
+ numberOfSteps = [[result objectAtIndex:0] objectAtIndex:0];
556
+ }
557
+ dispatch_group_leave(loadDetailsGroup);
558
+ }];
559
+ }else if (i==1){
560
+ // getting sleep pattern for the day past
561
+ [self fetchSleepPattern:[NSDate date] frequency:@"day" days:0 callback:^(NSArray * result) {
562
+ NSLog(@"Sleep result is, %@",result);
563
+ if([result count]>0){
564
+ for (NSDictionary* item in result) {
565
+ NSString* sleepValue = [item valueForKey:@"value"];
566
+ if([sleepValue isEqualToString:@"INBED"]||[sleepValue isEqualToString:@"ASLEEP"]){
567
+ NSDate* startDate = [item valueForKey:@"startDate"];
568
+ NSDate* endDate = [item valueForKey:@"endDate"];
569
+ NSTimeInterval duration = [endDate timeIntervalSinceDate:startDate] / 60;
570
+ totalSleepTime+=duration;
571
+ NSLog(@"Sleep value is, %@, while duration is %f",sleepValue,duration);
572
+ }
573
+ }
574
+ }
575
+ dispatch_group_leave(loadDetailsGroup);
576
+ }];
577
+ }
578
+ }
579
+
580
+ // Now outside the loop wait until everything is done. NOTE: this will
581
+ // not block execution, the provided block will be called
582
+ // asynchronously at a later point.
583
+ dispatch_group_notify(loadDetailsGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
584
+ self->gender= [self readGender];
585
+ if([self->gender isEqualToString:@"Male"]){
586
+ self->bmrCaloriesPerHour = 1662 / 24;
587
+ }else{
588
+ self->bmrCaloriesPerHour = 1493 / 24;
589
+ }
590
+ NSLog(@"the steps result is, %@",numberOfSteps);
591
+ NSLog(@"total sleep time is %f",totalSleepTime);
592
+ // if(!self->hasLoadedOnce){
593
+ NSDictionary *element = @{
594
+ @"numberOfSteps" : numberOfSteps,
595
+ @"sleepTime" : [NSNumber numberWithInt:totalSleepTime]
596
+ };
597
+ // NSString *javascript = [NSString stringWithFormat:@"updateFitnessPermissions(true,'%@','%ld')",numberOfSteps, sleepTime];
598
+ dispatch_async(dispatch_get_main_queue(), ^{
599
+ self->hasLoadedOnce = true;
600
+ callback(element);
601
+ });
602
+ // }
603
+ });
604
+ }
605
+
606
+ -(void) canAccessHealthKit: (void(^)(BOOL))callback {
607
+ double value = 1;
608
+ NSDate *startDate = [NSDate date];
609
+ NSDate *endDate = [NSDate date];
610
+
611
+ HKUnit *unit = [HKUnit countUnit];
612
+ HKQuantity *quantity = [HKQuantity quantityWithUnit:unit doubleValue:value];
613
+ HKQuantityType *type = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
614
+ HKQuantitySample *sample = [HKQuantitySample quantitySampleWithType:type quantity:quantity startDate:startDate endDate:endDate];
615
+
616
+ [[MyTatvaRnSdkViewManager sharedManager] saveObject:sample withCompletion:^(BOOL success, NSError *error) {
617
+ if (!success) {
618
+ NSLog(@"An error occured saving the step count sample %@. The error was: %@.", sample, error);
619
+ callback(NO);
620
+ }else{
621
+ [[MyTatvaRnSdkViewManager sharedManager] deleteObject:sample withCompletion:^(BOOL success, NSError * _Nullable error) {
622
+ if(!success){
623
+ callback(NO);
624
+ }else{
625
+ callback(YES);
626
+ }
627
+ }];
628
+ }
629
+ }];
630
+ }
631
+
632
+ -(void) fetchSleepPattern:(NSDate *) endDate frequency:(NSString*) frequency days:(NSInteger) days callback:(void(^)(NSArray*))callback{
633
+ NSDate *startDate;
634
+ NSDate *endDatePeriod;
635
+ if([frequency isEqualToString:@"day"]){
636
+ NSTimeInterval interval;
637
+ NSLog(@"startDate and endDate in fetchSleepPattern before is, %@ %@",startDate,endDatePeriod);
638
+ [self->calendar rangeOfUnit:NSCalendarUnitDay
639
+ startDate:&startDate
640
+ interval:&interval
641
+ forDate:endDate];
642
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
643
+ startDate = [startDate dateByAddingTimeInterval:-3600*2];
644
+ NSLog(@"startDate and endDate in fetchSleepPattern is, %@ %@",startDate,endDatePeriod);
645
+ }else if ([frequency isEqualToString:@"week"]){
646
+ NSTimeInterval interval;
647
+ [self->calendar rangeOfUnit:NSCalendarUnitWeekOfYear
648
+ startDate:&startDate
649
+ interval:&interval
650
+ forDate:endDate];
651
+ endDatePeriod = [startDate dateByAddingTimeInterval:interval-1];
652
+ }else if([frequency isEqualToString:@"custom"]){
653
+ endDatePeriod = endDate;
654
+ startDate = [self->calendar dateByAddingUnit:NSCalendarUnitDay
655
+ value:-days
656
+ toDate:endDatePeriod
657
+ options:0];
658
+ // NSLog(@"startDate and endDate in custom fetchSleepPattern is, %@, %@",startDate,endDatePeriod);
659
+ }
660
+ // NSLog(@"startDate and endDate in fetchSleepPattern is, %@ %@",startDate,endDatePeriod);
661
+ NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDatePeriod options:HKQueryOptionStrictStartDate];
662
+ [self fetchSleepCategorySamplesForPredicate:predicate
663
+ limit:HKObjectQueryNoLimit
664
+ completion:^(NSArray *results, NSError *error) {
665
+ if(results){
666
+ // NSLog(@"fetchSleepCategorySamplesForPredicate result, %@",results);
667
+ callback(results);
668
+ return;
669
+ } else {
670
+ // NSLog(@"error getting sleep samples: %@", error);
671
+ return;
672
+ }
673
+ }];
674
+ }
675
+
676
+ -(NSMutableArray*) getBlankSleepWeeks:(NSUInteger) currentCount date:(NSDate*) date{
677
+ NSMutableArray *result = [[NSMutableArray alloc]init];
678
+ NSInteger value = 1;
679
+ NSDate *nextDayTime=date;
680
+ NSNumber *nextDayTimeStamp;
681
+ NSDateComponents *dateComponents;
682
+ NSString* day;
683
+ NSLog(@"day is, %@",day);
684
+ int counter =(int) currentCount;
685
+ while(counter<7){
686
+ nextDayTime = [self->calendar dateByAddingUnit:NSCalendarUnitDay value:value toDate:nextDayTime options:NSCalendarMatchStrictly];
687
+ nextDayTimeStamp = [NSNumber numberWithDouble: [@(floor([nextDayTime timeIntervalSince1970] * 1000)) longLongValue]];
688
+ dateComponents = [self->calendar components: NSCalendarUnitWeekday fromDate: nextDayTime];
689
+ day = self->calendar.shortWeekdaySymbols[dateComponents.weekday-1];
690
+ NSDictionary *element = @{
691
+ @"sleepTime" : @0,
692
+ @"wakeupTime" : @0,
693
+ @"day" : day,
694
+ @"startTimestamp" : nextDayTimeStamp,
695
+ };
696
+ NSLog(@"element is %@",element);
697
+ [result addObject:[NSMutableDictionary dictionaryWithDictionary:element]];
698
+ counter++;
699
+ }
700
+ return result;
701
+ }
702
+
703
+ -(void) evaluateJavascript:(NSArray *) data type:(NSString *) type frequency:(NSString *) frequency activityTime:(NSString *) activityTime callback:(void(^)(NSArray*))callback{
704
+ NSString* hoursInDay = @"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]";
705
+ NSString* daysInWeek = @"[1,2,3,4,5,6,7]";
706
+ NSString* daysInMonth = @"[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]";
707
+ NSString* samples;
708
+ NSString *jsonArrayData;
709
+ if([frequency isEqualToString:@"day"]){
710
+ samples=hoursInDay;
711
+ }else if ([frequency isEqualToString:@"week"]){
712
+ samples=daysInWeek;
713
+ }else if ([frequency isEqualToString:@"month"]){
714
+ samples=daysInMonth;
715
+ }
716
+ if([type isEqualToString:@"steps"] || [type isEqualToString:@"calories"]){
717
+ if([type isEqualToString:@"steps"]){
718
+ jsonArrayData = [[data objectAtIndex:0] componentsJoinedByString:@","];
719
+ }else{
720
+ jsonArrayData = [[data objectAtIndex:1] componentsJoinedByString:@","];
721
+ }
722
+ }else{
723
+ jsonArrayData = [data componentsJoinedByString:@","];
724
+ }
725
+ NSString *javascript = [NSString stringWithFormat:@"DetailedGraph.updateData(%@,[%@],'%@','%@','%@')", samples, jsonArrayData, type,frequency, activityTime];
726
+ dispatch_async(dispatch_get_main_queue(), ^{
727
+ callback(@[javascript]);
728
+ });
729
+ }
730
+
731
+ -(void) renderGraphData:(NSString *) type frequency:(NSString *) frequency date:(NSDate *) date callback:(void(^)(NSArray*))callback{
732
+ if([type isEqualToString:@"steps"] || [type isEqualToString:@"distance"]||[type isEqualToString:@"calories"]){
733
+ dispatch_group_t loadDetailsGroup=dispatch_group_create();
734
+ __block NSArray* stepsOrDistance = 0;
735
+ __block NSString* totalActivityDuration = 0;
736
+ for (int i = 0; i<2; i++) {
737
+ dispatch_group_enter(loadDetailsGroup);
738
+ if(i==0){
739
+ [self getActivityTime:date frequency:frequency days:0 callback:^(NSMutableArray * result){
740
+ totalActivityDuration = [result objectAtIndex:0];
741
+ dispatch_group_leave(loadDetailsGroup);
742
+ }];
743
+ }else if(i==1){
744
+ if([type isEqualToString:@"steps"] || [type isEqualToString:@"calories"]){
745
+ if([frequency isEqualToString:@"day"]){
746
+ [self fetchHourlySteps:date callback:^(NSArray * result) {
747
+ stepsOrDistance = result;
748
+ dispatch_group_leave(loadDetailsGroup);
749
+ }];
750
+ }else{
751
+ [self fetchSteps:frequency endDate: date days:0 callback:^(NSArray * result) {
752
+ stepsOrDistance = result;
753
+ dispatch_group_leave(loadDetailsGroup);
754
+ }];
755
+ }
756
+ }else if ([type isEqualToString:@"distance"]){
757
+ if([frequency isEqualToString:@"day"]){
758
+ [self fetchHourlyDistanceWalkingRunning:date callback:^(NSArray * result) {
759
+ stepsOrDistance = result;
760
+ dispatch_group_leave(loadDetailsGroup);
761
+ }];
762
+ }else{
763
+ [self fetchDistanceWalkingRunning:frequency endDate: date days:0 callback:^(NSArray * result) {
764
+ stepsOrDistance = result;
765
+ dispatch_group_leave(loadDetailsGroup);
766
+ }];
767
+ }
768
+ }
769
+ }
770
+ }
771
+ dispatch_group_notify(loadDetailsGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
772
+ [self evaluateJavascript:stepsOrDistance type:type frequency:frequency activityTime:totalActivityDuration callback:^(NSArray * data) {
773
+ callback(data);
774
+ }];
775
+ });
776
+ }else if([type isEqualToString:@"sleep"]){
777
+ if([frequency isEqualToString:@"day"]){
778
+ [self fetchSleepPattern:date frequency:frequency days:0 callback:^(NSArray * results) {
779
+ NSNumber* sleepTime = 0;
780
+ NSNumber* wakeTime = 0;
781
+ int count = 0;
782
+ for (NSDictionary *object in results) {
783
+ NSString* sleepValue = [object valueForKey:@"value"];
784
+ if([sleepValue isEqualToString:@"INBED"]||[sleepValue isEqualToString:@"ASLEEP"]){
785
+ if(count==0){
786
+ sleepTime =
787
+ [NSNumber numberWithDouble: [@(floor([[object valueForKey:@"startDate"] timeIntervalSince1970] * 1000)) longLongValue]];
788
+
789
+ }
790
+ wakeTime =
791
+ [NSNumber numberWithDouble: [@(floor([[object valueForKey:@"endDate"] timeIntervalSince1970] * 1000)) longLongValue]];
792
+ count++;
793
+ }
794
+ }
795
+ NSLog(@"sleepTime and wakeTime data, %@ %@",sleepTime, wakeTime);
796
+
797
+ if(sleepTime && wakeTime){
798
+ NSString *javascript = [NSString stringWithFormat:@"DetailedGraph.updateDailySleep(%@,%@)", sleepTime,wakeTime];
799
+ callback(@[javascript]);
800
+ }else{
801
+ NSString *javascript = [NSString stringWithFormat:@"DetailedGraph.updateDailySleep(0,0)"];
802
+ callback(@[javascript]);
803
+ }
804
+ } ];
805
+ }else{
806
+ [self fetchSleepPattern:date frequency:frequency days:0 callback:^(NSArray * results) {
807
+ NSMutableArray *data = [[NSMutableArray alloc]init];
808
+ NSLog(@"weekly sleep results, %@", results);
809
+ if([results count]){
810
+ for (NSDictionary* item in results) {
811
+ NSString* sleepValue = [item valueForKey:@"value"];
812
+ if([sleepValue isEqualToString:@"INBED"]||[sleepValue isEqualToString:@"ASLEEP"]){
813
+ NSDate* startDate = [item valueForKey:@"startDate"];
814
+ NSDate* endDate = [item valueForKey:@"endDate"];
815
+ NSTimeInterval interval;
816
+ NSNumber* sleepTime =
817
+ [NSNumber numberWithDouble: [@(floor([startDate timeIntervalSince1970] * 1000)) longLongValue]];
818
+ NSNumber* wakeupTime =
819
+ [NSNumber numberWithDouble: [@(floor([endDate timeIntervalSince1970] * 1000)) longLongValue]];
820
+ NSLog(@"startDate before calendar function ,%@",startDate);
821
+ [self->calendar rangeOfUnit:NSCalendarUnitDay
822
+ startDate:&startDate
823
+ interval:&interval
824
+ forDate:endDate];
825
+ NSLog(@"startDate after calendar function ,%@",startDate);
826
+ NSNumber* startTimestamp =
827
+ [NSNumber numberWithDouble: [@(floor([startDate timeIntervalSince1970] * 1000)) longLongValue]];
828
+ NSDateComponents * dateComponents = [self->calendar components: NSCalendarUnitDay | NSCalendarUnitWeekday fromDate: endDate];
829
+ NSString* day =self->calendar.shortWeekdaySymbols[dateComponents.weekday - 1];
830
+ NSLog(@"Day name: %@", day);
831
+ NSDictionary *element = @{
832
+ @"sleepTime" : sleepTime,
833
+ @"wakeupTime" : wakeupTime,
834
+ @"day" : day,
835
+ @"startTimestamp" : startTimestamp,
836
+ };
837
+ NSMutableDictionary *elem = [NSMutableDictionary dictionaryWithDictionary:element];
838
+
839
+ NSLog(@"data is, ====>> %@",data);
840
+ if([data count]>0){
841
+ for (int i=0;i<[data count]; i++) {
842
+ NSMutableDictionary* item = [data objectAtIndex:i];
843
+ NSString* itemDay = [item objectForKey:@"day"];
844
+ NSString* itemSleepTime = [item objectForKey:@"sleepTime"];
845
+ if([itemDay isEqualToString:day]){
846
+ [elem setValue:itemSleepTime forKey:@"sleepTime"];
847
+ [data removeObjectAtIndex:i];
848
+ NSLog(@"removed day is, ====>> %@",itemDay);
849
+ }
850
+ }
851
+ [data addObject:elem];
852
+ }else{
853
+ [data addObject:elem];
854
+ }
855
+ }
856
+ }
857
+ }
858
+ if([data count]<7 && [data count]>0){
859
+ NSMutableDictionary* item = [data objectAtIndex:[data count]-1];
860
+ NSNumber* startTimeStamp = [item objectForKey:@"startTimestamp"];
861
+ NSTimeInterval unixTimeStamp = [startTimeStamp doubleValue] / 1000.0;
862
+ NSMutableArray* newData = [self getBlankSleepWeeks:[data count] date:[NSDate dateWithTimeIntervalSince1970:unixTimeStamp]];
863
+ [data addObjectsFromArray:newData];
864
+ }
865
+ NSLog(@"data is, %@",data);
866
+ NSData* jsonArray = [NSJSONSerialization dataWithJSONObject:data options:NSJSONWritingPrettyPrinted error:nil ];
867
+ NSString *jsonString = [[NSString alloc] initWithData:jsonArray encoding:NSUTF8StringEncoding];
868
+ NSString *javascript = [NSString stringWithFormat:@"DetailedGraph.updateSleepData(JSON.stringify(%@))", jsonString];
869
+ callback(@[javascript]);
870
+ }];
871
+ }
872
+
873
+ }
874
+ }
875
+
876
+ - (NSDate *)convertStringToDate:(NSString *)date {
877
+ NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
878
+ [formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZ"];
879
+ NSLocale *posix = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
880
+ [formatter setLocale:posix];
881
+ return [formatter dateFromString:date];
882
+ }
883
+
884
+ -(void) getDateRanges:(NSDate*) startDate callback:(void(^)(NSMutableArray*))callback{
885
+ NSCalendar *calendar = [NSCalendar currentCalendar];
886
+ dispatch_group_t loadDetailsGroup=dispatch_group_create();
887
+ NSDate *startOfToday = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601] startOfDayForDate:[NSDate date]];
888
+ NSDate *startOfNextDay = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601] dateByAddingUnit:NSCalendarUnitDay value:1 toDate:startOfToday options:0];
889
+ NSDate *endOfToday = [[NSCalendar calendarWithIdentifier:NSCalendarIdentifierISO8601] dateByAddingUnit:NSCalendarUnitSecond value:-1 toDate:startOfNextDay options:0];
890
+ NSDateComponents *days = [[NSDateComponents alloc] init];
891
+ NSInteger dayCount = 0;
892
+ NSMutableArray *dates=[NSMutableArray new];
893
+ NSDate* startingDate = startDate;
894
+ NSDateComponents *component = [calendar components:NSCalendarUnitDay
895
+ fromDate:startingDate
896
+ toDate:endOfToday
897
+ options:0];
898
+
899
+ NSInteger numberOfDays =[component day];
900
+ if(numberOfDays>30){
901
+ [component setDay:-30];
902
+ startingDate =[calendar dateByAddingComponents:component toDate:endOfToday options:0];
903
+ numberOfDays=30;
904
+ }else{
905
+ [component setDay:-numberOfDays-1];
906
+ startingDate =[calendar dateByAddingComponents:component toDate:endOfToday options:0];
907
+ }
908
+ NSLog(@"numberOfDays are ,%ld, while startingDate is,%@",(long)numberOfDays,startDate);
909
+
910
+ for (NSInteger i=numberOfDays; i>0; i--) {
911
+ dispatch_group_enter(loadDetailsGroup);
912
+ [days setDay: ++dayCount];
913
+ NSDate *date = [calendar dateByAddingComponents: days toDate: startingDate options: 0];
914
+ [dates addObject:date];
915
+ dispatch_group_leave(loadDetailsGroup);
916
+ }
917
+
918
+ dispatch_group_notify(loadDetailsGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
919
+ NSLog(@"dispatch_group_notify called %@",dates);
920
+ callback(dates);
921
+ });
922
+ }
923
+
924
+ -(void) preprocessEmbellishRequest:(NSArray*) steps calories:(NSArray*) calories distance:(NSArray*) distance date:(NSDate*) date callback:(void(^)(NSArray*))callback{
925
+ NSLog(@"steps=%@, calories=%@, distance=%@, date=%@",steps, calories, distance, date);
926
+ NSMutableArray* embellishData = [NSMutableArray new];
927
+ int count=0;
928
+ for (NSNumber* step in steps) {
929
+ NSDictionary *dict = @{
930
+ @"st" : step,
931
+ @"c" : [calories objectAtIndex:count],
932
+ @"d" : [distance objectAtIndex:count],
933
+ @"h" : [NSNumber numberWithInt:count],
934
+ @"s" : @"",
935
+ };
936
+ count++;
937
+ [embellishData addObject:dict];
938
+ }
939
+ NSLog(@"the httpBody is, %lu",(unsigned long)[embellishData count]);
940
+ NSTimeInterval unixDate = [date timeIntervalSince1970]*1000;
941
+ NSInteger finalDate = unixDate;
942
+ NSDictionary *httpBody = @{
943
+ @"data" : embellishData,
944
+ @"dt" : [NSNumber numberWithLong:finalDate],
945
+ };
946
+ callback(@[httpBody]);
947
+ }
948
+
949
+ -(void)callSyncData:(NSInteger) days dates:(NSMutableArray*)dates callback:(void(^)(NSArray*))callback{
950
+ dispatch_group_t syncDataGroup=dispatch_group_create();
951
+ __block NSArray* steps;
952
+ __block NSArray* calorie;
953
+ __block NSArray* distanceData;
954
+ __block NSArray* activityData;
955
+ __block NSArray* sleep;
956
+ // NSLog(@"days are %ld",(long)days);
957
+ for (int i = 0; i<4; i++) {
958
+ dispatch_group_enter(syncDataGroup);
959
+ if(i==0){
960
+ [self fetchSteps:@"custom" endDate:[NSDate date] days:days callback:^(NSArray * data) {
961
+ NSLog(@"steps data for custom range is, %@ length %lu",[data objectAtIndex:0],[[data objectAtIndex:0] count]);
962
+ steps = [data objectAtIndex:0];
963
+ calorie = [data objectAtIndex:1];
964
+ dispatch_group_leave(syncDataGroup);
965
+ }];
966
+ }else if(i==1){
967
+ [self fetchDistanceWalkingRunning:@"custom" endDate:[NSDate date] days:days callback:^(NSArray * distance) {
968
+ NSLog(@"distance data for custom range is, %@ length %lu",distance, [distance count]);
969
+ distanceData=distance;
970
+ dispatch_group_leave(syncDataGroup);
971
+ }];
972
+ }else if(i==2){
973
+ [self getActivityTime:[NSDate date] frequency:@"custom" days:days callback:^(NSMutableArray * activity) {
974
+ NSMutableArray* arr = [activity objectAtIndex:1];
975
+ NSLog(@"activity data for custom range is, %@ length %lu",activity, [arr count]);
976
+ activityData = arr;
977
+ dispatch_group_leave(syncDataGroup);
978
+ }];
979
+ }else if(i==3){
980
+ [self fetchSleepPattern:[NSDate date] frequency:@"custom" days:days callback:^(NSArray * sleepData) {
981
+ NSMutableArray *data = [[NSMutableArray alloc]init];
982
+ for (NSDictionary* item in sleepData) {
983
+ NSString* sleepValue = [item valueForKey:@"value"];
984
+ if([sleepValue isEqualToString:@"INBED"]||[sleepValue isEqualToString:@"ASLEEP"]){
985
+ NSDate* startDate = [item valueForKey:@"startDate"];
986
+ NSDate* endDate = [item valueForKey:@"endDate"];
987
+ NSTimeInterval interval;
988
+ NSNumber* sleepTime =
989
+ [NSNumber numberWithDouble: [@(floor([startDate timeIntervalSince1970] * 1000)) longLongValue]];
990
+ NSNumber* wakeupTime =
991
+ [NSNumber numberWithDouble: [@(floor([endDate timeIntervalSince1970] * 1000)) longLongValue]];
992
+ // NSLog(@"startDate before calendar function ,%@",startDate);
993
+ [self->calendar rangeOfUnit:NSCalendarUnitDay
994
+ startDate:&startDate
995
+ interval:&interval
996
+ forDate:endDate];
997
+ // NSLog(@"startDate after calendar function ,%@",startDate);
998
+ NSNumber* startTimestamp =
999
+ [NSNumber numberWithDouble: [@(floor([startDate timeIntervalSince1970] * 1000)) longLongValue]];
1000
+ NSDictionary *element = @{
1001
+ @"sleepTime" : sleepTime,
1002
+ @"wakeupTime" : wakeupTime,
1003
+ @"endDate" : endDate,
1004
+ @"startTimestamp" : startTimestamp,
1005
+ };
1006
+ NSMutableDictionary *elem = [NSMutableDictionary dictionaryWithDictionary:element];
1007
+
1008
+ if([data count]>0){
1009
+ for (int i=0;i<[data count]; i++) {
1010
+ NSMutableDictionary* item = [data objectAtIndex:i];
1011
+ NSDate* itemEndDate = [item objectForKey:@"endDate"];
1012
+ NSString* itemSleepTime = [item objectForKey:@"sleepTime"];
1013
+ if([[NSCalendar currentCalendar] isDate:itemEndDate inSameDayAsDate:endDate]){
1014
+ [elem setValue:itemSleepTime forKey:@"sleepTime"];
1015
+ [data removeObjectAtIndex:i];
1016
+ // NSLog(@"removed date is, ====>> %@",endDate);
1017
+ }
1018
+ }
1019
+ [data addObject:elem];
1020
+ }else{
1021
+ [data addObject:elem];
1022
+ }
1023
+ }
1024
+ }
1025
+ sleep = data;
1026
+ NSLog(@"fetchSleepPattern data is, ====>> %lu %@",(unsigned long)[data count],data);
1027
+ dispatch_group_leave(syncDataGroup);
1028
+ }];
1029
+ }
1030
+ }
1031
+ // NSLog(@"callSyncData steps=%@, calories=%@, distance=%@, activity=%@, sleep=%@",steps, calorie, distanceData, activityData, sleep);
1032
+
1033
+ dispatch_group_notify(syncDataGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
1034
+ if([steps count]>0 && [distanceData count]>0 && [activityData count]>0 && [sleep count]>0)
1035
+ {
1036
+ NSMutableArray* dailySyncData =[NSMutableArray new];
1037
+ int count = 0;
1038
+ for (NSDate* date in dates) {
1039
+ NSDictionary* dict = @{
1040
+ @"steps":[steps objectAtIndex:count],
1041
+ @"calories":[calorie objectAtIndex:count],
1042
+ @"distance":[distanceData objectAtIndex:count],
1043
+ @"date":date
1044
+ };
1045
+ [dailySyncData addObject:[NSMutableDictionary dictionaryWithDictionary:dict]];
1046
+ count++;
1047
+ }
1048
+ for (NSMutableDictionary* dict in dailySyncData) {
1049
+ for(NSMutableDictionary* sleepData in sleep){
1050
+ if([[NSCalendar currentCalendar] isDate:[sleepData objectForKey:@"endDate"] inSameDayAsDate:[dict objectForKey:@"date"]]){
1051
+ NSString* sleepTime = [sleepData objectForKey:@"sleepTime"];
1052
+ NSString* wakeupTime = [sleepData objectForKey:@"wakeupTime"];
1053
+ [dict setObject:[NSString stringWithFormat:@"%@-%@",sleepTime,wakeupTime] forKey:@"sleep"];
1054
+ }
1055
+ }
1056
+
1057
+ for(NSMutableDictionary* activity in activityData){
1058
+ if([[NSCalendar currentCalendar] isDate:[activity objectForKey:@"date"] inSameDayAsDate:[dict objectForKey:@"date"]]){
1059
+ NSString* activityValue = [activity objectForKey:@"value"];
1060
+ [dict setObject:activityValue forKey:@"activity"];
1061
+ }
1062
+ }
1063
+
1064
+ [dict setObject: [NSNumber numberWithDouble: [@(floor([[dict objectForKey:@"date"] timeIntervalSince1970] * 1000)) longLongValue]]
1065
+ forKey:@"date"];
1066
+ }
1067
+ NSDictionary *httpBody = @{
1068
+ @"fitnessData" : dailySyncData,
1069
+ };
1070
+ callback(@[httpBody]);
1071
+
1072
+ }
1073
+ });
1074
+ }
1075
+
1076
+ -(void)callEmbellishApi:(NSMutableArray*) dates callback:(void(^)(NSArray*))callback{
1077
+ for (NSDate* date in dates) {
1078
+ dispatch_group_t loadDetailsGroup=dispatch_group_create();
1079
+ __block NSArray* steps;
1080
+ __block NSArray* calories;
1081
+ __block NSArray* distance;
1082
+ for(int i = 0; i<2;i++){
1083
+ dispatch_group_enter(loadDetailsGroup);
1084
+ if(i==0){
1085
+ [self fetchHourlySteps:date callback:^(NSArray * data) {
1086
+ steps = [data objectAtIndex:0];
1087
+ calories = [data objectAtIndex:1];
1088
+ dispatch_group_leave(loadDetailsGroup);
1089
+ }];
1090
+ }else if(i==1){
1091
+ [self fetchHourlyDistanceWalkingRunning:date callback:^(NSArray * dist) {
1092
+ distance = dist;
1093
+ dispatch_group_leave(loadDetailsGroup);
1094
+ }];
1095
+ }
1096
+ }
1097
+ dispatch_group_notify(loadDetailsGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
1098
+ if([steps count]>0 && [calories count] > 0 && [distance count]>0){
1099
+ [self preprocessEmbellishRequest:steps calories:calories distance:distance date:date callback:^(NSArray * data) {
1100
+ NSLog(@"preprocessEmbellishRequest data, %@",data);
1101
+ callback(data);
1102
+ }];
1103
+ }
1104
+ });
1105
+ }
1106
+ }
1107
+
1108
+
1109
+ RCT_EXPORT_METHOD(connectToAppleHealth:(RCTResponseSenderBlock)callback)
1110
+ {
1111
+ // [self isHealthKitAvailable:callback];
1112
+ [self canAccessHealthKit:^(BOOL value){
1113
+ if(value){
1114
+ [self onHealthKitPermissionGranted:^(NSDictionary * data) {
1115
+ NSArray* finalData = @[data];
1116
+ callback(finalData);
1117
+ }];
1118
+ }else{
1119
+ // reject(@"Error", @"Unable to connect to Apple Health", nil);
1120
+ [self requestAuthorization:^(NSDictionary * data) {
1121
+ NSArray* finalData = @[data];
1122
+ callback(finalData);
1123
+ }];
1124
+ }
1125
+ }];
1126
+ }
1127
+
1128
+ RCT_EXPORT_METHOD(renderGraph:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
1129
+ {
1130
+ NSString *type = [input objectForKey:@"type"];
1131
+ NSString *frequency = [input objectForKey:@"frequency"];
1132
+ NSString *timestamp = [input objectForKey:@"timestamp"];
1133
+ NSDate *date = [NSDate dateWithTimeIntervalSince1970:[timestamp doubleValue]/1000];
1134
+ [self renderGraphData:type frequency:frequency date:date callback:^(NSArray * data) {
1135
+ NSLog(@"renderGraphData data is, %@",data);
1136
+ callback(@[[NSNull null], data]);
1137
+ }];
1138
+ }
1139
+
1140
+
1141
+ RCT_EXPORT_METHOD(updateApiUrl:(NSDictionary *)input)
1142
+ {
1143
+ NSTimeInterval gfHourlyLastSync = [[input objectForKey:@"gfHourlyLastSync"] doubleValue];
1144
+ NSTimeInterval googleFitLastSync = [[input objectForKey:@"googleFitLastSync"] doubleValue];
1145
+ NSDate* hourlyDataSyncTime = [NSDate dateWithTimeIntervalSince1970:gfHourlyLastSync/1000];
1146
+ NSDate* dailyDataSyncTime = [NSDate dateWithTimeIntervalSince1970:googleFitLastSync/1000];
1147
+ [self canAccessHealthKit:^(BOOL value){
1148
+ if(value){
1149
+ dispatch_group_t loadDetailsGroup = dispatch_group_create();
1150
+ // NSMutableArray *apiData = [NSMutableArray arrayWithCapacity:2];
1151
+ [self getDateRanges:hourlyDataSyncTime callback:^(NSMutableArray * dates) {
1152
+ if([dates count]>0){
1153
+ [self callEmbellishApi:dates callback:^(NSArray * data) {
1154
+ // [apiData addObject:data];
1155
+ NSLog(@"callEmbellishApi data is, %@",data);
1156
+ [self sendEventWithName:@"EventReminder" body:@{@"callEmbellishApi":data}];
1157
+ }];
1158
+ }
1159
+ }];
1160
+ [self getDateRanges:dailyDataSyncTime callback:^(NSMutableArray * dates) {
1161
+ if([dates count]>0){
1162
+ [self callSyncData:[dates count] dates:dates callback:^(NSArray * data) {
1163
+ // [apiData addObject:data];
1164
+ [self sendEventWithName:@"EventReminder" body:@{@"callSyncData":data}];
1165
+ }];
1166
+ }
1167
+ }];
1168
+ dispatch_group_notify(loadDetailsGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
1169
+ // callback([apiData copy]);
1170
+ });
1171
+ }else{
1172
+ [self requestAuthorization:^(NSDictionary * data) {
1173
+ // callback(@[data]);
1174
+ }];
1175
+ }
1176
+ }];
1177
+ // }
1178
+ }
1179
+
1180
+
1181
+ RCT_EXPORT_METHOD(fetchHourlyData:(NSInteger)gfHourlyLastSync resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
1182
+ NSLog(@"gfHourlyLastSync in fetchHourlyData is %ld",(long)gfHourlyLastSync);
1183
+ NSDate* hourlyDataSyncTime = [NSDate dateWithTimeIntervalSince1970:gfHourlyLastSync/1000];
1184
+ [self canAccessHealthKit:^(BOOL value){
1185
+ if(value){
1186
+ dispatch_group_t loadDetailsGroup=dispatch_group_create();
1187
+ __block NSArray* steps;
1188
+ __block NSArray* calories;
1189
+ __block NSArray* distance;
1190
+ for(int i = 0; i<2;i++){
1191
+ dispatch_group_enter(loadDetailsGroup);
1192
+ if(i==0){
1193
+ [self fetchHourlySteps:hourlyDataSyncTime callback:^(NSArray * data) {
1194
+ steps = [data objectAtIndex:0];
1195
+ calories = [data objectAtIndex:1];
1196
+ dispatch_group_leave(loadDetailsGroup);
1197
+ }];
1198
+ }else if(i==1){
1199
+ [self fetchHourlyDistanceWalkingRunning:hourlyDataSyncTime callback:^(NSArray * dist) {
1200
+ distance = dist;
1201
+ dispatch_group_leave(loadDetailsGroup);
1202
+ }];
1203
+ }
1204
+ }
1205
+ dispatch_group_notify(loadDetailsGroup,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
1206
+ if([steps count]>0 && [calories count] > 0 && [distance count]>0){
1207
+ [self preprocessEmbellishRequest:steps calories:calories distance:distance date:hourlyDataSyncTime callback:^(NSArray * data) {
1208
+ NSLog(@"fetchHourlyData data, %@",data);
1209
+ resolve(data);
1210
+ }];
1211
+ }
1212
+ });
1213
+ }else{
1214
+ NSError* error;
1215
+ reject(@"error", @"Error fetching hourly data", error);
1216
+ }
1217
+ }];
1218
+ }
1219
+
1220
+ RCT_EXPORT_METHOD(fetchDailyData:(NSInteger)googleFitLastSync resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
1221
+ NSLog(@"gfHourlyLastSync in fetchHourlyData is %ld",(long)googleFitLastSync);
1222
+ NSDate* dailyDataSyncTime = [NSDate dateWithTimeIntervalSince1970:googleFitLastSync/1000];
1223
+ [self canAccessHealthKit:^(BOOL value){
1224
+ if(value){
1225
+ [self getDateRanges:dailyDataSyncTime callback:^(NSMutableArray * dates) {
1226
+ if([dates count]>0){
1227
+ [self callSyncData:[dates count] dates:dates callback:^(NSArray * data) {
1228
+ NSLog(@"fetchDailyData data is, %@",data);
1229
+ resolve(data);
1230
+ }];
1231
+ }
1232
+ }];
1233
+ }else{
1234
+ NSError* error;
1235
+ reject(@"error", @"Error fetching daily data", error);
1236
+ }
1237
+ }];
1238
+ }
1239
+
1240
+ @end