Skip to content

Commit

Permalink
v1.4.2 - Added Updater
Browse files Browse the repository at this point in the history
  • Loading branch information
Elwador committed May 5, 2024
1 parent 54fc08f commit f911489
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 29 deletions.
10 changes: 5 additions & 5 deletions CRD/Downloader/Crunchyroll.cs
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ private async Task<DownloadResponse> DownloadMediaList(CrunchyEpMeta data, CrDow

StreamDetailsPop? curStream = null;
if (!dlFailed){
// Validate or adjust options.kstream

options.Kstream = options.Kstream >= 1 && options.Kstream <= streams.Count
? options.Kstream
: 1;
Expand Down Expand Up @@ -741,7 +741,7 @@ private async Task<DownloadResponse> DownloadMediaList(CrunchyEpMeta data, CrDow
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{
Expand All @@ -751,11 +751,11 @@ private async Task<DownloadResponse> DownloadMediaList(CrunchyEpMeta data, CrDow
};
}

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{
Expand Down
95 changes: 95 additions & 0 deletions CRD/Utils/Updater/Updater.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
26 changes: 19 additions & 7 deletions CRD/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
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;

[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){
_faTheme.CustomAccentColor = Color.Parse(Crunchyroll.Instance.CrunOptions.AccentColor);
}

if (Crunchyroll.Instance.CrunOptions.Theme == "System"){
_faTheme.PreferSystemTheme = true;
} else if (Crunchyroll.Instance.CrunOptions.Theme == "Dark"){
Expand All @@ -34,5 +47,4 @@ public async void Init(){
Application.Current.RequestedThemeVariant = ThemeVariant.Light;
}
}

}
7 changes: 4 additions & 3 deletions CRD/Views/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@
</Image>

<TextBlock Grid.Column="1"
Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
VerticalAlignment="Center"
>
Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
VerticalAlignment="Center">
</TextBlock>
</Grid>
</Border>
Expand All @@ -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"
Expand Down
49 changes: 35 additions & 14 deletions CRD/Views/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,44 @@
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;

public partial class MainWindow : AppWindow{
private Stack<object> navigationStack = new Stack<object>();


private object selectedNavVieItem;

public MainWindow(){
InitializeComponent();

TitleBar.ExtendsContentIntoTitleBar = true;
TitleBar.TitleBarHitTestType = TitleBarHitTestType.Complex;


//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 => {
if (message.Refresh){
Expand All @@ -48,11 +59,9 @@ public MainWindow(){

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);
Expand All @@ -63,39 +72,51 @@ public void ShowToast(string message, ToastType type, int durationInSeconds = 5)
this.FindControl<ToastNotification>("Toast").Show(message, type, durationInSeconds);
}


private void NavView_SelectionChanged(object? sender, NavigationViewSelectionChangedEventArgs e){
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){
Expand Down

0 comments on commit f911489

Please sign in to comment.