@quenty/avatareditorutils 7.14.0 → 7.14.1-canary.522.b5d379b.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [7.14.1-canary.522.b5d379b.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/avatareditorutils@7.14.0...@quenty/avatareditorutils@7.14.1-canary.522.b5d379b.0) (2024-11-24)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Reject promises when failing to succeed prompt ([8995ffc](https://github.com/Quenty/NevermoreEngine/commit/8995ffc94abe3e6e34f6a924f275177e7a22b641))
12
+
13
+
14
+ ### Features
15
+
16
+ * Break up logic into inventory and catalog to allow centralized querying ([939f8b1](https://github.com/Quenty/NevermoreEngine/commit/939f8b10398b9955129195b71e95f12bb29bd219))
17
+ * PlayerProductManagerClient queries inventory when inventory is available ([d159eea](https://github.com/Quenty/NevermoreEngine/commit/d159eeade8701bcbcd87e97126df3c3dfb155b8c))
18
+
19
+
20
+
21
+
22
+
6
23
  # [7.14.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/avatareditorutils@7.13.0...@quenty/avatareditorutils@7.14.0) (2024-11-13)
7
24
 
8
25
  **Note:** Version bump only for package @quenty/avatareditorutils
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/avatareditorutils",
3
- "version": "7.14.0",
3
+ "version": "7.14.1-canary.522.b5d379b.0",
4
4
  "description": "Provides utility functions to work with the Roblox AvatarEditorService",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -25,17 +25,22 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/brio": "^14.13.0",
29
- "@quenty/enumutils": "^3.3.0",
30
- "@quenty/loader": "^10.7.1",
31
- "@quenty/maid": "^3.4.0",
32
- "@quenty/memoize": "^1.5.1",
33
- "@quenty/promise": "^10.8.0",
34
- "@quenty/rx": "^13.13.0",
35
- "@quenty/symbol": "^3.3.0"
28
+ "@quenty/aggregator": "1.0.1-canary.522.b5d379b.0",
29
+ "@quenty/brio": "14.13.1-canary.522.b5d379b.0",
30
+ "@quenty/enumutils": "3.3.0",
31
+ "@quenty/loader": "10.7.1",
32
+ "@quenty/maid": "3.4.0",
33
+ "@quenty/memoize": "1.5.1",
34
+ "@quenty/observablecollection": "12.14.1-canary.522.b5d379b.0",
35
+ "@quenty/pagesutils": "5.8.1-canary.522.b5d379b.0",
36
+ "@quenty/promise": "10.8.0",
37
+ "@quenty/rx": "13.13.1-canary.522.b5d379b.0",
38
+ "@quenty/servicebag": "11.10.0",
39
+ "@quenty/symbol": "3.3.0",
40
+ "@quenty/valueobject": "13.13.1-canary.522.b5d379b.0"
36
41
  },
37
42
  "publishConfig": {
38
43
  "access": "public"
39
44
  },
40
- "gitHead": "451334becfa36a10b55fa53cbdd88091cdf9ddbf"
45
+ "gitHead": "b5d379b3553fb94b954870562e1bd2a57e9a1c10"
41
46
  }
@@ -0,0 +1,63 @@
1
+ --[=[
2
+ @class AvatarEditorInventory
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local BaseObject = require("BaseObject")
8
+ local ObservableMap = require("ObservableMap")
9
+ local Rx = require("Rx")
10
+ local PagesUtils = require("PagesUtils")
11
+ local Promise = require("Promise")
12
+
13
+ local AvatarEditorInventory = setmetatable({}, BaseObject)
14
+ AvatarEditorInventory.ClassName = "AvatarEditorInventory"
15
+ AvatarEditorInventory.__index = AvatarEditorInventory
16
+
17
+ function AvatarEditorInventory.new()
18
+ local self = setmetatable(BaseObject.new(), AvatarEditorInventory)
19
+
20
+ self._assetIdToAsset = self._maid:Add(ObservableMap.new())
21
+
22
+ return self
23
+ end
24
+
25
+ function AvatarEditorInventory:PromiseProcessPages(inventoryPages)
26
+ return Promise.spawn(function(resolve, reject)
27
+ local pageData = inventoryPages:GetCurrentPage()
28
+ while pageData do
29
+ for _, data in pairs(pageData) do
30
+ self._assetIdToAsset:Set(data.AssetId, data)
31
+ end
32
+
33
+ pageData = nil
34
+
35
+ if not inventoryPages.IsFinished then
36
+ local ok, err = PagesUtils.promiseAdvanceToNextPage(inventoryPages):Yield()
37
+ if not ok then
38
+ return reject(string.format("Failed to advance to next page due to %s", tostring(err)))
39
+ end
40
+
41
+ pageData = err
42
+ end
43
+ end
44
+
45
+ resolve()
46
+ end)
47
+ end
48
+
49
+ function AvatarEditorInventory:IsAssetIdInInventory(assetId)
50
+ return self._assetIdToAsset:Get(assetId) ~= nil
51
+ end
52
+
53
+ function AvatarEditorInventory:ObserveAssetIdInInventory(assetId)
54
+ assert(type(assetId) == "number", "Bad assetId")
55
+
56
+ return self._assetIdToAsset:ObserveAtKey(assetId):Pipe({
57
+ Rx.map(function(data)
58
+ return data ~= nil
59
+ end)
60
+ })
61
+ end
62
+
63
+ return AvatarEditorInventory
@@ -0,0 +1,110 @@
1
+ --[=[
2
+ @class AvatarEditorInventoryServiceClient
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local AvatarEditorService = game:GetService("AvatarEditorService")
8
+
9
+ local AvatarEditorInventory = require("AvatarEditorInventory")
10
+ local AvatarEditorUtils = require("AvatarEditorUtils")
11
+ local EnumUtils = require("EnumUtils")
12
+ local Maid = require("Maid")
13
+ local MemorizeUtils = require("MemorizeUtils")
14
+ local Promise = require("Promise")
15
+ local ValueObject = require("ValueObject")
16
+ local PagesProxy = require("PagesProxy")
17
+
18
+ local AvatarEditorInventoryServiceClient = {}
19
+ AvatarEditorInventoryServiceClient.ServiceName = "AvatarEditorInventoryServiceClient"
20
+
21
+ function AvatarEditorInventoryServiceClient:Init(serviceBag)
22
+ assert(not self._serviceBag, "Already initialized")
23
+ self._serviceBag = assert(serviceBag, "No serviceBag")
24
+ self._maid = Maid.new()
25
+
26
+ self._isAccessAllowed = self._maid:Add(ValueObject.new(false, "boolean"))
27
+ self._assetTypeToInventoryPromises = {}
28
+
29
+ self._maid:GiveTask(AvatarEditorService.PromptAllowInventoryReadAccessCompleted:Connect(function(avatarPromptResult)
30
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
31
+ self._isAccessAllowed.Value = true
32
+ end
33
+ end))
34
+
35
+ self._promiseInventoryPages = MemorizeUtils.memoize(function(avatarAssetTypes)
36
+ return AvatarEditorUtils.promiseInventoryPages(avatarAssetTypes)
37
+ :Then(function(catalogPages)
38
+ -- Allow for replay
39
+ return PagesProxy.new(catalogPages)
40
+ end)
41
+ end)
42
+ end
43
+
44
+ function AvatarEditorInventoryServiceClient:PromiseInventoryPages(avatarAssetTypes)
45
+ return self:PromiseEnsureAccess()
46
+ :Then(function()
47
+ return self._promiseInventoryPages(avatarAssetTypes)
48
+ end)
49
+ :Then(function(pagesProxy)
50
+ return pagesProxy:Clone()
51
+ end)
52
+ end
53
+
54
+ function AvatarEditorInventoryServiceClient:PromiseInventoryForAvatarAssetType(avatarAssetType)
55
+ assert(EnumUtils.isOfType(Enum.AvatarAssetType, avatarAssetType), "Bad avatarAssetType")
56
+
57
+ if self._assetTypeToInventoryPromises[avatarAssetType] then
58
+ return self._assetTypeToInventoryPromises[avatarAssetType]
59
+ end
60
+
61
+ local inventory = self._maid:Add(AvatarEditorInventory.new())
62
+
63
+ self._assetTypeToInventoryPromises[avatarAssetType] = AvatarEditorUtils.promiseInventoryPages({
64
+ avatarAssetType
65
+ })
66
+ :Then(function(inventoryPages)
67
+ return inventory:PromiseProcessPages(inventoryPages)
68
+ end)
69
+ :Then(function()
70
+ return inventory
71
+ end)
72
+
73
+ return self._assetTypeToInventoryPromises[avatarAssetType]
74
+ end
75
+
76
+ function AvatarEditorInventoryServiceClient:IsInventoryAccessAllowed()
77
+ return self._isAccessAllowed.Value
78
+ end
79
+
80
+ function AvatarEditorInventoryServiceClient:ObserveIsInventoryAccessAllowed()
81
+ return self._isAccessAllowed:Observe()
82
+ end
83
+
84
+ function AvatarEditorInventoryServiceClient:PromiseEnsureAccess()
85
+ if self._isAccessAllowed.Value then
86
+ return Promise.resolved()
87
+ end
88
+
89
+ if self._currentAccessPromise and self._currentAccessPromise:IsPending() then
90
+ return self._currentAccessPromise
91
+ end
92
+
93
+ local promise = self._maid:GivePromise(AvatarEditorUtils.promptAllowInventoryReadAccess())
94
+
95
+ promise:Then(function(avatarPromptResult)
96
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
97
+ self._isAccessAllowed.Value = true
98
+ end
99
+ end)
100
+
101
+ self._currentAccessPromise = promise
102
+
103
+ return self._currentAccessPromise
104
+ end
105
+
106
+ function AvatarEditorInventoryServiceClient:Destroy()
107
+ self._maid:DoCleaning()
108
+ end
109
+
110
+ return AvatarEditorInventoryServiceClient
@@ -456,7 +456,11 @@ function AvatarEditorUtils.promptAllowInventoryReadAccess()
456
456
  end)
457
457
 
458
458
  maid:GiveTask(AvatarEditorService.PromptAllowInventoryReadAccessCompleted:Connect(function(avatarPromptResult)
459
- promise:Resolve(avatarPromptResult)
459
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
460
+ promise:Resolve(avatarPromptResult)
461
+ else
462
+ promise:Reject(avatarPromptResult)
463
+ end
460
464
  end))
461
465
 
462
466
  local ok, err = pcall(function()
@@ -493,8 +497,12 @@ function AvatarEditorUtils.promptCreateOutfit(outfit: HumanoidDescription, rigTy
493
497
  maid:DoCleaning()
494
498
  end)
495
499
 
496
- maid:GiveTask(AvatarEditorService.PromptCreateOutfitCompleted:Connect(function(avatarPromptResult)
497
- promise:Resolve(avatarPromptResult)
500
+ maid:GiveTask(AvatarEditorService.PromptCreateOutfitCompleted:Connect(function(avatarPromptResult, failureType)
501
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
502
+ promise:Resolve(avatarPromptResult)
503
+ else
504
+ promise:Reject(avatarPromptResult, failureType)
505
+ end
498
506
  end))
499
507
 
500
508
  local ok, err = pcall(function()
@@ -526,7 +534,11 @@ function AvatarEditorUtils.promptDeleteOutfit(outfitId: number)
526
534
  end)
527
535
 
528
536
  maid:GiveTask(AvatarEditorService.PromptDeleteOutfitCompleted:Connect(function(avatarPromptResult)
529
- promise:Resolve(avatarPromptResult)
537
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
538
+ promise:Resolve(avatarPromptResult)
539
+ else
540
+ promise:Reject(avatarPromptResult)
541
+ end
530
542
  end))
531
543
 
532
544
  local ok, err = pcall(function()
@@ -558,7 +570,11 @@ function AvatarEditorUtils.promptRenameOutfit(outfitId: number)
558
570
  end)
559
571
 
560
572
  maid:GiveTask(AvatarEditorService.PromptRenameOutfitCompleted:Connect(function(avatarPromptResult)
561
- promise:Resolve(avatarPromptResult)
573
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
574
+ promise:Resolve(avatarPromptResult)
575
+ else
576
+ promise:Reject(avatarPromptResult)
577
+ end
562
578
  end))
563
579
 
564
580
  local ok, err = pcall(function()
@@ -590,7 +606,11 @@ function AvatarEditorUtils.promptSaveAvatar(humanoidDescription: HumanoidDescrip
590
606
  end)
591
607
 
592
608
  maid:GiveTask(AvatarEditorService.PromptSaveAvatarCompleted:Connect(function(avatarPromptResult)
593
- promise:Resolve(avatarPromptResult)
609
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
610
+ promise:Resolve(avatarPromptResult)
611
+ else
612
+ promise:Reject(avatarPromptResult)
613
+ end
594
614
  end))
595
615
 
596
616
  local ok, err = pcall(function()
@@ -626,7 +646,11 @@ function AvatarEditorUtils.promptSetFavorite(itemId: number, itemType: AvatarIte
626
646
  end)
627
647
 
628
648
  maid:GiveTask(AvatarEditorService.PromptSetFavoriteCompleted:Connect(function(avatarPromptResult)
629
- promise:Resolve(avatarPromptResult)
649
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
650
+ promise:Resolve(avatarPromptResult)
651
+ else
652
+ promise:Reject(avatarPromptResult)
653
+ end
630
654
  end))
631
655
 
632
656
  local ok, err = pcall(function()
@@ -662,7 +686,11 @@ function AvatarEditorUtils.promptUpdateOutfit(outfitId: number, updatedOutfit: H
662
686
  end)
663
687
 
664
688
  maid:GiveTask(AvatarEditorService.PromptUpdateOutfitCompleted:Connect(function(avatarPromptResult)
665
- promise:Resolve(avatarPromptResult)
689
+ if avatarPromptResult == Enum.AvatarPromptResult.Success then
690
+ promise:Resolve(avatarPromptResult)
691
+ else
692
+ promise:Reject(avatarPromptResult)
693
+ end
666
694
  end))
667
695
 
668
696
  local ok, err = pcall(function()
@@ -6,6 +6,9 @@ local require = require(script.Parent.loader).load(script)
6
6
 
7
7
  local MemorizeUtils = require("MemorizeUtils")
8
8
  local AvatarEditorUtils = require("AvatarEditorUtils")
9
+ local Aggregator = require("Aggregator")
10
+ local Maid = require("Maid")
11
+ local PagesProxy = require("PagesProxy")
9
12
 
10
13
  local CatalogSearchServiceCache = {}
11
14
  CatalogSearchServiceCache.ServiceName = "CatalogSearchServiceCache"
@@ -13,14 +16,22 @@ CatalogSearchServiceCache.ServiceName = "CatalogSearchServiceCache"
13
16
  function CatalogSearchServiceCache:Init(serviceBag)
14
17
  assert(not self._serviceBag, "Already initialized")
15
18
  self._serviceBag = assert(serviceBag, "No serviceBag")
19
+ self._maid = Maid.new()
16
20
 
21
+ -- TODO: If you scroll down long enough this leaks memory
17
22
  self._promiseSearchCatalog = MemorizeUtils.memoize(function(params)
18
23
  return AvatarEditorUtils.promiseSearchCatalog(params)
24
+ :Then(function(catalogPages)
25
+ return PagesProxy.new(catalogPages)
26
+ end)
19
27
  end)
20
28
 
21
- self._promiseInventoryPages = MemorizeUtils.memoize(function(avatarAssetTypes)
22
- return AvatarEditorUtils.promiseInventoryPages(avatarAssetTypes)
23
- end)
29
+ self._assetAggregator = self._maid:Add(Aggregator.new("AvatarEditorUtils.promiseBatchItemDetails", function(itemIds)
30
+ return AvatarEditorUtils.promiseBatchItemDetails(itemIds, Enum.AvatarItemType.Asset)
31
+ end))
32
+ self._bundleAggregator = self._maid:Add(Aggregator.new("AvatarEditorUtils.promiseBatchItemDetails", function(itemIds)
33
+ return AvatarEditorUtils.promiseBatchItemDetails(itemIds, Enum.AvatarItemType.Bundle)
34
+ end))
24
35
  end
25
36
 
26
37
  function CatalogSearchServiceCache:PromiseAvatarRules()
@@ -32,12 +43,25 @@ function CatalogSearchServiceCache:PromiseAvatarRules()
32
43
  return self._avatarRulesPromise
33
44
  end
34
45
 
46
+ function CatalogSearchServiceCache:PromiseItemDetails(assetId, avatarItemType)
47
+ if avatarItemType == Enum.AvatarItemType.Asset then
48
+ return self._assetAggregator:Promise(assetId)
49
+ elseif avatarItemType == Enum.AvatarItemType.Bundle then
50
+ return self._bundleAggregator:Promise(assetId)
51
+ else
52
+ error("Unknown avatarItemType")
53
+ end
54
+ end
55
+
35
56
  function CatalogSearchServiceCache:PromiseSearchCatalog(params)
36
57
  return self._promiseSearchCatalog(params)
58
+ :Then(function(pagesProxy)
59
+ return pagesProxy:Clone()
60
+ end)
37
61
  end
38
62
 
39
- function CatalogSearchServiceCache:PromiseInventoryPages(avatarAssetTypes)
40
- return self._promiseInventoryPages(avatarAssetTypes)
63
+ function CatalogSearchServiceCache:Destroy()
64
+ self._maid:DoCleaning()
41
65
  end
42
66
 
43
67
  return CatalogSearchServiceCache