Working on Updater Implementation

This commit is contained in:
DrHacknik 2020-01-22 16:29:11 -05:00 committed by Ash
parent 505f95848b
commit 41d4dbe30f
7 changed files with 248 additions and 10 deletions

View file

@ -37,6 +37,7 @@
<None Remove="Ui\assets\NROIcon.png" />
<None Remove="Ui\assets\NSOIcon.png" />
<None Remove="Ui\assets\NSPIcon.png" />
<None Remove="Ui\assets\Update.png" />
<None Remove="Ui\assets\XCIIcon.png" />
<None Remove="Ui\assets\DiscordLogo.png" />
<None Remove="Ui\assets\GitHubLogo.png" />
@ -58,6 +59,7 @@
<EmbeddedResource Include="Ui\assets\NROIcon.png" />
<EmbeddedResource Include="Ui\assets\NSOIcon.png" />
<EmbeddedResource Include="Ui\assets\NSPIcon.png" />
<EmbeddedResource Include="Ui\assets\Update.png" />
<EmbeddedResource Include="Ui\assets\XCIIcon.png" />
<EmbeddedResource Include="Ui\assets\DiscordLogo.png" />
<EmbeddedResource Include="Ui\assets\GitHubLogo.png" />

View file

@ -1,5 +1,8 @@
using Gtk;
using System.Reflection;
using Ryujinx.Updater.Parser;
using System.IO;
using System;
namespace Ryujinx.Ui
{
@ -29,5 +32,56 @@ namespace Ryujinx.Ui
{
CreateDialog("Ryujinx - Error", "Ryujinx has encountered an error", errorMessage);
}
internal static MessageDialog CreateAcceptDialog(string iconType, string acceptMessage)
{
MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Question, ButtonsType.YesNo, null)
{
Title = "Ryujinx - Update",
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets.Update.png"),
Text = "Would you like to update?",
SecondaryText = "Version " + acceptMessage + " is available.",
WindowPosition = WindowPosition.Center
};
messageDialog.SetSizeRequest(100, 20);
return messageDialog;
}
internal static MessageDialog CreateInfoDialog(string iconType, string titleMessage, string textMessage, string secText)
{
MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Info, ButtonsType.Ok, null)
{
Title = titleMessage,
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets." + iconType +".png"),
Text = textMessage,
SecondaryText = secText,
WindowPosition = WindowPosition.Center
};
messageDialog.SetSizeRequest(100, 20);
return messageDialog;
}
internal static async System.Threading.Tasks.Task<MessageDialog> CreateProgressDialogAsync(bool isInstall, string iconType, string titleMessage, string textMessage, string secText)
{
MessageDialog messageDialog = new MessageDialog(null, DialogFlags.Modal, MessageType.Info, ButtonsType.None, null)
{
Title = titleMessage,
Icon = new Gdk.Pixbuf(Assembly.GetExecutingAssembly(), "Ryujinx.Ui.assets." + iconType + ".png"),
Text = textMessage,
SecondaryText = secText,
WindowPosition = WindowPosition.Center
};
messageDialog.SetSizeRequest(100, 20);
if (isInstall == true)
{
await UpdateParser.ExtractPackageAsync();
}
else
{
Uri URL = new Uri(UpdateParser._BuildArt);
UpdateParser._Package.DownloadFileAsync(URL, Path.Combine(UpdateParser._RyuDir, "Data", "Update", "RyujinxPackage.zip"));
}
return messageDialog;
}
}
}

View file

@ -896,16 +896,18 @@ namespace Ryujinx.Ui
private void Update_Pressed(object sender, EventArgs args)
{
string ryuUpdater = System.IO.Path.Combine(_virtualFileSystem.GetBasePath(), "RyuUpdater.exe");
Ryujinx.Updater.Parser.UpdateParser.BeginParse();
return;
//string ryuUpdater = System.IO.Path.Combine(new VirtualFileSystem().GetBasePath(), "RyuUpdater.exe");
try
{
Process.Start(new ProcessStartInfo(ryuUpdater, "/U") { UseShellExecute = true });
}
catch(System.ComponentModel.Win32Exception)
{
GtkDialog.CreateErrorDialog("Update canceled by user or updater was not found");
}
//try
//{
// Process.Start(new ProcessStartInfo(ryuUpdater, "/U") { UseShellExecute = true });
//}
//catch(System.ComponentModel.Win32Exception)
//{
// GtkDialog.CreateErrorDialog("Update canceled by user or updater was not found");
//}
}
private void About_Pressed(object sender, EventArgs args)

View file

@ -323,7 +323,7 @@
<object class="GtkMenuItem" id="CheckUpdates">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Check for updates to Ryujinx (requires Ryujinx Installer)</property>
<property name="tooltip_text" translatable="yes">Check for updates to Ryujinx</property>
<property name="label" translatable="yes">Check for Updates</property>
<property name="use_underline">True</property>
<signal name="activate" handler="Update_Pressed" swapped="no"/>

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View file

@ -0,0 +1,151 @@
using Gtk;
using Newtonsoft.Json.Linq;
using Ryujinx.Common.Logging;
using Ryujinx.Ui;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Ryujinx.Updater.Parser
{
public class UpdateParser
{
private static string _JobID;
private static string _BuildVer;
private static string _BuildURL = "https://ci.appveyor.com/api/projects/gdkchan/ryujinx/branch/master";
public static string _BuildArt;
private static string _BuildCommit;
private static string _Branch;
private static string _PlatformExt;
public static string _RyuDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Ryujinx");
public static WebClient _Package = new WebClient();
private static string _URLStr;
public static int _PackageProgress;
public static double _Percentage;
public static void BeginParse()
{
try
{
//Detect current platform
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
_PlatformExt = "osx_x64.zip";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
_PlatformExt = "win_x64.zip";
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
_PlatformExt = "linux_x64.tar.gz";
WebClient JSONClient = new WebClient();
string FetchedJSON = JSONClient.DownloadString(_BuildURL);
var __JSONRoot = JObject.Parse(FetchedJSON);
var __Build = __JSONRoot["build"];
string __Version = (string)__Build["version"];
string __JobsID = (string)__Build["jobs"][0]["jobId"];
string __Branch = (string)__Build["branch"];
string __BuildCommit = (string)__Build["commitId"];
_JobID = __JobsID;
_BuildVer = __Version;
_BuildArt = "https://ci.appveyor.com/api/buildjobs/" + _JobID + "/artifacts/ryujinx-" + _BuildVer + "-" + _PlatformExt;
_BuildCommit = __BuildCommit.Substring(0, 7);
_Branch = __Branch;
Logger.PrintInfo(LogClass.Application, "Fetched JSON and Parsed:" + Environment.NewLine + "MetaData: JobID(" + __JobsID + ") BuildVer(" + __Version + ")" + Environment.NewLine + "BuildURL(" + _BuildArt + ")");
Logger.PrintInfo(LogClass.Application, "Commit-id: (" + _BuildCommit + ")" + " Branch: (" + _Branch + ")");
using (MessageDialog dialog = GtkDialog.CreateAcceptDialog("Update", _BuildVer))
{
if (dialog.Run() == (int)ResponseType.Yes)
{
dialog.Dispose();
GrabPackage();
}
}
}
catch (Exception ex)
{
Logger.PrintError(LogClass.Application, ex.Message);
GtkDialog.CreateErrorDialog("Update canceled by user or failed to grab or parse the information.\nPlease try at a later time, or report the error to our GitHub.");
return;
}
UpdateData data = new UpdateData()
{
JobID = _JobID,
BuildVer = _BuildVer,
BuildURL = _BuildURL,
BuildArt = _BuildArt,
BuildCommit = _BuildCommit,
Branch = _Branch
};
}
private static async void GrabPackage()
{
if (!Directory.Exists(Path.Combine(_RyuDir, "Data", "Update")) || !Directory.Exists(Path.Combine(_RyuDir, "Data")))
{
Directory.CreateDirectory(Path.Combine(_RyuDir, "Data", "Update"));
Directory.CreateDirectory(Path.Combine(_RyuDir, "Data"));
}
try
{
_Package.DownloadProgressChanged += new DownloadProgressChangedEventHandler(PackageDownloadProgress);
_Package.DownloadFileCompleted += new AsyncCompletedEventHandler(PackageDownloadedAsync);
using (MessageDialog dialog = await GtkDialog.CreateProgressDialogAsync(false, "Update", "Ryujinx - Update", "Downloading update " + _BuildVer + ", 0% complete...", "Please wait while we download the latest package"))
{
dialog.Run();
}
}
catch (Exception ex)
{
Logger.PrintError(LogClass.Application, ex.InnerException.ToString());
GtkDialog.CreateErrorDialog(ex.Message);
return;
}
}
private static async void PackageDownloadedAsync(object sender, AsyncCompletedEventArgs e)
{
if (e.Cancelled == true)
{
Logger.PrintError(LogClass.Application, "Package download failed or cancelled");
return;
}
else
{
Logger.PrintWarning(LogClass.Application, "Package is now installing");
using (MessageDialog dialog = await GtkDialog.CreateProgressDialogAsync(true, "Update", "Ryujinx - Update", "Installing update " + _BuildVer + "...", "Please wait while we install the latest package"))
{
dialog.Run();
}
return;
}
}
private static void PackageDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
_Percentage = e.ProgressPercentage;
_PackageProgress = e.ProgressPercentage;
}
public static async Task ExtractPackageAsync()
{
try
{
//using (ZipFile Package = ZipFile.Read(Path.Combine(_RyuDir, "Data", "Update", "RyujinxPackage.zip")))
//{
// await Task.Run(() => Package.ExtractAll(_InstallDir, ExtractExistingFileAction.OverwriteSilently));
//}
throw new Exception("This is a test exception.\nThis is the package extract thread.");
}
catch (Exception ex)
{
Logger.PrintError(LogClass.Application, "Package installation has failed\n" + ex.InnerException.ToString());
GtkDialog.CreateErrorDialog("Package installation has failed\nCheck the log for more information.");
return;
}
}
}
}

View file

@ -0,0 +1,29 @@
/* =========================================
* This service is responsible for parsing
* the appveyor json.
*
* =========================================
*
* Strings and other variables: These are stored for the config page.
*
* JobID: String, stores the parsed JobID.
* BuildVer: String, stores the parsed BuildVersion.
* BuildURL: String, stores the BuildURL.
* BuildArt: String, stores the parsed build artifact (URL).
* BuildCommit: String, stores the parsed build commit; and is stored in a five character substring.
* Branch: String, stores the parsed branch for the build.
* =========================================
*/
namespace Ryujinx.Updater
{
public struct UpdateData
{
public string JobID { get; set; }
public string BuildVer { get; set; }
public string BuildURL { get; set; }
public string BuildArt { get; set; }
public string BuildCommit { get; set; }
public string Branch { get; set; }
}
}