Skip to content

Commit

Permalink
Fixes #156 - Wired up reload JS from bundle file.
Browse files Browse the repository at this point in the history
  • Loading branch information
rozele committed Feb 21, 2016
1 parent 1eb9333 commit 377628f
Show file tree
Hide file tree
Showing 12 changed files with 265 additions and 13 deletions.
35 changes: 35 additions & 0 deletions ReactWindows/ReactNative/Bridge/JavaScriptBundleLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,18 @@ public static JavaScriptBundleLoader CreateFileLoader(string fileName)
return new FileJavaScriptBundleLoader(fileName);
}

/// <summary>
/// This loader will use the cached bundle from the
/// <see cref="DevSupport.IDevSupportManager"/>.
/// </summary>
/// <param name="sourceUrl">The source URL.</param>
/// <param name="cachedBundle">The cached bundle.</param>
/// <returns>The JavaScript bundle loader.</returns>
public static JavaScriptBundleLoader CreateCachedBundleFromNetworkLoader(string sourceUrl, string cachedBundle)
{
return new CachedJavaScriptBundleLoader(sourceUrl, cachedBundle);
}

class FileJavaScriptBundleLoader : JavaScriptBundleLoader
{
private string _script;
Expand Down Expand Up @@ -85,5 +97,28 @@ public override void LoadScript(IReactBridge bridge)
bridge.RunScript(_script);
}
}

class CachedJavaScriptBundleLoader : JavaScriptBundleLoader
{
private readonly string _cachedBundle;

public CachedJavaScriptBundleLoader(string sourceUrl, string cachedBundle)
{
SourceUrl = sourceUrl;
_cachedBundle = cachedBundle;
}

public override string SourceUrl { get; }

public override Task InitializeAsync()
{
return Task.FromResult(true);
}

public override void LoadScript(IReactBridge executor)
{
executor.RunScript(_cachedBundle);
}
}
}
}
72 changes: 66 additions & 6 deletions ReactWindows/ReactNative/DevSupport/DevSupportManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using ReactNative.Tracing;
using System;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;

namespace ReactNative.DevSupport
Expand All @@ -12,15 +14,24 @@ class DevSupportManager : IDevSupportManager
{
private const int NativeErrorCookie = -1;

private readonly IReactInstanceDevCommandsHandler _reactInstanceCommandsHandler;
private readonly string _jsBundleFile;
private readonly string _jsAppBundleName;
private readonly ShakeAccelerometer _accelerometer;

private readonly ShakeAccelerometer _accelerometer;

private RedBoxDialog _redBoxDialog;
private Action _dismissRedBoxDialog;
private bool _redBoxDialogOpen;
private DevOptionDialog _devOptionDialog;

public DevSupportManager(string jsAppBundleName)
public DevSupportManager(
IReactInstanceDevCommandsHandler reactInstanceCommandsHandler,
string jsBundleFile,
string jsAppBundleName)
{
_reactInstanceCommandsHandler = reactInstanceCommandsHandler;
_jsBundleFile = jsBundleFile;
_jsAppBundleName = jsAppBundleName;

_accelerometer = ShakeAccelerometer.GetDefault();
Expand All @@ -35,6 +46,12 @@ public DevSupportManager(string jsAppBundleName)

public bool IsEnabled { get; set; } = true;

public string SourceUrl
{
get;
set;
}

public string SourceMapUrl
{
get
Expand All @@ -49,6 +66,12 @@ public string SourceMapUrl
}
}

public string CachedJavaScriptBundle
{
get;
private set;
}

public void HandleException(Exception exception)
{
#if DEBUG
Expand All @@ -66,8 +89,29 @@ public void HandleException(Exception exception)
}
}

public void HandleReloadJavaScript()
public async void HandleReloadJavaScript()
{
DispatcherHelpers.AssertOnDispatcher();

var dismissRedBoxDialog = _dismissRedBoxDialog;
if (_redBoxDialogOpen && dismissRedBoxDialog != null)
{
dismissRedBoxDialog();
}

var progressDialog = new ProgressDialog("Please wait...", "Fetching JavaScript bundle.");
var dialogOperation = progressDialog.ShowAsync();

if (_jsBundleFile == null)
{
await ReloadJavaScriptFromServerAsync(progressDialog.Token);
}
else
{
await ReloadJavaScriptFromFileAsync(progressDialog.Token);
}

dialogOperation.Cancel();
}

public void ShowDevOptionsDialog()
Expand Down Expand Up @@ -132,7 +176,7 @@ public void UpdateJavaScriptError(string title, JArray details, int errorCookie)

private void ShowNewError(string title, IStackFrame[] stack, int errorCookie)
{
DispatcherHelpers.RunOnDispatcher(async () =>
DispatcherHelpers.RunOnDispatcher(() =>
{
if (_redBoxDialog == null)
{
Expand All @@ -151,13 +195,28 @@ private void ShowNewError(string title, IStackFrame[] stack, int errorCookie)
_redBoxDialog.Closed += (_, __) =>
{
_redBoxDialogOpen = false;
_dismissRedBoxDialog = null;
_redBoxDialog = null;
};
await _redBoxDialog.ShowAsync();
var asyncInfo = _redBoxDialog.ShowAsync();
_dismissRedBoxDialog = asyncInfo.Cancel;
});
}

private Task ReloadJavaScriptFromServerAsync(CancellationToken token)
{
// TODO: implement loading from bundle server
throw new NotImplementedException();
}

private Task ReloadJavaScriptFromFileAsync(CancellationToken token)
{
_reactInstanceCommandsHandler.OnBundleFileReloadRequest();
return Task.FromResult(true);
}

class DevOptionHandler
{
private readonly Action _onSelect;
Expand All @@ -174,12 +233,13 @@ public DevOptionHandler(string name, Action onSelect)

public void OnSelect()
{
_onSelect();
var asyncInfo = AsyncInfo;
if (asyncInfo != null)
{
asyncInfo.Cancel();
}

_onSelect();
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions ReactWindows/ReactNative/DevSupport/DisabledDevSupportManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ public bool IsEnabled
set;
}

public string SourceUrl
{
get
{
return null;
}
}

public string SourceMapUrl
{
get
Expand All @@ -19,6 +27,14 @@ public string SourceMapUrl
}
}

public string CachedJavaScriptBundle
{
get
{
return null;
}
}

public void HandleException(Exception exception)
{
}
Expand Down
10 changes: 10 additions & 0 deletions ReactWindows/ReactNative/DevSupport/IDevSupportManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,21 @@ public interface IDevSupportManager
/// </summary>
bool IsEnabled { get; set; }

/// <summary>
/// The source URL.
/// </summary>
string SourceUrl { get; }

/// <summary>
/// The source map URL.
/// </summary>
string SourceMapUrl { get; }

/// <summary>
/// The cached JavaScript bundle.
/// </summary>
string CachedJavaScriptBundle { get; }

/// <summary>
/// Handle a native exception.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using ReactNative.Bridge;
using System;

namespace ReactNative.DevSupport
{
/// <summary>
/// Interface used by <see cref="IDevSupportManager"/> for requesting React
/// instance regeneration based on the option that the user selects in the
/// developer options menu.
/// </summary>
public interface IReactInstanceDevCommandsHandler
{
/// <summary>
/// Action to notify the <see cref="IReactInstanceManager"/> about the
/// availability of a new JavaScript bundle downloaded from the server.
/// </summary>
void OnJavaScriptBundleLoadedFromServer();

/// <summary>
/// Action triggered when the user requests that the application be
/// reloaded from the initially specified bundle file.
/// </summary>
void OnBundleFileReloadRequest();
}
}
28 changes: 28 additions & 0 deletions ReactWindows/ReactNative/DevSupport/ProgressDialog.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<ContentDialog
x:Class="ReactNative.DevSupport.ProgressDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ReactNative.DevSupport"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="{x:Bind Path=Heading, Mode=OneTime}"
PrimaryButtonText="Dismiss"
PrimaryButtonClick="ContentDialog_PrimaryButtonClick">

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Name="MessageTextBlock"
Text="{x:Bind Path=Message, Mode=OneTime}"
HorizontalAlignment="Center"
Margin="0 10 0 0"
Grid.Row="0" />
<ProgressRing IsActive="True"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Grid.Row="1" />
</Grid>
</ContentDialog>
39 changes: 39 additions & 0 deletions ReactWindows/ReactNative/DevSupport/ProgressDialog.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Threading;
using Windows.UI.Xaml.Controls;

// The Content Dialog item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238

namespace ReactNative.DevSupport
{
public sealed partial class ProgressDialog : ContentDialog
{
private readonly CancellationTokenSource _cancellationTokenSource;

public ProgressDialog(string title, string message)
{
this.InitializeComponent();

Heading = title;
Message = message;

_cancellationTokenSource = new CancellationTokenSource();
}

public string Heading { get; }

public string Message { get; }

public CancellationToken Token
{
get
{
return _cancellationTokenSource.Token;
}
}

private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
_cancellationTokenSource.Cancel();
}
}
}
1 change: 0 additions & 1 deletion ReactWindows/ReactNative/DevSupport/ShakeAccelerometer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ public class ShakeAccelerometer
private readonly Accelerometer _instance;

private DateTime _lastDetected = DateTime.Now;
private bool _enabled;

private ShakeAccelerometer(Accelerometer instance)
{
Expand Down
Loading

0 comments on commit 377628f

Please sign in to comment.