cobrowse-sdk-react-native 2.11.2-unredaction.0 → 2.12.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.
@@ -30,5 +30,5 @@ android {
30
30
 
31
31
  dependencies {
32
32
  implementation 'com.facebook.react:react-native:+' // support react-native-v0.22-rc+
33
- implementation 'io.cobrowse:cobrowse-sdk-android:2.21.4'
33
+ implementation 'io.cobrowse:cobrowse-sdk-android:2.23.0'
34
34
  }
@@ -0,0 +1,22 @@
1
+ package io.cobrowse.reactnative;
2
+
3
+ import android.app.Activity;
4
+ import android.view.View;
5
+
6
+ import java.util.List;
7
+
8
+ import androidx.annotation.NonNull;
9
+ import androidx.annotation.Nullable;
10
+
11
+ public abstract class CobrowseIO {
12
+ public interface Delegate {
13
+ }
14
+
15
+ public interface RedactionDelegate extends Delegate {
16
+ @Nullable
17
+ List<View> redactedViews(@NonNull final Activity activity);
18
+
19
+ @Nullable
20
+ List<View> unredactedViews(@NonNull final Activity activity);
21
+ }
22
+ }
@@ -4,6 +4,8 @@ import android.app.Activity;
4
4
  import android.os.Handler;
5
5
  import android.util.Log;
6
6
  import android.view.View;
7
+ import android.view.ViewGroup;
8
+ import android.view.ViewParent;
7
9
 
8
10
  import com.facebook.react.bridge.Promise;
9
11
  import com.facebook.react.bridge.ReactApplicationContext;
@@ -15,13 +17,10 @@ import com.facebook.react.modules.core.DeviceEventManagerModule;
15
17
  import com.facebook.react.uimanager.NativeViewHierarchyManager;
16
18
  import com.facebook.react.uimanager.UIBlock;
17
19
  import com.facebook.react.uimanager.UIManagerModule;
18
- import com.facebook.react.views.view.ReactViewGroup;
19
20
 
20
21
  import java.util.ArrayList;
21
- import java.util.HashMap;
22
22
  import java.util.HashSet;
23
23
  import java.util.List;
24
- import java.util.Map;
25
24
  import java.util.Set;
26
25
 
27
26
  import androidx.annotation.NonNull;
@@ -35,7 +34,7 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule
35
34
  CobrowseIO.SessionLoadDelegate, CobrowseIO.RedactionDelegate,
36
35
  CobrowseIO.RemoteControlRequestDelegate {
37
36
 
38
- private static final String SESSION_LOADED = "session.loaded";
37
+ private static final String SESSION_LOADED = "session.loaded";
39
38
  private static final String SESSION_UPDATED = "session.updated";
40
39
  private static final String SESSION_ENDED = "session.ended";
41
40
  private static final String SESSION_REQUESTED = "session.requested";
@@ -60,6 +59,8 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule
60
59
  });
61
60
  }
62
61
 
62
+ public static io.cobrowse.reactnative.CobrowseIO.Delegate delegate;
63
+
63
64
  @NonNull
64
65
  public String getName() {
65
66
  return "CobrowseIO";
@@ -93,6 +94,11 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule
93
94
  .emit(SESSION_REQUESTED, Conversion.convert(session));
94
95
  }
95
96
 
97
+ @Override
98
+ public void handleRemoteControlRequest(@NonNull Activity activity, @NonNull Session session) {
99
+ // no-op, this will be handed on the JS side via an "updated" event handler
100
+ // this stub just disables the default native prompt in the SDK
101
+ }
96
102
  @ReactMethod
97
103
  public void setUnredactedTags(final ReadableArray reactTags, final Promise promise) {
98
104
  synchronized (unredactedTags) {
@@ -103,7 +109,7 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule
103
109
  }
104
110
  }
105
111
 
106
- private Set<View> unredactedViews() {
112
+ private Set<View> getUnredactedViews(@NonNull final Activity activity) {
107
113
  synchronized (unredactedTags) {
108
114
  HashSet<View> unredacted = new HashSet<>();
109
115
  for (Integer i : unredactedTags) {
@@ -113,68 +119,87 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule
113
119
  Log.i("CobrowseIO", "Failed to find unredacted view for tag " + i + ", error = " + e.getMessage());
114
120
  }
115
121
  }
122
+ if (delegate instanceof io.cobrowse.reactnative.CobrowseIO.RedactionDelegate) {
123
+ List<View> views = ((io.cobrowse.reactnative.CobrowseIO.RedactionDelegate) delegate).unredactedViews(activity);
124
+ if (views != null) unredacted.addAll(views);
125
+ }
116
126
  return unredacted;
117
127
  }
118
128
  }
119
129
 
120
- @Override
121
- public void handleRemoteControlRequest(@NonNull Activity activity, @NonNull Session session) {
122
- // no-op, this will be handed on the JS side via an "updated" event handler
123
- // this stub just disables the default native prompt in the SDK
130
+ private Set<View> getRedactedViews(@NonNull final Activity activity) {
131
+ HashSet<View> redacted = new HashSet<>(RedactedViewManager.redactedViews.keySet());
132
+ if (delegate instanceof io.cobrowse.reactnative.CobrowseIO.RedactionDelegate) {
133
+ List<View> views = ((io.cobrowse.reactnative.CobrowseIO.RedactionDelegate) delegate).redactedViews(activity);
134
+ if (views != null) redacted.addAll(views);
135
+ }
136
+ return redacted;
124
137
  }
125
138
 
126
139
  @Override
127
- public List<View> redactedViews(@NonNull final Activity activity) {
128
- HashSet<View> redacted = new HashSet<>();
129
- Set<View> unredacted = unredactedViews();
130
- // By default everything is redacted for Activities that contain
131
- // a ReactRootView.
132
- Set<View> rootViews = TreeUtils.findAllClosest(
133
- activity.getWindow().getDecorView().getRootView(),
134
- new Predicate<View>() {
135
- @Override
136
- public boolean test(View view) {
137
- return TreeUtils.isReactView(view);
138
- }
139
- });
140
- for (View root : rootViews) redacted.addAll(TreeUtils.directChildren(root));
141
-
142
- // Now we can actually start working out what should be unredacted
143
- // First work out the set of all parents of unredact()'ed nodes
144
- // Ignores nested unredacted nodes
145
- HashSet<View> unredactedParents = new HashSet<>();
146
- for (View v : unredacted) {
147
- if (!TreeUtils.hasAnyParent(v, unredacted))
148
- unredactedParents.addAll(TreeUtils.reactParents(v));
140
+ public List<View> redactedViews(@NonNull final Activity activity) {
141
+ final Set<View> redacted = this.getRedactedViews(activity);
142
+ final Set<View> unredacted = this.getUnredactedViews(activity);
143
+
144
+ // Project all unredactions to the root to get the full set of unredacted nodes
145
+ HashSet<View> projectedUnredacted = new HashSet<>();
146
+ for (View view : unredacted) {
147
+ projectedUnredacted.add(view);
148
+ projectedUnredacted.addAll(TreeUtils.allParents(view));
149
+ }
150
+
151
+ // Work out which nodes are explicitly redacted but need to be unredacted
152
+ // due to a nested unredaction tag (these redactions will be moved towards the
153
+ // leaves of the view hierarchy instead)
154
+ HashSet<View> redactedProjectedUnredactions = new HashSet<>(redacted);
155
+ redactedProjectedUnredactions.retainAll(projectedUnredacted);
156
+
157
+ // Start to build the set of redactions we should actually apply. We start off with
158
+ // the set of explicitly redacted nodes
159
+ HashSet<View> toRedact = new HashSet<>(redacted);
160
+
161
+ // remove any redactions that have unredacted decendants (i.e. any that appear in the
162
+ // projection of the unredaction). These are the redacted nodes we need to move towards
163
+ // the leaves of the tree
164
+ toRedact.removeAll(redactedProjectedUnredactions);
165
+
166
+ // Work out the set of all nodes that are siblings of any projected unredacted node
167
+ HashSet<View> projectedUnredactionSiblings = new HashSet<>();
168
+ for (View view : projectedUnredacted) {
169
+ ViewParent parent = view.getParent();
170
+ if (parent instanceof ViewGroup)
171
+ projectedUnredactionSiblings.addAll(TreeUtils.directChildren((ViewGroup) parent));
172
+ }
173
+
174
+ // Subtract the projected unredactions from the set of all siblings of projected
175
+ // unredactions. i.e. subtract things that should be definitely unredacted to leave
176
+ // a set we're not sure yet whether to redact or not
177
+ HashSet<View> potentiallyRedactedUnredactedSiblings = new HashSet<View>(projectedUnredactionSiblings);
178
+ potentiallyRedactedUnredactedSiblings.removeAll(projectedUnredacted);
179
+
180
+ // for each node we're not sure about yet, check if the closest redacted or unredacted ancestor
181
+ // is a redacted node, if so this descendant should also be redacted
182
+ for (View view : potentiallyRedactedUnredactedSiblings) {
183
+ View closest = TreeUtils.closest(view, new Predicate<View>() {
184
+ @Override
185
+ public boolean test(View view) {
186
+ return redacted.contains(view) || unredacted.contains(view);
187
+ }
188
+ });
189
+ if (redacted.contains(closest)) toRedact.add(view);
190
+ }
191
+
192
+ // Remove any empty ViewGroup from the redacted set, they're often used for wrapping
193
+ // or sizing other elements, and do not usually need to be redacted
194
+ // If it's absolutely necessary they are redacted, they can always be replaced with
195
+ // a <Redacted> tag instead
196
+ for (View v : new HashSet<>(toRedact)) {
197
+ if (v instanceof ViewGroup && ((ViewGroup) v).getChildCount() == 0) {
198
+ toRedact.remove(v);
149
199
  }
200
+ }
150
201
 
151
- // Then work out the set of all direct children of any unredacted parents
152
- // This should give us the set including unredacted nodes, their siblings,
153
- // and all their parents.
154
- for (View parent : unredactedParents) redacted.addAll(TreeUtils.directChildren(parent));
155
-
156
- // Then we can subtract the set of unredacted parents to find just the
157
- // set of unredacted nodes that are leaves of the parent subtree
158
- redacted.removeAll(unredactedParents);
159
-
160
- // Finally we can subtract the set of unredacted views to get the minimal
161
- // set of redactions that will redact everything that's not explicitly unredacted
162
- // whilst allowing the unredacted views to be visible
163
- redacted.removeAll(unredacted);
164
-
165
- // Remove any empty ReactViewGroup from the redacted set, they're often used for wrapping
166
- // or sizing other elements, and do not usually need to be redacted
167
- // If it's absolutely necessary they are redacted, they can always be replaced with
168
- // a <Redacted> tag instead
169
- for (View v : new HashSet<>(redacted))
170
- if (v instanceof ReactViewGroup && ((ReactViewGroup) v).getChildCount() == 0)
171
- redacted.remove(v);
172
-
173
- // Any explicitly redacted views surrounded by <Redacted> tags take precedence, so
174
- // re-add any tagged as such that the process above might have removed
175
- redacted.addAll(RedactedViewManager.redactedViews.keySet());
176
-
177
- return new ArrayList<>(redacted);
202
+ return new ArrayList<>(toRedact);
178
203
  }
179
204
 
180
205
  @ReactMethod
@@ -350,4 +375,5 @@ public class CobrowseIOModule extends ReactContextBaseJavaModule
350
375
  public void accessibilityServiceIsRunning(final Promise promise) {
351
376
  promise.resolve(CobrowseAccessibilityService.isRunning(getReactApplicationContext()));
352
377
  }
378
+
353
379
  }
@@ -4,11 +4,7 @@ import android.view.View;
4
4
  import android.view.ViewGroup;
5
5
  import android.view.ViewParent;
6
6
 
7
- import com.facebook.react.ReactRootView;
8
- import com.facebook.react.views.view.ReactViewGroup;
9
-
10
7
  import java.util.ArrayList;
11
- import java.util.Collections;
12
8
  import java.util.HashSet;
13
9
  import java.util.List;
14
10
  import java.util.Set;
@@ -38,32 +34,10 @@ class TreeUtils {
38
34
  return parents;
39
35
  }
40
36
 
41
- public static List<View> reactParents(View root) {
42
- List<View> parents = allParents(root);
43
- ArrayList<View> reactParents = new ArrayList<>(parents);
44
- for (View v : parents) {
45
- if (isReactView(v)) break;
46
- reactParents.remove(v);
47
- }
48
- return reactParents;
49
- }
50
-
51
- public static Set<View> findAllClosest(View root, Predicate<View> predicate) {
52
- HashSet<View> found = new HashSet<>();
53
- if (predicate.test(root)) found.add(root);
54
- else {
55
- for (View v : directChildren(root)) {
56
- found.addAll(findAllClosest(v, predicate));
57
- }
58
- }
59
- return found;
60
- }
61
-
62
- public static boolean isReactView(View view) {
63
- return view instanceof ReactRootView || view instanceof ReactViewGroup;
64
- }
65
-
66
- public static boolean hasAnyParent(View node, Set<View> matches) {
67
- return !Collections.disjoint(TreeUtils.allParents(node), matches);
37
+ public static View closest(View root, Predicate<View> predicate) {
38
+ if (predicate.test(root)) return root;
39
+ ViewParent parent = root.getParent();
40
+ if (parent instanceof ViewGroup) return closest((ViewGroup)parent, predicate);
41
+ return null;
68
42
  }
69
43
  }
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
11
11
  s.homepage = package["homepage"]
12
12
  s.source = { :git => 'https://github.com/cobrowseio/cobrowse-sdk-react-native.git' }
13
13
  s.platform = :ios, '9.0'
14
- s.dependency 'CobrowseIO/XCFramework', '2.19.0'
14
+ s.dependency 'CobrowseIO/XCFramework', '2.21.2'
15
15
  s.dependency 'React'
16
16
  s.source_files = 'ios/*.{h,m}'
17
17
  end
@@ -4,12 +4,6 @@
4
4
 
5
5
  +(NSArray*) allParents: (UIView*) root;
6
6
 
7
- +(NSArray*) reactParents: (UIView*) root;
8
-
9
- +(NSMutableSet*) findAllClosest: (BOOL (^)(UIView* view))predicate under: (UIView*) root;
10
-
11
- +(bool) isReactView: (UIView*) view;
12
-
13
- +(bool) hasAnyParent: (UIView*) view matches: (NSSet*) matches;
7
+ +(UIView*) closest: (BOOL (^)(UIView* view))predicate from: (UIView*) root;
14
8
 
15
9
  @end
@@ -1,6 +1,4 @@
1
1
  #import "RCTCBIOTreeUtils.h"
2
- #import <React/RCTRootView.h>
3
- #import <React/RCTView.h>
4
2
 
5
3
  @implementation RCTCBIOTreeUtils
6
4
 
@@ -14,34 +12,10 @@
14
12
  return parents;
15
13
  }
16
14
 
17
- +(NSArray*) reactParents: (UIView*) root {
18
- NSArray* allParents = [self allParents: root];
19
- NSMutableArray* reactParents = [allParents mutableCopy];
20
- for (id view in allParents) {
21
- if ([self isReactView:view]) break;
22
- [reactParents removeObject: view];
23
- }
24
- return reactParents;
25
- }
26
-
27
- +(NSMutableSet*) findAllClosest: (BOOL (^)(UIView* view))predicate under: (UIView*) root {
28
- NSMutableSet* found = [NSMutableSet set];
29
- if (predicate(root)) [found addObject:root];
30
- else {
31
- for (UIView* child in root.subviews) {
32
- [found addObjectsFromArray: [self findAllClosest:predicate under:child].allObjects];
33
- }
34
- }
35
- return found;
36
- }
37
-
38
- +(bool) isReactView: (UIView*) view {
39
- return [view isKindOfClass:RCTRootView.class] || [view isKindOfClass: RCTView.class];
40
- }
41
-
42
- +(bool) hasAnyParent: (UIView*) view matches: (NSSet*) matches {
43
- NSSet* parents = [NSSet setWithArray: [self allParents:view]];
44
- return [parents intersectsSet: matches];
15
+ +(UIView*) closest: (BOOL (^)(UIView* view))predicate from: (UIView*) root {
16
+ if (predicate(root)) return root;
17
+ else if (!root.superview) return nil;
18
+ else return [self closest:predicate from:root.superview];
45
19
  }
46
20
 
47
21
  @end
@@ -4,6 +4,20 @@
4
4
 
5
5
  @import CobrowseIO;
6
6
 
7
+
8
+ @protocol RCTCobrowseIODelegate <NSObject>
9
+
10
+ @optional
11
+
12
+ -(nonnull NSArray<UIView*>*) cobrowseRedactedViewsForViewController: (nonnull UIViewController*) vc;
13
+ -(nonnull NSArray<UIView*>*) cobrowseUnredactedViewsForViewController: (nonnull UIViewController*) vc;
14
+
15
+ @end
16
+
17
+
7
18
  @interface RCTCobrowseIO: RCTEventEmitter <RCTBridgeModule, CobrowseIODelegate>
8
19
 
20
+ @property (class, nullable) id<RCTCobrowseIODelegate> delegate;
21
+
9
22
  @end
23
+
@@ -14,6 +14,8 @@
14
14
  #define SESSION_ENDED "session.ended"
15
15
  #define SESSION_REQUESTED "session.requested"
16
16
 
17
+ static id<RCTCobrowseIODelegate> _Nullable _delegate;
18
+
17
19
  @import CobrowseIO;
18
20
 
19
21
  @implementation RCTCobrowseIO {
@@ -32,6 +34,14 @@ RCT_EXPORT_MODULE();
32
34
  return self;
33
35
  }
34
36
 
37
+ +(id<RCTCobrowseIODelegate>)delegate {
38
+ return _delegate;
39
+ }
40
+
41
+ +(void)setDelegate:(id<RCTCobrowseIODelegate>)delegate {
42
+ _delegate = delegate;
43
+ }
44
+
35
45
  + (BOOL)requiresMainQueueSetup {
36
46
  return YES;
37
47
  }
@@ -56,7 +66,15 @@ RCT_EXPORT_MODULE();
56
66
  if (hasListeners) [self sendEventWithName:@SESSION_LOADED body:[session toDict]];
57
67
  }
58
68
 
59
- -(NSSet<UIView*>*) unredactedViews {
69
+ -(NSSet<UIView*>*) redactedViews: (UIViewController*) vc {
70
+ NSMutableSet* views = [CBIOCobrowseRedactedManager.redactedViews mutableCopy];
71
+ if ([RCTCobrowseIO.delegate respondsToSelector:@selector(cobrowseRedactedViewsForViewController:)]) {
72
+ [views addObjectsFromArray: [RCTCobrowseIO.delegate cobrowseRedactedViewsForViewController:vc]];
73
+ }
74
+ return views;
75
+ }
76
+
77
+ -(NSSet<UIView*>*) unredactedViews: (UIViewController*) vc {
60
78
  NSMutableSet* views = [NSMutableSet set];
61
79
  @synchronized(unredactedTags) {
62
80
  for (id tag in unredactedTags) {
@@ -64,6 +82,9 @@ RCT_EXPORT_MODULE();
64
82
  if (v != nil) [views addObject:v];
65
83
  }
66
84
  }
85
+ if ([RCTCobrowseIO.delegate respondsToSelector:@selector(cobrowseUnredactedViewsForViewController:)]) {
86
+ [views addObjectsFromArray: [RCTCobrowseIO.delegate cobrowseUnredactedViewsForViewController:vc]];
87
+ }
67
88
  return views;
68
89
  }
69
90
 
@@ -85,59 +106,60 @@ RCT_EXPORT_MODULE();
85
106
  }
86
107
 
87
108
  -(NSArray<UIView *> *)cobrowseRedactedViewsForViewController:(UIViewController *)vc {
88
- NSMutableSet* redacted = [NSMutableSet set];
89
- NSSet* unredacted = self.unredactedViews;
90
-
91
- // By default everything managed by react is redacted for view controllers
92
- // that contain react views. If we were to always redact vc.view this would lead
93
- // to instances where windows that do not contain a RN context could
94
- // not be unredacted.
95
- // A simple example of this is the overlay window that cobrowse adds to
96
- // render its annotations. This window sits on top of all the other windows
97
- // and would always be redacted, effecivley redacting the entire screen all
98
- // the time.
99
- // To get around this, we only redact views below RCTViews or RCTRootViews
100
- // (not inclusive), as then it's always possible to add an unredact()'ed component
101
- // around a subview in the react tree to make parent visible.
102
- NSSet* rootViews = [RCTCBIOTreeUtils findAllClosest:^BOOL(UIView *view) {
103
- return [RCTCBIOTreeUtils isReactView: view];
104
- } under: vc.view];
105
- for (UIView* v in rootViews) [redacted addObjectsFromArray: v.subviews];
106
-
107
- // Now we can actually start working out what should be unredacted
108
- // First work out the set of all parents of unredact()'ed nodes
109
- // that are inside a react view (ignoring any nested unredaction)
110
- NSMutableSet* unredactedParents = [NSMutableSet set];
109
+ NSSet* redacted = [self redactedViews: vc];
110
+ NSSet* unredacted = [self unredactedViews: vc];
111
+
112
+ // Project all unredactions to the root to get the full set of unredacted nodes
113
+ NSMutableSet* projectedUnredacted = [NSMutableSet set];
111
114
  for (id view in unredacted) {
112
- if (![RCTCBIOTreeUtils hasAnyParent:view matches:unredacted])
113
- [unredactedParents addObjectsFromArray: [RCTCBIOTreeUtils reactParents: view]];
115
+ [projectedUnredacted addObject:view];
116
+ [projectedUnredacted addObjectsFromArray: [RCTCBIOTreeUtils allParents: view]];
114
117
  }
115
- // Then work out the set of all direct children of any unredacted parents
116
- // This should give us the set including unredacted nodes, their siblings,
117
- // and all their parents.
118
- for (UIView* parent in unredactedParents) [redacted addObjectsFromArray: parent.subviews];
119
-
120
- // Then we can subtract the set of unredacted parents to find just the
121
- // set of unredacted nodes that are leaves of the parent subtree
122
- for (id v in unredactedParents) [redacted removeObject:v];
123
-
124
- // Finally we can subtract the set of unredacted views to get the minimal
125
- // set of redactions that will redact everything that's not explicitly unredacted
126
- // whilst allowing the unredacted views to be visible
127
- for (UIView* v in unredacted) [redacted removeObject:v];
128
118
 
119
+ // Work out which nodes are explicitly redacted but need to be unredacted
120
+ // due to a nested unredaction tag (these redactions will be moved towards the
121
+ // leaves of the view hierarchy instead)
122
+ NSMutableSet* redactedProjectedUnredactions = [redacted mutableCopy];
123
+ [redactedProjectedUnredactions intersectSet: projectedUnredacted];
124
+
125
+ // Start to build the set of redactions we should actually apply. We start off with
126
+ // the set of explicitly redacted nodes
127
+ NSMutableSet* toRedact = [redacted mutableCopy];
128
+
129
+ // remove any redactions that have unredacted decendants (i.e. any that appear in the
130
+ // projection of the unredaction). These are the redacted nodes we need to move towards
131
+ // the leaves of the tree
132
+ [toRedact minusSet: redactedProjectedUnredactions];
133
+
134
+ // Work out the set of all nodes that are siblings of any projected unredacted node
135
+ NSMutableSet* projectedUnredactionSiblings = [NSMutableSet set];
136
+ for (UIView* view in projectedUnredacted) {
137
+ [projectedUnredactionSiblings addObjectsFromArray: view.superview.subviews];
138
+ }
139
+
140
+ // Subtract the projected unredactions from the set of all siblings of projected
141
+ // unredactions. i.e. subtract things that should be definitely unredacted to leave
142
+ // a set we're not sure yet whether to redact or not
143
+ NSMutableSet* potentiallyRedactedUnredactedSiblings = [projectedUnredactionSiblings mutableCopy];
144
+ [potentiallyRedactedUnredactedSiblings minusSet:projectedUnredacted];
145
+
146
+ // for each node we're not sure about yet, check if the closest redacted or unredacted ancestor
147
+ // is a redacted node, if so this descendant should also be redacted
148
+ for (UIView* view in potentiallyRedactedUnredactedSiblings) {
149
+ UIView* closest = [RCTCBIOTreeUtils closest:^BOOL(UIView *v) {
150
+ return [redacted containsObject:v] || [unredacted containsObject:v];
151
+ } from: view];
152
+ if ([redacted containsObject: closest]) [toRedact addObject: view];
153
+ }
154
+
129
155
  // Remove any empty RCTViews from the redacted set, they're often used for wrapping
130
156
  // or sizing other elements, and do not usually need to be redacted
131
157
  // If it's absolutely necessary they are redacted, they can always be replaced with
132
158
  // a <Redacted> tag instead
133
- for (UIView* v in [redacted copy])
134
- if ([v isKindOfClass:RCTView.class] && v.subviews.count == 0) [redacted removeObject: v];
135
-
136
- // Any explicitly redacted views surroudned by <Redacted> tags take precedence, so
137
- // re-add any tagged as such that the process above might have removed
138
- for (id v in CBIOCobrowseRedactedManager.redactedViews.allObjects) [redacted addObject: v];
159
+ for (UIView* v in [toRedact copy])
160
+ if ([v isKindOfClass:RCTView.class] && v.subviews.count == 0) [toRedact removeObject: v];
139
161
 
140
- return redacted.allObjects;;
162
+ return toRedact.allObjects;
141
163
  }
142
164
 
143
165
  - (bool) cobrowseShouldCaptureWindow:(UIWindow *)window {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cobrowse-sdk-react-native",
3
- "version": "2.11.2-unredaction.0",
3
+ "version": "2.12.0",
4
4
  "description": "Cobrowse SDK for React Native",
5
5
  "main": "js/index.js",
6
6
  "types": "ts/index.d.ts",
@@ -27,17 +27,17 @@
27
27
  ],
28
28
  "license": "Apache-2.0",
29
29
  "optionalDependencies": {
30
- "@types/react": "^17.0.38",
31
- "@types/react-native": "^0.66.15"
30
+ "@types/react": "^18.0.18",
31
+ "@types/react-native": "^0.69.6"
32
32
  },
33
33
  "dependencies": {
34
34
  "lodash": "^4.17.21"
35
35
  },
36
36
  "devDependencies": {
37
- "@types/react": "^17.0.38",
38
- "@types/react-native": "^0.66.15",
39
- "nodemon": "^2.0.15",
37
+ "@types/react": "^18.0.18",
38
+ "@types/react-native": "^0.69.6",
39
+ "nodemon": "^2.0.19",
40
40
  "ts-standard": "^11.0.0",
41
- "typescript": "^4.5.5"
41
+ "typescript": "^4.8.2"
42
42
  }
43
43
  }