Initial WPF Support (#385)
* initial support for WPF * update readme with WPF specific instructions * remove autogenerated .gitattributes file * reference RNW NPM package instead of hard-coded local reference
This commit is contained in:
parent
d48d7efc5d
commit
ebc6617ba4
@ -80,14 +80,18 @@ Add the `ReactNativeVideo` project to your solution.
|
|||||||
|
|
||||||
1. Open the solution in Visual Studio 2015
|
1. Open the solution in Visual Studio 2015
|
||||||
2. Right-click Solution icon in Solution Explorer > Add > Existing Project...
|
2. Right-click Solution icon in Solution Explorer > Add > Existing Project...
|
||||||
3. Select `node_modules\react-native-video\windows\ReactNativeVideo\ReactNativeVideo.csproj`
|
3.
|
||||||
|
UWP: Select `node_modules\react-native-video\windows\ReactNativeVideo\ReactNativeVideo.csproj`
|
||||||
|
WPF: Select `node_modules\react-native-video\windows\ReactNativeVideo.Net46\ReactNativeVideo.Net46.csproj`
|
||||||
|
|
||||||
**windows/myapp/myapp.csproj**
|
**windows/myapp/myapp.csproj**
|
||||||
|
|
||||||
Add a reference to `ReactNativeVideo` to your main application project. From Visual Studio 2015:
|
Add a reference to `ReactNativeVideo` to your main application project. From Visual Studio 2015:
|
||||||
|
|
||||||
1. Right-click main application project > Add > Reference...
|
1. Right-click main application project > Add > Reference...
|
||||||
2. Check `ReactNativeVideo` from Solution Projects.
|
2.
|
||||||
|
UWP: Check `ReactNativeVideo` from Solution Projects.
|
||||||
|
WPF: Check `ReactNativeVideo.Net46` from Solution Projects.
|
||||||
|
|
||||||
**MainPage.cs**
|
**MainPage.cs**
|
||||||
|
|
||||||
|
@ -27,7 +27,8 @@
|
|||||||
"eslint-config-airbnb": "4.0.0"
|
"eslint-config-airbnb": "4.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"keymirror": "0.1.1"
|
"keymirror": "0.1.1",
|
||||||
|
"react-native-windows": "0.41.0-rc.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "node_modules/.bin/eslint *.js"
|
"test": "node_modules/.bin/eslint *.js"
|
||||||
|
36
windows/ReactNativeVideo.Net46/Properties/AssemblyInfo.cs
Normal file
36
windows/ReactNativeVideo.Net46/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("ReactNativeVideo.Net46")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("ReactNativeVideo.Net46")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("2d8406ab-0674-42d3-8fe3-41d251403df8")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
74
windows/ReactNativeVideo.Net46/ReactNativeVideo.Net46.csproj
Normal file
74
windows/ReactNativeVideo.Net46/ReactNativeVideo.Net46.csproj
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProjectGuid>{2D8406AB-0674-42D3-8FE3-41D251403DF8}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>ReactNativeVideo.Net46</RootNamespace>
|
||||||
|
<AssemblyName>ReactNativeVideo.Net46</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||||
|
<PlatformTarget>x64</PlatformTarget>
|
||||||
|
<OutputPath>bin\x64\Release\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||||
|
<PlatformTarget>x86</PlatformTarget>
|
||||||
|
<OutputPath>bin\x86\Release\</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
|
<HintPath>$(SolutionDir)\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="PresentationCore" />
|
||||||
|
<Reference Include="PresentationFramework" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core" />
|
||||||
|
<Reference Include="System.Xaml" />
|
||||||
|
<Reference Include="System.Xml.Linq" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
|
<Reference Include="Microsoft.CSharp" />
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Net.Http" />
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="WindowsBase" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="ReactVideoEventType.cs" />
|
||||||
|
<Compile Include="ReactVideoEventTypeExtensions.cs" />
|
||||||
|
<Compile Include="ReactVideoPackage.cs" />
|
||||||
|
<Compile Include="ReactVideoView.cs" />
|
||||||
|
<Compile Include="ReactVideoViewManager.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="$(SolutionDir)\..\node_modules\react-native-windows\ReactWindows\ReactNative.Net46\ReactNative.Net46.csproj">
|
||||||
|
<Project>{22CBFF9C-FE36-43E8-A246-266C7635E662}</Project>
|
||||||
|
<Name>ReactNative.Net46</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
|
<Target Name="BeforeBuild">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
15
windows/ReactNativeVideo.Net46/ReactVideoEventType.cs
Normal file
15
windows/ReactNativeVideo.Net46/ReactVideoEventType.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace ReactNativeVideo
|
||||||
|
{
|
||||||
|
enum ReactVideoEventType
|
||||||
|
{
|
||||||
|
LoadStart,
|
||||||
|
Load,
|
||||||
|
Error,
|
||||||
|
Progress,
|
||||||
|
Seek,
|
||||||
|
End,
|
||||||
|
Stalled,
|
||||||
|
Resume,
|
||||||
|
ReadyForDisplay,
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using static System.FormattableString;
|
||||||
|
|
||||||
|
namespace ReactNativeVideo
|
||||||
|
{
|
||||||
|
static class ReactVideoEventTypeExtensions
|
||||||
|
{
|
||||||
|
public static string GetEventName(this ReactVideoEventType eventType)
|
||||||
|
{
|
||||||
|
switch (eventType)
|
||||||
|
{
|
||||||
|
case ReactVideoEventType.LoadStart:
|
||||||
|
return "onVideoLoadStart";
|
||||||
|
case ReactVideoEventType.Load:
|
||||||
|
return "onVideoLoad";
|
||||||
|
case ReactVideoEventType.Error:
|
||||||
|
return "onVideoError";
|
||||||
|
case ReactVideoEventType.Progress:
|
||||||
|
return "onVideoProgress";
|
||||||
|
case ReactVideoEventType.Seek:
|
||||||
|
return "onVideoSeek";
|
||||||
|
case ReactVideoEventType.End:
|
||||||
|
return "onVideoEnd";
|
||||||
|
case ReactVideoEventType.Stalled:
|
||||||
|
return "onPlaybackStalled";
|
||||||
|
case ReactVideoEventType.Resume:
|
||||||
|
return "onPlaybackResume";
|
||||||
|
case ReactVideoEventType.ReadyForDisplay:
|
||||||
|
return "onReadyForDisplay";
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException(
|
||||||
|
Invariant($"No event name added for event type '{eventType}'."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
windows/ReactNativeVideo.Net46/ReactVideoPackage.cs
Normal file
30
windows/ReactNativeVideo.Net46/ReactVideoPackage.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using ReactNative.Bridge;
|
||||||
|
using ReactNative.Modules.Core;
|
||||||
|
using ReactNative.UIManager;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ReactNativeVideo
|
||||||
|
{
|
||||||
|
public class ReactVideoPackage : IReactPackage
|
||||||
|
{
|
||||||
|
public IReadOnlyList<Type> CreateJavaScriptModulesConfig()
|
||||||
|
{
|
||||||
|
return Array.Empty<Type>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<INativeModule> CreateNativeModules(ReactContext reactContext)
|
||||||
|
{
|
||||||
|
return Array.Empty<INativeModule>();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IReadOnlyList<IViewManager> CreateViewManagers(ReactContext reactContext)
|
||||||
|
{
|
||||||
|
return new List<IViewManager>
|
||||||
|
{
|
||||||
|
new ReactVideoViewManager(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
359
windows/ReactNativeVideo.Net46/ReactVideoView.cs
Normal file
359
windows/ReactNativeVideo.Net46/ReactVideoView.cs
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using ReactNative.Bridge;
|
||||||
|
using ReactNative.UIManager;
|
||||||
|
using ReactNative.UIManager.Events;
|
||||||
|
using System;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Animation;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
|
||||||
|
namespace ReactNativeVideo
|
||||||
|
{
|
||||||
|
class ReactVideoView : Border, IDisposable
|
||||||
|
{
|
||||||
|
public const string EVENT_PROP_SEEK_TIME = "seekTime";
|
||||||
|
|
||||||
|
private readonly DispatcherTimer _timer;
|
||||||
|
|
||||||
|
private bool _isLoopingEnabled;
|
||||||
|
private bool _isPaused;
|
||||||
|
private bool _isMuted;
|
||||||
|
private bool _isCompleted;
|
||||||
|
private double _volume;
|
||||||
|
private double _rate;
|
||||||
|
|
||||||
|
private MediaPlayer _player;
|
||||||
|
private VideoDrawing _drawing;
|
||||||
|
private MediaTimeline _timeline;
|
||||||
|
private MediaClock _clock;
|
||||||
|
private DrawingBrush _brush;
|
||||||
|
|
||||||
|
public ReactVideoView()
|
||||||
|
{
|
||||||
|
_timer = new DispatcherTimer();
|
||||||
|
_timer.Interval = TimeSpan.FromMilliseconds(250.0);
|
||||||
|
_timer.Start();
|
||||||
|
_player = new MediaPlayer();
|
||||||
|
_drawing = new VideoDrawing();
|
||||||
|
_drawing.Rect = new Rect(0, 0, 100, 100); // Set the initial viewing area
|
||||||
|
_drawing.Player = _player;
|
||||||
|
_brush = new DrawingBrush(_drawing);
|
||||||
|
this.Background = _brush;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Source
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var uri = new Uri(value);
|
||||||
|
|
||||||
|
_player.Open(uri);
|
||||||
|
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher
|
||||||
|
.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.LoadStart.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
new JObject
|
||||||
|
{
|
||||||
|
{"src", uri}
|
||||||
|
}));
|
||||||
|
|
||||||
|
ApplyModifiers();
|
||||||
|
SubscribeEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsLoopingEnabled
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isLoopingEnabled = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMuted
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isMuted = value;
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.IsMuted = _isMuted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsPaused
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_isPaused = value;
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
if (_isPaused)
|
||||||
|
{
|
||||||
|
_player.Pause();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_player.Play();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Volume
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_volume = value;
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.Volume = _volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Rate
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_rate = value;
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.SpeedRatio = _rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double ProgressUpdateInterval
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_timer.Interval = TimeSpan.FromSeconds(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Seek(double seek)
|
||||||
|
{
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_player.Position = TimeSpan.FromSeconds(seek);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_player != null)
|
||||||
|
{
|
||||||
|
_timer.Tick -= OnTick;
|
||||||
|
_player.MediaOpened -= OnMediaOpened;
|
||||||
|
_player.MediaFailed -= OnMediaFailed;
|
||||||
|
_player.MediaEnded -= OnMediaEnded;
|
||||||
|
_player.BufferingStarted -= OnBufferingStarted;
|
||||||
|
_player.BufferingEnded -= OnBufferingEnded;
|
||||||
|
// _player.SeekCompleted -= OnSeekCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
_timer.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyModifiers()
|
||||||
|
{
|
||||||
|
IsLoopingEnabled = _isLoopingEnabled;
|
||||||
|
IsMuted = _isMuted;
|
||||||
|
IsPaused = _isPaused;
|
||||||
|
Volume = _volume;
|
||||||
|
Rate = _rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SubscribeEvents()
|
||||||
|
{
|
||||||
|
_timer.Tick += OnTick;
|
||||||
|
_player.MediaOpened += OnMediaOpened;
|
||||||
|
_player.MediaFailed += OnMediaFailed;
|
||||||
|
_player.MediaEnded += OnMediaEnded;
|
||||||
|
_player.BufferingStarted += OnBufferingStarted;
|
||||||
|
_player.BufferingEnded += OnBufferingEnded;
|
||||||
|
//_player.SeekCompleted += OnSeekCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTick(object sender, object e)
|
||||||
|
{
|
||||||
|
if (_player != null && !_isCompleted && !_isPaused)
|
||||||
|
{
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher
|
||||||
|
.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.Progress.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
new JObject
|
||||||
|
{
|
||||||
|
{ "currentTime", _player.Position.TotalSeconds },
|
||||||
|
{ "playableDuration", 0.0 /* TODO */ }
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMediaOpened(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
RunOnDispatcher(delegate
|
||||||
|
{
|
||||||
|
var width = _player.NaturalVideoWidth;
|
||||||
|
var height = _player.NaturalVideoHeight;
|
||||||
|
var orientation = (width > height) ? "landscape" : "portrait";
|
||||||
|
var size = new JObject
|
||||||
|
{
|
||||||
|
{ "width", width },
|
||||||
|
{ "height", height },
|
||||||
|
{ "orientation", orientation }
|
||||||
|
};
|
||||||
|
|
||||||
|
_drawing.Rect = new Rect(new Size(width, height));
|
||||||
|
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher
|
||||||
|
.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.Load.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
new JObject
|
||||||
|
{
|
||||||
|
{ "duration", _player.NaturalDuration.TimeSpan.TotalSeconds },
|
||||||
|
{ "currentTime", _player.Position.TotalSeconds },
|
||||||
|
{ "naturalSize", size },
|
||||||
|
{ "canPlayFastForward", false },
|
||||||
|
{ "canPlaySlowForward", false },
|
||||||
|
{ "canPlaySlow", false },
|
||||||
|
{ "canPlayReverse", false },
|
||||||
|
{ "canStepBackward", false },
|
||||||
|
{ "canStepForward", false }
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMediaFailed(object sender, ExceptionEventArgs args)
|
||||||
|
{
|
||||||
|
var errorData = new JObject
|
||||||
|
{
|
||||||
|
{ "what", args.ErrorException.HResult.ToString() },
|
||||||
|
{ "extra", args.ErrorException.Message }
|
||||||
|
};
|
||||||
|
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher
|
||||||
|
.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.Error.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
new JObject
|
||||||
|
{
|
||||||
|
{ "error", errorData }
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMediaEnded(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
if (_isLoopingEnabled)
|
||||||
|
{
|
||||||
|
_player.Position = TimeSpan.Zero;
|
||||||
|
_player.Play();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_isCompleted = true;
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher
|
||||||
|
.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.End.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBufferingStarted(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher
|
||||||
|
.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.Stalled.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
new JObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBufferingEnded(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher
|
||||||
|
.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.Resume.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
new JObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSeekCompleted(object sender, EventArgs args)
|
||||||
|
{
|
||||||
|
this.GetReactContext()
|
||||||
|
.GetNativeModule<UIManagerModule>()
|
||||||
|
.EventDispatcher.DispatchEvent(
|
||||||
|
new ReactVideoEvent(
|
||||||
|
ReactVideoEventType.Seek.GetEventName(),
|
||||||
|
this.GetTag(),
|
||||||
|
new JObject()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async void RunOnDispatcher(Action action)
|
||||||
|
{
|
||||||
|
await Application.Current.Dispatcher.InvokeAsync(action).Task.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ReactVideoEvent : Event
|
||||||
|
{
|
||||||
|
private readonly string _eventName;
|
||||||
|
private readonly JObject _eventData;
|
||||||
|
|
||||||
|
public ReactVideoEvent(string eventName, int viewTag, JObject eventData)
|
||||||
|
: base(viewTag, TimeSpan.FromTicks(Environment.TickCount))
|
||||||
|
{
|
||||||
|
_eventName = eventName;
|
||||||
|
_eventData = eventData;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string EventName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _eventName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanCoalesce
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Dispatch(RCTEventEmitter eventEmitter)
|
||||||
|
{
|
||||||
|
eventEmitter.receiveEvent(ViewTag, EventName, _eventData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
139
windows/ReactNativeVideo.Net46/ReactVideoViewManager.cs
Normal file
139
windows/ReactNativeVideo.Net46/ReactVideoViewManager.cs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using ReactNative.UIManager;
|
||||||
|
using ReactNative.UIManager.Annotations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace ReactNativeVideo
|
||||||
|
{
|
||||||
|
class ReactVideoViewManager : SimpleViewManager<ReactVideoView>
|
||||||
|
{
|
||||||
|
public override string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return "RCTVideo";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IReadOnlyDictionary<string, object> ExportedViewConstants
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "ScaleNone", ((int)Stretch.None).ToString() },
|
||||||
|
{ "ScaleToFill", ((int)Stretch.UniformToFill).ToString() },
|
||||||
|
{ "ScaleAspectFit", ((int)Stretch.Uniform).ToString() },
|
||||||
|
{ "ScaleAspectFill", ((int)Stretch.Fill).ToString() },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IReadOnlyDictionary<string, object> ExportedCustomDirectEventTypeConstants
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var events = new Dictionary<string, object>();
|
||||||
|
var eventTypes = Enum.GetValues(typeof(ReactVideoEventType)).OfType<ReactVideoEventType>();
|
||||||
|
foreach (var eventType in eventTypes)
|
||||||
|
{
|
||||||
|
events.Add(eventType.GetEventName(), new Dictionary<string, object>
|
||||||
|
{
|
||||||
|
{ "registrationName", eventType.GetEventName() },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("src")]
|
||||||
|
public void SetSource(ReactVideoView view, JObject source)
|
||||||
|
{
|
||||||
|
view.Source = source.Value<string>("uri");
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("resizeMode")]
|
||||||
|
public void SetResizeMode(ReactVideoView view, string resizeMode)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Resize Mode has not been implemented for WPF.");
|
||||||
|
// view.Stretch = (Stretch)int.Parse(resizeMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("repeat")]
|
||||||
|
public void SetRepeat(ReactVideoView view, bool repeat)
|
||||||
|
{
|
||||||
|
view.IsLoopingEnabled = repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("paused")]
|
||||||
|
public void SetPaused(ReactVideoView view, bool paused)
|
||||||
|
{
|
||||||
|
view.IsPaused = paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("muted")]
|
||||||
|
public void SetMuted(ReactVideoView view, bool muted)
|
||||||
|
{
|
||||||
|
view.IsMuted = muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("volume", DefaultDouble = 1.0)]
|
||||||
|
public void SetVolume(ReactVideoView view, double volume)
|
||||||
|
{
|
||||||
|
view.Volume = volume;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("seek")]
|
||||||
|
public void SetSeek(ReactVideoView view, double? seek)
|
||||||
|
{
|
||||||
|
if (seek.HasValue)
|
||||||
|
{
|
||||||
|
view.Seek(seek.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("rate", DefaultDouble = 1.0)]
|
||||||
|
public void SetPlaybackRate(ReactVideoView view, double rate)
|
||||||
|
{
|
||||||
|
view.Rate = rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("playInBackground")]
|
||||||
|
public void SetPlayInBackground(ReactVideoView view, bool playInBackground)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("Play in background has not been implemented on Windows.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Utilize MediaElement when user control enabled and MediaPlayer + VideoDrawing when disabled
|
||||||
|
[ReactProp("controls")]
|
||||||
|
public void SetControls(ReactVideoView view, bool controls)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException("User controls have not been implemented on WPF.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[ReactProp("progressUpdateInterval")]
|
||||||
|
public void SetProgressUpdateInterval(ReactVideoView view, double progressUpdateInterval)
|
||||||
|
{
|
||||||
|
view.ProgressUpdateInterval = progressUpdateInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnDropViewInstance(ThemedReactContext reactContext, ReactVideoView view)
|
||||||
|
{
|
||||||
|
base.OnDropViewInstance(reactContext, view);
|
||||||
|
view.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override ReactVideoView CreateViewInstance(ThemedReactContext reactContext)
|
||||||
|
{
|
||||||
|
return new ReactVideoView
|
||||||
|
{
|
||||||
|
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
4
windows/ReactNativeVideo.Net46/packages.config
Normal file
4
windows/ReactNativeVideo.Net46/packages.config
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net46" />
|
||||||
|
</packages>
|
49
windows/ReactNativeVideo.sln
Normal file
49
windows/ReactNativeVideo.sln
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 14
|
||||||
|
VisualStudioVersion = 14.0.25420.1
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNativeVideo.Net46", "ReactNativeVideo.Net46\ReactNativeVideo.Net46.csproj", "{2D8406AB-0674-42D3-8FE3-41D251403DF8}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNative.Net46", "..\node_modules\react-native-windows\ReactWindows\ReactNative.Net46\ReactNative.Net46.csproj", "{22CBFF9C-FE36-43E8-A246-266C7635E662}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||||
|
..\node_modules\react-native-windows\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{22cbff9c-fe36-43e8-a246-266c7635e662}*SharedItemsImports = 4
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|ARM = Debug|ARM
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|ARM = Release|ARM
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|ARM.ActiveCfg = Debug|x86
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x86.ActiveCfg = Debug|x64
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Debug|x86.Build.0 = Debug|x64
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|ARM.ActiveCfg = Release|x86
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x64.Build.0 = Release|x64
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{2D8406AB-0674-42D3-8FE3-41D251403DF8}.Release|x86.Build.0 = Release|x86
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x86.ActiveCfg = Debug|x86
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x86.Build.0 = Debug|x86
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x64.Build.0 = Release|x64
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x86.ActiveCfg = Release|x86
|
||||||
|
{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x86.Build.0 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
Loading…
Reference in New Issue
Block a user