@Override public void receiveCommand(SketchViewContainer root, int commandId, @Nullable ReadableArray args) { Assertions.assertNotNull(root); switch (commandId) { case COMMAND_CLEAR_SKETCH: root.sketchView.clear(); return; case COMMAND_CHANGE_TOOL: Assertions.assertNotNull(args); int toolId = args.getInt(0); root.sketchView.setToolType(toolId); return; case COMMAND_SAVE_SKETCH: try { SketchFile sketchFile = root.saveToLocalCache(); onSaveSketch(root, sketchFile); return; } catch (IOException e) { e.printStackTrace(); } default: throw new IllegalArgumentException(String.format(Locale.ENGLISH, "Unsupported command %d.", commandId)); } }
/** * Helper to forward onKeyUp commands from our host Activity. * This allows ReactFragment to handle double tap reloads and dev menus * * @param keyCode keyCode * @param event event * @return true if we handled onKeyUp */ @SuppressWarnings("unused") public boolean onKeyUp(int keyCode, KeyEvent event) { boolean handled = false; if (getReactNativeHost().getUseDeveloperSupport() && getReactNativeHost().hasInstance()) { if (keyCode == KeyEvent.KEYCODE_MENU) { getReactNativeHost().getReactInstanceManager().showDevOptionsDialog(); handled = true; } boolean didDoubleTapR = Assertions.assertNotNull(mDoubleTapReloadRecognizer).didDoubleTapR(keyCode, getActivity().getCurrentFocus()); if (didDoubleTapR) { getReactNativeHost().getReactInstanceManager().getDevSupportManager().handleReloadJS(); handled = true; } } return handled; }
protected ReactInstanceManager createReactInstanceManager() { ReactInstanceManagerBuilder builder = ReactInstanceManager.builder() .setApplication(mApplication) .setJSMainModuleName(getJSMainModuleName()) .setUseDeveloperSupport(getUseDeveloperSupport()) .setRedBoxHandler(getRedBoxHandler()) .setUIImplementationProvider(getUIImplementationProvider()) .setInitialLifecycleState(LifecycleState.BEFORE_CREATE); for (ReactPackage reactPackage : getPackages()) { builder.addPackage(reactPackage); } String jsBundleFile = getJSBundleFile(); if (jsBundleFile != null) { builder.setJSBundleFile(jsBundleFile); } else { builder.setBundleAssetName(Assertions.assertNotNull(getBundleAssetName())); } return builder.build(); }
@Override public long measure( YogaNode node, float width, YogaMeasureMode widthMode, float height, YogaMeasureMode heightMode) { // measure() should never be called before setThemedContext() EditText editText = Assertions.assertNotNull(mEditText); int fontSize = getFontSize(); editText.setTextSize( TypedValue.COMPLEX_UNIT_PX, fontSize == UNSET ? (int) Math.ceil(PixelUtil.toPixelFromSP(ViewDefaults.FONT_SIZE_SP)) : fontSize); if (mNumberOfLines != UNSET) { editText.setLines(mNumberOfLines); } editText.measure( MeasureUtil.getMeasureSpec(width, widthMode), MeasureUtil.getMeasureSpec(height, heightMode)); return YogaMeasureOutput.make(editText.getMeasuredWidth(), editText.getMeasuredHeight()); }
@Override public void receiveCommand( final RNSparkButton view, int commandType, @Nullable ReadableArray args) { Assertions.assertNotNull(view); Assertions.assertNotNull(args); switch (commandType) { case COMMAND_PLAY_ANIMATION: { view.playAnimation(); return; } default: throw new IllegalArgumentException(String.format( "Unsupported command %d received by %s.", commandType, getClass().getSimpleName())); } }
void addViewWithSubviewClippingEnabled(View child, int index, LayoutParams params) { Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); Assertions.assertNotNull(mAllChildren); addInArray(child, index); // we add view as "clipped" and then run {@link #updateSubviewClipStatus} to conditionally // attach it int clippedSoFar = 0; for (int i = 0; i < index; i++) { if (mAllChildren[i].getParent() == null) { clippedSoFar++; } } updateSubviewClipStatus(mClippingRect, index, clippedSoFar); child.addOnLayoutChangeListener(mChildrenLayoutChangeListener); }
public ReactEditText(Context context) { super(context); setFocusableInTouchMode(false); mInputMethodManager = (InputMethodManager) Assertions.assertNotNull(getContext().getSystemService(Context.INPUT_METHOD_SERVICE)); mDefaultGravityHorizontal = getGravity() & (Gravity.HORIZONTAL_GRAVITY_MASK | Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK); mDefaultGravityVertical = getGravity() & Gravity.VERTICAL_GRAVITY_MASK; mNativeEventCount = 0; mMostRecentEventCount = 0; mIsSettingTextFromJS = false; mIsJSSettingFocus = false; mBlurOnSubmit = true; mDisableFullscreen = false; mListeners = null; mTextWatcherDelegator = null; mStagedInputType = getInputType(); mKeyListener = new InternalKeyListener(); mScrollWatcher = null; }
/** * Finish a JS task. Doesn't actually stop the task on the JS side, only removes it from the list * of active tasks and notifies listeners. A task can only be finished once. * * @param taskId the unique id returned by {@link #startTask}. */ public synchronized void finishTask(final int taskId) { Assertions.assertCondition( mActiveTasks.remove(taskId), "Tried to finish non-existent task with id " + taskId + "."); Runnable timeout = mTaskTimeouts.get(taskId); if (timeout != null) { mHandler.removeCallbacks(timeout); mTaskTimeouts.remove(taskId); } UiThreadUtil.runOnUiThread(new Runnable() { @Override public void run() { for (HeadlessJsTaskEventListener listener : mHeadlessJsTaskEventListeners) { listener.onHeadlessJsTaskFinish(taskId); } } }); }
private void addGrandchildren( ReactShadowNode nativeParent, ReactShadowNode child, int index) { Assertions.assertCondition(!nativeParent.isLayoutOnly()); // `child` can't hold native children. Add all of `child`'s children to `parent`. int currentIndex = index; for (int i = 0; i < child.getChildCount(); i++) { ReactShadowNode grandchild = child.getChildAt(i); Assertions.assertCondition(grandchild.getNativeParent() == null); if (grandchild.isLayoutOnly()) { // Adding this child could result in adding multiple native views int grandchildCountBefore = nativeParent.getNativeChildCount(); addLayoutOnlyNode(nativeParent, grandchild, currentIndex); int grandchildCountAfter = nativeParent.getNativeChildCount(); currentIndex += grandchildCountAfter - grandchildCountBefore; } else { addNonLayoutNode(nativeParent, grandchild, currentIndex); currentIndex++; } } }
private void updateSubviewClipStatus(Rect clippingRect, int idx, int clippedSoFar) { View child = Assertions.assertNotNull(mAllChildren)[idx]; sHelperRect.set(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); boolean intersects = clippingRect .intersects(sHelperRect.left, sHelperRect.top, sHelperRect.right, sHelperRect.bottom); boolean needUpdateClippingRecursive = false; // We never want to clip children that are being animated, as this can easily break layout : // when layout animation changes size and/or position of views contained inside a listview that // clips offscreen children, we need to ensure that, when view exits the viewport, final size // and position is set prior to removing the view from its listview parent. // Otherwise, when view gets re-attached again, i.e when it re-enters the viewport after scroll, // it won't be size and located properly. Animation animation = child.getAnimation(); boolean isAnimating = animation != null && !animation.hasEnded(); if (!intersects && child.getParent() != null && !isAnimating) { // We can try saving on invalidate call here as the view that we remove is out of visible area // therefore invalidation is not necessary. super.removeViewsInLayout(idx - clippedSoFar, 1); needUpdateClippingRecursive = true; } else if (intersects && child.getParent() == null) { super.addViewInLayout(child, idx - clippedSoFar, sDefaultLayoutParam, true); invalidate(); needUpdateClippingRecursive = true; } else if (intersects) { // If there is any intersection we need to inform the child to update its clipping rect needUpdateClippingRecursive = true; } if (needUpdateClippingRecursive) { if (child instanceof ReactClippingViewGroup) { // we don't use {@link sHelperRect} until the end of this loop, therefore it's safe // to call this method that may write to the same {@link sHelperRect} object. ReactClippingViewGroup clippingChild = (ReactClippingViewGroup) child; if (clippingChild.getRemoveClippedSubviews()) { clippingChild.updateClippingRect(); } } } }
@Override public boolean canCoalesce() { // We can coalesce move events but not start/end events. Coalescing move events should probably // append historical move data like MotionEvent batching does. This is left as an exercise for // the reader. switch (Assertions.assertNotNull(mTouchEventType)) { case START: case END: case CANCEL: return false; case MOVE: return true; default: throw new RuntimeException("Unknown touch event type: " + mTouchEventType); } }
void removeViewWithSubviewClippingEnabled(View view) { Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mClippingRect); Assertions.assertNotNull(mAllChildren); view.removeOnLayoutChangeListener(mChildrenLayoutChangeListener); int index = indexOfChildInAllChildren(view); if (mAllChildren[index].getParent() != null) { int clippedSoFar = 0; for (int i = 0; i < index; i++) { if (mAllChildren[i].getParent() == null) { clippedSoFar++; } } super.removeViewsInLayout(index - clippedSoFar, 1); } removeFromArray(index); }
@Override public void doFrame(long frameTimeNanos) { if (isPaused.get() && !isRunningTasks.get()) { return; } // If the JS thread is busy for multiple frames we cancel any other pending runnable. if (mCurrentIdleCallbackRunnable != null) { mCurrentIdleCallbackRunnable.cancel(); } mCurrentIdleCallbackRunnable = new IdleCallbackRunnable(frameTimeNanos); getReactApplicationContext().runOnJSQueueThread(mCurrentIdleCallbackRunnable); Assertions.assertNotNull(mReactChoreographer).postFrameCallback( ReactChoreographer.CallbackType.IDLE_EVENT, this); }
public void removeAndDisposeAllChildren() { if (getChildCount() == 0) { return; } int decrease = 0; for (int i = getChildCount() - 1; i >= 0; i--) { if (mYogaNode != null && !mYogaNode.isMeasureDefined()) { mYogaNode.removeChildAt(i); } ReactShadowNode toRemove = getChildAt(i); toRemove.mParent = null; toRemove.dispose(); decrease += toRemove.mIsLayoutOnly ? toRemove.mTotalNativeChildren : 1; } Assertions.assertNotNull(mChildren).clear(); markUpdated(); mTotalNativeChildren -= decrease; updateNativeChildrenCountInParent(-decrease); }
private static Typeface createTypeface(String fontFamilyName, int style) { String extension = EXTENSIONS[style]; StringBuilder fileNameBuffer = new StringBuilder(32) .append(FONTS_ASSET_PATH) .append(fontFamilyName) .append(extension); int length = fileNameBuffer.length(); for (String fileExtension : FILE_EXTENSIONS) { String fileName = fileNameBuffer.append(fileExtension).toString(); try { return Typeface.createFromAsset(sAssetManager, fileName); } catch (RuntimeException e) { // unfortunately Typeface.createFromAsset throws an exception instead of returning null // if the typeface doesn't exist fileNameBuffer.setLength(length); } } return Assertions.assumeNotNull(Typeface.create(fontFamilyName, style)); }
public String getDebugServerHost() { // Check host setting first. If empty try to detect emulator type and use default // hostname for those String hostFromSettings = mPreferences.getString(PREFS_DEBUG_SERVER_HOST_KEY, null); if (!TextUtils.isEmpty(hostFromSettings)) { return Assertions.assertNotNull(hostFromSettings); } String host = AndroidInfoHelpers.getServerHost(); if (host.equals(AndroidInfoHelpers.DEVICE_LOCALHOST)) { FLog.w( TAG, "You seem to be running on device. Run 'adb reverse tcp:8081 tcp:8081' " + "to forward the debug server's port to the device."); } return host; }
@Override protected Result<ReactApplicationContext> doInBackground(ReactContextInitParams... params) { // TODO(t11687218): Look over all threading // Default priority is Process.THREAD_PRIORITY_BACKGROUND which means we'll be put in a cgroup // that only has access to a small fraction of CPU time. The priority will be reset after // this task finishes: https://android.googlesource.com/platform/frameworks/base/+/d630f105e8bc0021541aacb4dc6498a49048ecea/core/java/android/os/AsyncTask.java#256 Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT); Assertions.assertCondition(params != null && params.length > 0 && params[0] != null); try { JavaScriptExecutor jsExecutor = params[0].getJsExecutorFactory().create(); ReactApplicationContext reactApplicationContext = createReactContext(jsExecutor, params[0].getJsBundleLoader()); ReactMarker.logMarker(PRE_SETUP_REACT_CONTEXT_START); return Result.of(reactApplicationContext); } catch (Exception e) { // Pass exception to onPostExecute() so it can be handled on the main thread return Result.of(e); } }
/** * Initialize all the native modules */ @VisibleForTesting @Override public void initialize() { UiThreadUtil.assertOnUiThread(); Assertions.assertCondition( !mInitialized, "This catalyst instance has already been initialized"); // We assume that the instance manager blocks on running the JS bundle. If // that changes, then we need to set mAcceptCalls just after posting the // task that will run the js bundle. Assertions.assertCondition( mAcceptCalls, "RunJSBundle hasn't completed."); mInitialized = true; mNativeModulesQueueThread.runOnQueue(new Runnable() { @Override public void run() { mJavaRegistry.notifyJSInstanceInitialized(); } }); }
@Override public void onSensorChanged(SensorEvent sensorEvent) { if (sensorEvent.timestamp - mLastTimestamp < MIN_TIME_BETWEEN_SAMPLES_MS) { return; } Assertions.assertNotNull(mTimestamps); Assertions.assertNotNull(mMagnitudes); float ax = sensorEvent.values[0]; float ay = sensorEvent.values[1]; float az = sensorEvent.values[2]; mLastTimestamp = sensorEvent.timestamp; mTimestamps[mCurrentIndex] = sensorEvent.timestamp; mMagnitudes[mCurrentIndex] = Math.sqrt(ax * ax + ay * ay + az * az); maybeDispatchShake(sensorEvent.timestamp); mCurrentIndex = (mCurrentIndex + 1) % MAX_SAMPLES; }
public CatalystInstanceImpl build() { return new CatalystInstanceImpl( Assertions.assertNotNull(mReactQueueConfigurationSpec), Assertions.assertNotNull(mJSExecutor), Assertions.assertNotNull(mRegistry), Assertions.assertNotNull(mJSModuleRegistry), Assertions.assertNotNull(mJSBundleLoader), Assertions.assertNotNull(mNativeModuleCallExceptionHandler)); }
public final void addChild(AnimatedNode child) { if (mChildren == null) { mChildren = new ArrayList<>(DEFAULT_ANIMATED_NODE_CHILD_COUNT); } Assertions.assertNotNull(mChildren).add(child); child.onAttachedToNode(this); }
@Override public void onReportSuccess(final SpannedString spannedString) { isReporting = false; Assertions.assertNotNull(mReportButton).setEnabled(true); Assertions.assertNotNull(mLoadingIndicator).setVisibility(View.GONE); Assertions.assertNotNull(mReportTextView).setText(spannedString); }
private void clearFrameCallback() { HeadlessJsTaskContext headlessJsTaskContext = HeadlessJsTaskContext.getInstance(getReactApplicationContext()); if (mFrameCallbackPosted && isPaused.get() && !headlessJsTaskContext.hasActiveTasks()) { Assertions.assertNotNull(mReactChoreographer).removeFrameCallback( ReactChoreographer.CallbackType.TIMERS_EVENTS, mTimerFrameCallback); mFrameCallbackPosted = false; } }
/** * Show the report button, hide the report textview and the loading indicator. */ public void resetReporting(boolean enabled) { if (mRedBoxHandler == null || !mRedBoxHandler.isReportEnabled()) { return; } isReporting = false; Assertions.assertNotNull(mReportTextView).setVisibility(View.GONE); Assertions.assertNotNull(mLoadingIndicator).setVisibility(View.GONE); Assertions.assertNotNull(mLineSeparator).setVisibility(View.GONE); Assertions.assertNotNull(mReportButton).setVisibility( enabled ? View.VISIBLE : View.GONE); Assertions.assertNotNull(mReportButton).setEnabled(true); }
private ReactContext waitForReactContext() { Assertions.assertNotNull(mReactInstanceManager); try { while (true) { ReactContext reactContext = mReactInstanceManager.getCurrentReactContext(); if (reactContext != null) { return reactContext; } Thread.sleep(100); } } catch (InterruptedException e) { throw new RuntimeException(e); } }
/** * Same as {@link Activity#startActivityForResult(Intent, int)}, this just redirects the call to * the current activity. Returns whether the activity was started, as this might fail if this * was called before the context is in the right state. */ public boolean startActivityForResult(Intent intent, int code, Bundle bundle) { Activity activity = getCurrentActivity(); Assertions.assertNotNull(activity); activity.startActivityForResult(intent, code, bundle); return true; }
void removeAllViewsWithSubviewClippingEnabled() { Assertions.assertCondition(mRemoveClippedSubviews); Assertions.assertNotNull(mAllChildren); for (int i = 0; i < mAllChildrenCount; i++) { mAllChildren[i].removeOnLayoutChangeListener(mChildrenLayoutChangeListener); } removeAllViewsInLayout(); mAllChildrenCount = 0; }
private int indexOfChildInAllChildren(View child) { final int count = mAllChildrenCount; final View[] children = Assertions.assertNotNull(mAllChildren); for (int i = 0; i < count; i++) { if (children[i] == child) { return i; } } return -1; }
@Override public void dispatch(RCTEventEmitter rctEventEmitter) { TouchesHelper.sendTouchEvent( rctEventEmitter, Assertions.assertNotNull(mTouchEventType), getViewTag(), this); }
/** * Start listening for shakes. */ public void start(SensorManager manager) { Assertions.assertNotNull(manager); Sensor accelerometer = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); if (accelerometer != null) { mSensorManager = manager; mLastTimestamp = -1; mCurrentIndex = 0; mMagnitudes = new double[MAX_SAMPLES]; mTimestamps = new long[MAX_SAMPLES]; mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI); } }
private void enableFpsListener() { if (isScrollPerfLoggingEnabled()) { Assertions.assertNotNull(mFpsListener); Assertions.assertNotNull(mScrollPerfTag); mFpsListener.enable(mScrollPerfTag); } }
@Override public void updateClippingRect() { if (!mRemoveClippedSubviews) { return; } Assertions.assertNotNull(mClippingRect); ReactClippingViewGroupHelper.calculateClippingRect(this, mClippingRect); View contentView = getChildAt(0); if (contentView instanceof ReactClippingViewGroup) { ((ReactClippingViewGroup) contentView).updateClippingRect(); } }
public void assertNow() { Thread current = Thread.currentThread(); if (mThread == null) { mThread = current; } Assertions.assertCondition(mThread == current); }
@Override public void onReportError(final SpannedString spannedString) { isReporting = false; Assertions.assertNotNull(mReportButton).setEnabled(true); Assertions.assertNotNull(mLoadingIndicator).setVisibility(View.GONE); Assertions.assertNotNull(mReportTextView).setText(spannedString); }
/** * Animation engine should call this method when the animation is finished. Should be called only * once */ protected final void finish() { Assertions.assertCondition(!mIsFinished, "Animation must not already be finished!"); mIsFinished = true; if (!mCancelled) { if (mAnimatedView != null) { mPropertyUpdater.onFinish(mAnimatedView); } if (mAnimationListener != null) { mAnimationListener.onFinished(); } } }
/** * Returns the FpsInfo as if stop had been called at the given upToTimeMs. Only valid if * monitoring was started with {@link #startAndRecordFpsAtEachFrame()}. */ public @Nullable FpsInfo getFpsInfo(long upToTimeMs) { Assertions.assertNotNull(mTimeToFps, "FPS was not recorded at each frame!"); Map.Entry<Long, FpsInfo> bestEntry = mTimeToFps.floorEntry(upToTimeMs); if (bestEntry == null) { return null; } return bestEntry.getValue(); }
/** * Sets whether this node only contributes to the layout of its children without doing any * drawing or functionality itself. */ public final void setIsLayoutOnly(boolean isLayoutOnly) { Assertions.assertCondition(getParent() == null, "Must remove from no opt parent first"); Assertions.assertCondition(mNativeParent == null, "Must remove from native parent first"); Assertions.assertCondition(getNativeChildCount() == 0, "Must remove all native children first"); mIsLayoutOnly = isLayoutOnly; }