@ReactProp(name = ViewProps.TEXT_ALIGN) public void setTextAlign(ReactEditText view, @Nullable String textAlign) { if (textAlign == null || "auto".equals(textAlign)) { view.setGravityHorizontal(Gravity.NO_GRAVITY); } else if ("left".equals(textAlign)) { view.setGravityHorizontal(Gravity.LEFT); } else if ("right".equals(textAlign)) { view.setGravityHorizontal(Gravity.RIGHT); } else if ("center".equals(textAlign)) { view.setGravityHorizontal(Gravity.CENTER_HORIZONTAL); } else if ("justify".equals(textAlign)) { // Fallback gracefully for cross-platform compat instead of error view.setGravityHorizontal(Gravity.LEFT); } else { throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign); } }
@Override public void setTextBreakStrategy(@Nullable String textBreakStrategy) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return; } if (textBreakStrategy == null || "simple".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; } else if ("highQuality".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY; } else if ("balanced".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_BALANCED; } else { throw new JSApplicationIllegalArgumentException("Invalid textBreakStrategy: " + textBreakStrategy); } }
/** * Show a {@link PopupMenu}. * * @param reactTag the tag of the anchor view (the PopupMenu is displayed next to this view); this * needs to be the tag of a native view (shadow views can not be anchors) * @param items the menu items as an array of strings * @param success will be called with the position of the selected item as the first argument, or * no arguments if the menu is dismissed */ public void showPopupMenu(int reactTag, ReadableArray items, Callback success) { UiThreadUtil.assertOnUiThread(); View anchor = mTagsToViews.get(reactTag); if (anchor == null) { throw new JSApplicationIllegalArgumentException("Could not find view with tag " + reactTag); } PopupMenu popupMenu = new PopupMenu(getReactContextForView(reactTag), anchor); Menu menu = popupMenu.getMenu(); for (int i = 0; i < items.size(); i++) { menu.add(Menu.NONE, Menu.NONE, i, items.getString(i)); } PopupMenuCallbackHandler handler = new PopupMenuCallbackHandler(success); popupMenu.setOnMenuItemClickListener(handler); popupMenu.setOnDismissListener(handler); popupMenu.show(); }
static int getStyleFromString(@Nullable String styleStr) { if (styleStr == null) { throw new JSApplicationIllegalArgumentException( "ProgressBar needs to have a style, null received"); } else if (styleStr.equals("Horizontal")) { return android.R.attr.progressBarStyleHorizontal; } else if (styleStr.equals("Small")) { return android.R.attr.progressBarStyleSmall; } else if (styleStr.equals("Large")) { return android.R.attr.progressBarStyleLarge; } else if (styleStr.equals("Inverse")) { return android.R.attr.progressBarStyleInverse; } else if (styleStr.equals("SmallInverse")) { return android.R.attr.progressBarStyleSmallInverse; } else if (styleStr.equals("LargeInverse")) { return android.R.attr.progressBarStyleLargeInverse; } else if (styleStr.equals("Normal")) { return android.R.attr.progressBarStyle; } else { throw new JSApplicationIllegalArgumentException("Unknown ProgressBar style: " + styleStr); } }
@ReactProp(name = ViewProps.POSITION) public void setPosition(@Nullable String position) { if (isVirtual()) { return; } if (position == null) { setPositionType(YogaPositionType.RELATIVE); return; } switch (position) { case "relative": { setPositionType(YogaPositionType.RELATIVE); break; } case "absolute": { setPositionType(YogaPositionType.ABSOLUTE); break; } default: { throw new JSApplicationIllegalArgumentException( "invalid value for position: " + position); } } }
@Override public void receiveCommand(ReactViewGroup root, int commandId, @Nullable ReadableArray args) { switch (commandId) { case CMD_HOTSPOT_UPDATE: { if (args == null || args.size() != 2) { throw new JSApplicationIllegalArgumentException( "Illegal number of arguments for 'updateHotspot' command"); } if (Build.VERSION.SDK_INT >= 21) { float x = PixelUtil.toPixelFromDIP(args.getDouble(0)); float y = PixelUtil.toPixelFromDIP(args.getDouble(1)); root.drawableHotspotChanged(x, y); } break; } case CMD_SET_PRESSED: { if (args == null || args.size() != 1) { throw new JSApplicationIllegalArgumentException( "Illegal number of arguments for 'setPressed' command"); } root.setPressed(args.getBoolean(0)); break; } } }
@ReactProp(name = ViewProps.TEXT_BREAK_STRATEGY) public void setTextBreakStrategy(@Nullable String textBreakStrategy) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { return; } if (textBreakStrategy == null || "highQuality".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_HIGH_QUALITY; } else if ("simple".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; } else if ("balanced".equals(textBreakStrategy)) { mTextBreakStrategy = Layout.BREAK_STRATEGY_BALANCED; } else { throw new JSApplicationIllegalArgumentException("Invalid textBreakStrategy: " + textBreakStrategy); } markUpdated(); }
@ReactProp(name = ViewProps.DISPLAY) public void setDisplay(@Nullable String display) { if (isVirtual()) { return; } if (display == null) { setDisplay(YogaDisplay.FLEX); return; } switch (display) { case "flex": { setDisplay(YogaDisplay.FLEX); break; } case "none": { setDisplay(YogaDisplay.NONE); break; } default: { throw new JSApplicationIllegalArgumentException( "invalid value for display: " + display); } } }
/** * Converts JS resize modes into {@code ScalingUtils.ScaleType}. * See {@code ImageResizeMode.js}. */ public static ScalingUtils.ScaleType toScaleType(@Nullable String resizeModeValue) { if ("contain".equals(resizeModeValue)) { return ScalingUtils.ScaleType.FIT_CENTER; } if ("cover".equals(resizeModeValue)) { return ScalingUtils.ScaleType.CENTER_CROP; } if ("stretch".equals(resizeModeValue)) { return ScalingUtils.ScaleType.FIT_XY; } if ("center".equals(resizeModeValue)) { return ScalingUtils.ScaleType.CENTER_INSIDE; } if (resizeModeValue == null) { // Use the default. Never use null. return defaultValue(); } throw new JSApplicationIllegalArgumentException( "Invalid resize mode: '" + resizeModeValue + "'"); }
/** * Get photos from {@link MediaStore.Images}, most recent first. * * @param params a map containing the following keys: * <ul> * <li>first (mandatory): a number representing the number of photos to fetch</li> * <li> * after (optional): a cursor that matches page_info[end_cursor] returned by a * previous call to {@link #getPhotos} * </li> * <li>groupName (optional): an album name</li> * <li> * mimeType (optional): restrict returned images to a specific mimetype (e.g. * image/jpeg) * </li> * </ul> * @param promise the Promise to be resolved when the photos are loaded; for a format of the * parameters passed to this callback, see {@code getPhotosReturnChecker} in CameraRoll.js */ @ReactMethod public void getPhotos(final ReadableMap params, final Promise promise) { int first = params.getInt("first"); String after = params.hasKey("after") ? params.getString("after") : null; String groupName = params.hasKey("groupName") ? params.getString("groupName") : null; ReadableArray mimeTypes = params.hasKey("mimeTypes") ? params.getArray("mimeTypes") : null; if (params.hasKey("groupTypes")) { throw new JSApplicationIllegalArgumentException("groupTypes is not supported on Android"); } new GetPhotosTask( getReactApplicationContext(), first, after, groupName, mimeTypes, promise) .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }
/** * Return the URL the activity was started with * * @param promise a promise which is resolved with the initial URL */ @ReactMethod public void getInitialURL(Promise promise) { try { Activity currentActivity = getCurrentActivity(); String initialURL = null; if (currentActivity != null) { Intent intent = currentActivity.getIntent(); String action = intent.getAction(); Uri uri = intent.getData(); if (Intent.ACTION_VIEW.equals(action) && uri != null) { initialURL = uri.toString(); } } promise.resolve(initialURL); } catch (Exception e) { promise.reject(new JSApplicationIllegalArgumentException( "Could not get the initial URL : " + e.getMessage())); } }
/** * Determine whether or not an installed app can handle a given URL. * * @param url the URL to open * @param promise a promise that is always resolved with a boolean argument */ @ReactMethod public void canOpenURL(String url, Promise promise) { if (url == null || url.isEmpty()) { promise.reject(new JSApplicationIllegalArgumentException("Invalid URL: " + url)); return; } try { Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); // We need Intent.FLAG_ACTIVITY_NEW_TASK since getReactApplicationContext() returns // the ApplicationContext instead of the Activity context. intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); boolean canOpen = intent.resolveActivity(getReactApplicationContext().getPackageManager()) != null; promise.resolve(canOpen); } catch (Exception e) { promise.reject(new JSApplicationIllegalArgumentException( "Could not check if URL '" + url + "' can be opened: " + e.getMessage())); } }
@ReactProp(name = ViewProps.FLEX_WRAP) public void setFlexWrap(@Nullable String flexWrap) { if (isVirtual()) { return; } if (flexWrap == null) { setFlexWrap(YogaWrap.NO_WRAP); return; } switch (flexWrap) { case "nowrap": { setFlexWrap(YogaWrap.NO_WRAP); break; } case "wrap": { setFlexWrap(YogaWrap.WRAP); break; } default: { throw new JSApplicationIllegalArgumentException( "invalid value for flexWrap: " + flexWrap); } } }
public void updateViewProp( ViewManager viewManager, View viewToUpdate, ReactStylesDiffMap props) { try { if (mIndex == null) { VIEW_MGR_ARGS[0] = viewToUpdate; VIEW_MGR_ARGS[1] = extractProperty(props); mSetter.invoke(viewManager, VIEW_MGR_ARGS); Arrays.fill(VIEW_MGR_ARGS, null); } else { VIEW_MGR_GROUP_ARGS[0] = viewToUpdate; VIEW_MGR_GROUP_ARGS[1] = mIndex; VIEW_MGR_GROUP_ARGS[2] = extractProperty(props); mSetter.invoke(viewManager, VIEW_MGR_GROUP_ARGS); Arrays.fill(VIEW_MGR_GROUP_ARGS, null); } } catch (Throwable t) { FLog.e(ViewManager.class, "Error while updating prop " + mPropName, t); throw new JSApplicationIllegalArgumentException("Error while updating property '" + mPropName + "' of a view managed by: " + viewManager.getName(), t); } }
public void updateShadowNodeProp( ReactShadowNode nodeToUpdate, ReactStylesDiffMap props) { try { if (mIndex == null) { SHADOW_ARGS[0] = extractProperty(props); mSetter.invoke(nodeToUpdate, SHADOW_ARGS); Arrays.fill(SHADOW_ARGS, null); } else { SHADOW_GROUP_ARGS[0] = mIndex; SHADOW_GROUP_ARGS[1] = extractProperty(props); mSetter.invoke(nodeToUpdate, SHADOW_GROUP_ARGS); Arrays.fill(SHADOW_GROUP_ARGS, null); } } catch (Throwable t) { FLog.e(ViewManager.class, "Error while updating prop " + mPropName, t); throw new JSApplicationIllegalArgumentException("Error while updating property '" + mPropName + "' in shadow node of type: " + nodeToUpdate.getViewClass(), t); } }
public void disconnectAnimatedNodeFromView(int animatedNodeTag, int viewTag) { AnimatedNode node = mAnimatedNodes.get(animatedNodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag + " does not exists"); } if (!(node instanceof PropsAnimatedNode)) { throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" + "of type " + PropsAnimatedNode.class.getName()); } PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node; if (propsAnimatedNode.mConnectedViewTag != viewTag) { throw new JSApplicationIllegalArgumentException("Attempting to disconnect view that has " + "not been connected with the given animated node"); } propsAnimatedNode.mConnectedViewTag = -1; }
public void connectAnimatedNodeToView(int animatedNodeTag, int viewTag) { AnimatedNode node = mAnimatedNodes.get(animatedNodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag + " does not exists"); } if (!(node instanceof PropsAnimatedNode)) { throw new JSApplicationIllegalArgumentException("Animated node connected to view should be" + "of type " + PropsAnimatedNode.class.getName()); } PropsAnimatedNode propsAnimatedNode = (PropsAnimatedNode) node; if (propsAnimatedNode.mConnectedViewTag != -1) { throw new JSApplicationIllegalArgumentException("Animated node " + animatedNodeTag + " is " + "already attached to a view"); } propsAnimatedNode.mConnectedViewTag = viewTag; mUpdatedNodes.put(animatedNodeTag, node); }
@Override public void draw(Canvas canvas, Paint paint, float opacity) { opacity *= mOpacity; if (opacity > MIN_OPACITY_FOR_DRAW) { saveAndSetupCanvas(canvas); if (mPath == null) { throw new JSApplicationIllegalArgumentException( "Shapes should have a valid path (d) prop"); } if (setupFillPaint(paint, opacity)) { canvas.drawPath(mPath, paint); } if (setupStrokePaint(paint, opacity)) { canvas.drawPath(mPath, paint); } restoreCanvas(canvas); } markUpdateSeen(); }
@ReactProp(name = ViewProps.TEXT_ALIGN) public void setTextAlign(@Nullable String textAlign) { if (textAlign == null || "auto".equals(textAlign)) { mTextAlign = Gravity.NO_GRAVITY; } else if ("left".equals(textAlign)) { mTextAlign = Gravity.LEFT; } else if ("right".equals(textAlign)) { mTextAlign = Gravity.RIGHT; } else if ("center".equals(textAlign)) { mTextAlign = Gravity.CENTER_HORIZONTAL; } else if ("justify".equals(textAlign)) { // Fallback gracefully for cross-platform compat instead of error mTextAlign = Gravity.LEFT; } else { throw new JSApplicationIllegalArgumentException("Invalid textAlign: " + textAlign); } markUpdated(); }
private CropTask( ReactContext context, String uri, int x, int y, int width, int height, Callback success, Callback error) { super(context); if (x < 0 || y < 0 || width <= 0 || height <= 0) { throw new JSApplicationIllegalArgumentException(String.format( "Invalid crop rectangle: [%d, %d, %d, %d]", x, y, width, height)); } mContext = context; mUri = uri; mX = x; mY = y; mWidth = width; mHeight = height; mSuccess = success; mError = error; }
public void flattenAnimatedNodeOffset(int tag) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag + " does not exists or is not a 'value' node"); } ((ValueAnimatedNode) node).flattenOffset(); }
@Override public void receiveCommand( FlatViewGroup view, int commandId, @Nullable ReadableArray args) { switch (commandId) { case CMD_HOTSPOT_UPDATE: { if (args == null || args.size() != 2) { throw new JSApplicationIllegalArgumentException( "Illegal number of arguments for 'updateHotspot' command"); } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { view.getLocationOnScreen(TMP_INT_ARRAY); float x = PixelUtil.toPixelFromDIP(args.getDouble(0)) - TMP_INT_ARRAY[0]; float y = PixelUtil.toPixelFromDIP(args.getDouble(1)) - TMP_INT_ARRAY[1]; view.drawableHotspotChanged(x, y); } break; } case CMD_SET_PRESSED: { if (args == null || args.size() != 1) { throw new JSApplicationIllegalArgumentException( "Illegal number of arguments for 'setPressed' command"); } view.setPressed(args.getBoolean(0)); break; } } }
@ReactProp(name = ViewProps.TEXT_ALIGN_VERTICAL) public void setTextAlignVertical(ReactEditText view, @Nullable String textAlignVertical) { if (textAlignVertical == null || "auto".equals(textAlignVertical)) { view.setGravityVertical(Gravity.NO_GRAVITY); } else if ("top".equals(textAlignVertical)) { view.setGravityVertical(Gravity.TOP); } else if ("bottom".equals(textAlignVertical)) { view.setGravityVertical(Gravity.BOTTOM); } else if ("center".equals(textAlignVertical)) { view.setGravityVertical(Gravity.CENTER_VERTICAL); } else { throw new JSApplicationIllegalArgumentException("Invalid textAlignVertical: " + textAlignVertical); } }
public void apply() { if (mProgressBar == null) { throw new JSApplicationIllegalArgumentException("setStyle() not called"); } mProgressBar.setIndeterminate(mIndeterminate); setColor(mProgressBar); mProgressBar.setProgress((int) (mProgress * MAX_PROGRESS)); if (mAnimating) { mProgressBar.setVisibility(View.VISIBLE); } else { mProgressBar.setVisibility(View.GONE); } }
@ReactProp(name = "drawerPosition", defaultInt = Gravity.START) public void setDrawerPosition(ReactDrawerLayout view, int drawerPosition) { if (Gravity.START == drawerPosition || Gravity.END == drawerPosition) { view.setDrawerPosition(drawerPosition); } else { throw new JSApplicationIllegalArgumentException("Unknown drawerPosition " + drawerPosition); } }
public void addAnimatedEventToView(int viewTag, String eventName, ReadableMap eventMapping) { int nodeTag = eventMapping.getInt("animatedValueTag"); AnimatedNode node = mAnimatedNodes.get(nodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException("Animated node with tag " + nodeTag + " does not exists"); } if (!(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException("Animated node connected to event should be" + "of type " + ValueAnimatedNode.class.getName()); } ReadableArray path = eventMapping.getArray("nativeEventPath"); List<String> pathList = new ArrayList<>(path.size()); for (int i = 0; i < path.size(); i++) { pathList.add(path.getString(i)); } EventAnimationDriver event = new EventAnimationDriver(pathList, (ValueAnimatedNode) node); String key = viewTag + eventName; if (mEventDrivers.containsKey(key)) { mEventDrivers.get(key).add(event); } else { List<EventAnimationDriver> drivers = new ArrayList<>(1); drivers.add(event); mEventDrivers.put(key, drivers); } }
/** * Besides width/height, all other layout props on inline images are ignored */ @Override public void setWidth(Dynamic width) { if (width.getType() == ReadableType.Number) { mWidth = (float) width.asDouble(); } else { throw new JSApplicationIllegalArgumentException( "Inline images must not have percentage based width"); } }
/** * Starts a corresponding external activity for the given URL. * * For example, if the URL is "https://www.facebook.com", the system browser will be opened, * or the "choose application" dialog will be shown. * * @param url the URL to open */ @ReactMethod public void openURL(String url, Promise promise) { if (url == null || url.isEmpty()) { promise.reject(new JSApplicationIllegalArgumentException("Invalid URL: " + url)); return; } try { Activity currentActivity = getCurrentActivity(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); String selfPackageName = getReactApplicationContext().getPackageName(); ComponentName componentName = intent.resolveActivity( getReactApplicationContext().getPackageManager()); String otherPackageName = (componentName != null ? componentName.getPackageName() : ""); // If there is no currentActivity or we are launching to a different package we need to set // the FLAG_ACTIVITY_NEW_TASK flag if (currentActivity == null || !selfPackageName.equals(otherPackageName)) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } if (currentActivity != null) { currentActivity.startActivity(intent); } else { getReactApplicationContext().startActivity(intent); } promise.resolve(true); } catch (Exception e) { promise.reject(new JSApplicationIllegalArgumentException( "Could not open URL '" + url + "': " + e.getMessage())); } }
public void startAnimatingNode( int animationId, int animatedNodeTag, ReadableMap animationConfig, Callback endCallback) { AnimatedNode node = mAnimatedNodes.get(animatedNodeTag); if (node == null) { throw new JSApplicationIllegalArgumentException("Animated node with tag " + animatedNodeTag + " does not exists"); } if (!(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException("Animated node should be of type " + ValueAnimatedNode.class.getName()); } String type = animationConfig.getString("type"); final AnimationDriver animation; if ("frames".equals(type)) { animation = new FrameBasedAnimationDriver(animationConfig); } else if ("spring".equals(type)) { animation = new SpringAnimation(animationConfig); } else if ("decay".equals(type)) { animation = new DecayAnimation(animationConfig); } else { throw new JSApplicationIllegalArgumentException("Unsupported animation type: " + type); } animation.mId = animationId; animation.mEndCallback = endCallback; animation.mAnimatedValue = (ValueAnimatedNode) node; mActiveAnimations.put(animationId, animation); }
@ReactProp(name = ViewProps.ELLIPSIZE_MODE) public void setEllipsizeMode(ReactTextView view, @Nullable String ellipsizeMode) { if (ellipsizeMode == null || ellipsizeMode.equals("tail")) { view.setEllipsizeLocation(TextUtils.TruncateAt.END); } else if (ellipsizeMode.equals("head")) { view.setEllipsizeLocation(TextUtils.TruncateAt.START); } else if (ellipsizeMode.equals("middle")) { view.setEllipsizeLocation(TextUtils.TruncateAt.MIDDLE); } else { throw new JSApplicationIllegalArgumentException("Invalid ellipsizeMode: " + ellipsizeMode); } }
public static int parseOverScrollMode(String jsOverScrollMode) { if (jsOverScrollMode == null || jsOverScrollMode.equals(AUTO)) { return View.OVER_SCROLL_IF_CONTENT_SCROLLS; } else if (jsOverScrollMode.equals(OVER_SCROLL_ALWAYS)) { return View.OVER_SCROLL_ALWAYS; } else if (jsOverScrollMode.equals(OVER_SCROLL_NEVER)) { return View.OVER_SCROLL_NEVER; } else { throw new JSApplicationIllegalArgumentException("wrong overScrollMode: " + jsOverScrollMode); } }
public void setAnimatedNodeValue(int tag, double value) { AnimatedNode node = mAnimatedNodes.get(tag); if (node == null || !(node instanceof ValueAnimatedNode)) { throw new JSApplicationIllegalArgumentException("Animated node with tag " + tag + " does not exists or is not a 'value' node"); } ((ValueAnimatedNode) node).mValue = value; mUpdatedNodes.put(tag, node); }