Ionite
1 year ago
8 changed files with 680 additions and 6 deletions
@ -0,0 +1,393 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.ObjectModel; |
||||||
|
using System.IO; |
||||||
|
using System.Linq; |
||||||
|
using System.Threading.Tasks; |
||||||
|
using AsyncAwaitBestPractices; |
||||||
|
using Avalonia.Controls; |
||||||
|
using Avalonia.Controls.Notifications; |
||||||
|
using Avalonia.Layout; |
||||||
|
using Avalonia.Media; |
||||||
|
using Avalonia.Media.Imaging; |
||||||
|
using Avalonia.Threading; |
||||||
|
using CommunityToolkit.Mvvm.ComponentModel; |
||||||
|
using CommunityToolkit.Mvvm.Input; |
||||||
|
using FluentAvalonia.UI.Controls; |
||||||
|
using NLog; |
||||||
|
using Octokit; |
||||||
|
using StabilityMatrix.Avalonia.Services; |
||||||
|
using StabilityMatrix.Core.Helper; |
||||||
|
using StabilityMatrix.Core.Models; |
||||||
|
using StabilityMatrix.Core.Models.FileInterfaces; |
||||||
|
using StabilityMatrix.Core.Models.Packages; |
||||||
|
using StabilityMatrix.Core.Models.Progress; |
||||||
|
using StabilityMatrix.Core.Processes; |
||||||
|
using StabilityMatrix.Core.Python; |
||||||
|
using StabilityMatrix.Core.Services; |
||||||
|
using Notification = Avalonia.Controls.Notifications.Notification; |
||||||
|
using PackageVersion = StabilityMatrix.Core.Models.PackageVersion; |
||||||
|
|
||||||
|
namespace StabilityMatrix.Avalonia.ViewModels.Dialogs; |
||||||
|
|
||||||
|
|
||||||
|
public partial class InstallerViewModel : ViewModelBase |
||||||
|
{ |
||||||
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); |
||||||
|
|
||||||
|
private readonly ISettingsManager settingsManager; |
||||||
|
private readonly IPyRunner pyRunner; |
||||||
|
private readonly IDownloadService downloadService; |
||||||
|
private readonly INotificationService notificationService; |
||||||
|
private readonly ISharedFolders sharedFolders; |
||||||
|
private readonly IPrerequisiteHelper prerequisiteHelper; |
||||||
|
|
||||||
|
[ObservableProperty] private BasePackage selectedPackage; |
||||||
|
[ObservableProperty] private PackageVersion? selectedVersion; |
||||||
|
|
||||||
|
[ObservableProperty] private ObservableCollection<BasePackage>? availablePackages; |
||||||
|
[ObservableProperty] private ObservableCollection<GitHubCommit>? availableCommits; |
||||||
|
[ObservableProperty] private ObservableCollection<PackageVersion>? availableVersions; |
||||||
|
|
||||||
|
[ObservableProperty] private GitHubCommit? selectedCommit; |
||||||
|
|
||||||
|
[ObservableProperty] private string? releaseNotes; |
||||||
|
// [ObservableProperty] private bool isReleaseMode; |
||||||
|
|
||||||
|
// Version types (release or commit) |
||||||
|
[ObservableProperty] |
||||||
|
[NotifyPropertyChangedFor(nameof(ReleaseLabelText), |
||||||
|
nameof(IsReleaseMode), nameof(SelectedVersion))] |
||||||
|
private PackageVersionType selectedVersionType = PackageVersionType.Commit; |
||||||
|
|
||||||
|
[ObservableProperty] |
||||||
|
[NotifyPropertyChangedFor(nameof(IsReleaseModeAvailable))] |
||||||
|
private PackageVersionType availableVersionTypes = |
||||||
|
PackageVersionType.GithubRelease | PackageVersionType.Commit; |
||||||
|
public string ReleaseLabelText => SelectedVersionType == PackageVersionType.GithubRelease |
||||||
|
? "Version" : "Branch"; |
||||||
|
public bool IsReleaseMode |
||||||
|
{ |
||||||
|
get => SelectedVersionType == PackageVersionType.GithubRelease; |
||||||
|
set => SelectedVersionType = value ? PackageVersionType.GithubRelease : PackageVersionType.Commit; |
||||||
|
} |
||||||
|
|
||||||
|
public bool IsReleaseModeAvailable => AvailableVersionTypes.HasFlag(PackageVersionType.GithubRelease); |
||||||
|
|
||||||
|
[ObservableProperty] private bool showDuplicateWarning; |
||||||
|
|
||||||
|
[ObservableProperty] private string? installName; |
||||||
|
|
||||||
|
internal event EventHandler? PackageInstalled; |
||||||
|
|
||||||
|
public ProgressViewModel InstallProgress { get; } = new() |
||||||
|
{ |
||||||
|
|
||||||
|
}; |
||||||
|
|
||||||
|
public InstallerViewModel( |
||||||
|
ISettingsManager settingsManager, |
||||||
|
IPyRunner pyRunner, |
||||||
|
IDownloadService downloadService, INotificationService notificationService, |
||||||
|
ISharedFolders sharedFolders, |
||||||
|
IPrerequisiteHelper prerequisiteHelper) |
||||||
|
{ |
||||||
|
this.settingsManager = settingsManager; |
||||||
|
this.pyRunner = pyRunner; |
||||||
|
this.downloadService = downloadService; |
||||||
|
this.notificationService = notificationService; |
||||||
|
this.sharedFolders = sharedFolders; |
||||||
|
this.prerequisiteHelper = prerequisiteHelper; |
||||||
|
|
||||||
|
// AvailablePackages and SelectedPackage need to be set in init |
||||||
|
} |
||||||
|
|
||||||
|
public override async Task OnLoadedAsync() |
||||||
|
{ |
||||||
|
if (IsReleaseMode) |
||||||
|
{ |
||||||
|
var versions = (await SelectedPackage.GetAllVersions()).ToList(); |
||||||
|
AvailableVersions = new ObservableCollection<PackageVersion>(versions); |
||||||
|
if (!AvailableVersions.Any()) return; |
||||||
|
|
||||||
|
SelectedVersion = AvailableVersions[0]; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
var branches = (await SelectedPackage.GetAllBranches()).ToList(); |
||||||
|
AvailableVersions = new ObservableCollection<PackageVersion>(branches.Select(b => new PackageVersion |
||||||
|
{ |
||||||
|
TagName = b.Name, |
||||||
|
ReleaseNotesMarkdown = b.Commit.Label |
||||||
|
})); |
||||||
|
SelectedVersion = AvailableVersions.FirstOrDefault(x => |
||||||
|
x.TagName.ToLowerInvariant() is "master" or "main") ?? AvailableVersions[0]; |
||||||
|
} |
||||||
|
|
||||||
|
ReleaseNotes = SelectedVersion.ReleaseNotesMarkdown; |
||||||
|
} |
||||||
|
|
||||||
|
[RelayCommand] |
||||||
|
private async Task Install() |
||||||
|
{ |
||||||
|
await ActuallyInstall(); |
||||||
|
notificationService.Show(new Notification( |
||||||
|
$"Package {SelectedPackage.Name} installed successfully!", |
||||||
|
"Success", NotificationType.Success)); |
||||||
|
OnPackageInstalled(); |
||||||
|
} |
||||||
|
|
||||||
|
private async Task ActuallyInstall() |
||||||
|
{ |
||||||
|
if (string.IsNullOrWhiteSpace(InstallName)) |
||||||
|
{ |
||||||
|
notificationService.Show(new Notification("Package name is empty", |
||||||
|
"Please enter a name for the package", NotificationType.Error)); |
||||||
|
} |
||||||
|
|
||||||
|
await InstallGitIfNecessary(); |
||||||
|
|
||||||
|
var libraryDir = new DirectoryPath(settingsManager.LibraryDir, "Packages", InstallName); |
||||||
|
SelectedPackage.InstallLocation = $"{settingsManager.LibraryDir}\\Packages\\{InstallName}"; |
||||||
|
// SelectedPackage.DisplayName = InstallName; |
||||||
|
|
||||||
|
if (!PyRunner.PipInstalled || !PyRunner.VenvInstalled) |
||||||
|
{ |
||||||
|
InstallProgress.Text = "Installing dependencies..."; |
||||||
|
await pyRunner.Initialize(); |
||||||
|
if (!PyRunner.PipInstalled) |
||||||
|
{ |
||||||
|
await pyRunner.SetupPip(); |
||||||
|
} |
||||||
|
if (!PyRunner.VenvInstalled) |
||||||
|
{ |
||||||
|
await pyRunner.InstallPackage("virtualenv"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
var version = IsReleaseMode |
||||||
|
? await DownloadPackage(SelectedVersion!.TagName, false) |
||||||
|
: await DownloadPackage(SelectedCommit!.Sha, true); |
||||||
|
|
||||||
|
await InstallPackage(); |
||||||
|
|
||||||
|
InstallProgress.Text = "Setting up shared folder links..."; |
||||||
|
sharedFolders.SetupLinksForPackage(SelectedPackage, SelectedPackage.InstallLocation); |
||||||
|
|
||||||
|
InstallProgress.Text = "Done"; |
||||||
|
InstallProgress.IsIndeterminate = false; |
||||||
|
InstallProgress.Value = 100; |
||||||
|
EventManager.Instance.OnGlobalProgressChanged(100); |
||||||
|
|
||||||
|
var branch = SelectedVersionType == PackageVersionType.GithubRelease ? |
||||||
|
null : SelectedVersion!.TagName; |
||||||
|
|
||||||
|
var package = new InstalledPackage |
||||||
|
{ |
||||||
|
DisplayName = SelectedPackage.DisplayName, |
||||||
|
LibraryPath = $"Packages\\{InstallName}", |
||||||
|
Id = Guid.NewGuid(), |
||||||
|
PackageName = SelectedPackage.Name, |
||||||
|
PackageVersion = version, |
||||||
|
DisplayVersion = GetDisplayVersion(version, branch), |
||||||
|
InstalledBranch = branch, |
||||||
|
LaunchCommand = SelectedPackage.LaunchCommand, |
||||||
|
LastUpdateCheck = DateTimeOffset.Now |
||||||
|
}; |
||||||
|
await using var st = settingsManager.BeginTransaction(); |
||||||
|
st.Settings.InstalledPackages.Add(package); |
||||||
|
st.Settings.ActiveInstalledPackage = package.Id; |
||||||
|
|
||||||
|
InstallProgress.Value = 0; |
||||||
|
} |
||||||
|
|
||||||
|
private static string GetDisplayVersion(string version, string? branch) |
||||||
|
{ |
||||||
|
return branch == null ? version : $"{branch}@{version[..7]}"; |
||||||
|
} |
||||||
|
|
||||||
|
private Task<string?> DownloadPackage(string version, bool isCommitHash) |
||||||
|
{ |
||||||
|
InstallProgress.Text = "Downloading package..."; |
||||||
|
|
||||||
|
var progress = new Progress<ProgressReport>(progress => |
||||||
|
{ |
||||||
|
InstallProgress.IsIndeterminate = progress.IsIndeterminate; |
||||||
|
InstallProgress.Value = progress.Percentage; |
||||||
|
EventManager.Instance.OnGlobalProgressChanged((int) progress.Percentage); |
||||||
|
}); |
||||||
|
|
||||||
|
return SelectedPackage.DownloadPackage(version, isCommitHash, progress); |
||||||
|
} |
||||||
|
|
||||||
|
private async Task InstallPackage() |
||||||
|
{ |
||||||
|
InstallProgress.Text = "Installing package..."; |
||||||
|
SelectedPackage.ConsoleOutput += SelectedPackageOnConsoleOutput; |
||||||
|
try |
||||||
|
{ |
||||||
|
var progress = new Progress<ProgressReport>(progress => |
||||||
|
{ |
||||||
|
InstallProgress.IsIndeterminate = progress.IsIndeterminate; |
||||||
|
InstallProgress.Value = progress.Percentage; |
||||||
|
EventManager.Instance.OnGlobalProgressChanged((int) progress.Percentage); |
||||||
|
}); |
||||||
|
|
||||||
|
await SelectedPackage.InstallPackage(progress); |
||||||
|
} |
||||||
|
finally |
||||||
|
{ |
||||||
|
SelectedPackage.ConsoleOutput -= SelectedPackageOnConsoleOutput; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void SelectedPackageOnConsoleOutput(object? sender, ProcessOutput e) |
||||||
|
{ |
||||||
|
InstallProgress.Description = e.Text; |
||||||
|
} |
||||||
|
|
||||||
|
[RelayCommand] |
||||||
|
private async Task ShowPreview() |
||||||
|
{ |
||||||
|
var url = SelectedPackage.PreviewImageUri.ToString(); |
||||||
|
var imageStream = await downloadService.GetImageStreamFromUrl(url); |
||||||
|
var bitmap = new Bitmap(imageStream); |
||||||
|
|
||||||
|
var dialog = new ContentDialog |
||||||
|
{ |
||||||
|
Title = "Test title", |
||||||
|
PrimaryButtonText = "Open in Browser", |
||||||
|
CloseButtonText = "Close", |
||||||
|
Content = new Image |
||||||
|
{ |
||||||
|
Source = bitmap, |
||||||
|
Stretch = Stretch.Uniform, |
||||||
|
MaxHeight = 500, |
||||||
|
HorizontalAlignment = HorizontalAlignment.Center |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
var result = await dialog.ShowAsync(); |
||||||
|
if (result == ContentDialogResult.Primary) |
||||||
|
{ |
||||||
|
ProcessRunner.OpenUrl(url); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnSelectedPackageChanged(BasePackage? value) |
||||||
|
{ |
||||||
|
if (value == null) return; |
||||||
|
|
||||||
|
ReleaseNotes = string.Empty; |
||||||
|
AvailableVersions?.Clear(); |
||||||
|
AvailableCommits?.Clear(); |
||||||
|
|
||||||
|
AvailableVersionTypes = SelectedPackage.ShouldIgnoreReleases |
||||||
|
? PackageVersionType.Commit |
||||||
|
: PackageVersionType.GithubRelease | PackageVersionType.Commit; |
||||||
|
|
||||||
|
// Reset selected if not compatible |
||||||
|
if (!AvailableVersionTypes.HasFlag(SelectedVersionType)) |
||||||
|
{ |
||||||
|
SelectedVersionType = PackageVersionType.Commit; |
||||||
|
} |
||||||
|
|
||||||
|
var isReleaseMode = SelectedVersionType == PackageVersionType.GithubRelease; |
||||||
|
|
||||||
|
if (Design.IsDesignMode) return; |
||||||
|
|
||||||
|
Task.Run(async () => |
||||||
|
{ |
||||||
|
var versions = (await value.GetAllVersions(isReleaseMode)).ToList(); |
||||||
|
if (!versions.Any()) return; |
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(() => |
||||||
|
{ |
||||||
|
AvailableVersions = new ObservableCollection<PackageVersion>(versions); |
||||||
|
SelectedVersion = AvailableVersions[0]; |
||||||
|
ReleaseNotes = versions.First().ReleaseNotesMarkdown; |
||||||
|
}); |
||||||
|
|
||||||
|
if (!isReleaseMode) |
||||||
|
{ |
||||||
|
var commits = await value.GetAllCommits(SelectedVersion!.TagName); |
||||||
|
if (commits is null || commits.Count == 0) return; |
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(() => |
||||||
|
{ |
||||||
|
AvailableCommits = new ObservableCollection<GitHubCommit>(commits); |
||||||
|
SelectedCommit = AvailableCommits[0]; |
||||||
|
SelectedVersion = AvailableVersions?.FirstOrDefault(packageVersion => |
||||||
|
packageVersion.TagName.ToLowerInvariant() is "master" or "main"); |
||||||
|
}); |
||||||
|
} |
||||||
|
}).SafeFireAndForget(); |
||||||
|
} |
||||||
|
|
||||||
|
private async Task InstallGitIfNecessary() |
||||||
|
{ |
||||||
|
var progressHandler = new Progress<ProgressReport>(progress => |
||||||
|
{ |
||||||
|
if (progress.Message != null && progress.Message.Contains("Downloading")) |
||||||
|
{ |
||||||
|
InstallProgress.Text = $"Downloading prerequisites... {progress.Percentage:N0}%"; |
||||||
|
} |
||||||
|
else if (progress.Type == ProgressType.Extract) |
||||||
|
{ |
||||||
|
InstallProgress.Text = $"Installing git... {progress.Percentage:N0}%"; |
||||||
|
} |
||||||
|
else if (progress.Title != null && progress.Title.Contains("Unpacking")) |
||||||
|
{ |
||||||
|
InstallProgress.Text = $"Unpacking resources... {progress.Percentage:N0}%"; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
InstallProgress.Text = progress.Message; |
||||||
|
} |
||||||
|
|
||||||
|
InstallProgress.IsIndeterminate = progress.IsIndeterminate; |
||||||
|
InstallProgress.Value = Convert.ToInt32(progress.Percentage); |
||||||
|
}); |
||||||
|
|
||||||
|
await prerequisiteHelper.InstallAllIfNecessary(progressHandler); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnInstallNameChanged(string? value) |
||||||
|
{ |
||||||
|
ShowDuplicateWarning = |
||||||
|
settingsManager.Settings.InstalledPackages.Any(p => |
||||||
|
p.LibraryPath == $"Packages{Path.DirectorySeparatorChar}{value}"); |
||||||
|
} |
||||||
|
|
||||||
|
partial void OnSelectedVersionChanged(PackageVersion? value) |
||||||
|
{ |
||||||
|
ReleaseNotes = value?.ReleaseNotesMarkdown ?? string.Empty; |
||||||
|
if (value == null) return; |
||||||
|
|
||||||
|
SelectedCommit = null; |
||||||
|
AvailableCommits?.Clear(); |
||||||
|
|
||||||
|
if (!IsReleaseMode) |
||||||
|
{ |
||||||
|
Task.Run(async () => |
||||||
|
{ |
||||||
|
try |
||||||
|
{ |
||||||
|
var hashes = await SelectedPackage.GetAllCommits(value.TagName); |
||||||
|
if (hashes is null) throw new Exception("No commits found"); |
||||||
|
|
||||||
|
Dispatcher.UIThread.Post(() => |
||||||
|
{ |
||||||
|
AvailableCommits = new ObservableCollection<GitHubCommit>(hashes); |
||||||
|
SelectedCommit = AvailableCommits[0]; |
||||||
|
}); |
||||||
|
} |
||||||
|
catch (Exception e) |
||||||
|
{ |
||||||
|
Logger.Warn($"Error getting commits: {e.Message}"); |
||||||
|
} |
||||||
|
}).SafeFireAndForget(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private void OnPackageInstalled() => PackageInstalled?.Invoke(this, EventArgs.Empty); |
||||||
|
} |
@ -0,0 +1,232 @@ |
|||||||
|
<controls:UserControlBase xmlns="https://github.com/avaloniaui" |
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||||
|
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls" |
||||||
|
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels" |
||||||
|
xmlns:ui="using:FluentAvalonia.UI.Controls" |
||||||
|
xmlns:md="https://github.com/whistyun/Markdown.Avalonia" |
||||||
|
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData" |
||||||
|
xmlns:system="clr-namespace:System;assembly=System.Runtime" |
||||||
|
xmlns:dialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs" |
||||||
|
xmlns:packages="clr-namespace:StabilityMatrix.Core.Models.Packages;assembly=StabilityMatrix.Core" |
||||||
|
xmlns:models="clr-namespace:StabilityMatrix.Core.Models;assembly=StabilityMatrix.Core" |
||||||
|
xmlns:octokit="clr-namespace:Octokit;assembly=Octokit" |
||||||
|
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight" |
||||||
|
x:DataType="dialogs:InstallerViewModel" |
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" |
||||||
|
d:DataContext="{x:Static mocks:DesignData.InstallerViewModel}" |
||||||
|
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.InstallerDialog"> |
||||||
|
|
||||||
|
<controls:UserControlBase.Resources> |
||||||
|
</controls:UserControlBase.Resources> |
||||||
|
|
||||||
|
<Grid> |
||||||
|
<Grid.RowDefinitions> |
||||||
|
<RowDefinition Height="Auto" /> |
||||||
|
<RowDefinition Height="Auto" /> |
||||||
|
<RowDefinition Height="*" /> |
||||||
|
</Grid.RowDefinitions> |
||||||
|
|
||||||
|
<StackPanel |
||||||
|
Grid.Row="1" |
||||||
|
Margin="16,8,16,0" |
||||||
|
Orientation="Vertical" |
||||||
|
DataContext="{Binding InstallProgress}" |
||||||
|
IsVisible="{Binding IsProgressVisible}"> |
||||||
|
|
||||||
|
<TextBlock |
||||||
|
HorizontalAlignment="Center" |
||||||
|
Padding="8" |
||||||
|
Text="{Binding Text}" /> |
||||||
|
<ProgressBar |
||||||
|
IsIndeterminate="{Binding IsIndeterminate}" |
||||||
|
Maximum="100" |
||||||
|
Width="500" |
||||||
|
Value="{Binding Value}" /> |
||||||
|
<TextBlock |
||||||
|
FontSize="10" |
||||||
|
HorizontalAlignment="Center" |
||||||
|
Padding="4" |
||||||
|
Text="{Binding Description}" |
||||||
|
TextWrapping="Wrap" /> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<Grid Grid.Row="2" HorizontalAlignment="Left" ColumnDefinitions="Auto,Auto,*"> |
||||||
|
<ListBox |
||||||
|
Margin="16" |
||||||
|
ItemsSource="{Binding AvailablePackages}" |
||||||
|
SelectedItem="{Binding SelectedPackage, Mode=TwoWay}"> |
||||||
|
|
||||||
|
<!--<ListView.Style> |
||||||
|
<Style TargetType="ListView"> |
||||||
|
<Setter Property="Background" Value="#191919" /> |
||||||
|
</Style> |
||||||
|
</ListView.Style>--> |
||||||
|
|
||||||
|
<ListBox.Template> |
||||||
|
<ControlTemplate> |
||||||
|
<!-- BorderBrush="{KeyboardFocusBorderColorBrush}" --> |
||||||
|
<Border |
||||||
|
BorderThickness="1" |
||||||
|
CornerRadius="5"> |
||||||
|
<ItemsPresenter /> |
||||||
|
</Border> |
||||||
|
</ControlTemplate> |
||||||
|
</ListBox.Template> |
||||||
|
|
||||||
|
<ListBox.ItemTemplate> |
||||||
|
<DataTemplate DataType="{x:Type packages:BasePackage}"> |
||||||
|
<StackPanel Margin="8" VerticalAlignment="Top"> |
||||||
|
<TextBlock Margin="0,5,0,5" Text="{Binding DisplayName}" /> |
||||||
|
<TextBlock Margin="0,0,0,5" Text="{Binding ByAuthor}" /> |
||||||
|
</StackPanel> |
||||||
|
</DataTemplate> |
||||||
|
</ListBox.ItemTemplate> |
||||||
|
</ListBox> |
||||||
|
|
||||||
|
<StackPanel |
||||||
|
Grid.Column="1" |
||||||
|
Margin="16,16,0,16" |
||||||
|
Orientation="Vertical"> |
||||||
|
<TextBlock |
||||||
|
FontSize="24" |
||||||
|
FontWeight="Bold" |
||||||
|
Text="{Binding SelectedPackage.DisplayName, FallbackValue=Stable Diffusion Web UI}" /> |
||||||
|
<TextBlock FontSize="12" Text="{Binding SelectedPackage.ByAuthor, FallbackValue=by Automatic111}" /> |
||||||
|
|
||||||
|
<Button |
||||||
|
Background="Transparent" |
||||||
|
BorderBrush="Transparent" |
||||||
|
Command="{Binding ShowPreviewCommand}" |
||||||
|
Content="UI Preview" |
||||||
|
Margin="0,8,0,0"> |
||||||
|
<!--<Button.Style> |
||||||
|
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}"> |
||||||
|
<Setter Property="Foreground"> |
||||||
|
<Setter.Value> |
||||||
|
<SolidColorBrush Color="{DynamicResource SystemAccentColorSecondary}" /> |
||||||
|
</Setter.Value> |
||||||
|
</Setter> |
||||||
|
</Style> |
||||||
|
</Button.Style>--> |
||||||
|
</Button> |
||||||
|
|
||||||
|
<ui:HyperlinkButton Margin="0,0,0,8" NavigateUri="{Binding SelectedPackage.GithubUrl}"> |
||||||
|
<TextBlock TextWrapping="Wrap"> |
||||||
|
<Run Text="GitHub Page:" /> |
||||||
|
<Run Text="{Binding SelectedPackage.GithubUrl, Mode=OneWay}" TextDecorations="Underline" /> |
||||||
|
</TextBlock> |
||||||
|
</ui:HyperlinkButton> |
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal"> |
||||||
|
<ToggleButton |
||||||
|
Content="Releases" |
||||||
|
IsChecked="{Binding IsReleaseMode}" |
||||||
|
IsEnabled="{Binding IsReleaseModeAvailable}" /> |
||||||
|
<ToggleButton |
||||||
|
Content="Branches" |
||||||
|
IsChecked="{Binding !IsReleaseMode}" |
||||||
|
Margin="8,0,0,0" /> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<StackPanel Margin="0,16,0,0" Orientation="Horizontal"> |
||||||
|
<StackPanel Orientation="Vertical"> |
||||||
|
<Label Content="{Binding ReleaseLabelText, FallbackValue=Version}" /> |
||||||
|
<ComboBox |
||||||
|
ItemsSource="{Binding AvailableVersions}" |
||||||
|
MinWidth="200" |
||||||
|
SelectedItem="{Binding SelectedVersion}"> |
||||||
|
<ComboBox.ItemTemplate> |
||||||
|
<DataTemplate DataType="{x:Type models:PackageVersion}"> |
||||||
|
<StackPanel Margin="8,0,0,0" VerticalAlignment="Top"> |
||||||
|
<TextBlock |
||||||
|
Margin="0,4,0,4" |
||||||
|
Name="NameTextBlock" |
||||||
|
Text="{Binding TagName}" /> |
||||||
|
</StackPanel> |
||||||
|
</DataTemplate> |
||||||
|
</ComboBox.ItemTemplate> |
||||||
|
</ComboBox> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<StackPanel |
||||||
|
Margin="8,0,0,0" |
||||||
|
Orientation="Vertical" |
||||||
|
IsVisible="{Binding !IsReleaseMode}"> |
||||||
|
<Label Content="Commit" /> |
||||||
|
<ComboBox |
||||||
|
ItemsSource="{Binding AvailableCommits}" |
||||||
|
MinWidth="100" |
||||||
|
SelectedItem="{Binding SelectedCommit}"> |
||||||
|
<ComboBox.ItemTemplate> |
||||||
|
<DataTemplate DataType="{x:Type octokit:GitHubCommit}"> |
||||||
|
<StackPanel Margin="8,0,0,0" VerticalAlignment="Top"> |
||||||
|
<TextBlock |
||||||
|
Margin="0,4,0,4" |
||||||
|
Name="NameTextBlock" |
||||||
|
Text="{Binding Sha}" /> |
||||||
|
</StackPanel> |
||||||
|
</DataTemplate> |
||||||
|
</ComboBox.ItemTemplate> |
||||||
|
</ComboBox> |
||||||
|
</StackPanel> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<Label Content="Display Name" Margin="0,16,0,0" /> |
||||||
|
<StackPanel Orientation="Horizontal" IsVisible="{Binding ShowDuplicateWarning}"> |
||||||
|
<ui:SymbolIcon |
||||||
|
Foreground="{DynamicResource ThemeRedColor}" |
||||||
|
Margin="8" |
||||||
|
Symbol="Alert" /> |
||||||
|
<TextBlock |
||||||
|
Foreground="{DynamicResource ThemeRedColor}" |
||||||
|
Margin="0,8,8,8" |
||||||
|
TextAlignment="Left" |
||||||
|
TextWrapping="Wrap"> |
||||||
|
<Run Text="An installation with this name already exists." /> |
||||||
|
<LineBreak /> |
||||||
|
<Run Text="Please choose a different name or select a different Install Location." /> |
||||||
|
</TextBlock> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<TextBox |
||||||
|
Margin="0,0,0,8" |
||||||
|
Text="{Binding SelectedPackage.DisplayName}" /> |
||||||
|
|
||||||
|
<StackPanel Orientation="Horizontal"> |
||||||
|
<Button |
||||||
|
Command="{Binding InstallCommand}" |
||||||
|
Content="Install" |
||||||
|
Height="50" |
||||||
|
IsEnabled="{Binding !ShowDuplicateWarning}" |
||||||
|
Margin="0,16,0,0" |
||||||
|
VerticalAlignment="Top" |
||||||
|
Width="100" /> |
||||||
|
<controls:ProgressRing |
||||||
|
Height="25" |
||||||
|
IsIndeterminate="True" |
||||||
|
Margin="8,16,0,0" |
||||||
|
VerticalAlignment="Center" |
||||||
|
IsVisible="{Binding InstallProgress.IsProgressVisible}" |
||||||
|
Width="25" /> |
||||||
|
<TextBlock |
||||||
|
Margin="8,16,0,0" |
||||||
|
Text="Installing..." |
||||||
|
VerticalAlignment="Center" |
||||||
|
IsVisible="{Binding InstallProgress.IsProgressVisible}" /> |
||||||
|
</StackPanel> |
||||||
|
</StackPanel> |
||||||
|
|
||||||
|
<mdxaml:MarkdownScrollViewer |
||||||
|
Grid.Column="2" |
||||||
|
Margin="16" |
||||||
|
Source="{Binding ReleaseNotes, Mode=OneWay}"/> |
||||||
|
<ContentPresenter |
||||||
|
Grid.Column="0" |
||||||
|
Grid.ColumnSpan="3" |
||||||
|
x:Name="InstallerContentDialog" /> |
||||||
|
</Grid> |
||||||
|
</Grid> |
||||||
|
|
||||||
|
</controls:UserControlBase> |
@ -0,0 +1,17 @@ |
|||||||
|
using Avalonia.Markup.Xaml; |
||||||
|
using StabilityMatrix.Avalonia.Controls; |
||||||
|
|
||||||
|
namespace StabilityMatrix.Avalonia.Views.Dialogs; |
||||||
|
|
||||||
|
public partial class InstallerDialog : UserControlBase |
||||||
|
{ |
||||||
|
public InstallerDialog() |
||||||
|
{ |
||||||
|
InitializeComponent(); |
||||||
|
} |
||||||
|
|
||||||
|
private void InitializeComponent() |
||||||
|
{ |
||||||
|
AvaloniaXamlLoader.Load(this); |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue