Files
react-native-code-push/windows/CodePush.Net46/UpdateUtils.cs
Alexander Bodalevsky be96f07eda Added React Native Windows dotNet46 support (#684)
Added support react-native-windows dotNet
Added example for react-native-windows UWP based
Added example for react-native-windows dotNet based

Project structure:

CodePush.Shared - shared code between UWP and dotNet
CodePush - UWP specific code
CodePush.Net46 - dotNet specific code

For UWP solution it needs to be added the following projects:

CodePush.Shared
CodePush
For dotNet solution it needs to be added the following projects:

CodePush.Shared
CodePush.Net46
Examples:

Examples\CodePushDemoApp\windows\CodePushDemoApp.sln the solution contains both examples (UWP and dotNet).

Notes

Example for ARM configuration has not been tested. Since there is no changes in UWP part of implementation, there is low risk of failure.

In this implementation we tried to reuse UWP library as much as possible. The following issues are relevant for both platforms:

ZipFile.ExtractToDirectory is not reliable and throws exception if:
folder exists already
path is too long (> 250 chars)
Un-zipping is quite long operation. Does it make sense for async?
await UpdateUtils.UnzipBundleAsync(downloadFile.Path, unzippedFolder.Path);
2017-02-13 16:23:20 -08:00

71 lines
2.9 KiB
C#

using CodePush.Net46.Adapters.Http;
using Newtonsoft.Json.Linq;
using PCLStorage;
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace CodePush.ReactNative
{
internal class UpdateUtils
{
internal async static Task CopyNecessaryFilesFromCurrentPackageAsync(IFile diffManifestFile, IFolder currentPackageFolder, IFolder newPackageFolder)
{
await FileUtils.MergeFoldersAsync(currentPackageFolder, newPackageFolder).ConfigureAwait(false);
JObject diffManifest = await CodePushUtils.GetJObjectFromFileAsync(diffManifestFile).ConfigureAwait(false);
var deletedFiles = (JArray)diffManifest["deletedFiles"];
foreach (string fileNameToDelete in deletedFiles)
{
var fileToDelete = await newPackageFolder.GetFileAsync(fileNameToDelete).ConfigureAwait(false);
await fileToDelete.DeleteAsync().ConfigureAwait(false);
}
}
internal async static Task<string> FindJSBundleInUpdateContentsAsync(IFolder updateFolder, string expectedFileName)
{
foreach (IFile file in await updateFolder.GetFilesAsync().ConfigureAwait(false))
{
string fileName = file.Name;
if (fileName.Equals(expectedFileName))
{
return fileName;
}
}
foreach (IFolder folder in await updateFolder.GetFoldersAsync().ConfigureAwait(false))
{
string mainBundlePathInSubFolder = await FindJSBundleInUpdateContentsAsync(folder, expectedFileName).ConfigureAwait(false);
if (mainBundlePathInSubFolder != null)
{
return Path.Combine(folder.Name, mainBundlePathInSubFolder);
}
}
return null;
}
internal async static Task DownloadBundleAsync(string url, string fileName, IProgress<HttpProgress> downloadProgress)
{
var uri = new Uri(url);
var client = new WebClient();
client.DownloadProgressChanged += (s, e) =>
{
downloadProgress.Report(new HttpProgress
{
BytesReceived = (ulong)e.BytesReceived, //conversion long to ulong is safe
TotalBytesToReceive = (ulong)e.TotalBytesToReceive //because size can't be negative
});
};
await client.DownloadFileTaskAsync(uri, fileName);
}
internal static async Task<IFolder> GetCodePushFolderAsync()
{
var pathToCodePush = Path.Combine(CodePushUtils.GetAppFolder(), CodePushConstants.CodePushFolderPrefix);
return await FileSystem.Current.LocalStorage.CreateFolderAsync(pathToCodePush, CreationCollisionOption.OpenIfExists).ConfigureAwait(false);
}
}
}