v1.4.2 - Added Updater
This commit is contained in:
parent
54fc08fa24
commit
f911489021
|
@ -699,7 +699,7 @@ public class Crunchyroll{
|
||||||
|
|
||||||
StreamDetailsPop? curStream = null;
|
StreamDetailsPop? curStream = null;
|
||||||
if (!dlFailed){
|
if (!dlFailed){
|
||||||
// Validate or adjust options.kstream
|
|
||||||
options.Kstream = options.Kstream >= 1 && options.Kstream <= streams.Count
|
options.Kstream = options.Kstream >= 1 && options.Kstream <= streams.Count
|
||||||
? options.Kstream
|
? options.Kstream
|
||||||
: 1;
|
: 1;
|
||||||
|
@ -741,7 +741,7 @@ public class Crunchyroll{
|
||||||
MPDParsed streamPlaylists = MPDParser.Parse(streamPlaylistsReqResponse.ResponseContent, Languages.FindLang(crLocal), matchedUrl);
|
MPDParsed streamPlaylists = MPDParser.Parse(streamPlaylistsReqResponse.ResponseContent, Languages.FindLang(crLocal), matchedUrl);
|
||||||
|
|
||||||
List<string> streamServers = new List<string>(streamPlaylists.Data.Keys);
|
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){
|
if (streamServers.Count == 0){
|
||||||
return new DownloadResponse{
|
return new DownloadResponse{
|
||||||
|
@ -751,11 +751,11 @@ public class Crunchyroll{
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.X == 0){
|
if (options.StreamServer == 0){
|
||||||
options.X = 1;
|
options.StreamServer = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string selectedServer = streamServers[options.X - 1];
|
string selectedServer = streamServers[options.StreamServer - 1];
|
||||||
ServerData selectedList = streamPlaylists.Data[selectedServer];
|
ServerData selectedList = streamPlaylists.Data[selectedServer];
|
||||||
|
|
||||||
var videos = selectedList.video.Select(item => new VideoItem{
|
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.Media;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CRD.Downloader;
|
using CRD.Downloader;
|
||||||
|
using CRD.Utils.Updater;
|
||||||
using FluentAvalonia.Styling;
|
using FluentAvalonia.Styling;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace CRD.ViewModels;
|
namespace CRD.ViewModels;
|
||||||
|
|
||||||
public partial class MainWindowViewModel : ViewModelBase{
|
public partial class MainWindowViewModel : ViewModelBase{
|
||||||
private readonly FluentAvaloniaTheme _faTheme;
|
private readonly FluentAvaloniaTheme _faTheme;
|
||||||
|
|
||||||
public MainWindowViewModel(){
|
[ObservableProperty]
|
||||||
|
private bool _updateAvailable = true;
|
||||||
|
|
||||||
|
public MainWindowViewModel(){
|
||||||
_faTheme = App.Current.Styles[0] as FluentAvaloniaTheme;
|
_faTheme = App.Current.Styles[0] as FluentAvaloniaTheme;
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public async void Init(){
|
public async void Init(){
|
||||||
|
UpdateAvailable = await Updater.Instance.CheckForUpdatesAsync();
|
||||||
|
|
||||||
await Crunchyroll.Instance.Init();
|
await Crunchyroll.Instance.Init();
|
||||||
|
|
||||||
if (Crunchyroll.Instance.CrunOptions.AccentColor != null){
|
if (Crunchyroll.Instance.CrunOptions.AccentColor != null){
|
||||||
|
@ -34,5 +47,4 @@ public partial class MainWindowViewModel : ViewModelBase{
|
||||||
Application.Current.RequestedThemeVariant = ThemeVariant.Light;
|
Application.Current.RequestedThemeVariant = ThemeVariant.Light;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -39,8 +39,7 @@
|
||||||
|
|
||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1"
|
||||||
Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
|
Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center">
|
||||||
>
|
|
||||||
</TextBlock>
|
</TextBlock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
@ -65,6 +64,8 @@
|
||||||
IconSource="Library" />
|
IconSource="Library" />
|
||||||
</ui:NavigationView.MenuItems>
|
</ui:NavigationView.MenuItems>
|
||||||
<ui:NavigationView.FooterMenuItems>
|
<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"
|
<ui:NavigationViewItem Classes="SampleAppNav" Content="Account" Tag="Account"
|
||||||
IconSource="Contact" />
|
IconSource="Contact" />
|
||||||
<ui:NavigationViewItem Classes="SampleAppNav" Content="Settings" Tag="Settings"
|
<ui:NavigationViewItem Classes="SampleAppNav" Content="Settings" Tag="Settings"
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CRD.Downloader;
|
using CRD.Downloader;
|
||||||
|
using CRD.Utils.Updater;
|
||||||
using CRD.ViewModels;
|
using CRD.ViewModels;
|
||||||
using CRD.Views.Utils;
|
using CRD.Views.Utils;
|
||||||
using FluentAvalonia.Core;
|
using FluentAvalonia.Core;
|
||||||
using FluentAvalonia.UI.Controls;
|
using FluentAvalonia.UI.Controls;
|
||||||
using FluentAvalonia.UI.Navigation;
|
using FluentAvalonia.UI.Navigation;
|
||||||
using FluentAvalonia.UI.Windowing;
|
using FluentAvalonia.UI.Windowing;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using ReactiveUI;
|
using ReactiveUI;
|
||||||
|
|
||||||
namespace CRD.Views;
|
namespace CRD.Views;
|
||||||
|
@ -17,6 +24,9 @@ namespace CRD.Views;
|
||||||
public partial class MainWindow : AppWindow{
|
public partial class MainWindow : AppWindow{
|
||||||
private Stack<object> navigationStack = new Stack<object>();
|
private Stack<object> navigationStack = new Stack<object>();
|
||||||
|
|
||||||
|
|
||||||
|
private object selectedNavVieItem;
|
||||||
|
|
||||||
public MainWindow(){
|
public MainWindow(){
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
@ -27,6 +37,7 @@ public partial class MainWindow : AppWindow{
|
||||||
//select first element as default
|
//select first element as default
|
||||||
var nv = this.FindControl<NavigationView>("NavView");
|
var nv = this.FindControl<NavigationView>("NavView");
|
||||||
nv.SelectedItem = nv.MenuItems.ElementAt(0);
|
nv.SelectedItem = nv.MenuItems.ElementAt(0);
|
||||||
|
selectedNavVieItem = nv.SelectedItem;
|
||||||
|
|
||||||
MessageBus.Current.Listen<NavigationMessage>()
|
MessageBus.Current.Listen<NavigationMessage>()
|
||||||
.Subscribe(message => {
|
.Subscribe(message => {
|
||||||
|
@ -48,11 +59,9 @@ public partial class MainWindow : AppWindow{
|
||||||
|
|
||||||
MessageBus.Current.Listen<ToastMessage>()
|
MessageBus.Current.Listen<ToastMessage>()
|
||||||
.Subscribe(message => ShowToast(message.Message, message.Type, message.Seconds));
|
.Subscribe(message => ShowToast(message.Message, message.Type, message.Seconds));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static void ShowError(string message){
|
public static void ShowError(string message){
|
||||||
var window = new ErrorWindow();
|
var window = new ErrorWindow();
|
||||||
window.SetErrorMessage(message);
|
window.SetErrorMessage(message);
|
||||||
|
@ -68,34 +77,46 @@ public partial class MainWindow : AppWindow{
|
||||||
if (sender is NavigationView navView){
|
if (sender is NavigationView navView){
|
||||||
var selectedItem = navView.SelectedItem as NavigationViewItem;
|
var selectedItem = navView.SelectedItem as NavigationViewItem;
|
||||||
if (selectedItem != null){
|
if (selectedItem != null){
|
||||||
|
|
||||||
switch (selectedItem.Tag){
|
switch (selectedItem.Tag){
|
||||||
case "DownloadQueue":
|
case "DownloadQueue":
|
||||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
navView.Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
||||||
|
selectedNavVieItem = selectedItem;
|
||||||
break;
|
break;
|
||||||
case "AddDownload":
|
case "AddDownload":
|
||||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(AddDownloadPageViewModel));
|
navView.Content = Activator.CreateInstance(typeof(AddDownloadPageViewModel));
|
||||||
|
selectedNavVieItem = selectedItem;
|
||||||
break;
|
break;
|
||||||
case "Calendar":
|
case "Calendar":
|
||||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(CalendarPageViewModel));
|
navView.Content = Activator.CreateInstance(typeof(CalendarPageViewModel));
|
||||||
|
selectedNavVieItem = selectedItem;
|
||||||
break;
|
break;
|
||||||
case "History":
|
case "History":
|
||||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(HistoryPageViewModel));
|
navView.Content = Activator.CreateInstance(typeof(HistoryPageViewModel));
|
||||||
navigationStack.Clear();
|
navigationStack.Clear();
|
||||||
navigationStack.Push((sender as NavigationView).Content);
|
navigationStack.Push(navView.Content);
|
||||||
|
selectedNavVieItem = selectedItem;
|
||||||
break;
|
break;
|
||||||
case "Account":
|
case "Account":
|
||||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(AccountPageViewModel));
|
navView.Content = Activator.CreateInstance(typeof(AccountPageViewModel));
|
||||||
|
selectedNavVieItem = selectedItem;
|
||||||
break;
|
break;
|
||||||
case "Settings":
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
(sender as NavigationView).Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
// (sender as NavigationView).Content = Activator.CreateInstance(typeof(DownloadsPageViewModel));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ToastMessage(string message, ToastType type, int i){
|
public class ToastMessage(string message, ToastType type, int i){
|
||||||
|
|
Loading…
Reference in New Issue