diff --git a/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsFileMetadata.cs b/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsFileMetadata.cs
index 404c0cb288..9abb540761 100644
--- a/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsFileMetadata.cs
+++ b/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsFileMetadata.cs
@@ -28,9 +28,9 @@ public partial class NexusModsFileMetadata : IModelDefinition
/// The version of the file.
///
public static readonly StringAttribute Version = new(Namespace, nameof(Version));
-
+
///
- /// The size in bytes of the file.
+ /// The size of the file in bytes, this is optional in the NexusMods API for whatever reason.
///
public static readonly SizeAttribute Size = new(Namespace, nameof(Size)) { IsOptional = true };
@@ -42,5 +42,5 @@ public partial class NexusModsFileMetadata : IModelDefinition
///
/// Library Files that link to this file.
///
- public static readonly BackReferenceAttribute LibraryFiles = new(NexusModsLibraryFile.FileMetadata);
+ public static readonly BackReferenceAttribute LibraryFiles = new(NexusModsLibraryItem.FileMetadata);
}
diff --git a/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsLibraryFile.cs b/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsLibraryFile.cs
index 325593781a..89855aa0ff 100644
--- a/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsLibraryFile.cs
+++ b/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/NexusModsLibraryFile.cs
@@ -6,13 +6,13 @@
namespace NexusMods.Abstractions.NexusModsLibrary;
///
-/// Represented a originating from Nexus Mods.
+/// Represented a originating from Nexus Mods.
///
[PublicAPI]
-[Include]
-public partial class NexusModsLibraryFile : IModelDefinition
+[Include]
+public partial class NexusModsLibraryItem : IModelDefinition
{
- private const string Namespace = "NexusMods.Library.NexusModsLibraryFile";
+ private const string Namespace = "NexusMods.Library.NexusModsLibraryItem";
///
/// Remote metadata of the file on Nexus Mods.
diff --git a/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/Services.cs b/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/Services.cs
index 84be9a0a39..ba6052d599 100644
--- a/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/Services.cs
+++ b/src/Abstractions/NexusMods.Abstractions.NexusModsLibrary/Services.cs
@@ -18,7 +18,7 @@ public static IServiceCollection AddNexusModsLibraryModels(this IServiceCollecti
return serviceCollection
.AddNexusModsFileMetadataModel()
.AddNexusModsModPageMetadataModel()
- .AddNexusModsLibraryFileModel()
+ .AddNexusModsLibraryItemModel()
.AddCollectionMetadataModel()
.AddCollectionRevisionMetadataModel()
.AddCollectionRevisionModFileModel()
diff --git a/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsDownloadJob.cs b/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsDownloadJob.cs
index 832b24a1cc..e45e151bf7 100644
--- a/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsDownloadJob.cs
+++ b/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsDownloadJob.cs
@@ -4,6 +4,7 @@
using NexusMods.Abstractions.Library.Models;
using NexusMods.Abstractions.NexusModsLibrary;
using NexusMods.MnemonicDB.Abstractions;
+using NexusMods.MnemonicDB.Abstractions.TxFunctions;
using NexusMods.Networking.HttpDownloader;
using NexusMods.Paths;
@@ -34,19 +35,18 @@ public async ValueTask StartAsync(IJobContext
- public ValueTask AddMetadata(ITransaction transaction, LibraryFile.New libraryFile)
+ public ValueTask AddMetadata(ITransaction tx, LibraryFile.New libraryFile)
{
- libraryFile.GetLibraryItem(transaction).Name = FileMetadata.Name;
+ libraryFile.GetLibraryItem(tx).Name = FileMetadata.Name;
- _ = new NexusModsLibraryFile.New(transaction, libraryFile.Id)
+ // Not using .New here because we can't use the LibraryItem Id and don't have the LibraryItem in this method
+ tx.Add(libraryFile.Id, NexusModsLibraryItem.FileMetadataId, FileMetadata.Id);
+ tx.Add(libraryFile.Id, NexusModsLibraryItem.ModPageMetadataId, FileMetadata.ModPage.Id);
+
+ _ = new DownloadedFile.New(tx, libraryFile.Id)
{
- FileMetadataId = FileMetadata,
- ModPageMetadataId = FileMetadata.ModPage,
- DownloadedFile = new DownloadedFile.New(transaction, libraryFile.Id)
- {
- DownloadPageUri = HttpDownloadJob.Job.DownloadPageUri,
- LibraryFile = libraryFile,
- },
+ DownloadPageUri = HttpDownloadJob.Job.DownloadPageUri,
+ LibraryFile = libraryFile,
};
return ValueTask.CompletedTask;
diff --git a/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsLibrary.cs b/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsLibrary.cs
index e378abe252..93e841f13e 100644
--- a/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsLibrary.cs
+++ b/src/Networking/NexusMods.Networking.NexusWebApi/NexusModsLibrary.cs
@@ -141,13 +141,18 @@ private async Task DownloadImage(string? uri, CancellationToken token)
if (!files.TryGetFirst(x => x.FileId == fileId, out var fileInfo))
throw new NotImplementedException();
-
+
+ var size = Optional.None;
+ if (fileInfo.SizeInBytes.HasValue)
+ size = Size.FromLong((long)fileInfo.SizeInBytes!);
+
var newFile = new NexusModsFileMetadata.New(tx)
{
Name = fileInfo.Name,
Version = fileInfo.Version,
FileId = fileId,
ModPageId = modPage,
+ Size = size.HasValue ? size.Value : null,
};
if (fileInfo.SizeInBytes.HasValue)
diff --git a/src/NexusMods.App.UI/Pages/Library/LibraryItemRemovalInfo.cs b/src/NexusMods.App.UI/Pages/Library/LibraryItemRemovalInfo.cs
index 52565842f2..c1343c9394 100644
--- a/src/NexusMods.App.UI/Pages/Library/LibraryItemRemovalInfo.cs
+++ b/src/NexusMods.App.UI/Pages/Library/LibraryItemRemovalInfo.cs
@@ -20,19 +20,16 @@ public static LibraryItemRemovalInfo Determine(LibraryItem.ReadOnly toRemove, Lo
var info = new LibraryItemRemovalInfo();
// Check if it's a file which was downloaded.
- var isDownloadedFile = toRemove.TryGetAsDownloadedFile(out var downloadedFile);;
- switch (isDownloadedFile)
+ if (toRemove.TryGetAsNexusModsLibraryItem(out _))
{
- case true:
- info.IsNexus = downloadedFile.IsNexusModsLibraryFile();
- info.IsNonPermanent = !info.IsNexus;
- break;
- // Check if it's a LocalFile (manually added)
- case false when toRemove.TryGetAsLocalFile(out _):
- info.IsManuallyAdded = true;
- break;
+ info.IsNexus = true;
+ info.IsNonPermanent = !info.IsNexus;
}
-
+ else if (toRemove.TryGetAsLocalFile(out _))
+ {
+ info.IsManuallyAdded = true;
+ }
+
// Check if it's added to any loadout
info.Loadouts = loadouts.Where(loadout => loadout.GetLoadoutItemsByLibraryItem(toRemove).Any()).ToArray();
return info;
diff --git a/src/NexusMods.App.UI/Pages/NexusModsDataProvider.cs b/src/NexusMods.App.UI/Pages/NexusModsDataProvider.cs
index 90c396a39a..16700f0c1a 100644
--- a/src/NexusMods.App.UI/Pages/NexusModsDataProvider.cs
+++ b/src/NexusMods.App.UI/Pages/NexusModsDataProvider.cs
@@ -29,7 +29,7 @@ public NexusModsDataProvider(IServiceProvider serviceProvider)
public IObservable> ObserveFlatLibraryItems(LibraryFilter libraryFilter)
{
// NOTE(erri120): For the flat library view, we display each NexusModsLibraryFile
- return NexusModsLibraryFile
+ return NexusModsLibraryItem
.ObserveAll(_connection)
// only show library files for the currently selected game
.FilterOnObservable((file, _) => libraryFilter.GameObservable.Select(game => file.ModPageMetadata.GameDomain.Equals(game.Domain)))
@@ -47,13 +47,13 @@ public IObservable> ObserveNestedLibraryI
.FilterOnObservable((modPage, _) => libraryFilter.GameObservable.Select(game => modPage.GameDomain.Equals(game.Domain)))
// only show mod pages that have library files
.FilterOnObservable((_, e) => _connection
- .ObserveDatoms(NexusModsLibraryFile.ModPageMetadataId, e)
+ .ObserveDatoms(NexusModsLibraryItem.ModPageMetadataId, e)
.IsNotEmpty()
)
.Transform((modPage, _) => ToLibraryItemModel(modPage, libraryFilter));
}
- private LibraryItemModel ToLibraryItemModel(NexusModsLibraryFile.ReadOnly nexusModsLibraryFile, LibraryFilter libraryFilter)
+ private LibraryItemModel ToLibraryItemModel(NexusModsLibraryItem.ReadOnly nexusModsLibraryFile, LibraryFilter libraryFilter)
{
var linkedLoadoutItemsObservable = QueryHelper.GetLinkedLoadoutItems(_connection, nexusModsLibraryFile.Id, libraryFilter);
@@ -64,9 +64,8 @@ private LibraryItemModel ToLibraryItemModel(NexusModsLibraryFile.ReadOnly nexusM
};
model.CreatedAtDate.Value = nexusModsLibraryFile.GetCreatedAt();
- model.ItemSize.Value = nexusModsLibraryFile.AsDownloadedFile().AsLibraryFile().Size.ToString();
model.Version.Value = nexusModsLibraryFile.FileMetadata.Version;
-
+ model.ItemSize.Value = nexusModsLibraryFile.FileMetadata.Size.ToString();
return model;
}
@@ -75,7 +74,7 @@ private LibraryItemModel ToLibraryItemModel(NexusModsModPageMetadata.ReadOnly mo
// TODO: dispose
var cache = new SourceCache(static datom => datom.E);
var disposable = _connection
- .ObserveDatoms(NexusModsLibraryFile.ModPageMetadataId, modPageMetadata.Id)
+ .ObserveDatoms(NexusModsLibraryItem.ModPageMetadataId, modPageMetadata.Id)
.AsEntityIds()
.Adapt(new SourceCacheAdapter(cache))
.SubscribeWithErrorLogging();
@@ -83,7 +82,7 @@ private LibraryItemModel ToLibraryItemModel(NexusModsModPageMetadata.ReadOnly mo
var hasChildrenObservable = cache.Connect().IsNotEmpty();
var childrenObservable = cache.Connect().Transform((_, e) =>
{
- var libraryFile = NexusModsLibraryFile.Load(_connection.Db, e);
+ var libraryFile = NexusModsLibraryItem.Load(_connection.Db, e);
return ToLibraryItemModel(libraryFile, libraryFilter);
});
@@ -94,7 +93,7 @@ private LibraryItemModel ToLibraryItemModel(NexusModsModPageMetadata.ReadOnly mo
.Transform((_, e) => LibraryLinkedLoadoutItem.Load(_connection.Db, e));
var libraryFilesObservable = cache.Connect()
- .Transform((_, e) => NexusModsLibraryFile.Load(_connection.Db, e).AsDownloadedFile().AsLibraryFile().AsLibraryItem());
+ .Transform((_, e) => NexusModsLibraryItem.Load(_connection.Db, e).AsLibraryItem());
var numInstalledObservable = cache.Connect().TransformOnObservable((_, e) => _connection
.ObserveDatoms(LibraryLinkedLoadoutItem.LibraryItemId, e)
@@ -122,7 +121,7 @@ public IObservable> ObserveNestedLoadoutI
return NexusModsModPageMetadata
.ObserveAll(_connection)
.FilterOnObservable((_, modPageEntityId) => _connection
- .ObserveDatoms(NexusModsLibraryFile.ModPageMetadataId, modPageEntityId)
+ .ObserveDatoms(NexusModsLibraryItem.ModPageMetadataId, modPageEntityId)
.FilterOnObservable((d, _) => _connection
.ObserveDatoms(LibraryLinkedLoadoutItem.LibraryItemId, d.E)
.AsEntityIds()
@@ -135,7 +134,7 @@ public IObservable> ObserveNestedLoadoutI
// TODO: dispose
var cache = new SourceCache(static datom => datom.E);
var disposable = _connection
- .ObserveDatoms(NexusModsLibraryFile.ModPageMetadataId, modPage.Id).AsEntityIds()
+ .ObserveDatoms(NexusModsLibraryItem.ModPageMetadataId, modPage.Id).AsEntityIds()
.FilterOnObservable((_, e) => _connection.ObserveDatoms(LibraryLinkedLoadoutItem.LibraryItemId, e).IsNotEmpty())
// NOTE(erri120): DynamicData 9.0.4 is broken for value types because it uses ReferenceEquals. Temporary workaround is a custom equality comparer.
.MergeManyChangeSets((_, e) => _connection.ObserveDatoms(LibraryLinkedLoadoutItem.LibraryItemId, e).AsEntityIds(), equalityComparer: DatomEntityIdEqualityComparer.Instance)
diff --git a/src/NexusMods.Collections/InstallCollectionJob.cs b/src/NexusMods.Collections/InstallCollectionJob.cs
index bd16ac86c8..ca7b3ccc3c 100644
--- a/src/NexusMods.Collections/InstallCollectionJob.cs
+++ b/src/NexusMods.Collections/InstallCollectionJob.cs
@@ -211,7 +211,10 @@ private async Task EnsureNexusModDownloaded(Mod mod)
.FirstOrOptional(f => f.LibraryFiles.Any());
if (file.HasValue)
- return (mod, file.Value.LibraryFiles.First().AsDownloadedFile().AsLibraryFile());
+ {
+ if (!file.Value.LibraryFiles.First().AsLibraryItem().TryGetAsLibraryFile(out var firstLibraryFile))
+ return (mod, firstLibraryFile);
+ }
await using var tempPath = TemporaryFileManager.CreateFile();