v1.4.2 - Added Updater
This commit is contained in:
parent
54fc08fa24
commit
f911489021
|
@ -699,7 +699,7 @@ public class Crunchyroll{
|
|||
|
||||
StreamDetailsPop? curStream = null;
|
||||
if (!dlFailed){
|
||||
// Validate or adjust options.kstream
|
||||
|
||||
options.Kstream = options.Kstream >= 1 && options.Kstream <= streams.Count
|
||||
? options.Kstream
|
||||
: 1;
|
||||
|
@ -741,7 +741,7 @@ public class Crunchyroll{
|
|||
MPDParsed streamPlaylists = MPDParser.Parse(streamPlaylistsReqResponse.ResponseContent, Languages.FindLang(crLocal), matchedUrl);
|
||||
|
||||
List<string> streamServers = new List<string>(streamPlaylists.Data.Keys);
|
||||
options.X = options.X > streamServers.Count ? 1 : options.X;
|
||||
options.StreamServer = options.StreamServer > streamServers.Count ? 1 : options.StreamServer;
|
||||
|
||||
if (streamServers.Count == 0){
|
||||
return new DownloadResponse{
|
||||
|
@ -751,11 +751,11 @@ public class Crunchyroll{
|
|||
};
|
||||
}
|
||||
|
||||
if (options.X == 0){
|
||||
options.X = 1;
|
||||
if (options.StreamServer == 0){
|
||||
options.StreamServer = 1;
|
||||
}
|
||||
|
||||
string selectedServer = streamServers[options.X - 1];
|
||||
string selectedServer = streamServers[options.StreamServer - 1];
|
||||
ServerData selectedList = streamPlaylists.Data[selectedServer];
|
||||
|
||||
var videos = selectedList.video.Select(item => new VideoItem{
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CRD.Utils.Updater;
|
||||
|
||||
public class Updater{
|
||||
#region Singelton
|
||||
|
||||
private static Updater? _instance;
|
||||
private static readonly object Padlock = new();
|
||||
|
||||
public static Updater Instance{
|
||||
get{
|
||||
if (_instance == null){
|
||||
lock (Padlock){
|
||||
if (_instance == null){
|
||||
_instance = new Updater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string downloadUrl = "";
|
||||
private readonly string tempPath = Path.Combine(Path.GetTempPath(), "Update.zip");
|
||||
private readonly string extractPath = Path.Combine(Path.GetTempPath(), "ExtractedUpdate");
|
||||
|
||||
private readonly string apiEndpoint = "https://api.github.com/repos/Crunchy-DL/Crunchy-Downloader/releases/latest";
|
||||
|
||||
public async Task<bool> CheckForUpdatesAsync(){
|
||||
try{
|
||||
using (var client = new HttpClient()){
|
||||
client.DefaultRequestHeaders.Add("User-Agent", "C# App"); // GitHub API requires a user agent
|
||||
var response = await client.GetStringAsync(apiEndpoint);
|
||||
var releaseInfo = JsonConvert.DeserializeObject<dynamic>(response);
|
||||
|
||||
var latestVersion = releaseInfo.tag_name;
|
||||
downloadUrl = releaseInfo.assets[0].browser_download_url;
|
||||
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
var currentVersion = $"v{version?.Major}.{version?.Minor}.{version?.Build}";
|
||||
|
||||
|
||||
if (latestVersion != currentVersion){
|
||||
Console.WriteLine("Update available: " + latestVersion + " - Current Version: " + currentVersion);
|
||||
return true;
|
||||
} else{
|
||||
Console.WriteLine("No updates available.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (Exception e){
|
||||
Console.WriteLine("Failed to get Update information");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DownloadAndUpdateAsync(){
|
||||
try{
|
||||
using (var client = new HttpClient()){
|
||||
// Download the zip file
|
||||
var response = await client.GetAsync(downloadUrl, HttpCompletionOption.ResponseHeadersRead);
|
||||
using (var stream = await response.Content.ReadAsStreamAsync())
|
||||
using (var fileStream = new FileStream(tempPath, FileMode.Create, FileAccess.Write, FileShare.None)){
|
||||
await stream.CopyToAsync(fileStream);
|
||||
}
|
||||
|
||||
ZipFile.ExtractToDirectory(tempPath, extractPath, true);
|
||||
|
||||
ApplyUpdate(extractPath);
|
||||
}
|
||||
} catch (Exception e){
|
||||
Console.WriteLine("Failed to get Update");
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyUpdate(string updateFolder){
|
||||
var currentPath = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var updaterPath = Path.Combine(currentPath, "Updater.exe");
|
||||
var arguments = $"\"{currentPath.Substring(0, currentPath.Length - 1)}\" \"{updateFolder}\"";
|
||||
|
||||
System.Diagnostics.Process.Start(updaterPath, arguments);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
|
@ -1,23 +1,36 @@
|
|||
using Avalonia;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CRD.Downloader;
|
||||
using CRD.Utils.Updater;
|
||||
using FluentAvalonia.Styling;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace CRD.ViewModels;
|
||||
|
||||
public partial class MainWindowViewModel : ViewModelBase{
|
||||
private readonly FluentAvaloniaTheme _faTheme;
|
||||
|
||||
public MainWindowViewModel(){
|
||||
[ObservableProperty]
|
||||
private bool _updateAvailable = true;
|
||||
|
||||
public MainWindowViewModel(){
|
||||
_faTheme = App.Current.Styles[0] as FluentAvaloniaTheme;
|
||||
|
||||
Init();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public async void Init(){
|
||||
UpdateAvailable = await Updater.Instance.CheckForUpdatesAsync();
|
||||
|
||||
await Crunchyroll.Instance.Init();
|
||||
|
||||
if (Crunchyroll.Instance.CrunOptions.AccentColor != null){
|
||||
|
@ -34,5 +47,4 @@ public partial class MainWindowViewModel : ViewModelBase{
|
|||
Application.Current.RequestedThemeVariant = ThemeVariant.Light;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -39,8 +39,7 @@
|
|||
|
||||
<TextBlock Grid.Column="1"
|
||||
Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
|
||||
VerticalAlignment="Center"
|
||||
>
|
||||
VerticalAlignment="Center">
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
@ -65,6 +64,8 @@
|
|||
IconSource="Library" />
|
||||
</ui:NavigationView.MenuItems>
|
||||
<ui:NavigationView.FooterMenuItems>
|
||||
<ui:NavigationViewItem Classes="SampleAppNav" Content="Update Available" Tag="UpdateAvailable"
|
||||
IconSource="CloudDownload" Focusable="False" IsVisible="{Binding UpdateAvailable}" />
|
||||
<ui:NavigationViewItem Classes="SampleAppNav" Content="Account" Tag="Account"
|
||||
IconSource="Contact" />
|
||||
<ui:NavigationViewItem Classes="SampleAppNav" Content="Settings" Tag="Settings"
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Net.Http;
|
||||
using System.Reactive.Disposables;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CRD.Downloader;
|
||||
using CRD.Utils.Updater;
|
||||
using CRD.ViewModels;
|
||||
using CRD.Views.Utils;
|
||||
using FluentAvalonia.Core;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using FluentAvalonia.UI.Navigation;
|
||||
using FluentAvalonia.UI.Windowing;
|
||||
using Newtonsoft.Json;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace CRD.Views;
|
||||
|
@ -17,6 +24,9 @@ namespace CRD.Views;
|
|||
public partial class MainWindow : AppWindow{
|
||||
private Stack<object> navigationStack = new Stack<object>();
|
||||
|
||||
|
||||
private object selectedNavVieItem;
|
||||
|
||||
public MainWindow(){
|
||||
InitializeComponent();
|
||||
|
||||
|
@ -27,6 +37,7 @@ public partial class MainWindow : AppWindow{
|
|||
//select first element as default
|
||||
var nv = this.FindControl<NavigationView>("NavView");
|
||||
nv.SelectedItem = nv.MenuItems.ElementAt(0);
|
||||
selectedNavVieItem = nv.SelectedItem;
|
||||
|
||||
MessageBus.Current.Listen<NavigationMessage>()
|
||||
.Subscribe(message => {
|
||||
|
@ -48,11 +59,9 @@ public partial class MainWindow : AppWindow{
|
|||
|
||||
MessageBus.Current.Listen<ToastMessage>()
|
||||
.Subscribe(message => ShowToast(message.Message, message.Type, message.Seconds));
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void ShowError(string message){
|
||||
var window = new ErrorWindow();
|
||||
window.SetErrorMessage(message);
|
||||
|
@ -68,34 +77,46 @@ public partial class MainWindow : AppWindow{
|
|||
if (sender is NavigationView navView){
|
||||
var selectedItem = navView.SelectedItem as NavigationViewItem;
|
||||
if (selectedItem != null){
|
||||
|
||||
switch (selectedItem.Tag){
|
||||
case "DownloadQueue":
|
||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
||||
navView.Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
||||
selectedNavVieItem = selectedItem;
|
||||
break;
|
||||
case "AddDownload":
|
||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(AddDownloadPageViewModel));
|
||||
navView.Content = Activator.CreateInstance(typeof(AddDownloadPageViewModel));
|
||||
selectedNavVieItem = selectedItem;
|
||||
break;
|
||||
case "Calendar":
|
||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(CalendarPageViewModel));
|
||||
navView.Content = Activator.CreateInstance(typeof(CalendarPageViewModel));
|
||||
selectedNavVieItem = selectedItem;
|
||||
break;
|
||||
case "History":
|
||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(HistoryPageViewModel));
|
||||
navView.Content = Activator.CreateInstance(typeof(HistoryPageViewModel));
|
||||
navigationStack.Clear();
|
||||
navigationStack.Push((sender as NavigationView).Content);
|
||||
navigationStack.Push(navView.Content);
|
||||
selectedNavVieItem = selectedItem;
|
||||
break;
|
||||
case "Account":
|
||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(AccountPageViewModel));
|
||||
navView.Content = Activator.CreateInstance(typeof(AccountPageViewModel));
|
||||
selectedNavVieItem = selectedItem;
|
||||
break;
|
||||
case "Settings":
|
||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(SettingsPageViewModel));
|
||||
navView.Content = Activator.CreateInstance(typeof(SettingsPageViewModel));
|
||||
selectedNavVieItem = selectedItem;
|
||||
break;
|
||||
case "UpdateAvailable":
|
||||
Updater.Instance.DownloadAndUpdateAsync();
|
||||
break;
|
||||
default:
|
||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
||||
// (sender as NavigationView).Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public class ToastMessage(string message, ToastType type, int i){
|
||||
|
|
Loading…
Reference in New Issue