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

feat: add name query param to wearable collections from builder #6260

Merged
merged 4 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
Expand Up @@ -375,6 +375,8 @@ public async UniTask<IReadOnlyList<WearableItem>> RequestEmoteCollectionInBuilde
if (!success)
throw new Exception($"The request for collection of emotes '{collectionId}' failed!");

if (response.data?.results == null) continue;

foreach (BuilderWearable bw in response.data.results)
{
var wearable = bw.ToWearableItem($"{domain}/storage/contents/",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public interface IWearablesCatalogService : IService
UniTask<WearableItem> RequestWearableAsync(string wearableId, CancellationToken ct);
UniTask<WearableItem> RequestWearableFromBuilderAsync(string wearableId, CancellationToken ct);
UniTask<IReadOnlyList<WearableItem>> RequestWearableCollection(IEnumerable<string> collectionIds, CancellationToken cancellationToken, List<WearableItem> collectionBuffer = null);
UniTask<IReadOnlyList<WearableItem>> RequestWearableCollectionInBuilder(IEnumerable<string> collectionIds, CancellationToken cancellationToken, List<WearableItem> collectionBuffer = null);
UniTask<(IReadOnlyList<WearableItem> wearables, int totalAmount)> RequestWearableCollectionInBuilder(IEnumerable<string> collectionIds, CancellationToken cancellationToken, List<WearableItem> collectionBuffer = null, string nameFilter = null, int pageNumber = 1, int pageSize = 5000);

void AddWearablesToCatalog(IEnumerable<WearableItem> wearableItems);
void RemoveWearablesFromCatalog(IEnumerable<string> wearableIds);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,18 +346,31 @@ public async UniTask<IReadOnlyList<WearableItem>> RequestWearableCollection(IEnu
return wearables;
}

public async UniTask<IReadOnlyList<WearableItem>> RequestWearableCollectionInBuilder(IEnumerable<string> collectionIds,
CancellationToken cancellationToken, List<WearableItem> collectionBuffer = null)
public async UniTask<(IReadOnlyList<WearableItem> wearables, int totalAmount)> RequestWearableCollectionInBuilder(IEnumerable<string> collectionIds,
CancellationToken cancellationToken, List<WearableItem> collectionBuffer = null, string nameFilter = null,
int pageNumber = 1, int pageSize = 5000)
{
string domain = GetBuilderDomainUrl();
var wearables = collectionBuffer ?? new List<WearableItem>();

// Dictionary<string, string> queryParams = new ()
// {
// { "page", pageNumber.ToString() },
// { "limit", pageSize.ToString() },
// };
//
// if (!string.IsNullOrEmpty(nameFilter))
// queryParams["name"] = nameFilter;

var queryParams = new[]
{
("page", "1"),
("limit", "5000"),
("page", pageNumber.ToString()),
("limit", pageSize.ToString()),
("name", nameFilter),
};

var totalAmount = 0;

foreach (string collectionId in collectionIds)
{
var url = $"{domain}/collections/{collectionId}/items/";
Expand All @@ -366,6 +379,7 @@ public async UniTask<IReadOnlyList<WearableItem>> RequestWearableCollectionInBui
(WearableCollectionResponseFromBuilder response, bool success) = await lambdasService.GetFromSpecificUrl<WearableCollectionResponseFromBuilder>(
templateUrl, url,
isSigned: true,
// urlEncodedParams: queryParams.Select(pair => (pair.Key, pair.Value)).ToArray(),
urlEncodedParams: queryParams,
cancellationToken: cancellationToken);

Expand All @@ -382,9 +396,10 @@ public async UniTask<IReadOnlyList<WearableItem>> RequestWearableCollectionInBui
AddWearablesToCatalog(ws);

wearables.AddRange(ws);
totalAmount = response.data.total;
}

return wearables;
return (wearables, totalAmount);
}

public void AddWearablesToCatalog(IEnumerable<WearableItem> wearableItems)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,15 @@ public async UniTask<IReadOnlyList<WearableItem>> RequestWearableCollection(IEnu
return await lambdasWearablesCatalogService.RequestWearableCollection(collectionIds, cancellationToken, wearableBuffer);
}

public async UniTask<IReadOnlyList<WearableItem>> RequestWearableCollectionInBuilder(IEnumerable<string> collectionIds,
CancellationToken cancellationToken, List<WearableItem> wearableBuffer = null)
public async UniTask<(IReadOnlyList<WearableItem> wearables, int totalAmount)> RequestWearableCollectionInBuilder(
IEnumerable<string> collectionIds, CancellationToken cancellationToken,
List<WearableItem> collectionBuffer = null, string nameFilter = null, int pageNumber = 1, int pageSize = 5000)
{
if (!isInitialized)
await UniTask.WaitUntil(() => isInitialized, cancellationToken: cancellationToken);

return await lambdasWearablesCatalogService.RequestWearableCollectionInBuilder(collectionIds, cancellationToken, wearableBuffer);
return await lambdasWearablesCatalogService.RequestWearableCollectionInBuilder(collectionIds, cancellationToken,
collectionBuffer, nameFilter, pageNumber, pageSize);
}

public void AddWearablesToCatalog(IEnumerable<WearableItem> wearableItems) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,9 @@ public UniTask<IReadOnlyList<WearableItem>> RequestWearableCollection(IEnumerabl
CancellationToken cancellationToken, List<WearableItem> wearableBuffer = null) =>
throw new NotImplementedException("Supported by LambdasWearablesCatalogService");

public UniTask<IReadOnlyList<WearableItem>> RequestWearableCollectionInBuilder(IEnumerable<string> collectionIds,
CancellationToken cancellationToken, List<WearableItem> wearableBuffer = null) =>
public UniTask<(IReadOnlyList<WearableItem> wearables, int totalAmount)> RequestWearableCollectionInBuilder(
IEnumerable<string> collectionIds, CancellationToken cancellationToken,
List<WearableItem> collectionBuffer = null, string nameFilter = null, int pageNumber = 1, int pageSize = 5000) =>
throw new NotImplementedException("Supported by LambdasWearablesCatalogService");

private async UniTask<IReadOnlyList<WearableItem>> RequestWearablesByContextAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1121,12 +1121,13 @@ public IEnumerator IncludeCustomWearableCollection()
};

wearablesCatalogService.RequestWearableCollectionInBuilder(Arg.Is<IEnumerable<string>>(i => i.Count() == 1 && i.ElementAt(0) == "builder:collection"),
Arg.Any<CancellationToken>(), Arg.Any<List<WearableItem>>())
Arg.Any<CancellationToken>(), Arg.Any<List<WearableItem>>(),
Arg.Any<string>(), Arg.Any<int>(), Arg.Any<int>())
.Returns(call =>
{
List<WearableItem> wearables = (List<WearableItem>) call[2];
wearables.AddRange(nonPublishedWearableList);
return UniTask.FromResult(nonPublishedWearableList);
return UniTask.FromResult((nonPublishedWearableList, nonPublishedWearableList.Count));
});

wearablesCatalogService.RequestWearableCollection(Arg.Is<IEnumerable<string>>(i => i.Count() == 1 && i.ElementAt(0) == "urn:collection"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Pool;

Expand Down Expand Up @@ -266,29 +267,9 @@ private async UniTask<int> RequestWearablesAndShowThem(int page, CancellationTok

try
{
int ownedWearablesCount = wearables.Count;
int ownedWearablesTotalAmount = totalAmount;

customWearablesBuffer.Clear();

await UniTask.WhenAll(FetchCustomWearableCollections(customWearablesBuffer, cancellationToken),
FetchCustomWearableItems(customWearablesBuffer, cancellationToken));

int customWearablesCount = customWearablesBuffer.Count;
totalAmount += customWearablesCount;

if (ownedWearablesCount < PAGE_SIZE && customWearablesCount > 0)
{
int ownedWearablesStartingPage = (ownedWearablesTotalAmount / PAGE_SIZE) + 1;
int customWearablesOffsetPage = page - ownedWearablesStartingPage;
int skip = customWearablesOffsetPage * PAGE_SIZE;
// Fill the page considering the existing owned wearables
int count = PAGE_SIZE - ownedWearablesCount;
int until = skip + count;

for (int i = skip; i < customWearablesBuffer.Count && i < until; i++)
wearables.Add(customWearablesBuffer[i]);
}
totalAmount += await MergePublishedWearableCollections(page, wearables, totalAmount, cancellationToken);
totalAmount += await MergeBuilderWearableCollections(page, wearables, totalAmount, cancellationToken);
totalAmount += await MergeCustomWearableItems(page, wearables, totalAmount, cancellationToken);

customWearablesBuffer.Clear();
}
Expand All @@ -299,7 +280,7 @@ await UniTask.WhenAll(FetchCustomWearableCollections(customWearablesBuffer, canc
currentWearables = wearables.Select(ToWearableGridModel)
.ToDictionary(item => ExtendedUrnParser.GetShortenedUrn(item.WearableId), model => model);

view.SetWearablePages(page, Mathf.CeilToInt((float) totalAmount / PAGE_SIZE));
view.SetWearablePages(page, Mathf.CeilToInt((float)totalAmount / PAGE_SIZE));

// TODO: mark the wearables to be disposed if no references left
view.ClearWearables();
Expand All @@ -313,6 +294,53 @@ await UniTask.WhenAll(FetchCustomWearableCollections(customWearablesBuffer, canc
return 0;
}

private async UniTask<int> MergeCustomWearableItems(int page, List<WearableItem> wearables,
int totalAmount, CancellationToken cancellationToken) =>
await MergeToWearableResults(page, wearables, totalAmount, FetchCustomWearableItems, cancellationToken);

private async UniTask<int> MergePublishedWearableCollections(int page, List<WearableItem> wearables, int totalAmount,
CancellationToken cancellationToken) =>
await MergeToWearableResults(page, wearables, totalAmount, FetchPublishedWearableCollections, cancellationToken);

private async UniTask<int> MergeToWearableResults(int page, List<WearableItem> wearables, int totalAmount,
Func<List<WearableItem>, CancellationToken, UniTask> fetchOperation,
CancellationToken cancellationToken)
{
int startingPage = (totalAmount / PAGE_SIZE) + 1;
int pageOffset = page - startingPage;
int pageSize = PAGE_SIZE - wearables.Count;
int skip = pageOffset * PAGE_SIZE;
int until = skip + pageSize;

customWearablesBuffer.Clear();

await fetchOperation.Invoke(customWearablesBuffer, cancellationToken);

if (skip < 0) return customWearablesBuffer.Count;

for (int i = skip; i < customWearablesBuffer.Count && i < until; i++)
wearables.Add(customWearablesBuffer[i]);

return customWearablesBuffer.Count;
}

private async UniTask<int> MergeBuilderWearableCollections(int page, List<WearableItem> wearables, int totalAmount, CancellationToken cancellationToken)
{
int startingPage = (totalAmount / PAGE_SIZE) + 1;
int pageOffset = Mathf.Max(1, page - startingPage);
int pageSize = PAGE_SIZE - wearables.Count;

customWearablesBuffer.Clear();

int collectionsWearableCount = await FetchBuilderWearableCollections(pageOffset, PAGE_SIZE,
customWearablesBuffer, cancellationToken);

for (var i = 0; i < pageSize && i < customWearablesBuffer.Count; i++)
wearables.Add(customWearablesBuffer[i]);

return collectionsWearableCount;
}

private async UniTask FetchCustomWearableItems(ICollection<WearableItem> wearables, CancellationToken cancellationToken)
{
IReadOnlyList<string> customItems = await customNftCollectionService.GetConfiguredCustomNftItemsAsync(cancellationToken);
Expand All @@ -337,30 +365,46 @@ private async UniTask FetchCustomWearableItems(ICollection<WearableItem> wearabl
}
}

private async UniTask FetchCustomWearableCollections(
private async UniTask FetchPublishedWearableCollections(
List<WearableItem> wearableBuffer, CancellationToken cancellationToken)
{
IReadOnlyList<string> customCollections =
await customNftCollectionService.GetConfiguredCustomNftCollectionAsync(cancellationToken);

Debug.Log($"FetchCustomWearableCollections: {customCollections}");

HashSet<string> publishedCollections = HashSetPool<string>.Get();
HashSet<string> collectionsInBuilder = HashSetPool<string>.Get();
HashSet<string> collectionsToRequest = HashSetPool<string>.Get();

foreach (string collectionId in customCollections)
{
if (collectionId.StartsWith("urn", StringComparison.OrdinalIgnoreCase))
publishedCollections.Add(collectionId);
else
collectionsInBuilder.Add(collectionId);
}
collectionsToRequest.Add(collectionId);

await UniTask.WhenAll(wearablesCatalogService.RequestWearableCollection(publishedCollections, cancellationToken, wearableBuffer),
wearablesCatalogService.RequestWearableCollectionInBuilder(collectionsInBuilder, cancellationToken, wearableBuffer));
await wearablesCatalogService.RequestWearableCollection(collectionsToRequest, cancellationToken, wearableBuffer);

HashSetPool<string>.Release(publishedCollections);
HashSetPool<string>.Release(collectionsInBuilder);
HashSetPool<string>.Release(collectionsToRequest);
}

private async UniTask<int> FetchBuilderWearableCollections(
int pageNumber, int pageSize,
List<WearableItem> wearableBuffer,
CancellationToken cancellationToken)
{
IReadOnlyList<string> customCollections =
await customNftCollectionService.GetConfiguredCustomNftCollectionAsync(cancellationToken);

HashSet<string> collectionsToRequest = HashSetPool<string>.Get();

foreach (string collectionId in customCollections)
if (!collectionId.StartsWith("urn", StringComparison.OrdinalIgnoreCase))
collectionsToRequest.Add(collectionId);

(IReadOnlyList<WearableItem> _, int totalAmount) = await wearablesCatalogService.RequestWearableCollectionInBuilder(
collectionsToRequest, cancellationToken,
collectionBuffer: wearableBuffer,
nameFilter: nameFilter,
pageNumber: pageNumber, pageSize: pageSize);

HashSetPool<string>.Release(collectionsToRequest);

return totalAmount;
}

private WearableGridItemModel ToWearableGridModel(WearableItem wearable)
Expand All @@ -369,8 +413,7 @@ private WearableGridItemModel ToWearableGridModel(WearableItem wearable)

if (string.IsNullOrEmpty(wearable.rarity))
rarity = NftRarity.None;
else
if (!Enum.TryParse(wearable.rarity, true, out NftRarity result))
else if (!Enum.TryParse(wearable.rarity, true, out NftRarity result))
{
rarity = NftRarity.None;
Debug.LogWarning($"Could not parse the rarity \"{wearable.rarity}\" of the wearable '{wearable.id}'. Fallback to common.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@ public static ServiceLocator CreateMocked()
{
IWearablesCatalogService wearablesCatalogService = Substitute.For<IWearablesCatalogService>();



wearablesCatalogService.RequestWearableCollectionInBuilder(default, default, default)
.ReturnsForAnyArgs(UniTask.FromResult((IReadOnlyList<WearableItem>) Array.Empty<WearableItem>()));
.ReturnsForAnyArgs(UniTask.FromResult(((IReadOnlyList<WearableItem>) Array.Empty<WearableItem>(), 0)));

wearablesCatalogService.RequestWearableFromBuilderAsync(default, default)
.ReturnsForAnyArgs(UniTask.FromResult<WearableItem>(null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public static IWearablesCatalogService CreateTestCatalogLocal()
.ReturnsForAnyArgs(UniTask.FromResult<IReadOnlyList<WearableItem>>(Array.Empty<WearableItem>()));

wearablesCatalogService.RequestWearableCollectionInBuilder(default, default, default)
.ReturnsForAnyArgs(UniTask.FromResult<IReadOnlyList<WearableItem>>(Array.Empty<WearableItem>()));
.ReturnsForAnyArgs(UniTask.FromResult(((IReadOnlyList<WearableItem>) Array.Empty<WearableItem>(), 0)));

return wearablesCatalogService;
}
Expand Down