Browse Source

Moved more xaml strings to Resources for localization & fix connected model imports not adding to installedmodels list

pull/117/head
JT 1 year ago
parent
commit
c1f924f879
  1. 4
      CHANGELOG.md
  2. 531
      StabilityMatrix.Avalonia/Languages/Resources.Designer.cs
  3. 33
      StabilityMatrix.Avalonia/Languages/Resources.ja-JP.resx
  4. 177
      StabilityMatrix.Avalonia/Languages/Resources.resx
  5. 31
      StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml
  6. 34
      StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml
  7. 5
      StabilityMatrix.Avalonia/Views/Dialogs/ExceptionDialog.axaml
  8. 23
      StabilityMatrix.Avalonia/Views/Dialogs/InstallerDialog.axaml
  9. 5
      StabilityMatrix.Avalonia/Views/Dialogs/OneClickInstallDialog.axaml
  10. 5
      StabilityMatrix.Avalonia/Views/Dialogs/PackageModificationDialog.axaml
  11. 13
      StabilityMatrix.Avalonia/Views/Dialogs/SelectDataDirectoryDialog.axaml
  12. 11
      StabilityMatrix.Avalonia/Views/Dialogs/SelectModelVersionDialog.axaml
  13. 3
      StabilityMatrix.Avalonia/Views/Dialogs/UpdateDialog.axaml
  14. 11
      StabilityMatrix.Avalonia/Views/FirstLaunchSetupWindow.axaml
  15. 9
      StabilityMatrix.Avalonia/Views/MainWindow.axaml
  16. 169
      StabilityMatrix/Models/CheckpointFolder.cs

4
CHANGELOG.md

@ -16,7 +16,9 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2
### Fixed
- Fixed [#97](https://github.com/LykosAI/StabilityMatrix/issues/97) - Codeformer folder should now get linked correctly
- Fixed [#106](https://github.com/LykosAI/StabilityMatrix/issues/106) - ComfyUI should now install correctly on Windows machines with an AMD GPU using DirectML
- Fixed [#107](https://github.com/LykosAI/StabilityMatrix/issues/107) - Added `--autolaunch` option to SD.Next
- Fixed [#107](https://github.com/LykosAI/StabilityMatrix/issues/107) - Added `--autolaunch` option to SD.Next
- Fixed [#110](https://github.com/LykosAI/StabilityMatrix/issues/110) - Model Browser should properly navigate to the next page of Installed models
- Installed tag on model browser should now show for connected models imported via drag & drop
## v2.3.4
### Fixed

531
StabilityMatrix.Avalonia/Languages/Resources.Designer.cs generated

@ -68,6 +68,42 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Close.
/// </summary>
public static string Action_Close {
get {
return ResourceManager.GetString("Action_Close", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Continue.
/// </summary>
public static string Action_Continue {
get {
return ResourceManager.GetString("Action_Continue", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Delete.
/// </summary>
public static string Action_Delete {
get {
return ResourceManager.GetString("Action_Delete", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Exit Application.
/// </summary>
public static string Action_ExitApplication {
get {
return ResourceManager.GetString("Action_ExitApplication", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import.
/// </summary>
@ -77,6 +113,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Install.
/// </summary>
public static string Action_Install {
get {
return ResourceManager.GetString("Action_Install", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Launch.
/// </summary>
@ -86,6 +131,24 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to New.
/// </summary>
public static string Action_New {
get {
return ResourceManager.GetString("Action_New", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Open on CivitAI.
/// </summary>
public static string Action_OpenOnCivitAi {
get {
return ResourceManager.GetString("Action_OpenOnCivitAi", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Quit.
/// </summary>
@ -113,6 +176,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Rename.
/// </summary>
public static string Action_Rename {
get {
return ResourceManager.GetString("Action_Rename", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Save.
/// </summary>
@ -122,6 +194,60 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Search.
/// </summary>
public static string Action_Search {
get {
return ResourceManager.GetString("Action_Search", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show in Explorer.
/// </summary>
public static string Action_ShowInExplorer {
get {
return ResourceManager.GetString("Action_ShowInExplorer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Advanced Options.
/// </summary>
public static string Label_AdvancedOptions {
get {
return ResourceManager.GetString("Label_AdvancedOptions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to All Versions.
/// </summary>
public static string Label_AllVersions {
get {
return ResourceManager.GetString("Label_AllVersions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Base Model.
/// </summary>
public static string Label_BaseModel {
get {
return ResourceManager.GetString("Label_BaseModel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Become a Patron.
/// </summary>
public static string Label_BecomeAPatron {
get {
return ResourceManager.GetString("Label_BecomeAPatron", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Branches.
/// </summary>
@ -131,6 +257,87 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Categories.
/// </summary>
public static string Label_Categories {
get {
return ResourceManager.GetString("Label_Categories", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Close dialog when finished.
/// </summary>
public static string Label_CloseDialogWhenFinished {
get {
return ResourceManager.GetString("Label_CloseDialogWhenFinished", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Commit.
/// </summary>
public static string Label_Commit {
get {
return ResourceManager.GetString("Label_Commit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Connected Model.
/// </summary>
public static string Label_ConnectedModel {
get {
return ResourceManager.GetString("Label_ConnectedModel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Data Directory.
/// </summary>
public static string Label_DataDirectory {
get {
return ResourceManager.GetString("Label_DataDirectory", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to This is where model checkpoints, LORAs, web UIs, settings, etc. will be installed..
/// </summary>
public static string Label_DataDirectoryExplanation {
get {
return ResourceManager.GetString("Label_DataDirectoryExplanation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Data provided by CivitAI.
/// </summary>
public static string Label_DataProvidedByCivitAi {
get {
return ResourceManager.GetString("Label_DataProvidedByCivitAi", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Display Name.
/// </summary>
public static string Label_DisplayName {
get {
return ResourceManager.GetString("Label_DisplayName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Downloads.
/// </summary>
public static string Label_Downloads {
get {
return ResourceManager.GetString("Label_Downloads", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Drag &amp; Drop checkpoints here to import.
/// </summary>
@ -140,6 +347,96 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Drop file here to import.
/// </summary>
public static string Label_DropFileToImport {
get {
return ResourceManager.GetString("Label_DropFileToImport", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You may encounter errors when using a FAT32 or exFAT drive. Select a different drive for a smoother experience..
/// </summary>
public static string Label_FatWarning {
get {
return ResourceManager.GetString("Label_FatWarning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to First Page.
/// </summary>
public static string Label_FirstPage {
get {
return ResourceManager.GetString("Label_FirstPage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Folder.
/// </summary>
public static string Label_Folder {
get {
return ResourceManager.GetString("Label_Folder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import as Connected.
/// </summary>
public static string Label_ImportAsConnected {
get {
return ResourceManager.GetString("Label_ImportAsConnected", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search for connected metadata on new local imports.
/// </summary>
public static string Label_ImportAsConnectedExplanation {
get {
return ResourceManager.GetString("Label_ImportAsConnectedExplanation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Import Latest -.
/// </summary>
public static string Label_ImportLatest {
get {
return ResourceManager.GetString("Label_ImportLatest", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Indexing....
/// </summary>
public static string Label_Indexing {
get {
return ResourceManager.GetString("Label_Indexing", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An installation with this name already exists..
/// </summary>
public static string Label_InstallationWithThisNameExists {
get {
return ResourceManager.GetString("Label_InstallationWithThisNameExists", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Join Discord Server.
/// </summary>
public static string Label_JoinDiscord {
get {
return ResourceManager.GetString("Label_JoinDiscord", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Language.
/// </summary>
@ -149,6 +446,105 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Last Page.
/// </summary>
public static string Label_LastPage {
get {
return ResourceManager.GetString("Label_LastPage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Let&apos;s get started.
/// </summary>
public static string Label_LetsGetStarted {
get {
return ResourceManager.GetString("Label_LetsGetStarted", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to License Agreement..
/// </summary>
public static string Label_LicenseAgreement {
get {
return ResourceManager.GetString("Label_LicenseAgreement", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Local Model.
/// </summary>
public static string Label_LocalModel {
get {
return ResourceManager.GetString("Label_LocalModel", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Model Description.
/// </summary>
public static string Label_ModelDescription {
get {
return ResourceManager.GetString("Label_ModelDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Search models, #tags, or @users.
/// </summary>
public static string Label_ModelSearchWatermark {
get {
return ResourceManager.GetString("Label_ModelSearchWatermark", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Models Folder.
/// </summary>
public static string Label_ModelsFolder {
get {
return ResourceManager.GetString("Label_ModelsFolder", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Model Type.
/// </summary>
public static string Label_ModelType {
get {
return ResourceManager.GetString("Label_ModelType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A new version of Stability Matrix is available!.
/// </summary>
public static string Label_NewVersionAvailable {
get {
return ResourceManager.GetString("Label_NewVersionAvailable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Next Image.
/// </summary>
public static string Label_NextImage {
get {
return ResourceManager.GetString("Label_NextImage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Next Page.
/// </summary>
public static string Label_NextPage {
get {
return ResourceManager.GetString("Label_NextPage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Package Type.
/// </summary>
@ -158,6 +554,78 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Page.
/// </summary>
public static string Label_Page {
get {
return ResourceManager.GetString("Label_Page", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please choose a different name or select a different install location..
/// </summary>
public static string Label_PleaseChooseDifferentName {
get {
return ResourceManager.GetString("Label_PleaseChooseDifferentName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Portable Mode.
/// </summary>
public static string Label_PortableMode {
get {
return ResourceManager.GetString("Label_PortableMode", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to In Portable Mode, all data and settings will be stored in the same directory as the application. You will be able to move the application with its &apos;Data&apos; folder to a different location or computer..
/// </summary>
public static string Label_PortableModeExplanation {
get {
return ResourceManager.GetString("Label_PortableModeExplanation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Previous Image.
/// </summary>
public static string Label_PreviousImage {
get {
return ResourceManager.GetString("Label_PreviousImage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Previous Page.
/// </summary>
public static string Label_PreviousPage {
get {
return ResourceManager.GetString("Label_PreviousPage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to PyTorch Version.
/// </summary>
public static string Label_PyTorchVersion {
get {
return ResourceManager.GetString("Label_PyTorchVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to I have read and agree to the.
/// </summary>
public static string Label_ReadAndAgree {
get {
return ResourceManager.GetString("Label_ReadAndAgree", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Relaunch Required.
/// </summary>
@ -176,6 +644,60 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Shared Model Folder Strategy.
/// </summary>
public static string Label_SharedModelFolderStrategy {
get {
return ResourceManager.GetString("Label_SharedModelFolderStrategy", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show NSFW Content.
/// </summary>
public static string Label_ShowNsfwContent {
get {
return ResourceManager.GetString("Label_ShowNsfwContent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Skip first-time setup.
/// </summary>
public static string Label_SkipSetup {
get {
return ResourceManager.GetString("Label_SkipSetup", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sort.
/// </summary>
public static string Label_Sort {
get {
return ResourceManager.GetString("Label_Sort", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Period.
/// </summary>
public static string Label_TimePeriod {
get {
return ResourceManager.GetString("Label_TimePeriod", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An unexpected error occurred.
/// </summary>
public static string Label_UnexpectedErrorOccurred {
get {
return ResourceManager.GetString("Label_UnexpectedErrorOccurred", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unknown Package.
/// </summary>
@ -185,6 +707,15 @@ namespace StabilityMatrix.Avalonia.Languages {
}
}
/// <summary>
/// Looks up a localized string similar to Update Available.
/// </summary>
public static string Label_UpdateAvailable {
get {
return ResourceManager.GetString("Label_UpdateAvailable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Version.
/// </summary>

33
StabilityMatrix.Avalonia/Languages/Resources.ja-JP.resx

@ -20,4 +20,37 @@
<data name="Label_Language" xml:space="preserve">
<value>言語</value>
</data>
<data name="Action_ExitApplication" xml:space="preserve">
<value>アプリケーションを終了する</value>
</data>
<data name="Action_Import" xml:space="preserve">
<value>インポート</value>
</data>
<data name="Action_Install" xml:space="preserve">
<value>インストール</value>
</data>
<data name="Action_Launch" xml:space="preserve">
<value>打ち上げる</value>
</data>
<data name="Action_Relaunch" xml:space="preserve">
<value>再起動する</value>
</data>
<data name="Action_Quit" xml:space="preserve">
<value>やめる</value>
</data>
<data name="Action_RelaunchLater" xml:space="preserve">
<value>後で再起動する</value>
</data>
<data name="Label_BecomeAPatron" xml:space="preserve">
<value>パトロンになる</value>
</data>
<data name="Label_Branches" xml:space="preserve">
<value>ブランチ</value>
</data>
<data name="Label_TimePeriod" xml:space="preserve">
<value>期間</value>
</data>
<data name="Label_Sort" xml:space="preserve">
<value>注文</value>
</data>
</root>

177
StabilityMatrix.Avalonia/Languages/Resources.resx

@ -69,4 +69,181 @@
<data name="Label_DragAndDropCheckpointsHereToImport" xml:space="preserve">
<value>Drag &amp; Drop checkpoints here to import</value>
</data>
<data name="Label_UpdateAvailable" xml:space="preserve">
<value>Update Available</value>
</data>
<data name="Label_BecomeAPatron" xml:space="preserve">
<value>Become a Patron</value>
</data>
<data name="Label_JoinDiscord" xml:space="preserve">
<value>Join Discord Server</value>
</data>
<data name="Label_Downloads" xml:space="preserve">
<value>Downloads</value>
</data>
<data name="Action_Install" xml:space="preserve">
<value>Install</value>
</data>
<data name="Label_SkipSetup" xml:space="preserve">
<value>Skip first-time setup</value>
</data>
<data name="Label_UnexpectedErrorOccurred" xml:space="preserve">
<value>An unexpected error occurred</value>
</data>
<data name="Action_ExitApplication" xml:space="preserve">
<value>Exit Application</value>
</data>
<data name="Label_DisplayName" xml:space="preserve">
<value>Display Name</value>
</data>
<data name="Label_InstallationWithThisNameExists" xml:space="preserve">
<value>An installation with this name already exists.</value>
</data>
<data name="Label_PleaseChooseDifferentName" xml:space="preserve">
<value>Please choose a different name or select a different install location.</value>
</data>
<data name="Label_AdvancedOptions" xml:space="preserve">
<value>Advanced Options</value>
</data>
<data name="Label_Commit" xml:space="preserve">
<value>Commit</value>
</data>
<data name="Label_SharedModelFolderStrategy" xml:space="preserve">
<value>Shared Model Folder Strategy</value>
</data>
<data name="Label_PyTorchVersion" xml:space="preserve">
<value>PyTorch Version</value>
</data>
<data name="Label_CloseDialogWhenFinished" xml:space="preserve">
<value>Close dialog when finished</value>
</data>
<data name="Action_Close" xml:space="preserve">
<value>Close</value>
</data>
<data name="Label_DataDirectory" xml:space="preserve">
<value>Data Directory</value>
</data>
<data name="Label_DataDirectoryExplanation" xml:space="preserve">
<value>This is where model checkpoints, LORAs, web UIs, settings, etc. will be installed.</value>
</data>
<data name="Label_FatWarning" xml:space="preserve">
<value>You may encounter errors when using a FAT32 or exFAT drive. Select a different drive for a smoother experience.</value>
</data>
<data name="Label_PortableMode" xml:space="preserve">
<value>Portable Mode</value>
</data>
<data name="Label_PortableModeExplanation" xml:space="preserve">
<value>In Portable Mode, all data and settings will be stored in the same directory as the application. You will be able to move the application with its 'Data' folder to a different location or computer.</value>
</data>
<data name="Action_Continue" xml:space="preserve">
<value>Continue</value>
</data>
<data name="Label_PreviousImage" xml:space="preserve">
<value>Previous Image</value>
</data>
<data name="Label_NextImage" xml:space="preserve">
<value>Next Image</value>
</data>
<data name="Label_ModelDescription" xml:space="preserve">
<value>Model Description</value>
</data>
<data name="Label_NewVersionAvailable" xml:space="preserve">
<value>A new version of Stability Matrix is available!</value>
</data>
<data name="Label_ImportLatest" xml:space="preserve">
<value>Import Latest -</value>
</data>
<data name="Label_AllVersions" xml:space="preserve">
<value>All Versions</value>
</data>
<data name="Label_ModelSearchWatermark" xml:space="preserve">
<value>Search models, #tags, or @users</value>
</data>
<data name="Action_Search" xml:space="preserve">
<value>Search</value>
</data>
<data name="Label_Sort" xml:space="preserve">
<value>Sort</value>
</data>
<data name="Label_TimePeriod" xml:space="preserve">
<value>Period</value>
</data>
<data name="Label_ModelType" xml:space="preserve">
<value>Model Type</value>
</data>
<data name="Label_BaseModel" xml:space="preserve">
<value>Base Model</value>
</data>
<data name="Label_ShowNsfwContent" xml:space="preserve">
<value>Show NSFW Content</value>
</data>
<data name="Label_DataProvidedByCivitAi" xml:space="preserve">
<value>Data provided by CivitAI</value>
</data>
<data name="Label_Page" xml:space="preserve">
<value>Page</value>
</data>
<data name="Label_FirstPage" xml:space="preserve">
<value>First Page</value>
</data>
<data name="Label_PreviousPage" xml:space="preserve">
<value>Previous Page</value>
</data>
<data name="Label_NextPage" xml:space="preserve">
<value>Next Page</value>
</data>
<data name="Label_LastPage" xml:space="preserve">
<value>Last Page</value>
</data>
<data name="Action_Rename" xml:space="preserve">
<value>Rename</value>
</data>
<data name="Action_Delete" xml:space="preserve">
<value>Delete</value>
</data>
<data name="Action_OpenOnCivitAi" xml:space="preserve">
<value>Open on CivitAI</value>
</data>
<data name="Label_ConnectedModel" xml:space="preserve">
<value>Connected Model</value>
</data>
<data name="Label_LocalModel" xml:space="preserve">
<value>Local Model</value>
</data>
<data name="Action_ShowInExplorer" xml:space="preserve">
<value>Show in Explorer</value>
</data>
<data name="Action_New" xml:space="preserve">
<value>New</value>
</data>
<data name="Label_Folder" xml:space="preserve">
<value>Folder</value>
</data>
<data name="Label_DropFileToImport" xml:space="preserve">
<value>Drop file here to import</value>
</data>
<data name="Label_ImportAsConnected" xml:space="preserve">
<value>Import as Connected</value>
</data>
<data name="Label_ImportAsConnectedExplanation" xml:space="preserve">
<value>Search for connected metadata on new local imports</value>
</data>
<data name="Label_Indexing" xml:space="preserve">
<value>Indexing...</value>
</data>
<data name="Label_ModelsFolder" xml:space="preserve">
<value>Models Folder</value>
</data>
<data name="Label_Categories" xml:space="preserve">
<value>Categories</value>
</data>
<data name="Label_LetsGetStarted" xml:space="preserve">
<value>Let's get started</value>
</data>
<data name="Label_ReadAndAgree" xml:space="preserve">
<value>I have read and agree to the</value>
</data>
<data name="Label_LicenseAgreement" xml:space="preserve">
<value>License Agreement.</value>
</data>
</root>

31
StabilityMatrix.Avalonia/Views/CheckpointBrowserPage.axaml

@ -9,6 +9,7 @@
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels.CheckpointManager"
xmlns:checkpointBrowser="clr-namespace:StabilityMatrix.Avalonia.ViewModels.CheckpointBrowser"
xmlns:avalonia="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="700"
x:DataType="viewModels:CheckpointBrowserViewModel"
d:DataContext="{x:Static designData:DesignData.CheckpointBrowserViewModel}"
@ -149,7 +150,7 @@
Margin="0,8,0,0">
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Import Latest -" />
<TextBlock Text="{x:Static lang:Resources.Label_ImportLatest}" />
<TextBlock Margin="4,0,0,0"
Text="{Binding CivitModel.FullFilesSize}" />
</StackPanel>
@ -162,7 +163,7 @@
IsEnabled="{Binding !IsImporting}"
Command="{Binding ShowVersionDialogCommand}"
CommandParameter="{Binding CivitModel}"
Content="All Versions" />
Content="{x:Static lang:Resources.Label_AllVersions}" />
</Grid>
</StackPanel>
</controls:Card>
@ -177,7 +178,7 @@
<TextBox
HorizontalAlignment="Stretch"
Margin="8,0,0,0"
Watermark="Search models, #tags, or @users"
Watermark="{x:Static lang:Resources.Label_ModelSearchWatermark}"
Text="{Binding SearchQuery, Mode=TwoWay}" />
<Button
@ -197,7 +198,7 @@
IsVisible="{Binding SearchModelsCommand.IsRunning}"
MinWidth="16" />
<TextBlock
Text="Search"
Text="{x:Static lang:Resources.Action_Search}"
VerticalAlignment="Center"
IsVisible="{Binding !SearchModelsCommand.IsRunning}" />
</Grid>
@ -205,7 +206,7 @@
</Grid>
<DockPanel>
<StackPanel Margin="4, 8" Orientation="Vertical">
<Label Content="Sort" />
<Label Content="{x:Static lang:Resources.Label_Sort}" />
<ComboBox
ItemsSource="{Binding AllSortModes}"
MinWidth="100"
@ -213,7 +214,7 @@
</StackPanel>
<StackPanel Margin="4, 8" Orientation="Vertical">
<Label Content="Period" />
<Label Content="{x:Static lang:Resources.Label_TimePeriod}" />
<ComboBox
ItemsSource="{Binding AllCivitPeriods}"
MinWidth="100"
@ -221,7 +222,7 @@
</StackPanel>
<StackPanel Margin="4, 8" Orientation="Vertical">
<Label Content="Model Type" />
<Label Content="{x:Static lang:Resources.Label_ModelType}" />
<ComboBox
ItemsSource="{Binding AllModelTypes}"
MinWidth="100"
@ -229,7 +230,7 @@
</StackPanel>
<StackPanel Margin="4, 8" Orientation="Vertical">
<Label Content="Base Model" />
<Label Content="{x:Static lang:Resources.Label_BaseModel}" />
<ComboBox
ItemsSource="{Binding BaseModelOptions}"
MinWidth="100"
@ -238,7 +239,7 @@
<CheckBox
Content="Show NSFW Content"
Content="{x:Static lang:Resources.Label_ShowNsfwContent}"
HorizontalAlignment="Right"
IsChecked="{Binding ShowNsfw, Mode=TwoWay}"
Margin="8,8,8,0" />
@ -258,7 +259,7 @@
<TextBlock
Grid.Row="2"
Margin="16,8"
Text="Data provided by CivitAI"
Text="{x:Static lang:Resources.Label_DataProvidedByCivitAi}"
VerticalAlignment="Bottom" />
<StackPanel
@ -268,7 +269,7 @@
Orientation="Vertical"
IsVisible="{Binding HasSearched}">
<TextBlock Margin="0,0,4,4" TextAlignment="Center">
<Run Text="Page" />
<Run Text="{x:Static lang:Resources.Label_Page}" />
<Run Text="{Binding CurrentPageNumber, FallbackValue=1}" />
<Run Text="/" />
<Run Text="{Binding TotalPages, FallbackValue=5}" />
@ -277,26 +278,26 @@
<Button
Command="{Binding FirstPage}"
IsEnabled="{Binding CanGoToFirstPage}"
ToolTip.Tip="First Page"
ToolTip.Tip="{x:Static lang:Resources.Label_FirstPage}"
Margin="0,0,8,0">
<avalonia:Icon Value="fa-solid fa-backward-fast"/>
</Button>
<Button
Command="{Binding PreviousPage}"
ToolTip.Tip="Previous Page"
ToolTip.Tip="{x:Static lang:Resources.Label_PreviousPage}"
IsEnabled="{Binding CanGoToPreviousPage}"
Margin="0,0,8,0">
<avalonia:Icon Value="fa-solid fa-caret-left"/>
</Button>
<Button Command="{Binding NextPage}"
IsEnabled="{Binding CanGoToNextPage}"
ToolTip.Tip="Next Page"
ToolTip.Tip="{x:Static lang:Resources.Label_NextPage}"
Margin="0,0,8,0">
<avalonia:Icon Value="fa-solid fa-caret-right"/>
</Button>
<Button
Command="{Binding LastPage}"
ToolTip.Tip="Last Page"
ToolTip.Tip="{x:Static lang:Resources.Label_LastPage}"
IsEnabled="{Binding CanGoToLastPage}">
<avalonia:Icon Value="fa-solid fa-forward-fast"/>
</Button>

34
StabilityMatrix.Avalonia/Views/CheckpointsPage.axaml

@ -54,11 +54,11 @@
<controls:Card.ContextFlyout>
<ui:FAMenuFlyout>
<ui:MenuFlyoutItem Command="{Binding RenameCommand}"
Text="Rename" IconSource="Rename" />
Text="{x:Static lang:Resources.Action_Rename}" IconSource="Rename" />
<ui:MenuFlyoutItem Command="{Binding DeleteCommand}"
Text="Delete" IconSource="Delete" />
Text="{x:Static lang:Resources.Action_Delete}" IconSource="Delete" />
<ui:MenuFlyoutItem Command="{Binding OpenOnCivitAiCommand}"
Text="Open on CivitAI" IconSource="Link"
Text="{x:Static lang:Resources.Action_OpenOnCivitAi}" IconSource="Link"
IsVisible="{Binding IsConnectedModel}"/>
</ui:FAMenuFlyout>
</controls:Card.ContextFlyout>
@ -135,7 +135,7 @@
<ui:SymbolIcon
Foreground="LightGreen"
Symbol="CloudSyncComplete"
ToolTip.Tip="Connected Model" />
ToolTip.Tip="{x:Static lang:Resources.Label_ConnectedModel}" />
</Button>
<Button
Background="Transparent"
@ -152,7 +152,7 @@
<ui:SymbolIcon
Foreground="DimGray"
Symbol="CloudOffline"
ToolTip.Tip="Local Model" />
ToolTip.Tip="{x:Static lang:Resources.Label_LocalModel}" />
</Button>
</Grid>
<TextBlock
@ -215,18 +215,18 @@
<!-- Right click menu for a checkpoint folder -->
<Expander.ContextFlyout>
<ui:FAMenuFlyout>
<ui:MenuFlyoutItem Text="Show in Explorer" IconSource="Open"
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Action_ShowInExplorer}" IconSource="Open"
Command="{Binding ShowInExplorerCommand}"
CommandParameter="{Binding DirectoryPath}"/>
<!-- Only allow deletion of non-root folders (Parent is not null) -->
<ui:MenuFlyoutItem Text="Delete" IconSource="Delete"
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Action_Delete}" IconSource="Delete"
IsEnabled="{Binding ParentFolder, Converter={x:Static ObjectConverters.IsNotNull}}"
IsVisible="{Binding ParentFolder, Converter={x:Static ObjectConverters.IsNotNull}}"
Command="{Binding DeleteCommand}"/>
<ui:MenuFlyoutSeparator/>
<ui:MenuFlyoutSubItem Text="New" IconSource="Add">
<ui:MenuFlyoutSubItem Text="{x:Static lang:Resources.Action_New}" IconSource="Add">
<ui:MenuFlyoutSubItem.Items>
<ui:MenuFlyoutItem Text="Folder" IconSource="OpenFolder"
<ui:MenuFlyoutItem Text="{x:Static lang:Resources.Label_Folder}" IconSource="OpenFolder"
Command="{Binding CreateSubFolderCommand}"/>
</ui:MenuFlyoutSubItem.Items>
</ui:MenuFlyoutSubItem>
@ -284,7 +284,7 @@
Effect="{StaticResource TextDropShadowEffect}"
FontSize="24"
HorizontalAlignment="Center"
Text="Drop file here to import"
Text="{x:Static lang:Resources.Label_DropFileToImport}"
VerticalAlignment="Center"
IsVisible="{Binding IsCurrentDragTarget}" />
<StackPanel
@ -358,12 +358,12 @@
<Grid ColumnDefinitions="Auto,*" RowDefinitions="0.2*,*" Margin="4, 0">
<!-- Top settings bar -->
<ToggleSwitch
OffContent="Import as Connected"
OnContent="Import as Connected"
OffContent="{x:Static lang:Resources.Label_ImportAsConnected}"
OnContent="{x:Static lang:Resources.Label_ImportAsConnected}"
Grid.Column="0"
IsChecked="{Binding IsImportAsConnected}"
Margin="24,8"
ToolTip.Tip="Search for connected metadata on new local imports" />
ToolTip.Tip="{x:Static lang:Resources.Label_ImportAsConnectedExplanation}" />
<StackPanel
Grid.Column="1"
Grid.Row="0"
@ -372,7 +372,7 @@
Margin="16,0"
Orientation="Horizontal">
<TextBox Margin="16, 16"
Watermark="Search"
Watermark="{x:Static lang:Resources.Action_Search}"
Height="16"
MinWidth="150"
Text="{Binding SearchFilter, Mode=TwoWay}"/>
@ -382,15 +382,15 @@
BorderThickness="4"
IsIndeterminate="True"
IsVisible="{Binding IsIndexing}"/>
<TextBlock Text="Indexing..." FontSize="11"
<TextBlock Text="{x:Static lang:Resources.Label_Indexing}" FontSize="11"
VerticalAlignment="Center"
IsVisible="{Binding IsIndexing}"/>
<Button
Command="{Binding OpenModelsFolderCommand}">
<TextBlock Text="Models Folder"/>
<TextBlock Text="{x:Static lang:Resources.Label_ModelsFolder}"/>
</Button>
<DropDownButton
Content="Categories"
Content="{x:Static lang:Resources.Label_Categories}"
Margin="8"
VerticalAlignment="Center"
HorizontalAlignment="Right">

5
StabilityMatrix.Avalonia/Views/Dialogs/ExceptionDialog.axaml

@ -5,6 +5,7 @@
xmlns:dialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
d:DataContext="{x:Static mocks:DesignData.ExceptionViewModel}"
x:DataType="dialogs:ExceptionViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="550"
@ -21,7 +22,7 @@
Grid.Row="0"
Theme="{DynamicResource SubtitleTextBlockStyle}"
Margin="16"
Text="An unexpected error occured"
Text="{x:Static lang:Resources.Label_UnexpectedErrorOccurred}"
TextWrapping="Wrap"
VerticalAlignment="Top" />
@ -74,7 +75,7 @@
<Button
Name="ExitButton"
IsDefault="True"
Content="Exit Application"
Content="{x:Static lang:Resources.Action_ExitApplication}"
Click="ExitButton_OnClick"
Grid.Row="2"
HorizontalAlignment="Right"

23
StabilityMatrix.Avalonia/Views/Dialogs/InstallerDialog.axaml

@ -9,6 +9,7 @@
xmlns:packages="clr-namespace:StabilityMatrix.Core.Models.Packages;assembly=StabilityMatrix.Core"
xmlns:models="clr-namespace:StabilityMatrix.Core.Models;assembly=StabilityMatrix.Core"
xmlns:database="clr-namespace:StabilityMatrix.Core.Models.Database;assembly=StabilityMatrix.Core"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
x:DataType="dialogs:InstallerViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="700"
d:DataContext="{x:Static mocks:DesignData.InstallerViewModel}"
@ -49,7 +50,7 @@
<Label Grid.Row="1" Grid.Column="0"
Margin="8,0"
Content="Display Name" />
Content="{x:Static lang:Resources.Label_DisplayName}" />
<TextBox Grid.Row="2" Grid.Column="0"
MinWidth="250"
Margin="8,0"
@ -69,9 +70,9 @@
Foreground="{DynamicResource ThemeRedColor}"
TextAlignment="Left"
TextWrapping="Wrap">
<Run Text="An installation with this name already exists." />
<Run Text="{x:Static lang:Resources.Label_InstallationWithThisNameExists}" />
<LineBreak />
<Run Text="Please choose a different name or select a different Install Location." />
<Run Text="{x:Static lang:Resources.Label_PleaseChooseDifferentName}" />
</TextBlock>
</StackPanel>
@ -98,11 +99,11 @@
Orientation="Horizontal" Margin="0,8,0,8"
IsVisible="{Binding IsReleaseModeAvailable}">
<ToggleButton
Content="Releases"
Content="{x:Static lang:Resources.Label_Releases}"
IsChecked="{Binding IsReleaseMode}"
IsEnabled="{Binding IsReleaseModeAvailable}" />
<ToggleButton
Content="Branches"
Content="{x:Static lang:Resources.Label_Branches}"
IsChecked="{Binding !IsReleaseMode}"
Margin="8,0,0,0" />
</StackPanel>
@ -118,12 +119,12 @@
Margin="8"
IsVisible="{Binding !IsAdvancedMode}">
<Label Content="Advanced Options"
<Label Content="{x:Static lang:Resources.Label_AdvancedOptions}"
FontSize="18"
HorizontalAlignment="Center"
Margin="8,0,8,8" />
<Label Content="Commit"
<Label Content="{x:Static lang:Resources.Label_Commit}"
Margin="0,0,0,4"
IsVisible="{Binding !IsReleaseMode}" />
<ui:FAComboBox
@ -142,7 +143,7 @@
</ui:FAComboBox.ItemTemplate>
</ui:FAComboBox>
<Label Content="Shared Model Folder Strategy"
<Label Content="{x:Static lang:Resources.Label_SharedModelFolderStrategy}"
Margin="0,8,0,4" />
<ui:FAComboBox
ItemsSource="{Binding SelectedPackage.AvailableSharedFolderMethods}"
@ -158,7 +159,7 @@
</ui:FAComboBox.ItemTemplate>
</ui:FAComboBox>
<Label Content="PyTorch Version"
<Label Content="{x:Static lang:Resources.Label_PyTorchVersion}"
IsVisible="{Binding ShowTorchVersionOptions}"
Margin="0,8,0,4" />
<ui:FAComboBox
@ -187,14 +188,14 @@
Margin="0,32,0,0"
HorizontalAlignment="Center">
<Button
Content="Cancel"
Content="{x:Static lang:Resources.Action_Cancel}"
Command="{Binding Cancel}"
FontSize="20"
HorizontalAlignment="Center"
Margin="8,0,4,0"
Padding="16, 8, 16, 8" />
<Button
Content="Install"
Content="{x:Static lang:Resources.Action_Install}"
Command="{Binding InstallCommand}"
FontSize="20"
IsEnabled="{Binding CanInstall}"

5
StabilityMatrix.Avalonia/Views/Dialogs/OneClickInstallDialog.axaml

@ -6,6 +6,7 @@
xmlns:dialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
xmlns:designData="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:packages="clr-namespace:StabilityMatrix.Core.Models.Packages;assembly=StabilityMatrix.Core"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
mc:Ignorable="d" d:DesignWidth="700" d:DesignHeight="700"
x:DataType="dialogs:OneClickInstallViewModel"
d:DataContext="{x:Static designData:DesignData.OneClickInstallViewModel}"
@ -87,7 +88,7 @@
IsVisible="{Binding ShowInstallButton}"
HorizontalAlignment="Center">
<Button
Content="Install"
Content="{x:Static lang:Resources.Action_Install}"
Command="{Binding InstallCommand}"
FontSize="32"
HorizontalAlignment="Center"
@ -95,7 +96,7 @@
Margin="16"
Padding="16, 8, 16, 8" />
<Button Command="{Binding ToggleAdvancedModeCommand}"
Content="Skip first-time setup"
Content="{x:Static lang:Resources.Label_SkipSetup}"
FontSize="16"
HorizontalAlignment="Center"
Padding="16, 8, 16, 8"/>

5
StabilityMatrix.Avalonia/Views/Dialogs/PackageModificationDialog.axaml

@ -6,6 +6,7 @@
xmlns:dialogs="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Dialogs"
xmlns:avaloniaEdit="https://github.com/avaloniaui/avaloniaedit"
xmlns:base="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Base"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="base:ContentDialogProgressViewModelBase"
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.PackageModificationDialog">
@ -46,9 +47,9 @@
<CheckBox Grid.Row="4" IsChecked="{Binding CloseWhenFinished}"
HorizontalAlignment="Center"
Margin="4" Content="Close dialog when finished"/>
Margin="4" Content="{x:Static lang:Resources.Label_CloseDialogWhenFinished}"/>
<Button Grid.Row="5" Content="Close"
<Button Grid.Row="5" Content="{x:Static lang:Resources.Action_Close}"
FontSize="20"
HorizontalAlignment="Center"
Command="{Binding OnCloseButtonClick}"/>

13
StabilityMatrix.Avalonia/Views/Dialogs/SelectDataDirectoryDialog.axaml

@ -6,6 +6,7 @@
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
d:DataContext="{x:Static mocks:DesignData.SelectDataDirectoryViewModel}"
x:DataType="dialogs:SelectDataDirectoryViewModel"
x:CompileBindings="True"
@ -26,7 +27,7 @@
Title="Welcome back! In this update, you can optionally choose a custom location to store all data. If you choose a new location, or opt to use Portable Mode, you'll be able to migrate your existing data on the next page."/>
<Label
Content="Data Directory"
Content="{x:Static lang:Resources.Label_DataDirectory}"
FontSize="13"
Margin="0,16,0,0" />
<Grid ColumnDefinitions="*,Auto">
@ -50,14 +51,14 @@
</Grid>
<TextBlock
Text="This is where the model checkpoints, LORAs, web UIs, settings, etc. will be installed."
Text="{x:Static lang:Resources.Label_DataDirectoryExplanation}"
TextWrapping="Wrap"
Foreground="LightGray"
FontSize="12"
Margin="0,8,0,0" />
<TextBlock
Text="You may encounter errors when using a FAT32 or exFAT drive. Select a different drive for a smoother experience."
Text="{x:Static lang:Resources.Label_FatWarning}"
TextWrapping="Wrap"
Foreground="Yellow"
IsVisible="{Binding ShowFatWarning}"
@ -65,7 +66,7 @@
Margin="0,8,0,0" />
<CheckBox
Content="Portable Mode"
Content="{x:Static lang:Resources.Label_PortableMode}"
IsChecked="{Binding IsPortableMode, Mode=TwoWay}"
Margin="0,32,0,0" />
@ -75,7 +76,7 @@
FontSize="13"
Margin="0,8,0,0"
Padding="16"
Title="In Portable Mode, all data and settings will be stored in the same directory as the application. You will be able to move the application with its 'Data' folder to a different location or computer." />
Title="{x:Static lang:Resources.Label_PortableModeExplanation}" />
</StackPanel>
@ -94,7 +95,7 @@
</StackPanel>
<Button
Content="Continue"
Content="{x:Static lang:Resources.Action_Continue}"
IsDefault="True"
Command="{Binding OnPrimaryButtonClick}"
FontSize="16"

11
StabilityMatrix.Avalonia/Views/Dialogs/SelectModelVersionDialog.axaml

@ -10,6 +10,7 @@
xmlns:fluentAvalonia="clr-namespace:FluentIcons.FluentAvalonia;assembly=FluentIcons.FluentAvalonia"
xmlns:models="clr-namespace:StabilityMatrix.Avalonia.Models"
xmlns:avalonia="clr-namespace:Projektanker.Icons.Avalonia;assembly=Projektanker.Icons.Avalonia"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
d:DataContext="{x:Static designData:DesignData.SelectModelVersionViewModel}"
x:Class="StabilityMatrix.Avalonia.Views.Dialogs.SelectModelVersionDialog">
@ -64,13 +65,13 @@
<Button Command="{Binding PreviousImage}"
Margin="0,0,8,0"
IsEnabled="{Binding CanGoToPreviousImage}"
ToolTip.Tip="Previous Image"
ToolTip.Tip="{x:Static lang:Resources.Label_PreviousImage}"
ToolTip.Placement="Top">
<avalonia:Icon Value="fa-solid fa-caret-left"/>
</Button>
<Button Command="{Binding NextImage}"
IsEnabled="{Binding CanGoToNextImage}"
ToolTip.Tip="Next Image"
ToolTip.Tip="{x:Static lang:Resources.Label_NextImage}"
ToolTip.Placement="Top">
<avalonia:Icon Value="fa-solid fa-caret-right"/>
</Button>
@ -164,7 +165,7 @@
<Expander Grid.Column="0"
Grid.ColumnSpan="3"
Grid.Row="1"
Header="Model Description"
Header="{x:Static lang:Resources.Label_ModelDescription}"
ExpandDirection="Down"
Margin="8, 16">
<ScrollViewer MaxHeight="200">
@ -179,14 +180,14 @@
Margin="0,8,0,0"
HorizontalAlignment="Center">
<Button
Content="Cancel"
Content="{x:Static lang:Resources.Action_Cancel}"
HorizontalAlignment="Center"
Command="{Binding Cancel}"
Margin="8, 0" />
<Button
Margin="8, 0"
Content="Import"
Content="{x:Static lang:Resources.Action_Import}"
Command="{Binding Import}"
IsEnabled="{Binding IsImportEnabled}"
Classes="accent" />

3
StabilityMatrix.Avalonia/Views/Dialogs/UpdateDialog.axaml

@ -7,6 +7,7 @@
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:mdxaml="https://github.com/whistyun/Markdown.Avalonia.Tight"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
d:DataContext="{x:Static mocks:DesignData.UpdateViewModel}"
x:DataType="dialogs:UpdateViewModel"
mc:Ignorable="d" d:DesignWidth="700" d:DesignHeight="550"
@ -20,7 +21,7 @@
</TitleBar>-->
<TextBlock Grid.Row="0"
Text="A new version of Stability Matrix is available!"
Text="{x:Static lang:Resources.Label_NewVersionAvailable}"
HorizontalAlignment="Center"
FontWeight="Thin"
Margin="0,16,0,0"

11
StabilityMatrix.Avalonia/Views/FirstLaunchSetupWindow.axaml

@ -6,6 +6,7 @@
xmlns:vm="clr-namespace:StabilityMatrix.Avalonia.ViewModels"
xmlns:mocks="clr-namespace:StabilityMatrix.Avalonia.DesignData"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
d:DataContext="{x:Static mocks:DesignData.FirstLaunchSetupViewModel}"
x:DataType="vm:FirstLaunchSetupViewModel"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
@ -28,7 +29,7 @@
<Grid Margin="0,16,32,32" RowDefinitions="0.6*,0.4*">
<!-- Texts -->
<StackPanel Margin="32,64,0,0">
<TextBlock FontSize="24" Text="Let's get started" />
<TextBlock FontSize="24" Text="{x:Static lang:Resources.Label_LetsGetStarted}" />
<!-- Loading icon and text -->
<Grid Margin="0,8,0,0" ColumnDefinitions="0.15*,*">
<controls:RefreshBadge
@ -79,7 +80,7 @@
<TextBlock
VerticalAlignment="Top"
FontSize="14"
Text="I have read and agree to the"/>
Text="{x:Static lang:Resources.Label_ReadAndAgree}"/>
<ui:HyperlinkButton
VerticalAlignment="Top"
@ -87,7 +88,7 @@
Margin="1,0,0,0"
Classes="transparent"
NavigateUri="https://lykos.ai/matrix/license"
Content="License Agreement."
Content="{x:Static lang:Resources.Label_LicenseAgreement}"
Grid.Column="1" />
</Grid>
</CheckBox>
@ -102,11 +103,11 @@
<Button
Classes="danger"
Click="QuitButton_OnClick"
Content="Quit" />
Content="{x:Static lang:Resources.Action_Quit}" />
<Button
Classes="info"
Click="ContinueButton_OnClick"
Content="Continue"
Content="{x:Static lang:Resources.Action_Continue}"
IsEnabled="{Binding EulaAccepted, Mode=OneWay}" />
</UniformGrid>

9
StabilityMatrix.Avalonia/Views/MainWindow.axaml

@ -8,6 +8,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:StabilityMatrix.Avalonia.Controls"
xmlns:base="clr-namespace:StabilityMatrix.Avalonia.ViewModels.Base"
xmlns:lang="clr-namespace:StabilityMatrix.Avalonia.Languages"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="550"
d:DataContext="{x:Static mocks:DesignData.MainWindowViewModel}"
x:DataType="vm:MainWindowViewModel"
@ -79,7 +80,7 @@
<StackPanel>
<!-- Update button -->
<ui:NavigationViewItem Name="FooterUpdateItem"
Content="Update Available"
Content="{x:Static lang:Resources.Label_UpdateAvailable}"
IsVisible="{Binding IsUpdateAvailable}"
IsEnabled="{Binding IsUpdateAvailable}"
DataContext="{Binding UpdateViewModel}"
@ -91,7 +92,7 @@
<!-- Patreon -->
<ui:NavigationViewItem Name="PatreonPatreonItem"
Content="Become a Patron"
Content="{x:Static lang:Resources.Label_BecomeAPatron}"
Tapped="PatreonPatreonItem_OnTapped">
<ui:NavigationViewItem.IconSource>
<controls:FASymbolIconSource Symbol="fa-brands fa-patreon"/>
@ -100,7 +101,7 @@
<!-- Discord -->
<ui:NavigationViewItem Name="FooterDiscordItem"
Content="Discord Server"
Content="{x:Static lang:Resources.Label_JoinDiscord}"
Tapped="FooterDiscordItem_OnTapped">
<ui:NavigationViewItem.IconSource>
<controls:FASymbolIconSource Symbol="fa-brands fa-discord"/>
@ -109,7 +110,7 @@
<!-- Download flyout -->
<ui:NavigationViewItem Name="FooterDownloadItem"
Content="Downloads"
Content="{x:Static lang:Resources.Label_Downloads}"
IconSource="{Binding IconSource}"
DataContext="{Binding ProgressManagerViewModel}"
IsVisible="{Binding !!ProgressItems.Count}"

169
StabilityMatrix/Models/CheckpointFolder.cs

@ -26,9 +26,10 @@ public partial class CheckpointFolder : ObservableObject
private readonly ISettingsManager settingsManager;
private readonly IDownloadService downloadService;
private readonly ModelFinder modelFinder;
// ReSharper disable once FieldCanBeMadeReadOnly.Local
private bool useCategoryVisibility;
/// <summary>
/// Absolute path to the folder.
/// </summary>
@ -58,55 +59,59 @@ public partial class CheckpointFolder : ObservableObject
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsDragBlurEnabled))]
private bool isImportInProgress;
public bool IsDragBlurEnabled => IsCurrentDragTarget || IsImportInProgress;
public string TitleWithFilesCount => CheckpointFiles.Any() ? $"{Title} ({CheckpointFiles.Count})" : Title;
public string TitleWithFilesCount =>
CheckpointFiles.Any() ? $"{Title} ({CheckpointFiles.Count})" : Title;
public ProgressViewModel Progress { get; } = new();
public ObservableCollection<CheckpointFolder> SubFolders { get; init; } = new();
public ObservableCollection<CheckpointFile> CheckpointFiles { get; init; } = new();
public RelayCommand OnPreviewDragEnterCommand => new(() => IsCurrentDragTarget = true);
public RelayCommand OnPreviewDragLeaveCommand => new(() => IsCurrentDragTarget = false);
public CheckpointFolder(
IDialogFactory dialogFactory,
IDialogFactory dialogFactory,
ISettingsManager settingsManager,
IDownloadService downloadService,
ModelFinder modelFinder,
bool useCategoryVisibility = true)
bool useCategoryVisibility = true
)
{
this.dialogFactory = dialogFactory;
this.settingsManager = settingsManager;
this.downloadService = downloadService;
this.modelFinder = modelFinder;
this.useCategoryVisibility = useCategoryVisibility;
CheckpointFiles.CollectionChanged += OnCheckpointFilesChanged;
}
/// <summary>
/// When title is set, set the category enabled state from settings.
/// </summary>
// ReSharper disable once UnusedParameterInPartialMethod
partial void OnTitleChanged(string value)
{
if (!useCategoryVisibility) return;
if (!useCategoryVisibility)
return;
// Update folder type
var result = Enum.TryParse(Title, out SharedFolderType type);
FolderType = result ? type : new SharedFolderType();
IsCategoryEnabled = settingsManager.IsSharedFolderCategoryVisible(FolderType);
}
/// <summary>
/// When toggling the category enabled state, save it to settings.
/// </summary>
partial void OnIsCategoryEnabledChanged(bool value)
{
if (!useCategoryVisibility) return;
if (!useCategoryVisibility)
return;
if (value != settingsManager.IsSharedFolderCategoryVisible(FolderType))
{
settingsManager.SetSharedFolderCategoryVisible(FolderType, value);
@ -117,7 +122,8 @@ public partial class CheckpointFolder : ObservableObject
private void OnCheckpointFilesChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(nameof(TitleWithFilesCount));
if (e.NewItems == null) return;
if (e.NewItems == null)
return;
// On new added items, add event handler for deletion
foreach (CheckpointFile item in e.NewItems)
{
@ -155,7 +161,7 @@ public partial class CheckpointFolder : ObservableObject
{
Process.Start("explorer.exe", path);
}
/// <summary>
/// Imports files to the folder. Reports progress to instance properties.
/// </summary>
@ -163,25 +169,30 @@ public partial class CheckpointFolder : ObservableObject
{
Progress.IsIndeterminate = true;
Progress.IsProgressVisible = true;
var copyPaths = files.ToDictionary(k => k, v => Path.Combine(DirectoryPath, Path.GetFileName(v)));
var copyPaths = files.ToDictionary(
k => k,
v => Path.Combine(DirectoryPath, Path.GetFileName(v))
);
var progress = new Progress<ProgressReport>(report =>
{
Progress.IsIndeterminate = false;
Progress.Value = report.Percentage;
// For multiple files, add count
Progress.Text = copyPaths.Count > 1 ? $"Importing {report.Title} ({report.Message})" : $"Importing {report.Title}";
Progress.Text =
copyPaths.Count > 1
? $"Importing {report.Title} ({report.Message})"
: $"Importing {report.Title}";
});
await FileTransfers.CopyFiles(copyPaths, progress);
// Hash files and convert them to connected model if found
if (convertToConnected)
{
var modelFilesCount = copyPaths.Count;
var modelFiles = copyPaths.Values
.Select(path => new FilePath(path));
var modelFiles = copyPaths.Values.Select(path => new FilePath(path));
// Holds tasks for model queries after hash
var modelQueryTasks = new List<Task<bool>>();
@ -191,27 +202,42 @@ public partial class CheckpointFolder : ObservableObject
{
Progress.IsIndeterminate = false;
Progress.Value = report.Percentage;
Progress.Text = modelFilesCount > 1 ?
$"Computing metadata for {modelFile.Info.Name} ({i}/{modelFilesCount})" :
$"Computing metadata for {report.Title}";
Progress.Text =
modelFilesCount > 1
? $"Computing metadata for {modelFile.Info.Name} ({i}/{modelFilesCount})"
: $"Computing metadata for {report.Title}";
});
var hashBlake3 = await FileHash.GetBlake3Async(modelFile, hashProgress);
if (!string.IsNullOrWhiteSpace(hashBlake3))
{
settingsManager.Transaction(s =>
{
s.InstalledModelHashes ??= new HashSet<string>();
s.InstalledModelHashes.Add(hashBlake3);
});
}
// Start a task to query the model in background
var queryTask = Task.Run(async () =>
{
var result = await modelFinder.LocalFindModel(hashBlake3);
result ??= await modelFinder.RemoteFindModel(hashBlake3);
if (result is null) return false; // Not found
if (result is null)
return false; // Not found
var (model, version, file) = result.Value;
// Save connected model info json
var modelFileName = Path.GetFileNameWithoutExtension(modelFile.Info.Name);
var modelInfo = new ConnectedModelInfo(
model, version, file, DateTimeOffset.UtcNow);
model,
version,
file,
DateTimeOffset.UtcNow
);
await modelInfo.SaveJsonToDirectory(DirectoryPath, modelFileName);
// If available, save thumbnail
@ -222,7 +248,8 @@ public partial class CheckpointFolder : ObservableObject
if (imageExt is "jpg" or "jpeg" or "png")
{
var imageDownloadPath = Path.GetFullPath(
Path.Combine(DirectoryPath, $"{modelFileName}.preview.{imageExt}"));
Path.Combine(DirectoryPath, $"{modelFileName}.preview.{imageExt}")
);
await downloadService.DownloadToFileAsync(image.Url, imageDownloadPath);
}
}
@ -231,30 +258,29 @@ public partial class CheckpointFolder : ObservableObject
});
modelQueryTasks.Add(queryTask);
}
// Set progress to indeterminate
Progress.IsIndeterminate = true;
Progress.Text = "Checking connected model information";
// Wait for all model queries to finish
var modelQueryResults = await Task.WhenAll(modelQueryTasks);
var successCount = modelQueryResults.Count(r => r);
var totalCount = modelQueryResults.Length;
var failCount = totalCount - successCount;
await IndexAsync();
Progress.Value = 100;
Progress.Text = successCount switch
{
0 when failCount > 0 =>
"Import complete. No connected data found.",
> 0 when failCount > 0 =>
$"Import complete. Found connected data for {successCount} of {totalCount} models.",
0 when failCount > 0 => "Import complete. No connected data found.",
> 0 when failCount > 0
=> $"Import complete. Found connected data for {successCount} of {totalCount} models.",
_ => $"Import complete. Found connected data for all {totalCount} models."
};
DelayedClearProgress(TimeSpan.FromSeconds(1));
}
else
@ -271,33 +297,46 @@ public partial class CheckpointFolder : ObservableObject
/// </summary>
private void DelayedClearProgress(TimeSpan delay)
{
Task.Delay(delay).ContinueWith(_ =>
{
IsImportInProgress = false;
Progress.IsProgressVisible = false;
Progress.Value = 0;
Progress.Text = string.Empty;
});
Task.Delay(delay)
.ContinueWith(_ =>
{
IsImportInProgress = false;
Progress.IsProgressVisible = false;
Progress.Value = 0;
Progress.Text = string.Empty;
});
}
/// <summary>
/// Gets checkpoint files from folder index
/// </summary>
private async Task<List<CheckpointFile>> GetCheckpointFilesAsync(IProgress<ProgressReport>? progress = default)
private async Task<List<CheckpointFile>> GetCheckpointFilesAsync(
IProgress<ProgressReport>? progress = default
)
{
if (!Directory.Exists(DirectoryPath))
{
return new List<CheckpointFile>();
}
return await (progress switch
{
null => Task.Run(() =>
CheckpointFile.FromDirectoryIndex(dialogFactory, DirectoryPath).ToList()),
_ => Task.Run(() =>
CheckpointFile.FromDirectoryIndex(dialogFactory, DirectoryPath, progress).ToList())
});
return await (
progress switch
{
null
=> Task.Run(
() =>
CheckpointFile.FromDirectoryIndex(dialogFactory, DirectoryPath).ToList()
),
_
=> Task.Run(
() =>
CheckpointFile
.FromDirectoryIndex(dialogFactory, DirectoryPath, progress)
.ToList()
)
}
);
}
/// <summary>
@ -309,19 +348,23 @@ public partial class CheckpointFolder : ObservableObject
foreach (var folder in Directory.GetDirectories(DirectoryPath))
{
// Inherit our folder type
var subFolder = new CheckpointFolder(dialogFactory, settingsManager,
downloadService, modelFinder,
useCategoryVisibility: false)
var subFolder = new CheckpointFolder(
dialogFactory,
settingsManager,
downloadService,
modelFinder,
useCategoryVisibility: false
)
{
Title = Path.GetFileName(folder),
DirectoryPath = folder,
FolderType = FolderType
};
await subFolder.IndexAsync(progress);
SubFolders.Add(subFolder);
}
var checkpointFiles = await GetCheckpointFilesAsync();
CheckpointFiles.Clear();
foreach (var checkpointFile in checkpointFiles)

Loading…
Cancel
Save