/// <summary>
        /// Updates the extra data for the view with the given tag.
        /// </summary>
        /// <param name="tag">The view tag.</param>
        /// <param name="extraData">The extra data.</param>
        public void UpdateViewExtraData(int tag, object extraData)
        {
            DispatcherHelpers.AssertOnDispatcher();
            var viewManager  = ResolveViewManager(tag);
            var viewToUpdate = ResolveView(tag);

            viewManager.UpdateExtraData(viewToUpdate, extraData);
        }
        /// <summary>
        /// Updates the properties of the view with the given tag.
        /// </summary>
        /// <param name="tag">The view tag.</param>
        /// <param name="props">The properties.</param>
        public void UpdateProperties(int tag, ReactStylesDiffMap props)
        {
            DispatcherHelpers.AssertOnDispatcher();
            var viewManager  = ResolveViewManager(tag);
            var viewToUpdate = ResolveView(tag);

            viewManager.UpdateProperties(viewToUpdate, props);
        }
Exemplo n.º 3
0
 /// <summary>
 /// Initializes the <see cref="ReactChoreographer"/> instance.
 /// </summary>
 public static void Initialize()
 {
     if (s_instance == null)
     {
         DispatcherHelpers.AssertOnDispatcher();
         s_instance = new ReactChoreographer();
     }
 }
Exemplo n.º 4
0
 /// <summary>
 /// Adds a root view to the hierarchy.
 /// </summary>
 /// <param name="tag">The root view tag.</param>
 /// <param name="rootView">The root view.</param>
 /// <param name="themedRootContext">The React context.</param>
 public void AddRootView(
     int tag,
     SizeMonitoringCanvas rootView,
     ThemedReactContext themedRootContext)
 {
     DispatcherHelpers.AssertOnDispatcher();
     _nativeViewHierarchyManager.AddRootView(tag, rootView, themedRootContext);
 }
        /// <summary>
        /// Removes the value with the specified key.
        /// </summary>
        /// <param name="key"></param>
        public bool Remove(TKey key)
        {
            DispatcherHelpers.AssertOnDispatcher(key);
#if WINDOWS_UWP
            return(_dictionary.TryRemove(key, out _));
#else
            return(_dictionary.TryRemove(key, out _));
#endif
        }
        /// <summary>
        /// Set the value associated with the key. Replaces existing value associated with the key, if any.
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void AddOrUpdate(TKey key, TValue value)
        {
            DispatcherHelpers.AssertOnDispatcher(key);
#if WINDOWS_UWP
            _dictionary.AddOrUpdate(key, value, (k, v) => value);
#else
            _dictionary.AddOrUpdate(key, value, (k, v) => value);
#endif
        }
 private void AddRootViewParent(int tag, FrameworkElement view, ThemedReactContext themedContext)
 {
     DispatcherHelpers.AssertOnDispatcher();
     _tagsToViews.Add(tag, view);
     _tagsToViewManagers.Add(tag, _rootViewManager);
     _rootTags.Add(tag, true);
     view.SetTag(tag);
     view.SetReactContext(themedContext);
 }
Exemplo n.º 8
0
 /// <summary>
 /// Awaits the currently initializing React context, or returns null if context fails to initialize.
 /// </summary>
 /// <param name="token">A token to cancel the request.</param>
 /// <returns>
 /// A task to await the React context.
 /// </returns>
 public async Task <ReactContext> TryGetReactContextAsync(CancellationToken token)
 {
     DispatcherHelpers.AssertOnDispatcher();
     using (await _lock.LockAsync())
     {
         // By this point context has already been created due to the serialized aspect of context initialization.
         return(_currentReactContext);
     }
 }
 /// <summary>
 /// Disposes the <see cref="ReactChoreographer"/> instance.
 /// </summary>
 public static void Dispose()
 {
     if (s_instance != null)
     {
         DispatcherHelpers.AssertOnDispatcher();
         ((IDisposable)s_instance).Dispose();
         s_instance = null;
     }
 }
        private void DropView(Widget view)
        {
            DispatcherHelpers.AssertOnDispatcher();
            var tag = view.GetTag();

            if (!_rootTags.ContainsKey(tag))
            {
                Log.Fatal(ReactConstants.Tag, "## DropView ## tag:" + tag);
                // For non-root views, we notify the view manager with `OnDropViewInstance`
                var mgr = ResolveViewManager(tag);
                mgr.OnDropViewInstance(view.GetReactContext(), view);
            }

            var viewManager = default(IViewManager);

            if (_tagsToViewManagers.TryGetValue(tag, out viewManager))
            {
                var ViewParentManager = viewManager as IViewParentManager;
                if (ViewParentManager != null)
                {
                    // it should be a view with 'Container' props
                    Log.Fatal(ReactConstants.Tag, "## ViewParentManager:" + ViewParentManager + ", ChildCount:" + ViewParentManager.GetChildCount(view));
                    for (var i = ViewParentManager.GetChildCount(view) - 1; i >= 0; --i)
                    {
                        var child        = ViewParentManager.GetChildAt(view, i);
                        var managedChild = default(Widget);
                        if (_tagsToViews.TryGetValue(child.GetTag(), out managedChild))
                        {
                            DropView(managedChild);
                        }
                    }

                    ViewParentManager.RemoveAllChildren(view);
                }
            }

            Log.Fatal(ReactConstants.Tag, "## Remove View:[" + tag + "] & ViewMgr Mapping Relationship");

            _tagsToViews.Remove(tag);
            _tagsToViewManagers.Remove(tag);

            // release sub views ('rootview' will only be destroyed while OnTeminate being invoked)
            if (1 != tag)
            {
                Log.Fatal(ReactConstants.Tag, ">>>>> release view component:[" + tag + "]");

                // Clean View <-> Tag
                if (false == view.RemoveViewInfo())
                {
                    Log.Fatal(ReactConstants.Tag, "Failed to clean current view info");
                }

                // hmm ... Life is Over
                view.Unrealize();
            }
        }
        /// <summary>
        /// Animation loop performs BFS over the graph of animated nodes.
        /// </summary>
        /// <remarks>
        /// We use incremented <see cref="_animatedGraphBFSColor"/> to mark
        /// nodes as visited in each of the BFS passes, which saves additional
        /// loops for clearing "visited" states.
        ///
        /// First BFS starts with nodes that are in <see cref="_updatedNodes" />
        /// (this is, their value has been modified from JS in the last batch
        /// of JS operations) or directly attached to an active animation
        /// (thus linked to objects from <see cref="_activeAnimations"/>). In
        /// that step we calculate an attribute <see cref="AnimatedNode.ActiveIncomingNodes"/>.
        /// The second BFS runs in topological order over the sub-graph of
        /// *active* nodes. This is done by adding nodes to the BFS queue only
        /// if all its "predecessors" have already been visited.
        /// </remarks>
        /// <param name="renderingTime">Frame rendering time.</param>
        public void RunUpdates(TimeSpan renderingTime)
        {
            DispatcherHelpers.AssertOnDispatcher();
            var hasFinishedAnimations = false;

            for (var i = 0; i < _updatedNodes.Count; ++i)
            {
                var node = _updatedNodes[i];
                _runUpdateNodeList.Add(node);
            }

            // Clean _updatedNodes queue
            _updatedNodes.Clear();

            for (var i = 0; i < _activeAnimations.Count; ++i)
            {
                var animation = _activeAnimations[i];
                animation.RunAnimationStep(renderingTime);
                var valueNode = animation.AnimatedValue;
                _runUpdateNodeList.Add(valueNode);
                if (animation.HasFinished)
                {
                    hasFinishedAnimations = true;
                }
            }

            UpdateNodes(_runUpdateNodeList);
            _runUpdateNodeList.Clear();

            // Cleanup finished animations. Iterate over the array of animations and override ones that has
            // finished, then resize `_activeAnimations`.
            if (hasFinishedAnimations)
            {
                int dest = 0;
                for (var i = 0; i < _activeAnimations.Count; ++i)
                {
                    var animation = _activeAnimations[i];
                    if (!animation.HasFinished)
                    {
                        _activeAnimations[dest++] = animation;
                    }
                    else
                    {
                        animation.EndCallback.Invoke(new JObject
                        {
                            { "finished", true },
                        });
                    }
                }

                for (var i = _activeAnimations.Count - 1; i >= dest; --i)
                {
                    _activeAnimations.RemoveAt(i);
                }
            }
        }
Exemplo n.º 12
0
        private void DetachViewFromInstance(ReactRootView rootView, IReactInstance reactInstance)
        {
            DispatcherHelpers.AssertOnDispatcher();

            var uiManagerModule = reactInstance.GetNativeModule <UIManagerModule>();

            uiManagerModule.DetachRootView(rootView);

            reactInstance.GetJavaScriptModule <AppRegistry>().unmountApplicationComponentAtRootTag(rootView.GetTag());
        }
 /// <summary>
 /// Awaits the currently initializing React context, or returns null if context fails to initialize.
 /// </summary>
 /// <param name="token">A token to cancel the request.</param>
 /// <returns>
 /// A task to await the React context.
 /// </returns>
 public async Task <ReactContext> TryGetReactContextAsync(CancellationToken token)
 {
     RnLog.Info(ReactConstants.RNW, $"ReactInstanceManager: TryGetReactContextAsync - entry");
     DispatcherHelpers.AssertOnDispatcher();
     using (await _lock.LockAsync())
     {
         // By this point context has already been created due to the serialized aspect of context initialization.
         RnLog.Info(ReactConstants.RNW, $"ReactInstanceManager: TryGetReactContextAsync - execute/returning existing {(_currentReactContext == null ? "null" : "valid")} context");
         return(_currentReactContext);
     }
 }
Exemplo n.º 14
0
        /// <summary>
        /// Hooks into the measurement event to potentially attach the React
        /// root view.
        /// </summary>
        /// <param name="availableSize">The available size.</param>
        /// <returns>The desired size.</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            DispatcherHelpers.AssertOnDispatcher(this);

            var result = base.MeasureOverride(availableSize);

            // Fire and forget async
            Forget(MeasureOverrideHelperAsync());

            return(result);
        }
 /// <summary>
 /// Instantiates the <see cref="DeviceEventManagerModule"/>.
 /// </summary>
 /// <param name="reactContext">The React context.</param>
 /// <param name="onBackPressed">
 /// The action to take when back is pressed.
 /// </param>
 public DeviceEventManagerModule(
     ReactContext reactContext,
     Action onBackPressed)
     : base(reactContext)
 {
     _invokeDefaultBackPressAction = () =>
     {
         DispatcherHelpers.AssertOnDispatcher();
         onBackPressed();
     };
 }
Exemplo n.º 16
0
        /// <summary>
        /// Frees resources associated with this root view.
        /// </summary>
        /// <remarks>
        /// Has to be called under the dispatcher associated with the view.
        /// </remarks>
        public async Task StopReactApplicationAsync()
        {
            DispatcherHelpers.AssertOnDispatcher(this);

            var reactInstanceManager = _reactInstanceManager;

            if (!_attachScheduled && reactInstanceManager != null)
            {
                await reactInstanceManager.DetachRootViewAsync(this);
            }
        }
Exemplo n.º 17
0
        /// <summary>
        /// Called when the host receives the resume event.
        /// </summary>
        public void OnResume()
        {
            DispatcherHelpers.AssertOnDispatcher();

            if (_rctEventEmitter == null)
            {
                _rctEventEmitter = _reactContext.GetJavaScriptModule <RCTEventEmitter>();
            }

            CompositionTarget.Rendering += ScheduleDispatch;
        }
 private void AddRootViewParent(int tag, Widget view, ThemedReactContext themedContext)
 {
     Log.Info(ReactConstants.Tag, "### [BGN] AddRootViewParent ### ");
     DispatcherHelpers.AssertOnDispatcher();
     _tagsToViews.Add(tag, view);
     _tagsToViewManagers.Add(tag, _rootViewManager);
     _rootTags.Add(tag, true);
     view.SetTag(tag);
     view.SetReactContext(themedContext);
     Log.Info(ReactConstants.Tag, "### [END] AddRootViewParent ### ");
 }
Exemplo n.º 19
0
        /// <summary>
        /// Registers a new root view.
        /// </summary>
        /// <param name="rootView">The root view instance.</param>
        /// <returns>The root view tag.</returns>
        /// <remarks>
        /// JavaScript can use the returned tag with to add or remove children
        /// to this view through <see cref="manageChildren(int, int[], int[], int[], int[], int[])"/>.
        /// </remarks>
        public async Task <int> AddMeasuredRootViewAsync(ReactRootView rootView)
        {
            // Called on main dispatcher thread
            DispatcherHelpers.AssertOnDispatcher();

            var tag = _nextRootTag;

            _nextRootTag += RootViewTagIncrement;

            // Set tag early in case of concurrent DetachRootViewAsync
            rootView.SetTag(tag);

            var context = new ThemedReactContext(Context);

            await DispatcherHelpers.CallOnDispatcher(rootView.Dispatcher, () =>
            {
                var width  = rootView.ActualWidth;
                var height = rootView.ActualHeight;

                _layoutActionQueue.Dispatch(() =>
                {
                    _uiImplementation.RegisterRootView(rootView, tag, width, height, context);
                });

                var resizeCount = 0;

                rootView.SetOnSizeChangedListener((sender, args) =>
                {
                    var currentCount = ++resizeCount;
                    var newWidth     = args.NewSize.Width;
                    var newHeight    = args.NewSize.Height;

                    _layoutActionQueue.Dispatch(() =>
                    {
                        if (currentCount == resizeCount)
                        {
                            _layoutActionQueue.AssertOnThread();
                            _uiImplementation.UpdateRootNodeSize(tag, newWidth, newHeight);
                        }
                    });
                });

                rootView.StartTouchHandling();

#if WINDOWS_UWP
                // Register view in DeviceInfoModule for tracking its dimensions
                Context.GetNativeModule <DeviceInfoModule>().RegisterRootView(rootView, tag);
#endif
                return(true);
            }, true); // Allow inlining

            return(tag);
        }
        /// <summary>
        /// Gets the animation with the given identifier.
        /// </summary>
        /// <param name="animationId">The animation identifier.</param>
        /// <returns>The animation with the given identifier.</returns>
        public ReactAnimation GetAnimation(int animationId)
        {
            DispatcherHelpers.AssertOnDispatcher();
            var result = default(ReactAnimation);

            if (_registry.TryGetValue(animationId, out result))
            {
                return(result);
            }

            return(null);
        }
        /// <summary>
        /// Removes the animation with the given identifier.
        /// </summary>
        /// <param name="animationId">The animation identifier.</param>
        /// <returns>The animation with the given identifier.</returns>
        public ReactAnimation RemoveAnimation(int animationId)
        {
            DispatcherHelpers.AssertOnDispatcher();
            var animation = GetAnimation(animationId);

            if (animation != null)
            {
                _registry.Remove(animationId);
            }

            return(animation);
        }
Exemplo n.º 22
0
        private void DetachViewFromInstance(ReactRootView rootView, IReactInstance reactInstance)
        {
            DispatcherHelpers.AssertOnDispatcher();

            if (-1 != rootView.GetTag())
            {
                reactInstance.GetJavaScriptModule <AppRegistry>().unmountApplicationComponentAtRootTag(rootView.GetTag());
            }

            // timming issue
            Thread.Sleep(2 * 1000);
        }
Exemplo n.º 23
0
        /// <summary>
        /// Unregister <paramref name="rootView"/> and stop keeping track of his dimensions
        /// </summary>
        /// <param name="rootView">The react root view</param>
        public void UnregisterRootView(ReactRootView rootView)
        {
            DispatcherHelpers.AssertOnDispatcher(rootView);

            var info = _registeredViews.Values.SingleOrDefault(i => i.RootView == rootView);

            if (info != null && _registeredViews.TryRemove(info.ApplicationView, out info))
            {
                info.ApplicationView.VisibleBoundsChanged  -= OnVisibleBoundsChanged;
                info.DisplayInformation.OrientationChanged -= OnOrientationChanged;
            }
        }
Exemplo n.º 24
0
        private void RecreateReactContextInBackgroundInner()
        {
            DispatcherHelpers.AssertOnDispatcher();

            if (_useDeveloperSupport && _jsBundleFile == null && _jsMainModuleName != null)
            {
                _devSupportManager.HandleReloadJavaScript();
            }
            else
            {
                RecreateReactContextInBackgroundFromBundleFile();
            }
        }
        private Task <ReactContext> CreateReactContextCoreAsync(CancellationToken token)
        {
            DispatcherHelpers.AssertOnDispatcher();

            if (_useDeveloperSupport && _jsBundleFile == null)
            {
                return(CreateReactContextFromDevManagerAsync(token));
            }
            else
            {
                return(CreateReactContextFromBundleAsync(token));
            }
        }
        /// <summary>
        /// Called when the application is suspended.
        /// </summary>
        public void OnSuspend()
        {
            DispatcherHelpers.AssertOnDispatcher();

            _defaultBackButtonHandler = null;

            if (_useDeveloperSupport)
            {
                _devSupportManager.IsEnabled = false;
            }

            MoveToBeforeResumeLifecycleState();
        }
        /// <summary>
        /// Used when the application resumes to reset the back button handling
        /// in JavaScript.
        /// </summary>
        /// <param name="onBackPressed">
        /// The action to take when back is pressed.
        /// </param>
        public void OnResume(Action onBackPressed)
        {
            DispatcherHelpers.AssertOnDispatcher();

            _defaultBackButtonHandler = onBackPressed;

            if (_useDeveloperSupport)
            {
                _devSupportManager.IsEnabled = true;
            }

            MoveToResumedLifecycleState(false);
        }
Exemplo n.º 28
0
        /// <summary>
        /// Unsets the size changed event handler.
        /// </summary>
        public void RemoveSizeChanged()
        {
            DispatcherHelpers.AssertOnDispatcher(this);

            var sizeChangedEventHandler = _sizeChangedEventHandler;

            if (sizeChangedEventHandler != null)
            {
                SizeChanged -= sizeChangedEventHandler;
            }

            _sizeChangedEventHandler = null;
        }
Exemplo n.º 29
0
        private void ScheduleDispatch(object sender, object e)
        {
            DispatcherHelpers.AssertOnDispatcher();

            var activity = Tracer.Trace(Tracer.TRACE_TAG_REACT_BRIDGE, "ScheduleDispatch").Start();

            MoveStagedEventsToDispatchQueue();

            if (!Volatile.Read(ref _hasDispatchScheduled))
            {
                _hasDispatchScheduled = true;
                _reactContext.RunOnJavaScriptQueueThread(() => DispatchEvents(activity));
            }
        }
        /// <summary>
        /// Remove the root view with the given tag.
        /// </summary>
        /// <param name="rootViewTag">The root view tag.</param>
        public void RemoveRootView(int rootViewTag)
        {
            DispatcherHelpers.AssertOnDispatcher();
            if (!_rootTags.ContainsKey(rootViewTag))
            {
                throw new InvalidOperationException(
                          Invariant($"View with tag '{rootViewTag}' is not registered as a root view."));
            }

            var rootView = _tagsToViews[rootViewTag];

            DropView(rootView);
            _rootTags.Remove(rootViewTag);
        }