hunk.code_window:   NSString *whenInUseUsageDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"];
     if (!(alwaysUsageDescription || whenInUseUsageDescription)) {
       EXFatal(EXErrorWithMessage(@"This app is missing NSLocationAlwaysUsageDescription or NSLocationWhenInUseUsageDescription, so location services will fail. Add one of these keys to your bundle's Info.plist."));
       systemStatus = kCLAuthorizationStatusDenied;
     } else {
       systemStatus = [CLLocationManager authorizationStatus];
     }
  
hunk.labels: keep replace replace keep keep keep keep keep
hunk.after_edit:   if (!whenInUseUsageDescription) {
       EXFatal(EXErrorWithMessage(@"This app is missing NSLocationWhenInUseUsageDescription, so location services will fail. Add one of these keys to your bundle's Info.plist."));
  
hunk.file_path: modules/expo-permissions/ios/EXPermissions/EXLocationRequester.m
hunk.type: replace
file: package versioned.host.exp.exponent.modules.api.components.gesturehandler;
  
  import android.content.Context;
  import android.os.Handler;
  import android.view.MotionEvent;
  
  public class LongPressGestureHandler extends GestureHandler<LongPressGestureHandler> {
  
    private static final long DEFAULT_MIN_DURATION_MS = 500; // 1 sec
    private static float DEFAULT_MAX_DIST_DP = 10; // 20dp
  
    private long mMinDurationMs = DEFAULT_MIN_DURATION_MS;
    private float mMaxDistSq;
    private float mStartX, mStartY;
    private Handler mHandler;
  
    public LongPressGestureHandler(Context context) {
      setShouldCancelWhenOutside(true);
      mMaxDistSq = DEFAULT_MAX_DIST_DP * context.getResources().getDisplayMetrics().density;
    }
  
    public void setMinDurationMs(long minDurationMs) {
      mMinDurationMs = minDurationMs;
    }
  
    public LongPressGestureHandler setMaxDist(float maxDist) {
      mMaxDistSq = maxDist * maxDist;
      return this;
    }
  
    @Override
    protected void onHandle(MotionEvent event) {
      if (getState() == STATE_UNDETERMINED) {
        begin();
        mStartX = event.getRawX();
        mStartY = event.getRawY();
        mHandler = new Handler();
        mHandler.postDelayed(new Runnable() {
          @Override
          public void run() {
            activate();
          }
        }, mMinDurationMs);
      }
      if (event.getActionMasked() == MotionEvent.ACTION_UP) {
        if (mHandler != null) {
          mHandler.removeCallbacksAndMessages(null);
          mHandler = null;
        }
        if (getState() == STATE_ACTIVE) {
          end();
        } else {
          fail();
        }
      } else {
        // calculate distance from start
        float deltaX = event.getRawX() - mStartX;
        float deltaY = event.getRawY() - mStartY;
        float distSq = deltaX * deltaX + deltaY * deltaY;
        if (distSq > mMaxDistSq) {
          if (getState() == STATE_ACTIVE) {
            cancel();
          } else {
            fail();
          }
        }
      }
    }
  
    @Override
    protected void onStateChange(int newState, int previousState) {
      if (mHandler != null) {
        mHandler.removeCallbacksAndMessages(null);
        mHandler = null;
      }
    }
  }
  