Skip to content

Commit

Permalink
Merge pull request LykosAI#359 from ionite34/more-drag-n-drop
Browse files Browse the repository at this point in the history
  • Loading branch information
ionite34 authored Nov 21, 2023
2 parents 7bf16db + da92d45 commit 1cdfbc2
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 105 deletions.
17 changes: 12 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,20 @@ and this project adheres to [Semantic Versioning 2.0](https://semver.org/spec/v2

## v2.7.0-dev.2
### Added
- Outputs Page
- Added Refresh button to update gallery from file system changes
### Changed
- Outputs Page
- Updated button and menu layout
#### General
- Added an X button to all search fields to instantly clear them (Esc key also works)
#### Outputs Page
- Added Refresh button to update gallery from file system changes
#### Checkpoints Page
- Added the ability to drag & drop checkpoints between different folders
## Changed
#### Outputs Page
- Updated button and menu layout
#### Packages Page
- Rearranged Add Package dialog slightly to accommodate longer package list
### Fixed
- Fixed InvalidOperation errors when signing into accounts shortly after signing out, while the previous account update is still running
- Fixed Outputs page reverting back to Shared Output Folder every time the page is reloaded

## v2.7.0-dev.1
### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,11 @@ public void LastPage()
CurrentPageNumber = TotalPages;
}

public void ClearSearchQuery()
{
SearchQuery = string.Empty;
}

partial void OnShowNsfwChanged(bool value)
{
settingsManager.Transaction(s => s.ModelBrowserNsfwEnabled, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public partial class CheckpointFile : ViewModelBase
[ObservableProperty]
private CivitModelType modelType;

[ObservableProperty]
private CheckpointFolder parentFolder;

public string FileName => Path.GetFileName(FilePath);

public ObservableCollection<string> Badges { get; set; } = new();
Expand Down Expand Up @@ -136,6 +139,8 @@ private async Task DeleteAsync()
RemoveFromParentList();
}

public void OnMoved() => RemoveFromParentList();

[RelayCommand]
private async Task RenameAsync()
{
Expand Down Expand Up @@ -218,6 +223,7 @@ private void OpenOnCivitAi()
/// - {filename}.cm-info.json (connected model info)
/// </summary>
public static IEnumerable<CheckpointFile> FromDirectoryIndex(
CheckpointFolder parentFolder,
string directory,
SearchOption searchOption = SearchOption.TopDirectoryOnly
)
Expand Down Expand Up @@ -266,6 +272,8 @@ public static IEnumerable<CheckpointFile> FromDirectoryIndex(
checkpointFile.PreviewImagePath = Assets.NoImage.ToString();
}

checkpointFile.ParentFolder = parentFolder;

yield return checkpointFile;
}
}
Expand Down Expand Up @@ -327,13 +335,14 @@ var file in Directory.EnumerateFiles(
/// Index with progress reporting.
/// </summary>
public static IEnumerable<CheckpointFile> FromDirectoryIndex(
CheckpointFolder parentFolder,
string directory,
IProgress<ProgressReport> progress,
SearchOption searchOption = SearchOption.TopDirectoryOnly
)
{
var current = 0ul;
foreach (var checkpointFile in FromDirectoryIndex(directory, searchOption))
foreach (var checkpointFile in FromDirectoryIndex(parentFolder, directory, searchOption))
{
current++;
progress.Report(new ProgressReport(current, "Indexing", checkpointFile.FileName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using StabilityMatrix.Avalonia.Services;
using StabilityMatrix.Avalonia.ViewModels.Base;
using StabilityMatrix.Core.Attributes;
using StabilityMatrix.Core.Exceptions;
using StabilityMatrix.Core.Extensions;
using StabilityMatrix.Core.Helper;
using StabilityMatrix.Core.Models;
Expand Down Expand Up @@ -212,6 +213,10 @@ public async Task OnDrop(DragEventArgs e)
var paths = files.Select(f => f.Path.LocalPath).ToArray();
await ImportFilesAsync(paths, settingsManager.Settings.IsImportAsConnected);
}
else if (e.Data.Get("Context") is CheckpointFile file)
{
await MoveBetweenFolders(file);
}
}
catch (Exception)
{
Expand Down Expand Up @@ -320,6 +325,71 @@ private async Task CreateSubFolder()
}
}

public async Task MoveBetweenFolders(CheckpointFile sourceFile)
{
var delay = 1.5f;
try
{
Progress.Value = 0;
var sourcePath = new FilePath(sourceFile.FilePath);
var fileNameWithoutExt = Path.GetFileNameWithoutExtension(sourcePath);
var sourceCmInfoPath = Path.Combine(
sourcePath.Directory,
$"{fileNameWithoutExt}.cm-info.json"
);
var sourcePreviewPath = Path.Combine(
sourcePath.Directory,
$"{fileNameWithoutExt}.preview.jpeg"
);
var destinationFilePath = Path.Combine(DirectoryPath, sourcePath.Name);
var destinationCmInfoPath = Path.Combine(
DirectoryPath,
$"{fileNameWithoutExt}.cm-info.json"
);
var destinationPreviewPath = Path.Combine(
DirectoryPath,
$"{fileNameWithoutExt}.preview.jpeg"
);

// Move files
if (File.Exists(sourcePath))
{
Progress.Text = $"Moving {sourcePath.Name}...";
await FileTransfers.MoveFileAsync(sourcePath, destinationFilePath);
}

Progress.Value = 33;
Progress.Text = $"Moving {sourcePath.Name} metadata...";

if (File.Exists(sourceCmInfoPath))
{
await FileTransfers.MoveFileAsync(sourceCmInfoPath, destinationCmInfoPath);
}

Progress.Value = 66;

if (File.Exists(sourcePreviewPath))
{
await FileTransfers.MoveFileAsync(sourcePreviewPath, destinationPreviewPath);
}

Progress.Value = 100;
Progress.Text = $"Moved {sourcePath.Name} to {Title}";
sourceFile.OnMoved();
BackgroundIndex();
delay = 0.5f;
}
catch (FileTransferExistsException)
{
Progress.Value = 0;
Progress.Text = "Failed to move file: destination file exists";
}
finally
{
DelayedClearProgress(TimeSpan.FromSeconds(delay));
}
}

/// <summary>
/// Imports files to the folder. Reports progress to instance properties.
/// </summary>
Expand Down Expand Up @@ -505,7 +575,7 @@ private IEnumerable<CheckpointFile> GetCheckpointFiles()
return Enumerable.Empty<CheckpointFile>();
}

return CheckpointFile.FromDirectoryIndex(DirectoryPath);
return CheckpointFile.FromDirectoryIndex(this, DirectoryPath);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ public override void OnLoaded()
Logger.Info($"OnLoadedAsync in {sw.ElapsedMilliseconds}ms");
}

public void ClearSearchQuery()
{
SearchFilter = string.Empty;
}

// ReSharper disable once UnusedParameterInPartialMethod
partial void OnSearchFilterChanged(string value)
{
Expand Down
119 changes: 71 additions & 48 deletions StabilityMatrix.Avalonia/ViewModels/OutputsPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,10 @@ public partial class OutputsPageViewModel : PageViewModelBase

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CanShowOutputTypes))]
private PackageOutputCategory selectedCategory;
private PackageOutputCategory? selectedCategory;

[ObservableProperty]
private SharedOutputType selectedOutputType;
private SharedOutputType? selectedOutputType;

[ObservableProperty]
[NotifyPropertyChangedFor(nameof(NumImagesSelected))]
Expand Down Expand Up @@ -136,6 +136,8 @@ ILogger<OutputsPageViewModel> logger
settings => settings.OutputsImageSize,
delay: TimeSpan.FromMilliseconds(250)
);

RefreshCategories();
}

public override void OnLoaded()
Expand All @@ -148,49 +150,8 @@ public override void OnLoaded()

Directory.CreateDirectory(settingsManager.ImagesDirectory);

var packageCategories = settingsManager.Settings.InstalledPackages
.Where(x => !x.UseSharedOutputFolder)
.Select(packageFactory.GetPackagePair)
.WhereNotNull()
.Where(
p =>
p.BasePackage.SharedOutputFolders != null
&& p.BasePackage.SharedOutputFolders.Any()
)
.Select(
pair =>
new PackageOutputCategory
{
Path = Path.Combine(
pair.InstalledPackage.FullPath!,
pair.BasePackage.OutputFolderName
),
Name = pair.InstalledPackage.DisplayName ?? ""
}
)
.ToList();

packageCategories.Insert(
0,
new PackageOutputCategory
{
Path = settingsManager.ImagesDirectory,
Name = "Shared Output Folder"
}
);

packageCategories.Insert(
1,
new PackageOutputCategory
{
Path = settingsManager.ImagesInferenceDirectory,
Name = "Inference"
}
);

Categories = new ObservableCollection<PackageOutputCategory>(packageCategories);
SelectedCategory = Categories.First();
SelectedOutputType = SharedOutputType.All;
SelectedCategory ??= Categories.First();
SelectedOutputType ??= SharedOutputType.All;
SearchQuery = string.Empty;
ImageSize = settingsManager.Settings.OutputsImageSize;

Expand All @@ -216,14 +177,14 @@ partial void OnSelectedCategoryChanged(
GetOutputs(path);
}

partial void OnSelectedOutputTypeChanged(SharedOutputType oldValue, SharedOutputType newValue)
partial void OnSelectedOutputTypeChanged(SharedOutputType? oldValue, SharedOutputType? newValue)
{
if (oldValue == newValue)
if (oldValue == newValue || newValue == null)
return;

var path =
newValue == SharedOutputType.All
? SelectedCategory.Path
? SelectedCategory?.Path
: Path.Combine(SelectedCategory.Path, newValue.ToString());
GetOutputs(path);
}
Expand Down Expand Up @@ -299,6 +260,7 @@ public Task CopyImage(string imagePath)

public void Refresh()
{
Dispatcher.UIThread.Post(RefreshCategories);
Dispatcher.UIThread.Post(OnLoaded);
}

Expand Down Expand Up @@ -502,6 +464,11 @@ var path in Directory.EnumerateFiles(
IsConsolidating = false;
}

public void ClearSearchQuery()
{
SearchQuery = string.Empty;
}

private void GetOutputs(string directory)
{
if (!settingsManager.IsLibraryDirSet)
Expand Down Expand Up @@ -533,4 +500,60 @@ private void GetOutputs(string directory)
OutputsCache.EditDiff(files);
}
}

private void RefreshCategories()
{
if (Design.IsDesignMode)
return;

if (!settingsManager.IsLibraryDirSet)
return;

var previouslySelectedCategory = SelectedCategory;

var packageCategories = settingsManager.Settings.InstalledPackages
.Where(x => !x.UseSharedOutputFolder)
.Select(packageFactory.GetPackagePair)
.WhereNotNull()
.Where(
p =>
p.BasePackage.SharedOutputFolders != null
&& p.BasePackage.SharedOutputFolders.Any()
)
.Select(
pair =>
new PackageOutputCategory
{
Path = Path.Combine(
pair.InstalledPackage.FullPath!,
pair.BasePackage.OutputFolderName
),
Name = pair.InstalledPackage.DisplayName ?? ""
}
)
.ToList();

packageCategories.Insert(
0,
new PackageOutputCategory
{
Path = settingsManager.ImagesDirectory,
Name = "Shared Output Folder"
}
);

packageCategories.Insert(
1,
new PackageOutputCategory
{
Path = settingsManager.ImagesInferenceDirectory,
Name = "Inference"
}
);

Categories = new ObservableCollection<PackageOutputCategory>(packageCategories);
SelectedCategory =
Categories.FirstOrDefault(x => x.Name == previouslySelectedCategory?.Name)
?? Categories.First();
}
}
Loading

0 comments on commit 1cdfbc2

Please sign in to comment.