Browse Source

redesigned packages page & made it the first tab & removed old launch page from tabs

pull/629/head
JT 9 months ago
parent
commit
2303759eec
  1. 3
      StabilityMatrix.Avalonia/App.axaml.cs
  2. 73
      StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml
  3. 12
      StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs
  4. 73
      StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs
  5. 11
      StabilityMatrix.Avalonia/ViewModels/RunningPackageViewModel.cs
  6. 8
      StabilityMatrix.Avalonia/Views/ConsoleOutputPage.axaml
  7. 276
      StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml
  8. 607
      StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml
  9. 3
      StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs

3
StabilityMatrix.Avalonia/App.axaml.cs

@ -328,9 +328,8 @@ public sealed class App : Application
{
Pages =
{
provider.GetRequiredService<LaunchPageViewModel>(),
provider.GetRequiredService<InferenceViewModel>(),
provider.GetRequiredService<NewPackageManagerViewModel>(),
provider.GetRequiredService<InferenceViewModel>(),
provider.GetRequiredService<CheckpointsPageViewModel>(),
provider.GetRequiredService<CheckpointBrowserViewModel>(),
provider.GetRequiredService<OutputsPageViewModel>()

73
StabilityMatrix.Avalonia/Styles/ButtonStyles.axaml

@ -99,6 +99,43 @@
</Style>
</Style>
<!-- Danger -->
<Style Selector="Button.borderless-danger">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ThemeRedColor}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
</Style>
<Style Selector="^:pointerover">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ThemeDarkRedColor}"/>
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" />
</Style>
</Style>
<Style Selector="^:pressed">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ThemeDarkDarkRedColor}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" />
</Style>
</Style>
<Style Selector="^:disabled">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
</Style>
</Style>
</Style>
<!-- Info -->
<Style Selector="Button.info">
<Style Selector="^ /template/ ui|FABorder#Root">
@ -140,6 +177,42 @@
</Style>
</Style>
<Style Selector="Button.borderless-info">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ThemeLightBlueColor}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForeground}" />
</Style>
<Style Selector="^:pointerover">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ThemeBlueColor}"/>
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" />
</Style>
</Style>
<Style Selector="^:pressed">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ThemeDarkBlueColor}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundPressed}" />
</Style>
</Style>
<Style Selector="^:disabled">
<Style Selector="^ /template/ ui|FABorder#Root">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
</Style>
<Style Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
</Style>
</Style>
</Style>
<!--Accent Button-->
<Style Selector="Button.accent">
<Style Selector="^ /template/ ui|FABorder#Root">

12
StabilityMatrix.Avalonia/ViewModels/CheckpointManager/CheckpointFolder.cs

@ -111,6 +111,10 @@ public partial class CheckpointFolder : ViewModelBase
public IObservableCollection<string> BaseModelOptions { get; } =
new ObservableCollectionExtended<string>();
private IEnumerable<string> allModelOptions = Enum.GetValues<CivitBaseModelType>()
.Where(x => x != CivitBaseModelType.All)
.Select(x => x.GetStringValue());
public CheckpointFolder(
ISettingsManager settingsManager,
IDownloadService downloadService,
@ -175,11 +179,7 @@ public partial class CheckpointFolder : ViewModelBase
SubFoldersCache.Refresh();
});
BaseModelOptionsCache.AddOrUpdate(
Enum.GetValues<CivitBaseModelType>()
.Where(x => x != CivitBaseModelType.All)
.Select(x => x.GetStringValue())
);
BaseModelOptionsCache.AddOrUpdate(allModelOptions);
CheckpointFiles.CollectionChanged += OnCheckpointFilesChanged;
// DisplayedCheckpointFiles = CheckpointFiles;
@ -187,7 +187,7 @@ public partial class CheckpointFolder : ViewModelBase
private bool BaseModelFilter(CheckpointFile file)
{
return file.IsConnectedModel
return file.IsConnectedModel && allModelOptions.Contains(file.ConnectedModel!.BaseModel)
? BaseModelOptions.Contains(file.ConnectedModel!.BaseModel)
: BaseModelOptions.Contains("Other");
}

73
StabilityMatrix.Avalonia/ViewModels/PackageManager/PackageCardViewModel.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Linq;
using System.Threading;
@ -96,13 +97,10 @@ public partial class PackageCardViewModel(
private void RunningPackagesOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (
e.NewItems?.OfType<KeyValuePair<Guid, RunningPackageViewModel>>().Select(x => x.Value)
is not { } newItems
)
if (runningPackageService.RunningPackages.Select(x => x.Value) is not { } runningPackages)
return;
var runningViewModel = newItems.FirstOrDefault(
var runningViewModel = runningPackages.FirstOrDefault(
x => x.RunningPackage.InstalledPackage.Id == Package?.Id
);
if (runningViewModel is not null)
@ -114,6 +112,7 @@ public partial class PackageCardViewModel(
else if (runningViewModel is null && IsRunning)
{
IsRunning = false;
ShowWebUiButton = false;
}
}
@ -165,6 +164,7 @@ public partial class PackageCardViewModel(
if (Design.IsDesignMode && Package?.DisplayName == "Running Comfy")
{
IsRunning = true;
IsUpdateAvailable = true;
ShowWebUiButton = true;
}
@ -422,6 +422,21 @@ public partial class PackageCardViewModel(
versionOptions.CommitHash = latest.Sha;
}
var confirmationDialog = new BetterContentDialog
{
Title = Resources.Label_AreYouSure,
Content =
$"{Package.DisplayName} will be updated to the latest version ({versionOptions.GetReadableVersionString()})",
PrimaryButtonText = Resources.Action_Continue,
SecondaryButtonText = Resources.Action_Cancel,
DefaultButton = ContentDialogButton.Primary,
IsSecondaryButtonEnabled = true,
};
var dialogResult = await confirmationDialog.ShowAsync();
if (dialogResult != ContentDialogResult.Primary)
return;
var updatePackageStep = new UpdatePackageStep(
settingsManager,
Package,
@ -583,6 +598,54 @@ public partial class PackageCardViewModel(
await runningPackageService.StopPackage(Package.Id);
IsRunning = false;
ShowWebUiButton = false;
}
[RelayCommand]
private async Task Restart()
{
await Stop();
await Launch();
}
[RelayCommand]
private async Task ShowLaunchOptions()
{
var basePackage = packageFactory.FindPackageByName(Package?.PackageName);
if (basePackage == null)
{
logger.LogWarning("Package {Name} not found", Package?.PackageName);
return;
}
var viewModel = vmFactory.Get<LaunchOptionsViewModel>();
viewModel.Cards = LaunchOptionCard
.FromDefinitions(basePackage.LaunchOptions, Package?.LaunchArgs ?? [])
.ToImmutableArray();
logger.LogDebug("Launching config dialog with cards: {CardsCount}", viewModel.Cards.Count);
var dialog = new BetterContentDialog
{
ContentVerticalScrollBarVisibility = ScrollBarVisibility.Disabled,
IsPrimaryButtonEnabled = true,
PrimaryButtonText = Resources.Action_Save,
CloseButtonText = Resources.Action_Cancel,
FullSizeDesired = true,
DefaultButton = ContentDialogButton.Primary,
ContentMargin = new Thickness(32, 16),
Padding = new Thickness(0, 16),
Content = new LaunchOptionsDialog { DataContext = viewModel, }
};
var result = await dialog.ShowAsync();
if (result == ContentDialogResult.Primary && Package != null)
{
// Save config
var args = viewModel.AsLaunchArgs();
settingsManager.SaveLaunchArgs(Package.Id, args);
}
}
private async Task<bool> HasUpdate()

11
StabilityMatrix.Avalonia/ViewModels/RunningPackageViewModel.cs

@ -39,6 +39,9 @@ public partial class RunningPackageViewModel : PageViewModelBase, IDisposable, I
[ObservableProperty]
private bool isRunning = true;
[ObservableProperty]
private string consoleInput = string.Empty;
/// <inheritdoc/>
public RunningPackageViewModel(
ISettingsManager settingsManager,
@ -118,18 +121,20 @@ public partial class RunningPackageViewModel : PageViewModelBase, IDisposable, I
}
[RelayCommand]
private async Task SendToConsole(string input)
private async Task SendToConsole()
{
Console.PostLine(input);
Console.PostLine(ConsoleInput);
if (RunningPackage?.BasePackage is BaseGitPackage gitPackage)
{
var venv = gitPackage.VenvRunner;
var process = venv?.Process;
if (process is not null)
{
await process.StandardInput.WriteLineAsync(input);
await process.StandardInput.WriteLineAsync(ConsoleInput);
}
}
ConsoleInput = string.Empty;
}
public void Dispose()

8
StabilityMatrix.Avalonia/Views/ConsoleOutputPage.axaml

@ -73,14 +73,14 @@
WordWrap="True" />
<Grid Grid.Row="2" ColumnDefinitions="*, Auto"
Margin="8,4,8,8">
<TextBox Grid.Column="0" Name="ManualInputBox"
Margin="16,4,16,16">
<TextBox Grid.Column="0" Text="{Binding ConsoleInput, Mode=TwoWay}"
Margin="0,0,8,0"/>
<Button Grid.Column="1"
Classes="accent"
IsDefault="True"
Content="{x:Static lang:Resources.Action_Send}"
Command="{Binding SendToConsoleCommand}"
CommandParameter="{Binding #ManualInputBox.Text}"/>
Command="{Binding SendToConsoleCommand}"/>
</Grid>
</Grid>
</controls:UserControlBase>

276
StabilityMatrix.Avalonia/Views/PackageManager/PackageInstallBrowserView.axaml

@ -40,151 +40,151 @@
CornerRadius="4"
Source="{Binding PreviewImageUri}" />
<StackPanel Grid.Column="1" Orientation="Vertical">
<TextBlock Text="{Binding DisplayName}"
FontWeight="Light"
Margin="16,0,0,0"
FontSize="20" />
<TextBlock Text="{Binding ByAuthor}"
FontWeight="Light"
Margin="16,0,0,0"
FontSize="13" />
<TextBlock Text="{Binding DisplayName}"
FontWeight="Light"
Margin="16,0,0,0"
FontSize="20" />
<TextBlock Text="{Binding ByAuthor}"
FontWeight="Light"
Margin="16,0,0,0"
FontSize="13" />
<TextBlock TextWrapping="Wrap"
Text="{Binding Blurb}"
FontWeight="Light"
Margin="16,8,0,8"
FontSize="16" />
<TextBlock TextWrapping="Wrap"
Text="{Binding Disclaimer}"
IsVisible="{Binding Disclaimer, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Foreground="OrangeRed"
FontWeight="Light"
Margin="16,-4,0,4"
FontSize="14" />
<TextBlock TextWrapping="Wrap"
Text="{Binding Blurb}"
FontWeight="Light"
Margin="16,8,0,8"
FontSize="16" />
<TextBlock TextWrapping="Wrap"
Text="{Binding Disclaimer}"
IsVisible="{Binding Disclaimer, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
Foreground="OrangeRed"
FontWeight="Light"
Margin="16,-4,0,4"
FontSize="14" />
<ItemsRepeater Margin="16, 8, 0, 0"
ItemsSource="{Binding AvailableTorchVersions}">
<ItemsRepeater.Layout>
<StackLayout Orientation="Horizontal" />
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="{x:Type models:TorchVersion}">
<controls:Card
Tag="{Binding }"
HorizontalAlignment="Left"
Padding="4"
Margin="0,0,8,0"
VerticalAlignment="Top">
<ItemsRepeater Margin="16, 8, 0, 0"
ItemsSource="{Binding AvailableTorchVersions}">
<ItemsRepeater.Layout>
<StackLayout Orientation="Horizontal" />
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="{x:Type models:TorchVersion}">
<controls:Card
Tag="{Binding }"
HorizontalAlignment="Left"
Padding="4"
Margin="0,0,8,0"
VerticalAlignment="Top">
<controls:Card.Styles>
<Style Selector="controls|Card[Tag=Cuda]">
<Setter Property="Background"
Value="{DynamicResource ThemeGreenColorTransparent}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeGreenColorTransparent}" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
<controls:Card.Styles>
<Style Selector="controls|Card[Tag=Cuda]">
<Setter Property="Background"
Value="{DynamicResource ThemeGreenColorTransparent}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeGreenColorTransparent}" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="NVIDIA"
TextAlignment="Center"
VerticalAlignment="Center" />
</Template>
</Setter>
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="NVIDIA"
TextAlignment="Center"
VerticalAlignment="Center" />
</Template>
</Setter>
</Style>
<Style Selector="controls|Card[Tag=Rocm]">
<Setter Property="Background"
Value="{DynamicResource ThemeDarkRedColor}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeDarkRedColor}" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
<Style Selector="controls|Card[Tag=Rocm]">
<Setter Property="Background"
Value="{DynamicResource ThemeDarkRedColor}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeDarkRedColor}" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="AMD (Linux)"
TextAlignment="Center"
VerticalAlignment="Center"
ToolTip.Tip="For AMD GPUs that support ROCm on Linux" />
</Template>
</Setter>
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="AMD (Linux)"
TextAlignment="Center"
VerticalAlignment="Center"
ToolTip.Tip="For AMD GPUs that support ROCm on Linux" />
</Template>
</Setter>
</Style>
<Style Selector="controls|Card[Tag=DirectMl]">
<Setter Property="Background"
Value="{DynamicResource ThemeDarkBlueColor}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeDarkBlueColor}" />
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="DirectML"
TextAlignment="Center"
VerticalAlignment="Center"
ToolTip.Tip="For any DirectX compatible GPU on Windows" />
</Template>
</Setter>
</Style>
<Style Selector="controls|Card[Tag=Mps]">
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="White" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
<Style Selector="controls|Card[Tag=DirectMl]">
<Setter Property="Background"
Value="{DynamicResource ThemeDarkBlueColor}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeDarkBlueColor}" />
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="DirectML"
TextAlignment="Center"
VerticalAlignment="Center"
ToolTip.Tip="For any DirectX compatible GPU on Windows" />
</Template>
</Setter>
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="macOS"
TextAlignment="Center"
Foreground="Black"
VerticalAlignment="Center" />
</Template>
</Setter>
</Style>
<Style Selector="controls|Card[Tag=Cpu]">
<Setter Property="Background"
Value="{DynamicResource ThemeBlueGreyColor}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeBlueGreyColor}" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
<Style Selector="controls|Card[Tag=Mps]">
<Setter Property="Background" Value="White" />
<Setter Property="BorderBrush" Value="White" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="macOS"
TextAlignment="Center"
Foreground="Black"
VerticalAlignment="Center" />
</Template>
</Setter>
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="CPU"
TextAlignment="Center"
VerticalAlignment="Center" />
</Template>
</Setter>
</Style>
</controls:Card.Styles>
</controls:Card>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
<Style Selector="controls|Card[Tag=Cpu]">
<Setter Property="Background"
Value="{DynamicResource ThemeBlueGreyColor}" />
<Setter Property="BorderBrush"
Value="{DynamicResource ThemeBlueGreyColor}" />
<Style
Selector="^ /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground"
Value="{DynamicResource ButtonForeground}" />
</Style>
<Setter Property="Content">
<Template>
<TextBlock
FontWeight="Medium"
HorizontalAlignment="Center"
Text="CPU"
TextAlignment="Center"
VerticalAlignment="Center" />
</Template>
</Setter>
</Style>
</controls:Card.Styles>
</controls:Card>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</StackPanel>

607
StabilityMatrix.Avalonia/Views/PackageManagerPage.axaml

@ -12,12 +12,13 @@
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:converters="clr-namespace:StabilityMatrix.Avalonia.Converters"
xmlns:avalonia="clr-namespace:SpacedGridControl.Avalonia;assembly=SpacedGridControl.Avalonia"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
xmlns:markupExtensions="clr-namespace:StabilityMatrix.Avalonia.MarkupExtensions"
mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="450"
x:DataType="viewModels:PackageManagerViewModel"
x:CompileBindings="True"
d:DataContext="{x:Static designData:DesignData.PackageManagerViewModel}"
x:Class="StabilityMatrix.Avalonia.Views.PackageManagerPage">
<controls:UserControlBase.Resources>
<converters:BooleanChoiceMultiConverter x:Key="BoolChoiceMultiConverter" />
</controls:UserControlBase.Resources>
@ -32,216 +33,34 @@
<ItemsRepeater.ItemTemplate>
<DataTemplate DataType="{x:Type packageManager:PackageCardViewModel}">
<controls:Card Padding="8"
MinWidth="400"
CornerRadius="8">
<controls:Card.Background>
<MultiBinding Converter="{StaticResource BoolChoiceMultiConverter}">
<Binding Path="IsRunning" />
<DynamicResource ResourceKey="ThemeDarkDarkGreenColorBrush"/>
<DynamicResource ResourceKey="ButtonBackground"/>
<DynamicResource ResourceKey="ThemeDarkDarkGreenColorBrush" />
<DynamicResource ResourceKey="ButtonBackground" />
</MultiBinding>
</controls:Card.Background>
<Grid RowDefinitions="Auto, Auto, Auto, Auto"
ColumnDefinitions="*,Auto">
<TextBlock Grid.Row="0"
Grid.Column="0"
ToolTip.Tip="{Binding Package.DisplayName, FallbackValue=''}"
Text="{Binding Package.DisplayName, FallbackValue=''}"
TextTrimming="WordEllipsis"
TextAlignment="Left" />
<Button
Grid.Row="0"
Grid.Column="1"
HorizontalContentAlignment="Right"
HorizontalAlignment="Right"
VerticalContentAlignment="Top"
VerticalAlignment="Top"
Padding="4,1"
Margin="4,0,0,0"
Classes="transparent"
Width="24"
BorderThickness="0">
<ui:SymbolIcon FontSize="18" Symbol="MoreVertical" />
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft">
<MenuItem Header="{x:Static lang:Resources.Action_CheckForUpdates}"
IsVisible="{Binding !IsUnknownPackage}"
Command="{Binding OnLoadedAsync}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Refresh" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
Header="{OnPlatform Default={x:Static lang:Resources.Action_OpenInExplorer}, macOS={x:Static lang:Resources.Action_OpenInFinder}}"
Command="{Binding OpenFolder}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="OpenFolder" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
Header="{x:Static lang:Resources.Action_OpenGithub}"
IsVisible="{Binding !IsUnknownPackage}"
Command="{Binding OpenOnGitHubCommand}">
<MenuItem.Icon>
<icons:Icon
Value="fa-brands fa-github" />
</MenuItem.Icon>
</MenuItem>
<Separator/>
<MenuItem
Header="{x:Static lang:Resources.Label_PythonPackages}"
IsVisible="{Binding !IsUnknownPackage}"
Command="{Binding OpenPythonPackagesDialogCommand}">
<MenuItem.Icon>
<icons:Icon
Value="fa-brands fa-python" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
Header="Extensions"
IsVisible="{Binding CanUseExtensions}"
Command="{Binding OpenExtensionsDialogCommand}">
<MenuItem.Icon>
<icons:Icon
Value="fa-solid fa-puzzle-piece" />
</MenuItem.Icon>
</MenuItem>
<Separator IsVisible="{Binding CanUseSharedOutput}" />
<MenuItem Header="{x:Static lang:Resources.Label_SharedModelStrategyShort}"
IsVisible="{Binding !IsUnknownPackage}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="FolderLink" />
</MenuItem.Icon>
<!-- ReSharper disable Xaml.RedundantResource -->
<MenuItem Header="Symlink"
Command="{Binding ToggleSharedModelSymlink}"
IsVisible="{Binding CanUseSymlinkMethod}">
<MenuItem.Icon>
<CheckBox IsChecked="{Binding IsSharedModelSymlink}"
Margin="8,0,0,0"
Padding="0"
Width="28" Height="28">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Config"
Command="{Binding ToggleSharedModelConfig}"
IsVisible="{Binding CanUseConfigMethod}">
<MenuItem.Icon>
<CheckBox Margin="8,0,0,0"
Padding="0"
Width="28" Height="28"
IsChecked="{Binding IsSharedModelConfig}">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="None"
Command="{Binding ToggleSharedModelNone}">
<MenuItem.Icon>
<CheckBox IsChecked="{Binding IsSharedModelDisabled}"
Margin="8,0,0,0"
Padding="0"
Width="28" Height="28">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<!-- ReSharper enable Xaml.RedundantResource -->
</MenuItem>
<MenuItem
Header="{x:Static lang:Resources.Label_UseSharedOutputFolder}"
Command="{Binding ToggleSharedOutput}"
IsVisible="{Binding CanUseSharedOutput}">
<MenuItem.Icon>
<CheckBox Margin="8,0,0,0"
Padding="0"
Width="28" Height="28"
IsChecked="{Binding UseSharedOutput}">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="{x:Static lang:Resources.Action_Uninstall}"
Command="{Binding Uninstall}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Delete" />
</MenuItem.Icon>
</MenuItem>
</MenuFlyout>
</Button.Flyout>
</Button>
<TextBlock Grid.Row="1"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="2,0,0,0"
VerticalAlignment="Center"
Text="{Binding InstalledVersion}" />
<Border Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0,8"
Background="#AA000000"
IsVisible="{Binding IsRunning}"
CornerRadius="4"
ZIndex="1">
<Button Classes="danger"
FontSize="16"
MinWidth="100"
MinHeight="40"
Command="{Binding StopCommand}"
HorizontalAlignment="Center"
HorizontalContentAlignment="Center">
<StackPanel Orientation="Horizontal">
<icons:Icon Value="fa-solid fa-stop"
FontSize="20"
Margin="0,0,8,0"/>
<TextBlock Text="{x:Static lang:Resources.Action_Stop}"/>
</StackPanel>
</Button>
</Border>
<!-- Normal packages shows image -->
<Grid ColumnDefinitions="Auto, *">
<controls:BetterAdvancedImage
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0,8,0,8"
Height="180"
Width="225"
CornerRadius="4"
Height="150"
Width="150"
Margin="4, 8"
CornerRadius="8"
HorizontalAlignment="Center"
VerticalContentAlignment="Top"
HorizontalContentAlignment="Center"
Source="{Binding CardImageSource}"
IsVisible="{Binding !IsUnknownPackage}"
Stretch="UniformToFill" />
<!-- Unknown packages panel -->
<Border
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
Margin="0,8,0,8"
Height="180"
Width="225"
CornerRadius="4"
Height="150"
Width="150"
Margin="4, 8"
CornerRadius="8"
HorizontalAlignment="Center"
IsVisible="{Binding IsUnknownPackage}"
Background="#202020">
@ -252,114 +71,328 @@
TextWrapping="Wrap"
Text="{x:Static lang:Resources.Label_UnknownPackage}" />
</Border>
<Grid Grid.Column="1" RowDefinitions="Auto, Auto, Auto, *"
ColumnDefinitions="Auto, *">
<TextBlock Grid.Column="0"
Grid.Row="0"
Text="{Binding Package.DisplayName}"
Margin="8,0,8,0"
FontWeight="SemiBold"
MaxWidth="200"
TextWrapping="NoWrap"
TextTrimming="CharacterEllipsis"
ToolTip.Tip="{Binding Package.DisplayName}"
FontSize="16" />
<TextBlock Grid.Column="0"
Grid.Row="1"
FontSize="13"
Foreground="{DynamicResource TextControlPlaceholderForeground}"
Margin="8,0,8,0"
VerticalAlignment="Center"
Text="{Binding InstalledVersion}" />
<Button
Grid.Row="0"
Grid.Column="1"
HorizontalContentAlignment="Right"
HorizontalAlignment="Right"
VerticalContentAlignment="Top"
VerticalAlignment="Top"
Padding="4"
Margin="4,0,0,0"
Classes="transparent"
Width="24"
BorderThickness="0">
<ui:SymbolIcon FontSize="18" Symbol="MoreVertical" />
<Button.Flyout>
<MenuFlyout Placement="BottomEdgeAlignedLeft">
<MenuItem Header="{x:Static lang:Resources.Action_CheckForUpdates}"
IsVisible="{Binding !IsUnknownPackage}"
Command="{Binding OnLoadedAsync}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Refresh" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
Header="{OnPlatform Default={x:Static lang:Resources.Action_OpenInExplorer}, macOS={x:Static lang:Resources.Action_OpenInFinder}}"
Command="{Binding OpenFolder}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="OpenFolder" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
Header="{x:Static lang:Resources.Action_OpenGithub}"
IsVisible="{Binding !IsUnknownPackage}"
Command="{Binding OpenOnGitHubCommand}">
<MenuItem.Icon>
<icons:Icon
Value="fa-brands fa-github" />
</MenuItem.Icon>
</MenuItem>
<Separator />
<Grid
Grid.Row="3"
Grid.Column="0"
Grid.ColumnSpan="2"
IsVisible="{Binding !IsUnknownPackage}"
ColumnDefinitions="*,Auto">
<!-- Launch and update buttons -->
<Button Grid.Column="0" Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
Command="{Binding Launch}">
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="!IsRunning" />
<Binding Path="!IsUnknownPackage" />
</MultiBinding>
</Button.IsVisible>
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<icons:Icon Value="fa-solid fa-rocket"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{x:Static lang:Resources.Action_Launch}" />
</StackPanel>
</Button>
<Button Grid.Column="1" Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
Command="{Binding Update}">
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="IsUpdateAvailable" />
<Binding Path="!IsRunning" />
</MultiBinding>
</Button.IsVisible>
<StackPanel Orientation="Horizontal"
Margin="10,2">
<icons:Icon Value="fa-solid fa-download"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{x:Static lang:Resources.Action_Update}" />
</StackPanel>
</Button>
<Button Grid.Column="0" Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
IsVisible="{Binding IsRunning}"
Command="{Binding NavToConsole}">
<StackPanel Orientation="Horizontal"
Margin="0,2,0,2">
<icons:Icon Value="fa-solid fa-terminal"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="Console"/>
</StackPanel>
</Button>
<Button Grid.Column="1" Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
IsVisible="{Binding ShowWebUiButton}"
Command="{Binding LaunchWebUi}">
<StackPanel Orientation="Horizontal" Margin="8,2,8,2">
<icons:Icon Value="fa-solid fa-up-right-from-square"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="Web UI" />
</StackPanel>
</Button>
</Grid>
<MenuItem
Header="{x:Static lang:Resources.Label_PythonPackages}"
IsVisible="{Binding !IsUnknownPackage}"
Command="{Binding OpenPythonPackagesDialogCommand}">
<MenuItem.Icon>
<icons:Icon
Value="fa-brands fa-python" />
</MenuItem.Icon>
</MenuItem>
<MenuItem
Header="Extensions"
IsVisible="{Binding CanUseExtensions}"
Command="{Binding OpenExtensionsDialogCommand}">
<MenuItem.Icon>
<icons:Icon
Value="fa-solid fa-puzzle-piece" />
</MenuItem.Icon>
</MenuItem>
<!-- Import button (for unknown) -->
<Button Grid.Row="3" Grid.Column="0" Classes="transparent-info"
Grid.ColumnSpan="2"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
Command="{Binding Import}"
IsVisible="{Binding IsUnknownPackage}">
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<icons:Icon Value="fa-solid fa-circle-question"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{x:Static lang:Resources.Action_Import}" />
</StackPanel>
</Button>
<Separator IsVisible="{Binding CanUseSharedOutput}" />
<MenuItem
Header="{x:Static lang:Resources.Label_SharedModelStrategyShort}"
IsVisible="{Binding !IsUnknownPackage}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="FolderLink" />
</MenuItem.Icon>
<!-- ReSharper disable Xaml.RedundantResource -->
<MenuItem Header="Symlink"
Command="{Binding ToggleSharedModelSymlink}"
IsVisible="{Binding CanUseSymlinkMethod}">
<MenuItem.Icon>
<CheckBox IsChecked="{Binding IsSharedModelSymlink}"
Margin="8,0,0,0"
Padding="0"
Width="28" Height="28">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5" />
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Config"
Command="{Binding ToggleSharedModelConfig}"
IsVisible="{Binding CanUseConfigMethod}">
<MenuItem.Icon>
<CheckBox Margin="8,0,0,0"
Padding="0"
Width="28" Height="28"
IsChecked="{Binding IsSharedModelConfig}">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5" />
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="None"
Command="{Binding ToggleSharedModelNone}">
<MenuItem.Icon>
<CheckBox IsChecked="{Binding IsSharedModelDisabled}"
Margin="8,0,0,0"
Padding="0"
Width="28" Height="28">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5" />
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<!-- ReSharper enable Xaml.RedundantResource -->
</MenuItem>
<MenuItem
Header="{x:Static lang:Resources.Label_UseSharedOutputFolder}"
Command="{Binding ToggleSharedOutput}"
IsVisible="{Binding CanUseSharedOutput}">
<MenuItem.Icon>
<CheckBox Margin="8,0,0,0"
Padding="0"
Width="28" Height="28"
IsChecked="{Binding UseSharedOutput}">
<CheckBox.RenderTransform>
<ScaleTransform ScaleX="1.5" ScaleY="1.5" />
</CheckBox.RenderTransform>
</CheckBox>
</MenuItem.Icon>
</MenuItem>
<Separator />
<MenuItem Header="{x:Static lang:Resources.Action_Uninstall}"
Command="{Binding Uninstall}">
<MenuItem.Icon>
<ui:SymbolIcon Symbol="Delete" />
</MenuItem.Icon>
</MenuItem>
</MenuFlyout>
</Button.Flyout>
</Button>
<StackPanel Grid.Row="2"
Grid.Column="0"
Margin="0,4,0,0"
Orientation="Horizontal">
<Button Classes="transparent-full"
Margin="4,4,0,0"
Padding="4"
ToolTip.Tip="{x:Static lang:Resources.Action_CheckForUpdates}"
Command="{Binding OnLoadedAsync}"
>
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="!IsUnknownPackage" />
<Binding Path="!IsUpdateAvailable" />
</MultiBinding>
</Button.IsVisible>
<ui:SymbolIcon Symbol="Refresh"
FontSize="20"/>
</Button>
<Button Classes="transparent-full"
Margin="4,4,0,0"
Padding="4"
IsEnabled="{Binding !IsRunning}"
ToolTip.Tip="{x:Static lang:Resources.Label_UpdateAvailable}"
markupExtensions:ShowDisabledTooltipExtension.ShowOnDisabled="True"
Command="{Binding Update}">
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="!IsUnknownPackage" />
<Binding Path="IsUpdateAvailable" />
</MultiBinding>
</Button.IsVisible>
<ui:SymbolIcon Symbol="CloudDownload"
IsEnabled="{Binding !IsRunning}"
FontSize="24">
<ui:SymbolIcon.Styles>
<Style Selector="ui|SymbolIcon">
<Setter Property="Foreground" Value="Lime" />
</Style>
<Style Selector="ui|SymbolIcon:disabled">
<Setter Property="Foreground" Value="Gray" />
</Style>
</ui:SymbolIcon.Styles>
</ui:SymbolIcon>
</Button>
<Button Classes="transparent-full"
Margin="4,4,0,0"
Padding="4"
ToolTip.Tip="Launch Options"
IsVisible="{Binding !IsUnknownPackage}"
Command="{Binding ShowLaunchOptionsCommand}">
<ui:SymbolIcon Symbol="SettingsFilled"
FontSize="20"/>
</Button>
</StackPanel>
<UniformGrid Grid.Column="0"
Grid.ColumnSpan="2"
Grid.Row="3"
VerticalAlignment="Bottom"
Margin="8,8,8,0">
<Button Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
Command="{Binding Launch}">
<Button.IsVisible>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="!IsRunning" />
<Binding Path="!IsUnknownPackage" />
</MultiBinding>
</Button.IsVisible>
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<icons:Icon Value="fa-solid fa-rocket"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{x:Static lang:Resources.Action_Launch}" />
</StackPanel>
</Button>
<Button Classes="borderless-danger"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
IsVisible="{Binding IsRunning}"
Command="{Binding StopCommand}">
<StackPanel Orientation="Horizontal"
Margin="0,2">
<icons:Icon Value="fa-solid fa-stop"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{x:Static lang:Resources.Action_Stop}" />
</StackPanel>
</Button>
<Button Classes="borderless-info"
BorderBrush="Transparent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
IsVisible="{Binding IsRunning}"
Command="{Binding RestartCommand}">
<StackPanel Orientation="Horizontal"
Margin="0,2">
<icons:Icon Value="fa-solid fa-arrow-rotate-left"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{x:Static lang:Resources.Action_Restart}" />
</StackPanel>
</Button>
<Button Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
IsVisible="{Binding IsRunning}"
Command="{Binding NavToConsole}">
<StackPanel Orientation="Horizontal"
Margin="0,2,0,2">
<icons:Icon Value="fa-solid fa-terminal"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="Console" />
</StackPanel>
</Button>
<Button Classes="accent"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
IsVisible="{Binding ShowWebUiButton}"
Command="{Binding LaunchWebUi}">
<StackPanel Orientation="Horizontal" Margin="8,2,8,2">
<icons:Icon Value="fa-solid fa-up-right-from-square"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="Web UI" />
</StackPanel>
</Button>
<Button Classes="transparent-info"
VerticalAlignment="Bottom"
HorizontalAlignment="Stretch"
Command="{Binding Import}"
IsVisible="{Binding IsUnknownPackage}">
<StackPanel Orientation="Horizontal" Margin="0,2,0,2">
<icons:Icon Value="fa-solid fa-circle-question"
Margin="0,0,8,0"
FontSize="14" />
<TextBlock Text="{x:Static lang:Resources.Action_Import}" />
</StackPanel>
</Button>
</UniformGrid>
</Grid>
<!-- Update overlay -->
<Border
Grid.Row="0" Grid.RowSpan="4"
Grid.Column="0"
Grid.ColumnSpan="2"
Background="#DD000000"
CornerRadius="4"
CornerRadius="8"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
IsVisible="{Binding IsProgressVisible}" />
<Grid Grid.Row="0" Grid.RowSpan="4"
Grid.Column="0"
IsVisible="{Binding IsProgressVisible}"/>
<Grid Grid.Column="0"
Grid.ColumnSpan="2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
RowDefinitions="Auto, *"
IsVisible="{Binding IsProgressVisible}">
IsVisible="{Binding IsProgressVisible}"
RowDefinitions="Auto, *">
<controls:ProgressRing
HorizontalAlignment="Center"
IsIndeterminate="{Binding IsIndeterminate}"
Width="150"
Height="150"
Width="120"
Height="120"
StartAngle="90"
EndAngle="450"
Value="{Binding Value}"

3
StabilityMatrix.Core/Models/DownloadPackageVersionOptions.cs

@ -7,4 +7,7 @@ public class DownloadPackageVersionOptions
public string? VersionTag { get; set; }
public bool IsLatest { get; set; }
public bool IsPrerelease { get; set; }
public string GetReadableVersionString() =>
!string.IsNullOrWhiteSpace(VersionTag) ? VersionTag : $"{BranchName}@{CommitHash?[..7]}";
}

Loading…
Cancel
Save