Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better state checks for collections #2360

Merged
merged 3 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using NexusMods.Abstractions.Loadouts;
using NexusMods.Abstractions.NexusModsLibrary;
using NexusMods.Abstractions.NexusModsLibrary.Models;
using NexusMods.MnemonicDB.Abstractions.Attributes;
using NexusMods.MnemonicDB.Abstractions.Models;

Expand All @@ -12,7 +13,17 @@ namespace NexusMods.Abstractions.Collections;
public partial class NexusCollectionLoadoutGroup : IModelDefinition
{
private const string Namespace = "NexusMods.Collections.NexusCollectionLoadoutGroup";


/// <summary>
/// The collection.
/// </summary>
public static readonly ReferenceAttribute<CollectionMetadata> Collection = new(Namespace, nameof(Collection)) { IsIndexed = true };

/// <summary>
/// The revision.
/// </summary>
public static readonly ReferenceAttribute<CollectionRevisionMetadata> Revision = new(Namespace, nameof(Revision)) { IsIndexed = true };

/// <summary>
/// The collection library file.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public CollectionDownloadViewModel(
var osInterop = serviceProvider.GetRequiredService<IOSInterop>();
var nexusModsLibrary = serviceProvider.GetRequiredService<NexusModsLibrary>();
var collectionDownloader = new CollectionDownloader(serviceProvider);
var loginManager = serviceProvider.GetRequiredService<ILoginManager>();

var tileImagePipeline = ImagePipelines.GetCollectionTileImagePipeline(serviceProvider);
var backgroundImagePipeline = ImagePipelines.GetCollectionBackgroundImagePipeline(serviceProvider);
Expand Down Expand Up @@ -77,18 +78,14 @@ public CollectionDownloadViewModel(
RequiredDownloadsCount = requiredDownloadCount;
OptionalDownloadsCount = optionalDownloadCount;

var loginManager = serviceProvider.GetRequiredService<ILoginManager>();
DownloadAllCommand = loginManager.IsPremiumObservable.ToObservable().ToReactiveCommand<Unit>(
DownloadAllCommand = _canDownload.ToReactiveCommand<Unit>(
executeAsync: (_, cancellationToken) => collectionDownloader.DownloadAll(_revision, onlyRequired: true, db: connection.Db, cancellationToken: cancellationToken),
awaitOperation: AwaitOperation.Drop,
configureAwait: false
);

InstallCollectionCommand = new ReactiveCommand(
executeAsync: async (_, _) =>
{
await InstallCollectionJob.Create(serviceProvider, targetLoadout, revisionMetadata);
},
InstallCollectionCommand = _canInstall.ToReactiveCommand<Unit>(
executeAsync: async (_, _) => { await InstallCollectionJob.Create(serviceProvider, targetLoadout, revisionMetadata); },
awaitOperation: AwaitOperation.Drop,
configureAwait: false
);
Expand Down Expand Up @@ -134,25 +131,35 @@ public CollectionDownloadViewModel(
this.WhenActivated(disposables =>
{
TreeDataGridAdapter.Activate();
Disposable.Create(TreeDataGridAdapter, static adapter => adapter.Deactivate());
Disposable.Create(TreeDataGridAdapter, static adapter => adapter.Deactivate()).AddTo(disposables);

Observable
var numDownloadedObservable = Observable
.Return(_revision)
.OffUi()
.SelectMany(revision => collectionDownloader.RequiredDownloadedCountObservable(revision))
.SelectMany(revision => collectionDownloader.RequiredDownloadedCountObservable(revision));

var isPremiumObservable = loginManager.IsPremiumObservable;
var isCollectionInstalledObservable = collectionDownloader.IsCollectionInstalled(_revision);

numDownloadedObservable.CombineLatest(isPremiumObservable, isCollectionInstalledObservable)
.OnUI()
.Subscribe(count =>
.Subscribe(tuple =>
{
if (count == RequiredDownloadsCount)
var (numDownloaded, isPremium, isCollectionInstalled) = tuple;
var hasDownloaded = numDownloaded == RequiredDownloadsCount;

_canInstall.OnNext(!isCollectionInstalled && hasDownloaded);
_canDownload.OnNext(!hasDownloaded && isPremium);

if (hasDownloaded)
{
CollectionStatusText = Language.CollectionDownloadViewModel_Ready_to_install;
}
else
{
CollectionStatusText = string.Format(Language.CollectionDownloadViewModel_Num_required_mods_downloaded, count, RequiredDownloadsCount);
CollectionStatusText = string.Format(Language.CollectionDownloadViewModel_Num_required_mods_downloaded, numDownloaded, RequiredDownloadsCount);
}
})
.AddTo(disposables);
}).AddTo(disposables);

ImagePipelines.CreateObservable(_collection.Id, tileImagePipeline)
.ObserveOnUIThreadDispatcher()
Expand Down Expand Up @@ -183,6 +190,9 @@ public CollectionDownloadViewModel(
});
}

private readonly BehaviorSubject<bool> _canDownload = new(initialValue: false);
private readonly BehaviorSubject<bool> _canInstall = new(initialValue: false);

public string Name => _collection.Name;
public string Summary => _collection.Summary;
public ulong EndorsementCount => _collection.Endorsements;
Expand Down
8 changes: 8 additions & 0 deletions src/NexusMods.Collections/CollectionDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,4 +320,12 @@ public async ValueTask DownloadAll(
}
});
}

/// <summary>
/// Checks whether the collection is installed.
/// </summary>
public IObservable<bool> IsCollectionInstalled(CollectionRevisionMetadata.ReadOnly revision)
{
return _connection.ObserveDatoms(NexusCollectionLoadoutGroup.Revision, revision).IsNotEmpty();
}
}
2 changes: 2 additions & 0 deletions src/NexusMods.Collections/InstallCollectionJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ public class InstallCollectionJob : IJobDefinitionWithStart<InstallCollectionJob
{
var group = new NexusCollectionLoadoutGroup.New(tx, out var id)
{
CollectionId = RevisionMetadata.Collection,
RevisionId = RevisionMetadata,
LibraryFileId = SourceCollection,
CollectionGroup = new CollectionGroup.New(tx, id)
{
Expand Down
15 changes: 7 additions & 8 deletions src/NexusMods.DataModel/Synchronizer/SynchronizerService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,13 @@ private IObservable<LoadoutSynchronizerState> CreateStatusObservable(LoadoutId l

// Potentially long operation, run on thread pool
var diffFound = await Task.Run(() =>
{
_logger.LogInformation("Checking for changes in loadout {LoadoutId}", loadoutId);
var diffTree = GetApplyDiffTree(loadoutId);
var diffFound = diffTree.GetAllDescendentFiles().Any(f => f.Item.Value.ChangeType != FileChangeType.None);
_logger.LogInformation("Changes found in loadout {LoadoutId}: {DiffFound}", loadoutId, diffFound);
return diffFound;
}
);
{
_logger.LogDebug("Checking for changes in loadout {LoadoutId}", loadoutId);
var diffTree = GetApplyDiffTree(loadoutId);
var diffFound = diffTree.GetAllDescendentFiles().Any(f => f.Item.Value.ChangeType != FileChangeType.None);
_logger.LogDebug("Changes found in loadout {LoadoutId}: {DiffFound}", loadoutId, diffFound);
return diffFound;
});

return diffFound ? LoadoutSynchronizerState.NeedsSync : LoadoutSynchronizerState.Current;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
Name: SDV.4_11_2024.rocksdb.zip,
OldFingerprint: None,
NewFingerprint: 0xDC3041F8AE1C27E9,
NewFingerprint: 0xF310EDA75F1BF2BE,
LoadoutItemGroups: 201,
Files: 16729,
Created: 2024-11-04 17:45:27
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ This schema is written to a markdown file for both documentation and validation
models in the app, then validate the tests to update this file.

## Statistics
- Fingerprint: 0x60C019D68BA4BF2F
- Total attributes: 145
- Fingerprint: 0xCD1114F5443525AD
- Total attributes: 147
- Total namespaces: 58

## Attributes
Expand All @@ -18,7 +18,9 @@ models in the app, then validate the tests to update this file.
| NexusMods.Collections.DirectDownloadLibraryFile/LogicalFileName | Utf8 | False | False | False |
| NexusMods.Collections.DirectDownloadLibraryFile/Md5 | UInt128 | True | False | False |
| NexusMods.Collections.NexusCollectionBundledLoadoutGroup/CollectionLibraryFile | Reference | False | False | False |
| NexusMods.Collections.NexusCollectionLoadoutGroup/Collection | Reference | True | False | False |
| NexusMods.Collections.NexusCollectionLoadoutGroup/LibraryFile | Reference | False | False | False |
| NexusMods.Collections.NexusCollectionLoadoutGroup/Revision | Reference | True | False | False |
| NexusMods.DataModel.SchemaVersioning.SchemaVersionModel/Fingerprint | UInt64 | False | False | False |
| NexusMods.DataModel.Settings/Name | Utf8 | True | False | False |
| NexusMods.DataModel.Settings/Value | Utf8 | False | False | False |
Expand Down
Loading