hunk.code_window:   public void shouldCheckOptions() {
       if (mManifestUrl != null && mKernel.hasOptionsForManifestUrl(mManifestUrl)) {
         handleOptions(mKernel.popOptionsForManifestUrl(mManifestUrl));
       }
       clearNotifications();
     }
  
hunk.labels: keep keep keep keep keep replace keep keep
hunk.after_edit:     // this is old code from before `Expo.Notifications.dismissAllNotificationsAsync` existed
       // since removing it is a breaking change (people have to call ^^^ explicitly if they want
       // this behavior) we only do it starting in SDK 28
       // TODO: eric: remove this once SDK 27 is phased out
       if (mSDKVersion != null && ABIVersion.toNumber(mSDKVersion) < ABIVersion.toNumber("28.0.0")) {
         clearNotifications();
       }
  
hunk.file_path: android/expoview/src/main/java/host/exp/exponent/experience/ExperienceActivity.java
hunk.type: replace
file: /**
   * 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.
   *
   * @providesModule LayoutAnimation
   * @flow
   * @format
   */
  'use strict';
  
  const PropTypes = require('prop-types');
  const UIManager = require('../ReactNative/UIManager');
  
  /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
   * found when Flow v0.54 was deployed. To see the error delete this comment and
   * run Flow. */
  const keyMirror = require('fbjs/lib/keyMirror');
  
  const {checkPropTypes} = PropTypes;
  
  const TypesEnum = {
    spring: true,
    linear: true,
    easeInEaseOut: true,
    easeIn: true,
    easeOut: true,
    keyboard: true,
  };
  const Types = keyMirror(TypesEnum);
  
  const PropertiesEnum = {
    opacity: true,
    scaleXY: true,
  };
  const Properties = keyMirror(PropertiesEnum);
  
  const animType = PropTypes.shape({
    duration: PropTypes.number,
    delay: PropTypes.number,
    springDamping: PropTypes.number,
    initialVelocity: PropTypes.number,
    type: PropTypes.oneOf(Object.keys(Types)).isRequired,
    property: PropTypes.oneOf(
      // Only applies to create/delete
      Object.keys(Properties),
    ),
  });
  
  type Anim = {
    duration?: number,
    delay?: number,
    springDamping?: number,
    initialVelocity?: number,
    type?: $Enum<typeof TypesEnum>,
    property?: $Enum<typeof PropertiesEnum>,
  };
  
  const configType = PropTypes.shape({
    duration: PropTypes.number.isRequired,
    create: animType,
    update: animType,
    delete: animType,
  });
  
  type Config = {
    duration: number,
    create?: Anim,
    update?: Anim,
    delete?: Anim,
  };
  
  function checkConfig(config: Config, location: string, name: string) {
    checkPropTypes({config: configType}, {config}, location, name);
  }
  
  function configureNext(config: Config, onAnimationDidEnd?: Function) {
    if (__DEV__) {
      checkConfig(config, 'config', 'LayoutAnimation.configureNext');
    }
    UIManager.configureNextLayoutAnimation(
      config,
      onAnimationDidEnd || function() {},
      function() {
        /* unused */
      },
    );
  }
  
  function create(duration: number, type, creationProp): Config {
    return {
      duration,
      create: {
        type,
        property: creationProp,
      },
      update: {
        type,
      },
      delete: {
        type,
        property: creationProp,
      },
    };
  }
  
  const Presets = {
    easeInEaseOut: create(300, Types.easeInEaseOut, Properties.opacity),
    linear: create(500, Types.linear, Properties.opacity),
    spring: {
      duration: 700,
      create: {
        type: Types.linear,
        property: Properties.opacity,
      },
      update: {
        type: Types.spring,
        springDamping: 0.4,
      },
      delete: {
        type: Types.linear,
        property: Properties.opacity,
      },
    },
  };
  
  /**
   * Automatically animates views to their new positions when the
   * next layout happens.
   *
   * A common way to use this API is to call it before calling `setState`.
   *
   * Note that in order to get this to work on **Android** you need to set the following flags via `UIManager`:
   *
   *     UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
   */
  const LayoutAnimation = {
    /**
     * Schedules an animation to happen on the next layout.
     *
     * @param config Specifies animation properties:
     *
     *   - `duration` in milliseconds
     *   - `create`, config for animating in new views (see `Anim` type)
     *   - `update`, config for animating views that have been updated
     * (see `Anim` type)
     *
     * @param onAnimationDidEnd Called when the animation finished.
     * Only supported on iOS.
     * @param onError Called on error. Only supported on iOS.
     */
    configureNext,
    /**
     * Helper for creating a config for `configureNext`.
     */
    create,
    Types,
    Properties,
    checkConfig,
    Presets,
    easeInEaseOut: configureNext.bind(null, Presets.easeInEaseOut),
    linear: configureNext.bind(null, Presets.linear),
    spring: configureNext.bind(null, Presets.spring),
  };
  
  module.exports = LayoutAnimation;
  