/// <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); }
/// <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> /// 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); }
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(); }); }
/// <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); }