Merge pull request #337 from rozele/windows

Adds react-native-windows support for UWP
This commit is contained in:
Hagen Hübel 2017-10-05 19:07:52 +02:00 committed by GitHub
commit 7f222be4e3
27 changed files with 3163 additions and 0 deletions

78
windows/.gitignore vendored Normal file
View File

@ -0,0 +1,78 @@
*AppPackages*
*BundleArtifacts*
*ReactAssets*
#OS junk files
[Tt]humbs.db
*.DS_Store
#Visual Studio files
*.[Oo]bj
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.[Cc]ache
*.ilk
*.log
*.lib
*.sbr
*.sdf
*.opensdf
*.opendb
*.unsuccessfulbuild
ipch/
[Oo]bj/
[Bb]in
[Dd]ebug*/
[Rr]elease*/
Ankh.NoLoad
#MonoDevelop
*.pidb
*.userprefs
#Tooling
_ReSharper*/
*.resharper
[Tt]est[Rr]esult*
*.sass-cache
#Project files
[Bb]uild/
#Subversion files
.svn
# Office Temp Files
~$*
# vim Temp Files
*~
#NuGet
packages/
*.nupkg
#ncrunch
*ncrunch*
*crunch*.local.xml
# visual studio database projects
*.dbmdl
#Test files
*.testsettings
#Other files
*.DotSettings
.vs/
*project.lock.json

9
windows/.npmignore Normal file
View File

@ -0,0 +1,9 @@
# Make sure we don't publish build artifacts to NPM
ARM/
Debug/
x64/
x86/
bin/
obj/
.vs/

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
IgnorableNamespaces="uap mp">
<Identity Name="ad16a47e-d1a1-4328-9c43-c9609e328e36"
Publisher="CN=ericroz"
Version="1.0.0.0" />
<mp:PhoneIdentity PhoneProductId="ad16a47e-d1a1-4328-9c43-c9609e328e36" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
<Properties>
<DisplayName>RNFS.Tests</DisplayName>
<PublisherDisplayName>ericroz</PublisherDisplayName>
<Logo>Assets\StoreLogo.png</Logo>
</Properties>
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
</Dependencies>
<Resources>
<Resource Language="x-generate" />
</Resources>
<Applications>
<Application Id="vstest.executionengine.universal.App"
Executable="$targetnametoken$.exe"
EntryPoint="RNFS.Tests.App">
<uap:VisualElements
DisplayName="RNFS.Tests"
Square150x150Logo="Assets\Square150x150Logo.png"
Square44x44Logo="Assets\Square44x44Logo.png"
Description="RNFS.Tests"
BackgroundColor="transparent">
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
<uap:SplashScreen Image="Assets\SplashScreen.png" />
</uap:VisualElements>
</Application>
</Applications>
<Capabilities>
<Capability Name="internetClientServer" />
</Capabilities>
</Package>

View File

@ -0,0 +1,18 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("RNFS.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RNFS.Tests")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyMetadata("TargetPlatform","UAP")]
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]

View File

@ -0,0 +1,29 @@
<!--
This file contains Runtime Directives used by .NET Native. The defaults here are suitable for most
developers. However, you can modify these parameters to modify the behavior of the .NET Native
optimizer.
Runtime Directives are documented at http://go.microsoft.com/fwlink/?LinkID=391919
To fully enable reflection for App1.MyClass and all of its public/private members
<Type Name="App1.MyClass" Dynamic="Required All"/>
To enable dynamic creation of the specific instantiation of AppClass<T> over System.Int32
<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32" Activate="Required Public" />
Using the Namespace directive to apply reflection policy to all the types in a particular namespace
<Namespace Name="DataClasses.ViewModels" Seralize="All" />
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Application>
<!--
An Assembly element with Name="*Application*" applies to all assemblies in
the application package. The asterisks are not wildcards.
-->
<Assembly Name="*Application*" Dynamic="Required All" />
<!-- Add your application specific runtime directives here. -->
</Application>
</Directives>

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.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)' == '' ">x86</Platform>
<ProjectGuid>{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}</ProjectGuid>
<OutputType>AppContainerExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RNFS.Tests</RootNamespace>
<AssemblyName>RNFS.Tests</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.14393.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10586.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<PackageCertificateKeyFile>RNFS.Tests_TemporaryKey.pfx</PackageCertificateKeyFile>
<UnitTestPlatformVersion Condition="'$(UnitTestPlatformVersion)' == ''">$(VisualStudioVersion)</UnitTestPlatformVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>true</Prefer32Bit>
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
</PropertyGroup>
<ItemGroup>
<!--A reference to the entire .Net Framework and Windows SDK are automatically included-->
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<SDKReference Include="TestPlatform.Universal, Version=$(UnitTestPlatformVersion)" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UnitTestApp.xaml.cs">
<DependentUpon>UnitTestApp.xaml</DependentUpon>
</Compile>
<Compile Include="RNFSManagerTests.cs" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="UnitTestApp.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
</ItemGroup>
<ItemGroup>
<AppxManifest Include="Package.appxmanifest">
<SubType>Designer</SubType>
</AppxManifest>
<None Include="RNFS.Tests_TemporaryKey.pfx" />
</ItemGroup>
<ItemGroup>
<Content Include="Properties\UnitTestApp.rd.xml" />
<Content Include="Assets\LockScreenLogo.scale-200.png" />
<Content Include="Assets\SplashScreen.scale-200.png" />
<Content Include="Assets\Square150x150Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.scale-200.png" />
<Content Include="Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
<Content Include="Assets\StoreLogo.png" />
<Content Include="Assets\Wide310x150Logo.scale-200.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\node_modules\react-native-windows\ReactWindows\ReactNative\ReactNative.csproj">
<Project>{c7673ad5-e3aa-468c-a5fd-fa38154e205c}</Project>
<Name>ReactNative</Name>
</ProjectReference>
<ProjectReference Include="..\RNFs\RNFS.csproj">
<Project>{746610d0-8693-11e7-a20d-bf83f7366778}</Project>
<Name>RNFS</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- 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>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">C:\src\react-native-fs\windows\RNFS.Tests\project.lock.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\ericroz\.nuget\packages\</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">ProjectJson</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.3.0</NuGetToolVersion>
</PropertyGroup>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)mstest.testadapter\1.1.18\build\uap10.0\MSTest.TestAdapter.props" Condition="Exists('$(NuGetPackageRoot)mstest.testadapter\1.1.18\build\uap10.0\MSTest.TestAdapter.props')" />
</ImportGroup>
</Project>

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)mstest.testadapter\1.1.18\build\uap10.0\MSTest.TestAdapter.targets" Condition="Exists('$(NuGetPackageRoot)mstest.testadapter\1.1.18\build\uap10.0\MSTest.TestAdapter.targets')" />
</ImportGroup>
</Project>

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
<Application
x:Class="RNFS.Tests.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:RNFS.Tests"
RequestedTheme="Light">
</Application>

View File

@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
namespace RNFS.Tests
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
sealed partial class App : Application
{
/// <summary>
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
this.DebugSettings.EnableFrameRateCounter = true;
}
#endif
Frame rootFrame = Window.Current.Content as Frame;
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (rootFrame == null)
{
// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
//TODO: Load state from previously suspended application
}
// Place the frame in the current Window
Window.Current.Content = rootFrame;
}
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI();
// Ensure the current window is active
Window.Current.Activate();
Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(e.Arguments);
}
/// <summary>
/// Invoked when Navigation to a certain page fails
/// </summary>
/// <param name="sender">The Frame which failed navigation</param>
/// <param name="e">Details about the navigation failure</param>
void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
}
/// <summary>
/// Invoked when application execution is being suspended. Application state is saved
/// without knowing whether the application will be terminated or resumed with the contents
/// of memory still intact.
/// </summary>
/// <param name="sender">The source of the suspend request.</param>
/// <param name="e">Details about the suspend request.</param>
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.SuspendingOperation.GetDeferral();
//TODO: Save application state and stop any background activity
deferral.Complete();
}
}
}

View File

@ -0,0 +1,18 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.3",
"MSTest.TestAdapter": "1.1.18",
"MSTest.TestFramework": "1.1.18"
},
"frameworks": {
"uap10.0.10586": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}

120
windows/RNFS.sln Normal file
View File

@ -0,0 +1,120 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26730.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RNFS", "RNFs\RNFS.csproj", "{746610D0-8693-11E7-A20D-BF83F7366778}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNative", "..\node_modules\react-native-windows\ReactWindows\ReactNative\ReactNative.csproj", "{C7673AD5-E3AA-468C-A5FD-FA38154E205C}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "ReactNative.Shared", "..\node_modules\react-native-windows\ReactWindows\ReactNative.Shared\ReactNative.Shared.shproj", "{EEA8B852-4D07-48E1-8294-A21AB5909FE5}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChakraBridge", "..\node_modules\react-native-windows\ReactWindows\ChakraBridge\ChakraBridge.vcxproj", "{4B72C796-16D5-4E3A-81C0-3E36F531E578}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RNFS.Tests", "RNFS.Tests\RNFS.Tests.csproj", "{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\node_modules\react-native-windows\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{c7673ad5-e3aa-468c-a5fd-fa38154e205c}*SharedItemsImports = 4
..\node_modules\react-native-windows\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{eea8b852-4d07-48e1-8294-a21ab5909fe5}*SharedItemsImports = 13
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Development|ARM = Development|ARM
Development|x64 = Development|x64
Development|x86 = Development|x86
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{746610D0-8693-11E7-A20D-BF83F7366778}.Debug|ARM.ActiveCfg = Debug|ARM
{746610D0-8693-11E7-A20D-BF83F7366778}.Debug|ARM.Build.0 = Debug|ARM
{746610D0-8693-11E7-A20D-BF83F7366778}.Debug|x64.ActiveCfg = Debug|x64
{746610D0-8693-11E7-A20D-BF83F7366778}.Debug|x64.Build.0 = Debug|x64
{746610D0-8693-11E7-A20D-BF83F7366778}.Debug|x86.ActiveCfg = Debug|x86
{746610D0-8693-11E7-A20D-BF83F7366778}.Debug|x86.Build.0 = Debug|x86
{746610D0-8693-11E7-A20D-BF83F7366778}.Development|ARM.ActiveCfg = Development|ARM
{746610D0-8693-11E7-A20D-BF83F7366778}.Development|ARM.Build.0 = Development|ARM
{746610D0-8693-11E7-A20D-BF83F7366778}.Development|x64.ActiveCfg = Development|x64
{746610D0-8693-11E7-A20D-BF83F7366778}.Development|x64.Build.0 = Development|x64
{746610D0-8693-11E7-A20D-BF83F7366778}.Development|x86.ActiveCfg = Development|x86
{746610D0-8693-11E7-A20D-BF83F7366778}.Development|x86.Build.0 = Development|x86
{746610D0-8693-11E7-A20D-BF83F7366778}.Release|ARM.ActiveCfg = Release|ARM
{746610D0-8693-11E7-A20D-BF83F7366778}.Release|ARM.Build.0 = Release|ARM
{746610D0-8693-11E7-A20D-BF83F7366778}.Release|x64.ActiveCfg = Release|x64
{746610D0-8693-11E7-A20D-BF83F7366778}.Release|x64.Build.0 = Release|x64
{746610D0-8693-11E7-A20D-BF83F7366778}.Release|x86.ActiveCfg = Release|x86
{746610D0-8693-11E7-A20D-BF83F7366778}.Release|x86.Build.0 = Release|x86
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.ActiveCfg = Debug|ARM
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.Build.0 = Debug|ARM
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.ActiveCfg = Debug|x64
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.Build.0 = Debug|x64
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.ActiveCfg = Debug|x86
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.Build.0 = Debug|x86
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|ARM.ActiveCfg = Debug|ARM
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|ARM.Build.0 = Debug|ARM
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x64.ActiveCfg = Debug|x64
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x64.Build.0 = Debug|x64
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x86.ActiveCfg = Debug|x86
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x86.Build.0 = Debug|x86
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.ActiveCfg = Release|ARM
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.Build.0 = Release|ARM
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.ActiveCfg = Release|x64
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.Build.0 = Release|x64
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.ActiveCfg = Release|x86
{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.Build.0 = Release|x86
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|ARM.ActiveCfg = Debug|ARM
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|ARM.Build.0 = Debug|ARM
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x64.ActiveCfg = Debug|x64
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x64.Build.0 = Debug|x64
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x86.ActiveCfg = Debug|Win32
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x86.Build.0 = Debug|Win32
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|ARM.ActiveCfg = Debug|ARM
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|ARM.Build.0 = Debug|ARM
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x64.ActiveCfg = Debug|x64
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x64.Build.0 = Debug|x64
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x86.ActiveCfg = Debug|Win32
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x86.Build.0 = Debug|Win32
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|ARM.ActiveCfg = Release|ARM
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|ARM.Build.0 = Release|ARM
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x64.ActiveCfg = Release|x64
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x64.Build.0 = Release|x64
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x86.ActiveCfg = Release|Win32
{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x86.Build.0 = Release|Win32
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|ARM.ActiveCfg = Debug|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|ARM.Build.0 = Debug|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|ARM.Deploy.0 = Debug|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|x64.ActiveCfg = Debug|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|x64.Build.0 = Debug|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|x64.Deploy.0 = Debug|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|x86.ActiveCfg = Debug|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|x86.Build.0 = Debug|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Debug|x86.Deploy.0 = Debug|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|ARM.ActiveCfg = Debug|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|ARM.Build.0 = Debug|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|ARM.Deploy.0 = Debug|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|x64.ActiveCfg = Debug|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|x64.Build.0 = Debug|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|x64.Deploy.0 = Debug|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|x86.ActiveCfg = Debug|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|x86.Build.0 = Debug|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Development|x86.Deploy.0 = Debug|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|ARM.ActiveCfg = Release|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|ARM.Build.0 = Release|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|ARM.Deploy.0 = Release|ARM
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|x64.ActiveCfg = Release|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|x64.Build.0 = Release|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|x64.Deploy.0 = Release|x64
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|x86.ActiveCfg = Release|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|x86.Build.0 = Release|x86
{8D2229AC-F6EC-4FBD-9AAC-FE4792DA98C6}.Release|x86.Deploy.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FBB6610F-6707-4A34-9D3B-3E0709F7822A}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,31 @@
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("RNFS")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RNFS")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 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")]
[assembly: ComVisible(false)]
[assembly: InternalsVisibleTo("RNFS.Tests")]

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This file contains Runtime Directives, specifications about types your application accesses
through reflection and other dynamic code patterns. Runtime Directives are used to control the
.NET Native optimizer and ensure that it does not remove code accessed by your library. If your
library does not do any reflection, then you generally do not need to edit this file. However,
if your library reflects over types, especially types passed to it or derived from its types,
then you should write Runtime Directives.
The most common use of reflection in libraries is to discover information about types passed
to the library. Runtime Directives have three ways to express requirements on types passed to
your library.
1. Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
Use these directives to reflect over types passed as a parameter.
2. SubTypes
Use a SubTypes directive to reflect over types derived from another type.
3. AttributeImplies
Use an AttributeImplies directive to indicate that your library needs to reflect over
types or methods decorated with an attribute.
For more information on writing Runtime Directives for libraries, please visit
http://go.microsoft.com/fwlink/?LinkID=391919
-->
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="RNFS">
<!-- add directives for your library here -->
</Library>
</Directives>

153
windows/RNFS/RNFS.csproj Normal file
View File

@ -0,0 +1,153 @@
<?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)' == '' ">x86</Platform>
<ProjectGuid>{746610D0-8693-11E7-A20D-BF83F7366778}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RNFS</RootNamespace>
<AssemblyName>RNFS</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.10586.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ReactWindowsRoot>..\..\node_modules</ReactWindowsRoot>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' != 'Development'">
<ReactWindowsRoot>..\..</ReactWindowsRoot>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Development|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Development\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<NoStdLib>true</NoStdLib>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Development|ARM'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Development\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<NoStdLib>true</NoStdLib>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Development|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Development\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<NoStdLib>true</NoStdLib>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RNFSManager.cs" />
<Compile Include="RNFSPackage.cs" />
<EmbeddedResource Include="Properties\RNFS.rd.xml" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\node_modules\react-native-windows\ReactWindows\ReactNative\ReactNative.csproj">
<Project>{c7673ad5-e3aa-468c-a5fd-fa38154e205c}</Project>
<Name>ReactNative</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- 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>

645
windows/RNFS/RNFSManager.cs Normal file
View File

@ -0,0 +1,645 @@
using Newtonsoft.Json.Linq;
using ReactNative.Bridge;
using ReactNative.Modules.Core;
using ReactNative.Modules.Network;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel;
using Windows.Storage;
namespace RNFS
{
class RNFSManager : ReactContextNativeModuleBase
{
private const int FileType = 0;
private const int DirectoryType = 1;
private static readonly IReadOnlyDictionary<string, Func<HashAlgorithm>> s_hashAlgorithms =
new Dictionary<string, Func<HashAlgorithm>>
{
{ "md5", () => MD5.Create() },
{ "sha1", () => SHA1.Create() },
{ "sha256", () => SHA256.Create() },
{ "sha384", () => SHA384.Create() },
{ "sha512", () => SHA512.Create() },
};
private readonly TaskCancellationManager<int> _tasks = new TaskCancellationManager<int>();
private readonly HttpClient _httpClient = new HttpClient();
private RCTNativeAppEventEmitter _emitter;
public RNFSManager(ReactContext reactContext)
: base(reactContext)
{
}
public override string Name
{
get
{
return "RNFSManager";
}
}
internal RCTNativeAppEventEmitter Emitter
{
get
{
if (_emitter == null)
{
return Context.GetJavaScriptModule<RCTNativeAppEventEmitter>();
}
return _emitter;
}
set
{
_emitter = value;
}
}
public override IReadOnlyDictionary<string, object> Constants
{
get
{
var constants = new Dictionary<string, object>
{
{ "RNFSMainBundlePath", Package.Current.InstalledLocation.Path },
{ "RNFSCachesDirectoryPath", ApplicationData.Current.LocalCacheFolder.Path },
{ "RNFSRoamingDirectoryPath", ApplicationData.Current.RoamingFolder.Path },
{ "RNFSDocumentDirectoryPath", ApplicationData.Current.LocalFolder.Path },
{ "RNFSTemporaryDirectoryPath", ApplicationData.Current.TemporaryFolder.Path },
{ "RNFSFileTypeRegular", 0 },
{ "RNFSFileTypeDirectory", 1 },
};
var external = GetFolderPathSafe(() => KnownFolders.RemovableDevices);
if (external != null)
{
var externalItems = KnownFolders.RemovableDevices.GetItemsAsync().AsTask().Result;
if (externalItems.Count > 0)
{
constants.Add("RNFSExternalDirectoryPath", externalItems[0].Path);
}
constants.Add("RNFSExternalDirectoryPaths", externalItems.Select(i => i.Path).ToArray());
}
var pictures = GetFolderPathSafe(() => KnownFolders.PicturesLibrary);
if (pictures != null)
{
constants.Add("RNFSPicturesDirectoryPath", pictures);
}
return constants;
}
}
[ReactMethod]
public async void writeFile(string filepath, string base64Content, IPromise promise)
{
try
{
// TODO: open file on background thread?
using (var file = File.OpenWrite(filepath))
{
var data = Convert.FromBase64String(base64Content);
await file.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
}
promise.Resolve(null);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void appendFile(string filepath, string base64Content, IPromise promise)
{
try
{
// TODO: open file on background thread?
using (var file = File.Open(filepath, FileMode.Append))
{
var data = Convert.FromBase64String(base64Content);
await file.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
}
promise.Resolve(null);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void write(string filepath, string base64Content, int position, IPromise promise)
{
try
{
// TODO: open file on background thread?
using (var file = File.OpenWrite(filepath))
{
if (position >= 0)
{
file.Position = position;
}
var data = Convert.FromBase64String(base64Content);
await file.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
}
promise.Resolve(null);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public void exists(string filepath, IPromise promise)
{
try
{
promise.Resolve(File.Exists(filepath) || Directory.Exists(filepath));
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void readFile(string filepath, IPromise promise)
{
try
{
if (!File.Exists(filepath))
{
RejectFileNotFound(promise, filepath);
return;
}
// TODO: open file on background thread?
string base64Content;
using (var file = File.OpenRead(filepath))
{
var length = (int)file.Length;
var buffer = new byte[length];
await file.ReadAsync(buffer, 0, length).ConfigureAwait(false);
base64Content = Convert.ToBase64String(buffer);
}
promise.Resolve(base64Content);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void read(string filepath, int length, int position, IPromise promise)
{
try
{
if (!File.Exists(filepath))
{
RejectFileNotFound(promise, filepath);
return;
}
// TODO: open file on background thread?
string base64Content;
using (var file = File.OpenRead(filepath))
{
file.Position = position;
var buffer = new byte[length];
await file.ReadAsync(buffer, 0, length).ConfigureAwait(false);
base64Content = Convert.ToBase64String(buffer);
}
promise.Resolve(base64Content);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void hash(string filepath, string algorithm, IPromise promise)
{
var hashAlgorithmFactory = default(Func<HashAlgorithm>);
if (!s_hashAlgorithms.TryGetValue(algorithm, out hashAlgorithmFactory))
{
promise.Reject(null, "Invalid hash algorithm.");
return;
}
try
{
if (!File.Exists(filepath))
{
RejectFileNotFound(promise, filepath);
return;
}
await Task.Run(() =>
{
var hexBuilder = new StringBuilder();
using (var hashAlgorithm = hashAlgorithmFactory())
{
hashAlgorithm.Initialize();
var hash = default(byte[]);
using (var file = File.OpenRead(filepath))
{
hash = hashAlgorithm.ComputeHash(file);
}
foreach (var b in hash)
{
hexBuilder.Append(string.Format("{0:x2}", b));
}
}
promise.Resolve(hexBuilder.ToString());
}).ConfigureAwait(false);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public void moveFile(string filepath, string destPath, IPromise promise)
{
try
{
// TODO: move file on background thread?
File.Move(filepath, destPath);
promise.Resolve(true);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void copyFile(string filepath, string destPath, IPromise promise)
{
try
{
await Task.Run(() => File.Copy(filepath, destPath)).ConfigureAwait(false);
promise.Resolve(null);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void readDir(string directory, IPromise promise)
{
try
{
await Task.Run(() =>
{
var info = new DirectoryInfo(directory);
if (!info.Exists)
{
promise.Reject(null, "Folder does not exist");
return;
}
var fileMaps = new JArray();
foreach (var item in info.EnumerateFileSystemInfos())
{
var fileMap = new JObject
{
{ "mtime", ConvertToUnixTimestamp(item.LastWriteTime) },
{ "name", item.Name },
{ "path", item.FullName },
};
var fileItem = item as FileInfo;
if (fileItem != null)
{
fileMap.Add("type", FileType);
fileMap.Add("size", fileItem.Length);
}
else
{
fileMap.Add("type", DirectoryType);
fileMap.Add("size", 0);
}
fileMaps.Add(fileMap);
}
promise.Resolve(fileMaps);
});
}
catch (Exception ex)
{
Reject(promise, directory, ex);
}
}
[ReactMethod]
public void stat(string filepath, IPromise promise)
{
try
{
FileSystemInfo fileSystemInfo = new FileInfo(filepath);
if (!fileSystemInfo.Exists)
{
fileSystemInfo = new DirectoryInfo(filepath);
if (!fileSystemInfo.Exists)
{
promise.Reject(null, "File does not exist.");
return;
}
}
var fileInfo = fileSystemInfo as FileInfo;
var statMap = new JObject
{
{ "ctime", ConvertToUnixTimestamp(fileSystemInfo.CreationTime) },
{ "mtime", ConvertToUnixTimestamp(fileSystemInfo.LastWriteTime) },
{ "size", fileInfo?.Length ?? 0 },
{ "type", fileInfo != null ? FileType: DirectoryType },
};
promise.Resolve(statMap);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void unlink(string filepath, IPromise promise)
{
try
{
var directoryInfo = new DirectoryInfo(filepath);
var fileInfo = default(FileInfo);
if (directoryInfo.Exists)
{
await Task.Run(() => Directory.Delete(filepath, true)).ConfigureAwait(false);
}
else if ((fileInfo = new FileInfo(filepath)).Exists)
{
await Task.Run(() => File.Delete(filepath)).ConfigureAwait(false);
}
else
{
promise.Reject(null, "File does not exist.");
return;
}
promise.Resolve(null);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void mkdir(string filepath, JObject options, IPromise promise)
{
try
{
await Task.Run(() => Directory.CreateDirectory(filepath)).ConfigureAwait(false);
promise.Resolve(null);
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public async void downloadFile(JObject options, IPromise promise)
{
var filepath = options.Value<string>("toFile");
try
{
var url = new Uri(options.Value<string>("fromUrl"));
var jobId = options.Value<int>("jobId");
var headers = (JObject)options["headers"];
var progressDivider = options.Value<int>("progressDivider");
var request = new HttpRequestMessage(HttpMethod.Get, url);
foreach (var header in headers)
{
request.Headers.Add(header.Key, header.Value.Value<string>());
}
await _tasks.AddAndInvokeAsync(jobId, token =>
ProcessRequestAsync(promise, request, filepath, jobId, progressDivider, token));
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
[ReactMethod]
public void stopDownload(int jobId)
{
_tasks.Cancel(jobId);
}
[ReactMethod]
public async void getFSInfo(IPromise promise)
{
try
{
var properties = await ApplicationData.Current.LocalFolder.Properties.RetrievePropertiesAsync(
new[]
{
"System.FreeSpace",
"System.Capacity",
})
.AsTask()
.ConfigureAwait(false);
promise.Resolve(new JObject
{
{ "freeSpace", (ulong)properties["System.FreeSpace"] },
{ "totalSpace", (ulong)properties["System.Capacity"] },
});
}
catch (Exception ex)
{
promise.Reject(null, "getFSInfo is not available");
}
}
[ReactMethod]
public async void touch(string filepath, double mtime, double ctime, IPromise promise)
{
try
{
await Task.Run(() =>
{
var fileInfo = new FileInfo(filepath);
if (!fileInfo.Exists)
{
using (File.Create(filepath)) { }
}
fileInfo.CreationTimeUtc = ConvertFromUnixTimestamp(ctime);
fileInfo.LastWriteTimeUtc = ConvertFromUnixTimestamp(mtime);
promise.Resolve(fileInfo.FullName);
});
}
catch (Exception ex)
{
Reject(promise, filepath, ex);
}
}
public override void OnReactInstanceDispose()
{
_tasks.CancelAllTasks();
_httpClient.Dispose();
}
private async Task ProcessRequestAsync(IPromise promise, HttpRequestMessage request, string filepath, int jobId, int progressIncrement, CancellationToken token)
{
try
{
using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, token))
{
var headersMap = new JObject();
foreach (var header in response.Headers)
{
headersMap.Add(header.Key, string.Join(",", header.Value));
}
var contentLength = response.Content.Headers.ContentLength;
SendEvent($"DownloadBegin-{jobId}", new JObject
{
{ "jobId", jobId },
{ "statusCode", (int)response.StatusCode },
{ "contentLength", contentLength },
{ "headers", headersMap },
});
// TODO: open file on background thread?
var totalRead = 0;
using (var fileStream = File.OpenWrite(filepath))
using (var stream = await response.Content.ReadAsStreamAsync())
{
var contentLengthForProgress = contentLength ?? -1;
var nextProgressIncrement = progressIncrement;
var buffer = new byte[8 * 1024];
var read = 0;
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
token.ThrowIfCancellationRequested();
await fileStream.WriteAsync(buffer, 0, read);
if (contentLengthForProgress >= 0)
{
totalRead += read;
if (totalRead * 100 / contentLengthForProgress >= nextProgressIncrement ||
totalRead == contentLengthForProgress)
{
SendEvent("DownloadProgress-" + jobId, new JObject
{
{ "jobId", jobId },
{ "contentLength", contentLength },
{ "bytesWritten", totalRead },
});
nextProgressIncrement += progressIncrement;
}
}
}
}
promise.Resolve(new JObject
{
{ "jobId", jobId },
{ "statusCode", (int)response.StatusCode },
{ "bytesWritten", totalRead },
});
}
}
finally
{
request.Dispose();
}
}
private void Reject(IPromise promise, String filepath, Exception ex)
{
if (ex is FileNotFoundException) {
RejectFileNotFound(promise, filepath);
return;
}
promise.Reject(null, ex.Message, ex);
}
private void RejectFileNotFound(IPromise promise, String filepath)
{
promise.Reject("ENOENT", "ENOENT: no such file or directory, open '" + filepath + "'");
}
private void SendEvent(string eventName, JObject eventData)
{
Emitter.emit(eventName, eventData);
}
private static string GetFolderPathSafe(Func<StorageFolder> getFolder)
{
try
{
return getFolder().Path;
}
catch (UnauthorizedAccessException)
{
return null;
}
}
public static double ConvertToUnixTimestamp(DateTime date)
{
var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var diff = date.ToUniversalTime() - origin;
return Math.Floor(diff.TotalSeconds);
}
public static DateTime ConvertFromUnixTimestamp(double timestamp)
{
var origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
var diff = TimeSpan.FromSeconds(timestamp);
var dateTimeUtc = origin + diff;
return dateTimeUtc.ToLocalTime();
}
}
}

View File

@ -0,0 +1,53 @@
using ReactNative.Bridge;
using ReactNative.Modules.Core;
using ReactNative.UIManager;
using System;
using System.Collections.Generic;
namespace RNFS
{
/// <summary>
/// Package defining core framework modules (e.g., <see cref="UIManagerModule"/>).
/// It should be used for modules that require special integration with
/// other framework parts (e.g., with the list of packages to load view
/// managers from).
/// </summary>
public class RNFSPackage : IReactPackage
{
/// <summary>
/// Creates the list of native modules to register with the react
/// instance.
/// </summary>
/// <param name="reactContext">The react application context.</param>
/// <returns>The list of native modules.</returns>
public IReadOnlyList<INativeModule> CreateNativeModules(ReactContext reactContext)
{
return new List<INativeModule>
{
new RNFSManager(reactContext),
};
}
/// <summary>
/// Creates the list of JavaScript modules to register with the
/// react instance.
/// </summary>
/// <returns>The list of JavaScript modules.</returns>
public IReadOnlyList<Type> CreateJavaScriptModulesConfig()
{
return new List<Type>(0);
}
/// <summary>
/// Creates the list of view managers that should be registered with
/// the <see cref="UIManagerModule"/>.
/// </summary>
/// <param name="reactContext">The react application context.</param>
/// <returns>The list of view managers.</returns>
public IReadOnlyList<IViewManager> CreateViewManagers(
ReactContext reactContext)
{
return new List<IViewManager>(0);
}
}
}

16
windows/RNFS/project.json Normal file
View File

@ -0,0 +1,16 @@
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}