-
-
Notifications
You must be signed in to change notification settings - Fork 101
/
RNHapticFeedback.mm
128 lines (109 loc) · 4.67 KB
/
RNHapticFeedback.mm
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#import "RNHapticFeedback.h"
#import <UIKit/UIKit.h>
#import <sys/utsname.h>
#import "DeviceUtils.h"
#import <AudioToolbox/AudioToolbox.h>
#import <AudioToolbox/AudioServices.h>
static UISelectionFeedbackGenerator *selectionGenerator = nil;
static NSMutableDictionary<NSString*, UIImpactFeedbackGenerator*> *impactGeneratorMap = nil;
static UINotificationFeedbackGenerator *notificationGenerator = nil;
@implementation RNHapticFeedback
@synthesize bridge = _bridge;
- (void)setBridge:(RCTBridge *)bridge
{
_bridge = bridge;
}
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
RCT_EXPORT_MODULE();
#ifdef RCT_NEW_ARCH_ENABLED
RCT_EXPORT_METHOD(trigger:(NSString *)type options:(JS::NativeHapticFeedback::SpecTriggerOptions&)options)
{
BOOL enableVibrateFallback = options.enableVibrateFallback().value();
#else
RCT_EXPORT_METHOD(trigger:(NSString *)type options:(NSDictionary *)options)
{
BOOL enableVibrateFallback = [[options objectForKey:@"enableVibrateFallback"]boolValue];
#endif
if ([self supportsHaptic]){
if ([type isEqual: @"impactLight"]) {
[self generateImpactFeedback:UIImpactFeedbackStyleLight];
} else if ([type isEqual:@"impactMedium"]) {
[self generateImpactFeedback:UIImpactFeedbackStyleMedium];
} else if ([type isEqual:@"impactHeavy"]) {
[self generateImpactFeedback:UIImpactFeedbackStyleHeavy];
} else if ([type isEqual:@"rigid"]) {
[self generateImpactFeedback:UIImpactFeedbackStyleRigid];
} else if ([type isEqual:@"soft"]) {
[self generateImpactFeedback:UIImpactFeedbackStyleSoft];
} else if ([type isEqual:@"notificationSuccess"]) {
[self generateNotificationFeedback:UINotificationFeedbackTypeSuccess];
} else if ([type isEqual:@"notificationWarning"]) {
[self generateNotificationFeedback:UINotificationFeedbackTypeWarning];
} else if ([type isEqual:@"notificationError"]) {
[self generateNotificationFeedback:UINotificationFeedbackTypeError];
} else {
[self generateSelectionFeedback];
}
} else if ([self supportsHapticFor6SAnd6SPlus]) {
// generates alternative haptic feedback
if ([type isEqual: @"impactMedium"]) {
AudioServicesPlaySystemSound((SystemSoundID) 1520);
} else if ([type isEqual:@"notificationWarning"]) {
AudioServicesPlaySystemSound((SystemSoundID) 1521);
} else {
// Default selection haptic feedback
AudioServicesPlaySystemSound((SystemSoundID) 1519);
}
} else if (enableVibrateFallback) {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
}
}
-(Boolean)supportsHaptic {
return [[UIDevice currentDevice] systemVersion].floatValue >= 10.0
&& [DeviceUtils deviceVersion:@"iPhone"] > 8;
}
-(Boolean)supportsHapticFor6SAnd6SPlus {
return [[UIDevice currentDevice] systemVersion].floatValue >= 10.0
&& ([[DeviceUtils platform] isEqualToString:@"iPhone8,1"] // iPhone 6S
|| [[DeviceUtils platform] isEqualToString:@"iPhone8,2"]); // iPhone 6S Plus
}
-(void)generateSelectionFeedback{
if (selectionGenerator == nil){
selectionGenerator = [[UISelectionFeedbackGenerator alloc] init];
[selectionGenerator prepare];
}
[selectionGenerator selectionChanged];
[selectionGenerator prepare];
}
-(void)generateImpactFeedback:(UIImpactFeedbackStyle)style{
NSString *key = [[NSNumber numberWithInteger: style] stringValue];
if (impactGeneratorMap == nil)
impactGeneratorMap = [[NSMutableDictionary alloc] init];
if ([impactGeneratorMap objectForKey:key] == nil){
[impactGeneratorMap setValue:[[UIImpactFeedbackGenerator alloc] initWithStyle:style] forKey:key];
[[impactGeneratorMap objectForKey:key] prepare];
}
UIImpactFeedbackGenerator *generator = [impactGeneratorMap objectForKey:key];
[generator impactOccurred];
[generator prepare];
}
-(void)generateNotificationFeedback:(UINotificationFeedbackType)notificationType{
if (notificationGenerator == nil){
notificationGenerator = [[UINotificationFeedbackGenerator alloc] init];
[notificationGenerator prepare];
}
[notificationGenerator notificationOccurred:notificationType];
[notificationGenerator prepare];
}
// Thanks to this guard, we won't compile this code when we build for the old architecture.
#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params
{
return std::make_shared<facebook::react::NativeHapticFeedbackSpecJSI>(params);
}
#endif
@end