Пример #1
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 int AddMeasuredRootView(SizeMonitoringCanvas rootView)
        {
            var tag = _nextRootTag;

            _nextRootTag += RootViewTagIncrement;

            var width  = rootView.ActualWidth;
            var height = rootView.ActualHeight;

            var context = new ThemedReactContext(Context);

            _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);
                    }
                });
            });

            return(tag);
        }
Пример #2
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);
        }
Пример #3
0
        /// <summary>
        /// Calls a function on a message queue and returns a task to await the response.
        /// </summary>
        /// <typeparam name="T">Type of response.</typeparam>
        /// <param name="actionQueue">The message queue thread.</param>
        /// <param name="func">The function.</param>
        /// <returns>A task to await the result.</returns>
        public static Task <T> RunAsync <T>(this IActionQueue actionQueue, Func <T> func)
        {
            var taskCompletionSource = new TaskCompletionSource <T>();

            actionQueue.Dispatch(() =>
            {
                try
                {
                    var result = func();

                    // TaskCompletionSource<T>.SetResult can call continuations
                    // on the awaiter of the task completion source. We want to
                    // prevent the action queue thread from executing these
                    // continuations.
                    Task.Run(() => taskCompletionSource.SetResult(result));
                }
                catch (Exception ex)
                {
                    // TaskCompletionSource<T>.SetException can call continuations
                    // on the awaiter of the task completion source. We want to
                    // prevent the action queue thread from executing these
                    // continuations.
                    Task.Run(() => taskCompletionSource.SetException(ex));
                }
            });

            return(taskCompletionSource.Task);
        }
        /// <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 int AddMeasuredRootView(ReactRootView rootView)
        {
            // Called on main dispatcher thread
            DispatcherHelpers.AssertOnDispatcher();

            var tag = _nextRootTag;

            _nextRootTag += RootViewTagIncrement;

            var context = new ThemedReactContext(Context);

            DispatcherHelpers.RunOnDispatcher(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);
                        }
                    });
                });
            }, true); // Allow inlining

            return(tag);
        }
        /// <summary>
        /// Calls a function on a message queue and returns a task to await the response.
        /// </summary>
        /// <typeparam name="T">Type of response.</typeparam>
        /// <param name="actionQueue">The message queue thread.</param>
        /// <param name="func">The function.</param>
        /// <returns>A task to await the result.</returns>
        public static Task <T> RunAsync <T>(this IActionQueue actionQueue, Func <T> func)
        {
            var taskCompletionSource = new TaskCompletionSource <T>();

            actionQueue.Dispatch(() =>
            {
                var result = func();

                // TaskCompletionSource<T>.SetResult can call continuations
                // on the awaiter of the task completion source.
                Task.Run(() => taskCompletionSource.SetResult(result));
            });

            return(taskCompletionSource.Task);
        }
Пример #6
0
        private void ProcessResponse(JToken response)
        {
            if (response == null || response.Type == JTokenType.Null || response.Type == JTokenType.Undefined)
            {
                return;
            }

            var messages = response as JArray;

            if (messages == null)
            {
                throw new InvalidOperationException(
                          "Did not get valid calls back from JavaScript. Message type: " + response.Type);
            }

            if (messages.Count < 3)
            {
                throw new InvalidOperationException(
                          "Did not get valid calls back from JavaScript. Message count: " + messages.Count);
            }

            var moduleIds   = messages[0] as JArray;
            var methodIds   = messages[1] as JArray;
            var paramsArray = messages[2] as JArray;

            if (moduleIds == null || methodIds == null || paramsArray == null ||
                moduleIds.Count != methodIds.Count || moduleIds.Count != paramsArray.Count)
            {
                throw new InvalidOperationException(
                          "Did not get valid calls back from JavaScript. JSON: " + response);
            }

            _nativeModulesQueueThread.Dispatch(() =>
            {
                for (var i = 0; i < moduleIds.Count; ++i)
                {
                    var moduleId = moduleIds[i].Value <int>();
                    var methodId = methodIds[i].Value <int>();
                    var args     = (JArray)paramsArray[i];

                    _reactCallback.Invoke(moduleId, methodId, args);
                }
                ;

                _reactCallback.OnBatchComplete();
            });
        }
Пример #7
0
        /// <summary>
        /// Hook needed to cleanup the local state (_reactTagToOperationQueue)
        /// </summary>
        /// <param name="tags">List of deleted tags..</param>
        private void OnViewsDropped(List <int> tags)
        {
            //
            // We synchronize access to _reactTagToOperationQueue by using same action queue used by the other code paths.
            // Cleaning up can be done lazily, a way to mark this work unit as "Idle Scheduling" would benefit performance.
            if (_uiManagerActionQueue == null)
            {
                _uiManagerActionQueue = _reactContext.GetNativeModule <UIManagerModule>().ActionQueue;
            }

            _uiManagerActionQueue.Dispatch(() =>
            {
                foreach (var tag in tags)
                {
                    _reactTagToOperationQueue.Remove(tag);
                }
            });
        }
        /// <summary>
        /// Calls a function on a message queue and returns a task to await the response.
        /// </summary>
        /// <typeparam name="T">Type of response.</typeparam>
        /// <param name="actionQueue">The message queue thread.</param>
        /// <param name="func">The function.</param>
        /// <returns>A task to await the result.</returns>
        public static Task <T> RunAsync <T>(this IActionQueue actionQueue, Func <T> func)
        {
            var taskCompletionSource = new TaskCompletionSource <T>(/*TaskCreationOptions.RunContinuationsAsynchronously*/);

            actionQueue.Dispatch(() =>
            {
                try
                {
                    var result = func();
                    taskCompletionSource.SetResult(result);
                }
                catch (Exception ex)
                {
                    taskCompletionSource.SetException(ex);
                }
            });

            return(taskCompletionSource.Task);
        }