Skip to content

Commit 40e3c4b

Browse files
committed
Fixes microsoft#151 - Adds shake menu for dev options.
1 parent f05e9ea commit 40e3c4b

File tree

5 files changed

+213
-2
lines changed

5 files changed

+213
-2
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<ContentDialog
2+
x:Class="ReactNative.DevSupport.DevOptionDialog"
3+
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5+
xmlns:local="using:ReactNative.DevSupport"
6+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
7+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
8+
mc:Ignorable="d"
9+
Title="Dev Options"
10+
PrimaryButtonText="Cancel"
11+
PrimaryButtonClick="ContentDialog_PrimaryButtonClick">
12+
13+
<StackPanel Name="OptionsStackPanel">
14+
<StackPanel.Resources>
15+
<Style TargetType="Button">
16+
<Setter Property="Margin" Value="2" />
17+
<Setter Property="HorizontalAlignment" Value="Stretch" />
18+
</Style>
19+
</StackPanel.Resources>
20+
</StackPanel>
21+
</ContentDialog>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using Windows.UI.Xaml;
3+
using Windows.UI.Xaml.Controls;
4+
5+
// The Content Dialog item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
6+
7+
namespace ReactNative.DevSupport
8+
{
9+
sealed partial class DevOptionDialog : ContentDialog
10+
{
11+
private static readonly Thickness s_buttonMargin = new Thickness(2);
12+
13+
public DevOptionDialog()
14+
{
15+
this.InitializeComponent();
16+
}
17+
18+
public void Add(string name, Action onSelect)
19+
{
20+
var button = new Button
21+
{
22+
Content = name,
23+
};
24+
25+
button.Click += (sender, args) => onSelect();
26+
27+
OptionsStackPanel.Children.Add(button);
28+
}
29+
30+
private void ContentDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
31+
{
32+
}
33+
}
34+
}

ReactWindows/ReactNative/DevSupport/DevSupportManager.cs

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using ReactNative.Tracing;
55
using System;
66
using System.Runtime.ExceptionServices;
7+
using System.Threading.Tasks;
8+
using Windows.Foundation;
79

810
namespace ReactNative.DevSupport
911
{
@@ -12,13 +14,24 @@ class DevSupportManager : IDevSupportManager
1214
private const int NativeErrorCookie = -1;
1315

1416
private readonly string _jsAppBundleName;
17+
private readonly ShakeAccelerometer _accelerometer;
1518

1619
private RedBoxDialog _redBoxDialog;
1720
private bool _redBoxDialogOpen;
21+
private DevOptionDialog _devOptionDialog;
1822

1923
public DevSupportManager(string jsAppBundleName)
2024
{
2125
_jsAppBundleName = jsAppBundleName;
26+
27+
_accelerometer = ShakeAccelerometer.GetDefault();
28+
if (_accelerometer != null)
29+
{
30+
_accelerometer.Shaken += (sender, args) =>
31+
{
32+
ShowDevOptionsDialog();
33+
};
34+
}
2235
}
2336

2437
public bool IsEnabled { get; set; } = true;
@@ -50,6 +63,44 @@ public void HandleException(Exception exception)
5063
}
5164
}
5265

66+
public void HandleReloadJavaScript()
67+
{
68+
}
69+
70+
public void ShowDevOptionsDialog()
71+
{
72+
DispatcherHelpers.RunOnDispatcher(() =>
73+
{
74+
if (_devOptionDialog != null || !IsEnabled)
75+
{
76+
return;
77+
}
78+
79+
_devOptionDialog = new DevOptionDialog();
80+
_devOptionDialog.Closed += (_, __) =>
81+
{
82+
_devOptionDialog = null;
83+
};
84+
85+
var options = new[]
86+
{
87+
new DevOptionHandler("Reload JavaScript", HandleReloadJavaScript),
88+
};
89+
90+
foreach (var option in options)
91+
{
92+
_devOptionDialog.Add(option.Name, option.OnSelect);
93+
}
94+
95+
var asyncInfo = _devOptionDialog.ShowAsync();
96+
97+
foreach (var option in options)
98+
{
99+
option.AsyncInfo = asyncInfo;
100+
}
101+
});
102+
}
103+
53104
public void ShowNewJavaScriptError(string title, JArray details, int exceptionId)
54105
{
55106
ShowNewError(title, StackTraceHelper.ConvertJavaScriptStackTrace(details), exceptionId);
@@ -90,13 +141,43 @@ private void ShowNewError(string title, IStackFrame[] stack, int errorCookie)
90141
return;
91142
}
92143

144+
_redBoxDialogOpen = true;
93145
_redBoxDialog.ErrorCookie = errorCookie;
94146
_redBoxDialog.Title = title;
95147
_redBoxDialog.StackTrace = stack;
96-
_redBoxDialog.Opened += (_, __) => _redBoxDialogOpen = true;
97-
_redBoxDialog.Closed += (_, __) => _redBoxDialogOpen = false;
148+
_redBoxDialog.Closed += (_, __) =>
149+
{
150+
_redBoxDialogOpen = false;
151+
_redBoxDialog = null;
152+
};
153+
98154
await _redBoxDialog.ShowAsync();
99155
});
100156
}
157+
158+
class DevOptionHandler
159+
{
160+
private readonly Action _onSelect;
161+
162+
public DevOptionHandler(string name, Action onSelect)
163+
{
164+
Name = name;
165+
_onSelect = onSelect;
166+
}
167+
168+
public string Name { get; }
169+
170+
public IAsyncInfo AsyncInfo { get; set; }
171+
172+
public void OnSelect()
173+
{
174+
_onSelect();
175+
var asyncInfo = AsyncInfo;
176+
if (asyncInfo != null)
177+
{
178+
asyncInfo.Cancel();
179+
}
180+
}
181+
}
101182
}
102183
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
using System;
2+
using Windows.Devices.Sensors;
3+
4+
namespace ReactNative.DevSupport
5+
{
6+
/// <summary>
7+
/// A static class that manages the Shaken event for the Accelerometer.
8+
/// </summary>
9+
public class ShakeAccelerometer
10+
{
11+
private const double AccelerationThreshold = 2;
12+
private const int ShakenInterval = 500;
13+
14+
private static ShakeAccelerometer s_instance;
15+
16+
private readonly Accelerometer _instance;
17+
18+
private DateTime _lastDetected = DateTime.Now;
19+
private bool _enabled;
20+
21+
private ShakeAccelerometer(Accelerometer instance)
22+
{
23+
_instance = instance;
24+
_instance.ReadingChanged += OnReadingChanged;
25+
}
26+
27+
/// <summary>
28+
/// Raised whenever the Accelerometer detects a shaking gesture.
29+
/// </summary>
30+
public event EventHandler Shaken;
31+
32+
/// <summary>
33+
/// Get the default shake accelerometer.
34+
/// </summary>
35+
/// <returns>The default shake accelerometer.</returns>
36+
public static ShakeAccelerometer GetDefault()
37+
{
38+
if (s_instance == null)
39+
{
40+
var accelerometer = Accelerometer.GetDefault();
41+
if (accelerometer != null)
42+
{
43+
s_instance = new ShakeAccelerometer(accelerometer);
44+
}
45+
}
46+
47+
return s_instance;
48+
}
49+
50+
private void OnReadingChanged(Accelerometer sender, AccelerometerReadingChangedEventArgs args)
51+
{
52+
double g = Math.Round(Square(args.Reading.AccelerationX) + Square(args.Reading.AccelerationY) + Square(args.Reading.AccelerationZ));
53+
if (g > AccelerationThreshold && DateTime.Now.Subtract(_lastDetected).Milliseconds > ShakenInterval)
54+
{
55+
_lastDetected = DateTime.Now;
56+
Shaken?.Invoke(null, EventArgs.Empty);
57+
}
58+
}
59+
60+
private static double Square(double value)
61+
{
62+
return value * value;
63+
}
64+
}
65+
}

ReactWindows/ReactNative/ReactNative.csproj

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,14 @@
148148
<Compile Include="Bridge\Queue\MessageQueueThreadSpec.cs" />
149149
<Compile Include="Bridge\ReflectionReactDelegateFactory.cs" />
150150
<Compile Include="Collections\HeapBasedPriorityQueue.cs" />
151+
<Compile Include="DevSupport\DevOptionDialog.xaml.cs">
152+
<DependentUpon>DevOptionDialog.xaml</DependentUpon>
153+
</Compile>
151154
<Compile Include="DevSupport\DevSupportManager.cs" />
152155
<Compile Include="DevSupport\DisabledDevSupportManager.cs" />
153156
<Compile Include="DevSupport\IStackFrame.cs" />
154157
<Compile Include="DevSupport\RedBoxDialog.cs" />
158+
<Compile Include="DevSupport\ShakeAccelerometer.cs" />
155159
<Compile Include="DevSupport\StackFrameExtensions.cs" />
156160
<Compile Include="DevSupport\StackTraceHelper.cs" />
157161
<Compile Include="Hosting\Bridge\ChakraJavaScriptExecutor.cs" />
@@ -309,6 +313,12 @@
309313
<HintPath>..\References\Facebook.CSSLayout.dll</HintPath>
310314
</Reference>
311315
</ItemGroup>
316+
<ItemGroup>
317+
<Page Include="DevSupport\DevOptionDialog.xaml">
318+
<SubType>Designer</SubType>
319+
<Generator>MSBuild:Compile</Generator>
320+
</Page>
321+
</ItemGroup>
312322
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
313323
<VisualStudioVersion>14.0</VisualStudioVersion>
314324
</PropertyGroup>

0 commit comments

Comments
 (0)