react-native-gleam 1.0.4 → 1.0.5

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.
@@ -11,6 +11,7 @@ import android.graphics.RectF
11
11
  import android.graphics.Shader
12
12
  import android.os.SystemClock
13
13
  import android.view.Choreographer
14
+ import android.view.View
14
15
  import android.view.animation.DecelerateInterpolator
15
16
  import androidx.annotation.UiThread
16
17
  import com.facebook.react.bridge.Arguments
@@ -171,6 +172,22 @@ class GleamView(context: Context) : ReactViewGroup(context) {
171
172
  }
172
173
  }
173
174
 
175
+ override fun onVisibilityChanged(changedView: View, visibility: Int) {
176
+ super.onVisibilityChanged(changedView, visibility)
177
+ if (!didAttach) return
178
+
179
+ if (visibility == VISIBLE) {
180
+ if (loading) {
181
+ registerClock()
182
+ invalidate()
183
+ } else if (!isTransitioning) {
184
+ contentOpacity = 1f
185
+ shimmerOpacity = 0f
186
+ invalidate()
187
+ }
188
+ }
189
+ }
190
+
174
191
  /** Called by ViewManager when the view is dropped */
175
192
  fun cleanup() {
176
193
  unregisterClock()
package/ios/GleamView.mm CHANGED
@@ -26,6 +26,7 @@ static GleamView * __strong *_views = NULL;
26
26
  static NSUInteger _viewCount = 0;
27
27
  static NSUInteger _viewCapacity = 0;
28
28
  static CADisplayLink *_displayLink;
29
+ static void *kHiddenKVOContext = &kHiddenKVOContext;
29
30
 
30
31
  static void _startDisplayLinkIfNeeded(void) {
31
32
  if (_displayLink) return;
@@ -103,6 +104,7 @@ static void _unregisterView(GleamView *view) {
103
104
  CGFloat _contentAlpha;
104
105
  CGFloat _lastSetChildrenAlpha;
105
106
  BOOL _didInitialSetup;
107
+ BOOL _isObservingHidden;
106
108
  }
107
109
 
108
110
  + (ComponentDescriptorProvider)componentDescriptorProvider
@@ -158,6 +160,9 @@ static void _unregisterView(GleamView *view) {
158
160
  @"transform": [NSNull null],
159
161
  };
160
162
  _shimmerLayer.locations = @[@0.0, @0.5, @1.0];
163
+
164
+ [self addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:kHiddenKVOContext];
165
+ _isObservingHidden = YES;
161
166
  }
162
167
  return self;
163
168
  }
@@ -236,6 +241,10 @@ static void _unregisterView(GleamView *view) {
236
241
 
237
242
  - (void)prepareForRecycle
238
243
  {
244
+ if (_isObservingHidden) {
245
+ [self removeObserver:self forKeyPath:@"hidden" context:kHiddenKVOContext];
246
+ _isObservingHidden = NO;
247
+ }
239
248
  [super prepareForRecycle];
240
249
  [self _unregisterClock];
241
250
  _isTransitioning = NO;
@@ -249,6 +258,9 @@ static void _unregisterView(GleamView *view) {
249
258
  _loading = YES;
250
259
  _wasLoading = YES;
251
260
  _didInitialSetup = NO;
261
+
262
+ [self addObserver:self forKeyPath:@"hidden" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:kHiddenKVOContext];
263
+ _isObservingHidden = YES;
252
264
  }
253
265
 
254
266
  // Invariant: a registered view (_isRegistered=YES) is held by the static
@@ -259,6 +271,10 @@ static void _unregisterView(GleamView *view) {
259
271
  // by the display link on the main thread. The view leaks in _views but no crash.
260
272
  - (void)dealloc
261
273
  {
274
+ if (_isObservingHidden) {
275
+ _isObservingHidden = NO;
276
+ [self removeObserver:self forKeyPath:@"hidden" context:kHiddenKVOContext];
277
+ }
262
278
  if (_isRegistered) {
263
279
  _isRegistered = NO;
264
280
  if ([NSThread isMainThread]) {
@@ -375,6 +391,36 @@ static void _unregisterView(GleamView *view) {
375
391
 
376
392
  #pragma mark - Private
377
393
 
394
+ - (void)observeValueForKeyPath:(NSString *)keyPath
395
+ ofObject:(id)object
396
+ change:(NSDictionary<NSKeyValueChangeKey,id> *)change
397
+ context:(void *)context
398
+ {
399
+ if (context != kHiddenKVOContext) {
400
+ [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
401
+ return;
402
+ }
403
+
404
+ BOOL wasHidden = [change[NSKeyValueChangeOldKey] boolValue];
405
+ BOOL isHidden = [change[NSKeyValueChangeNewKey] boolValue];
406
+
407
+ if (wasHidden && !isHidden) {
408
+ // hidden YES→NO: ancestor removed display:'none' — resync visual state
409
+ if (_loading) {
410
+ if (_shimmerLayer.superlayer != self.layer) {
411
+ [self.layer addSublayer:_shimmerLayer];
412
+ }
413
+ [self _registerClock];
414
+ } else if (!_isTransitioning) {
415
+ [self _setChildrenAlphaIfNeeded:1.0];
416
+ _shimmerOpacity = 0.0;
417
+ _shimmerLayer.opacity = 0.0;
418
+ [_shimmerLayer removeFromSuperlayer];
419
+ [self _unregisterClock];
420
+ }
421
+ }
422
+ }
423
+
378
424
  - (CGFloat)_computeProgressWithTime:(CFTimeInterval)now
379
425
  {
380
426
  CGFloat effectiveTime = fmax(now - _delay, 0.0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-gleam",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Native-powered shimmer loading effect for React Native",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",