/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.react.views.swiperefresh;

import android.support.v4.widget.SwipeRefreshLayout;
import android.view.MotionEvent;

import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.events.NativeGestureUtil;
import com.facebook.react.uimanager.PixelUtil;

/**
 * Basic extension of {@link SwipeRefreshLayout} with ReactNative-specific functionality.
 */
public class ReactSwipeRefreshLayout extends SwipeRefreshLayout {

  private static final float DEFAULT_CIRCLE_TARGET = 64;

  private boolean mDidLayout = false;

  private boolean mRefreshing = false;
  private float mProgressViewOffset = 0;


  public ReactSwipeRefreshLayout(ReactContext reactContext) {
    super(reactContext);
  }

  @Override
  public void setRefreshing(boolean refreshing) {
    mRefreshing = refreshing;

    // `setRefreshing` must be called after the initial layout otherwise it
    // doesn't work when mounting the component with `refreshing = true`.
    // Known Android issue: https://code.google.com/p/android/issues/detail?id=77712
    if (mDidLayout) {
      super.setRefreshing(refreshing);
    }
  }

  public void setProgressViewOffset(float offset) {
    mProgressViewOffset = offset;

    // The view must be measured before calling `getProgressCircleDiameter` so
    // don't do it before the initial layout.
    if (mDidLayout) {
      int diameter = getProgressCircleDiameter();
      int start = Math.round(PixelUtil.toPixelFromDIP(offset)) - diameter;
      int end = Math.round(PixelUtil.toPixelFromDIP(offset + DEFAULT_CIRCLE_TARGET) - diameter);
      setProgressViewOffset(false, start, end);
    }
  }

  @Override
  public void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);

    if (!mDidLayout) {
      mDidLayout = true;

      // Update values that must be set after initial layout.
      setProgressViewOffset(mProgressViewOffset);
      setRefreshing(mRefreshing);
    }
  }

  @Override
  public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (super.onInterceptTouchEvent(ev)) {
      NativeGestureUtil.notifyNativeGestureStarted(this, ev);
      return true;
    }
    return false;
  }
}

@@ -436,16 +436,55 @@
 onEvent;
+%0Aimport android.view.ViewConfiguration;
 %0A%0Aimport
@@ -524,16 +524,63 @@
 ontext;%0A
+import com.facebook.react.uimanager.PixelUtil;%0A
 import c
@@ -636,55 +636,8 @@
 til;
-%0Aimport com.facebook.react.uimanager.PixelUtil;
 %0A%0A/*
@@ -895,17 +895,16 @@
  false;%0A
-%0A
   privat
@@ -975,16 +975,102 @@
 et = 0;%0A
+  private int mTouchSlop;%0A  private float mPrevTouchX;%0A  private boolean mIntercepted;
 %0A%0A  publ
@@ -1150,16 +1150,91 @@
 ntext);%0A
+    mTouchSlop = ViewConfiguration.get(reactContext).getScaledTouchSlop();%0A
   %7D%0A%0A  @
@@ -2495,32 +2495,573 @@
 ng);%0A    %7D%0A  %7D%0A%0A
+  /**%0A   * %7B@link SwipeRefreshLayout%7D overrides %7B@link ViewGroup#requestDisallowInterceptTouchEvent%7D and%0A   * swallows it. This means that any component underneath SwipeRefreshLayout will now interact%0A   * incorrectly with Views that are above SwipeRefreshLayout. We fix that by transmitting the call%0A   * to this View's parents.%0A   */%0A  @Override%0A  public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) %7B%0A    if (getParent() != null) %7B%0A      getParent().requestDisallowInterceptTouchEvent(disallowIntercept);%0A    %7D%0A  %7D%0A%0A
   @Override%0A  pu
@@ -3121,16 +3121,49 @@
     if (
+shouldInterceptTouchEvent(ev) && 
 super.on
@@ -3297,11 +3297,847 @@
 lse;%0A  %7D
+%0A%0A  /**%0A   * %7B@link SwipeRefreshLayout%7D completely bypasses ViewGroup's %22disallowIntercept%22 by overriding%0A   * %7B@link ViewGroup#onInterceptTouchEvent%7D and never calling super.onInterceptTouchEvent().%0A   * This means that horizontal scrolls will always be intercepted, even though they shouldn't, so%0A   * we have to check for that manually here.%0A   */%0A  private boolean shouldInterceptTouchEvent(MotionEvent ev) %7B%0A    switch (ev.getAction()) %7B%0A      case MotionEvent.ACTION_DOWN:%0A        mPrevTouchX = ev.getX();%0A        mIntercepted = false;%0A        break;%0A%0A      case MotionEvent.ACTION_MOVE:%0A        final float eventX = ev.getX();%0A        final float xDiff = Math.abs(eventX - mPrevTouchX);%0A%0A        if (mIntercepted %7C%7C xDiff %3E mTouchSlop) %7B%0A          mIntercepted = true;%0A          return false;%0A        %7D%0A    %7D%0A    return true;%0A  %7D
 %0A%7D%0A

Fix ReactSwipeRefreshLayout