Skip to content

Commit 9120b16

Browse files
feat: coalesced event (#592)
* feat: coalesced event * fix: revert upgrade changes * fix: revert upgrade changes * fix: typo * Apply suggestions from code review Co-authored-by: Jacob Parker <jacobparker1992@gmail.com> * fix: review * Update ios/RNCSafeAreaProvider.m Co-authored-by: Jacob Parker <jacobparker1992@gmail.com> * fix: format * fix: format * fix: rename * fix: format --------- Co-authored-by: Jacob Parker <jacobparker1992@gmail.com>
1 parent fee2881 commit 9120b16

6 files changed

+135
-18
lines changed

ios/RNCOnInsetsChangeEvent.h

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#import <Foundation/Foundation.h>
2+
#import <React/RCTEventDispatcherProtocol.h>
3+
4+
@interface RNCOnInsetsChangeEvent : NSObject <RCTEvent>
5+
6+
- (instancetype)initWithEventName:(NSString *)eventName
7+
reactTag:(NSNumber *)reactTag
8+
insets:(UIEdgeInsets)insets
9+
frame:(CGRect)frame
10+
coalescingKey:(uint16_t)coalescingKey NS_DESIGNATED_INITIALIZER;
11+
12+
@end

ios/RNCOnInsetsChangeEvent.m

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#import "RNCOnInsetsChangeEvent.h"
2+
#import <React/RCTAssert.h>
3+
4+
@implementation RNCOnInsetsChangeEvent {
5+
UIEdgeInsets _insets;
6+
CGRect _frame;
7+
uint16_t _coalescingKey;
8+
}
9+
10+
@synthesize eventName = _eventName;
11+
@synthesize viewTag = _viewTag;
12+
13+
- (instancetype)initWithEventName:(NSString *)eventName
14+
reactTag:(NSNumber *)reactTag
15+
insets:(UIEdgeInsets)insets
16+
frame:(CGRect)frame
17+
coalescingKey:(uint16_t)coalescingKey
18+
{
19+
RCTAssertParam(reactTag);
20+
21+
if ((self = [super init])) {
22+
_eventName = [eventName copy];
23+
_viewTag = reactTag;
24+
_frame = frame;
25+
_insets = insets;
26+
_coalescingKey = coalescingKey;
27+
}
28+
29+
return self;
30+
}
31+
32+
RCT_NOT_IMPLEMENTED(-(instancetype)init)
33+
34+
- (uint16_t)coalescingKey
35+
{
36+
return _coalescingKey;
37+
}
38+
39+
- (NSDictionary *)body
40+
{
41+
NSDictionary *body = @{
42+
@"insets" : @{
43+
@"top" : @(_insets.top),
44+
@"right" : @(_insets.right),
45+
@"bottom" : @(_insets.bottom),
46+
@"left" : @(_insets.left),
47+
},
48+
@"frame" : @{
49+
@"x" : @(_frame.origin.x),
50+
@"y" : @(_frame.origin.y),
51+
@"width" : @(_frame.size.width),
52+
@"height" : @(_frame.size.height),
53+
},
54+
};
55+
56+
return body;
57+
}
58+
59+
- (BOOL)canCoalesce
60+
{
61+
return YES;
62+
}
63+
64+
- (RNCOnInsetsChangeEvent *)coalesceWithEvent:(RNCOnInsetsChangeEvent *)newEvent
65+
{
66+
return newEvent;
67+
}
68+
69+
+ (NSString *)moduleDotMethod
70+
{
71+
return @"RCTEventEmitter.receiveEvent";
72+
}
73+
74+
- (NSArray *)arguments
75+
{
76+
return @[ self.viewTag, RCTNormalizeInputEventName(self.eventName), [self body] ];
77+
}
78+
79+
@end

ios/RNCSafeAreaProvider.h

+6
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44
#import <AppKit/AppKit.h>
55
#endif
66

7+
#import <React/RCTEventDispatcherProtocol.h>
78
#import <React/RCTView.h>
89

910
NS_ASSUME_NONNULL_BEGIN
1011

1112
@interface RNCSafeAreaProvider : RCTView
1213

14+
- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher NS_DESIGNATED_INITIALIZER;
15+
16+
// NOTE: currently these event props are only declared so we can export the
17+
// event names to JS - we don't call the blocks directly because events
18+
// need to be coalesced before sending, for performance reasons.
1319
@property (nonatomic, copy) RCTBubblingEventBlock onInsetsChange;
1420

1521
@end

ios/RNCSafeAreaProvider.m

+31-17
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,32 @@
11
#import "RNCSafeAreaProvider.h"
22

33
#import <React/RCTBridge.h>
4+
#import <React/RCTEventDispatcher.h>
45
#import <React/RCTUIManager.h>
6+
#import "RCTUIManagerObserverCoordinator.h"
7+
#import "RNCOnInsetsChangeEvent.h"
58
#import "RNCSafeAreaUtils.h"
69

10+
@interface RNCSafeAreaProvider () <RCTUIManagerObserver>
11+
12+
@end
13+
714
@implementation RNCSafeAreaProvider {
15+
id<RCTEventDispatcherProtocol> _eventDispatcher;
816
UIEdgeInsets _currentSafeAreaInsets;
917
CGRect _currentFrame;
1018
BOOL _initialInsetsSent;
1119
}
1220

13-
- (instancetype)init
21+
- (instancetype)initWithEventDispatcher:(id<RCTEventDispatcherProtocol>)eventDispatcher
1422
{
15-
if ((self = [super init])) {
23+
RCTAssertParam(eventDispatcher);
24+
25+
if ((self = [super initWithFrame:CGRectZero])) {
1626
#if !TARGET_OS_TV && !TARGET_OS_OSX
27+
28+
_eventDispatcher = eventDispatcher;
29+
1730
[NSNotificationCenter.defaultCenter addObserver:self
1831
selector:@selector(invalidateSafeAreaInsets)
1932
name:UIKeyboardDidShowNotification
@@ -58,6 +71,7 @@ - (void)invalidateSafeAreaInsets
5871
safeAreaInsets = NSEdgeInsetsZero;
5972
}
6073
#endif
74+
6175
CGRect frame = [self convertRect:self.bounds toView:RNCParentViewController(self).view];
6276

6377
if (_initialInsetsSent &&
@@ -69,27 +83,19 @@ - (void)invalidateSafeAreaInsets
6983
CGRectEqualToRect(frame, _currentFrame)) {
7084
return;
7185
}
72-
7386
_initialInsetsSent = YES;
7487
_currentSafeAreaInsets = safeAreaInsets;
7588
_currentFrame = frame;
7689

7790
[NSNotificationCenter.defaultCenter postNotificationName:RNCSafeAreaDidChange object:self userInfo:nil];
7891

79-
self.onInsetsChange(@{
80-
@"insets" : @{
81-
@"top" : @(safeAreaInsets.top),
82-
@"right" : @(safeAreaInsets.right),
83-
@"bottom" : @(safeAreaInsets.bottom),
84-
@"left" : @(safeAreaInsets.left),
85-
},
86-
@"frame" : @{
87-
@"x" : @(frame.origin.x),
88-
@"y" : @(frame.origin.y),
89-
@"width" : @(frame.size.width),
90-
@"height" : @(frame.size.height),
91-
},
92-
});
92+
RNCOnInsetsChangeEvent *onInsetsChangeEvent = [[RNCOnInsetsChangeEvent alloc] initWithEventName:@"onInsetsChange"
93+
reactTag:self.reactTag
94+
insets:safeAreaInsets
95+
frame:frame
96+
coalescingKey:0];
97+
98+
[_eventDispatcher sendEvent:onInsetsChangeEvent];
9399
}
94100

95101
- (void)layoutSubviews
@@ -99,4 +105,12 @@ - (void)layoutSubviews
99105
[self invalidateSafeAreaInsets];
100106
}
101107

108+
RCT_NOT_IMPLEMENTED(-(instancetype)initWithFrame : (CGRect)frame)
109+
RCT_NOT_IMPLEMENTED(-(instancetype)initWithCoder : (NSCoder *)aDecoder)
110+
111+
- (void)dealloc
112+
{
113+
[_eventDispatcher.bridge.uiManager.observerCoordinator removeObserver:self];
114+
}
115+
102116
@end

ios/RNCSafeAreaProviderManager.m

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ - (UIView *)view
1414
- (NSView *)view
1515
#endif
1616
{
17-
return [RNCSafeAreaProvider new];
17+
return [[RNCSafeAreaProvider alloc] initWithEventDispatcher:self.bridge.eventDispatcher];
1818
}
1919

2020
@end

ios/RNSafeAreaContext.xcodeproj/project.pbxproj

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
0C7844F027C02D03001807FB /* RNCSafeAreaProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 0C7844ED27C02D03001807FB /* RNCSafeAreaProvider.m */; };
2020
AA53A9EE2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m in Sources */ = {isa = PBXBuildFile; fileRef = AA53A9ED2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m */; };
2121
C923EDBC220C2C1A00D3100F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C923EDBB220C2C1A00D3100F /* SystemConfiguration.framework */; };
22+
D697AA982D6F1D0A009C6433 /* RNCChangeEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = D697AA972D6F1D08009C6433 /* RNCChangeEvent.m */; };
2223
/* End PBXBuildFile section */
2324

2425
/* Begin PBXCopyFilesBuildPhase section */
@@ -59,6 +60,8 @@
5960
AA53A9EC2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCSafeAreaViewEdgeModes.h; sourceTree = "<group>"; };
6061
AA53A9ED2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCSafeAreaViewEdgeModes.m; sourceTree = "<group>"; };
6162
C923EDBB220C2C1A00D3100F /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
63+
D697AA962D6F1CE5009C6433 /* RNCChangeEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNCChangeEvent.h; sourceTree = "<group>"; };
64+
D697AA972D6F1D08009C6433 /* RNCChangeEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNCChangeEvent.m; sourceTree = "<group>"; };
6265
/* End PBXFileReference section */
6366

6467
/* Begin PBXFrameworksBuildPhase section */
@@ -84,6 +87,8 @@
8487
58B511D21A9E6C8500147676 = {
8588
isa = PBXGroup;
8689
children = (
90+
D697AA972D6F1D08009C6433 /* RNCChangeEvent.m */,
91+
D697AA962D6F1CE5009C6433 /* RNCChangeEvent.h */,
8792
AA53A9EC2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.h */,
8893
AA53A9ED2A321C01009AB3B2 /* RNCSafeAreaViewEdgeModes.m */,
8994
0C7844EE27C02D03001807FB /* Fabric */,
@@ -183,6 +188,7 @@
183188
0C7844E827C02CEE001807FB /* RNCSafeAreaView.m in Sources */,
184189
0C7844E627C02CEE001807FB /* RNCSafeAreaViewEdges.m in Sources */,
185190
0C7844E527C02CEE001807FB /* RNCSafeAreaViewManager.m in Sources */,
191+
D697AA982D6F1D0A009C6433 /* RNCChangeEvent.m in Sources */,
186192
0C7844EF27C02D03001807FB /* RNCSafeAreaContext.mm in Sources */,
187193
0C7844E127C02CEE001807FB /* RNCSafeAreaViewLocalData.m in Sources */,
188194
0C7844E227C02CEE001807FB /* RNCSafeAreaViewMode.m in Sources */,

0 commit comments

Comments
 (0)