@quenty/observablecollection 12.10.1-canary.513.484c203.0 → 12.11.1
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,17 +3,17 @@
|
|
|
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
|
-
## [12.
|
|
6
|
+
## [12.11.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/observablecollection@12.11.0...@quenty/observablecollection@12.11.1) (2024-11-04)
|
|
7
7
|
|
|
8
|
+
**Note:** Version bump only for package @quenty/observablecollection
|
|
8
9
|
|
|
9
|
-
### Features
|
|
10
10
|
|
|
11
|
-
* Add __iter implementations ([b8e614a](https://github.com/Quenty/NevermoreEngine/commit/b8e614a8fda875c03237dc6cde18cf817beec0c4))
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
### Performance Improvements
|
|
15
13
|
|
|
16
|
-
|
|
14
|
+
# [12.11.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/observablecollection@12.10.0...@quenty/observablecollection@12.11.0) (2024-11-03)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @quenty/observablecollection
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/observablecollection",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.11.1",
|
|
4
4
|
"description": "A set of observable collections, such as sets, maps, sorted lists, and more.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -27,23 +27,23 @@
|
|
|
27
27
|
"Quenty"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@quenty/baseobject": "10.7.
|
|
31
|
-
"@quenty/brio": "14.
|
|
32
|
-
"@quenty/ducktype": "5.7.
|
|
33
|
-
"@quenty/loader": "10.7.
|
|
34
|
-
"@quenty/maid": "3.4.0",
|
|
35
|
-
"@quenty/promise": "10.7.1
|
|
36
|
-
"@quenty/rx": "13.
|
|
37
|
-
"@quenty/signal": "7.8.
|
|
38
|
-
"@quenty/steputils": "3.5.2",
|
|
39
|
-
"@quenty/symbol": "3.2.0",
|
|
40
|
-
"@quenty/valueobject": "13.
|
|
30
|
+
"@quenty/baseobject": "^10.7.1",
|
|
31
|
+
"@quenty/brio": "^14.11.1",
|
|
32
|
+
"@quenty/ducktype": "^5.7.1",
|
|
33
|
+
"@quenty/loader": "^10.7.1",
|
|
34
|
+
"@quenty/maid": "^3.4.0",
|
|
35
|
+
"@quenty/promise": "^10.7.1",
|
|
36
|
+
"@quenty/rx": "^13.11.1",
|
|
37
|
+
"@quenty/signal": "^7.8.1",
|
|
38
|
+
"@quenty/steputils": "^3.5.2",
|
|
39
|
+
"@quenty/symbol": "^3.2.0",
|
|
40
|
+
"@quenty/valueobject": "^13.11.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@quenty/blend": "12.
|
|
43
|
+
"@quenty/blend": "^12.11.1"
|
|
44
44
|
},
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "01c43a0ddd3c5e0cb2d9027313dbfa9852eedef1"
|
|
49
49
|
}
|
|
@@ -73,15 +73,6 @@ function ObservableCountingMap.isObservableMap(value)
|
|
|
73
73
|
return DuckTypeUtils.isImplementation(ObservableCountingMap, value)
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
--[=[
|
|
77
|
-
Allows iteration over the observable counting map
|
|
78
|
-
|
|
79
|
-
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
80
|
-
]=]
|
|
81
|
-
function ObservableCountingMap:__iter()
|
|
82
|
-
return pairs(self._map)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
76
|
--[=[
|
|
86
77
|
Observes the current set of active keys
|
|
87
78
|
@return Observable<{ T }>
|
|
@@ -89,19 +89,6 @@ function ObservableList:Observe()
|
|
|
89
89
|
})
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
--[=[
|
|
93
|
-
Allows iteration over the observable map
|
|
94
|
-
|
|
95
|
-
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
96
|
-
]=]
|
|
97
|
-
function ObservableList:__iter()
|
|
98
|
-
return coroutine.wrap(function()
|
|
99
|
-
for index, value in self._keyList do
|
|
100
|
-
coroutine.yield(index, self._contents[value])
|
|
101
|
-
end
|
|
102
|
-
end)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
92
|
--[=[
|
|
106
93
|
Observes all items in the list
|
|
107
94
|
@return Observable<Brio<T>>
|
|
@@ -74,16 +74,6 @@ function ObservableMap.isObservableMap(value)
|
|
|
74
74
|
return DuckTypeUtils.isImplementation(ObservableMap, value)
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
--[=[
|
|
78
|
-
Allows iteration over the observable map
|
|
79
|
-
|
|
80
|
-
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
81
|
-
]=]
|
|
82
|
-
function ObservableMap:__iter()
|
|
83
|
-
return pairs(self._map)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
|
|
87
77
|
--[=[
|
|
88
78
|
Observes all keys in the map
|
|
89
79
|
@return Observable<Brio<TKey>>
|
|
@@ -65,15 +65,6 @@ function ObservableSet.isObservableSet(value)
|
|
|
65
65
|
return DuckTypeUtils.isImplementation(ObservableSet, value)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
--[=[
|
|
69
|
-
Allows iteration over the observable set
|
|
70
|
-
|
|
71
|
-
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
72
|
-
]=]
|
|
73
|
-
function ObservableSet:__iter()
|
|
74
|
-
return pairs(self._set)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
68
|
--[=[
|
|
78
69
|
Observes all items in the set
|
|
79
70
|
@return Observable<Brio<T>>
|
|
@@ -60,12 +60,13 @@ function ObservableSortedList.new(isReversed, compare)
|
|
|
60
60
|
|
|
61
61
|
self._indexObservers = self._maid:Add(ObservableSubscriptionTable.new())
|
|
62
62
|
self._contentIndexObservers = self._maid:Add(ObservableSubscriptionTable.new())
|
|
63
|
-
self._keyObservables = self._maid:Add(ObservableSubscriptionTable.new())
|
|
64
63
|
|
|
65
64
|
self._sortValue = {} -- { [Symbol]: number }
|
|
66
65
|
self._contents = {} -- { [Symbol]: T }
|
|
67
66
|
self._indexes = {} -- { [Symbol]: number }
|
|
68
67
|
|
|
68
|
+
self._keyObservables = {} -- { [Symbol]: { Subscription } }
|
|
69
|
+
|
|
69
70
|
self._isReversed = isReversed or false
|
|
70
71
|
self._compare = compare or defaultCompare
|
|
71
72
|
|
|
@@ -123,19 +124,6 @@ function ObservableSortedList:Observe()
|
|
|
123
124
|
})
|
|
124
125
|
end
|
|
125
126
|
|
|
126
|
-
--[=[
|
|
127
|
-
Allows iteration over the observable map
|
|
128
|
-
|
|
129
|
-
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
130
|
-
]=]
|
|
131
|
-
function ObservableSortedList:__iter()
|
|
132
|
-
return coroutine.wrap(function()
|
|
133
|
-
for index, value in self._keyList do
|
|
134
|
-
coroutine.yield(index, self._contents[value])
|
|
135
|
-
end
|
|
136
|
-
end)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
127
|
function ObservableSortedList:Contains(value)
|
|
140
128
|
-- TODO: Binary search
|
|
141
129
|
for _, item in pairs(self._contents) do
|
|
@@ -251,16 +239,33 @@ end
|
|
|
251
239
|
function ObservableSortedList:ObserveIndexByKey(key)
|
|
252
240
|
assert(Symbol.isSymbol(key), "Bad key")
|
|
253
241
|
|
|
254
|
-
return
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
242
|
+
return Observable.new(function(sub)
|
|
243
|
+
local maid = Maid.new()
|
|
244
|
+
self._keyObservables[key] = self._keyObservables[key] or {}
|
|
245
|
+
table.insert(self._keyObservables[key], sub)
|
|
246
|
+
|
|
247
|
+
local currentIndex = self._indexes[key]
|
|
248
|
+
if currentIndex then
|
|
249
|
+
sub:Fire(currentIndex)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
maid:GiveTask(function()
|
|
253
|
+
local list = self._keyObservables[key]
|
|
254
|
+
if not list then
|
|
255
|
+
return
|
|
261
256
|
end
|
|
262
|
-
|
|
263
|
-
|
|
257
|
+
|
|
258
|
+
local index = table.find(list, sub)
|
|
259
|
+
if index then
|
|
260
|
+
table.remove(list, index)
|
|
261
|
+
if #list == 0 then
|
|
262
|
+
self._keyObservables[key] = nil
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end)
|
|
266
|
+
|
|
267
|
+
return maid
|
|
268
|
+
end)
|
|
264
269
|
end
|
|
265
270
|
|
|
266
271
|
--[=[
|
|
@@ -332,10 +337,15 @@ function ObservableSortedList:Add(item, observeValue)
|
|
|
332
337
|
end
|
|
333
338
|
|
|
334
339
|
maid:GiveTask(function()
|
|
340
|
+
local observableSubs = self._keyObservables[key]
|
|
341
|
+
self._keyObservables[key] = nil
|
|
342
|
+
|
|
335
343
|
self:_removeItemByKey(key, item)
|
|
336
344
|
|
|
337
345
|
-- Fire off the index change on the value
|
|
338
|
-
|
|
346
|
+
if observableSubs then
|
|
347
|
+
self:_completeSubs(observableSubs)
|
|
348
|
+
end
|
|
339
349
|
|
|
340
350
|
self._contents[key] = nil
|
|
341
351
|
self._sortValue[key] = nil
|
|
@@ -349,7 +359,7 @@ function ObservableSortedList:Add(item, observeValue)
|
|
|
349
359
|
end
|
|
350
360
|
|
|
351
361
|
function ObservableSortedList:_assignSortValue(key, item, sortValue)
|
|
352
|
-
|
|
362
|
+
self:_debugVerifyIntegrity()
|
|
353
363
|
|
|
354
364
|
if sortValue ~= nil then
|
|
355
365
|
local currentIndex = self._indexes[key]
|
|
@@ -358,12 +368,18 @@ function ObservableSortedList:_assignSortValue(key, item, sortValue)
|
|
|
358
368
|
self._sortValue[key] = sortValue
|
|
359
369
|
self:_updateIndex(key, item, targetIndex, sortValue)
|
|
360
370
|
else
|
|
371
|
+
local observableSubs = self._keyObservables[key]
|
|
372
|
+
|
|
361
373
|
-- calling this also may unsubscribe some observables.
|
|
362
374
|
self:_removeItemByKey(key, item)
|
|
363
|
-
|
|
375
|
+
|
|
376
|
+
if observableSubs then
|
|
377
|
+
-- fire nil index
|
|
378
|
+
self:_fireSubs(observableSubs, nil)
|
|
379
|
+
end
|
|
364
380
|
end
|
|
365
381
|
|
|
366
|
-
|
|
382
|
+
self:_debugVerifyIntegrity()
|
|
367
383
|
end
|
|
368
384
|
|
|
369
385
|
|
|
@@ -580,7 +596,11 @@ function ObservableSortedList:_queueDeferredChange()
|
|
|
580
596
|
if self._indexes[lastChange.key] == lastChange.newIndex then
|
|
581
597
|
changed = true
|
|
582
598
|
|
|
583
|
-
self._keyObservables
|
|
599
|
+
local subs = self._keyObservables[lastChange.key]
|
|
600
|
+
if subs then
|
|
601
|
+
self:_fireSubs(subs, lastChange.newIndex)
|
|
602
|
+
end
|
|
603
|
+
|
|
584
604
|
self._indexObservers:Fire(lastChange.newIndex, self._contents[lastChange.key])
|
|
585
605
|
end
|
|
586
606
|
end
|
|
@@ -662,9 +682,7 @@ function ObservableSortedList:_lowBinarySearch(sortValue)
|
|
|
662
682
|
while true do
|
|
663
683
|
local mid = math.floor((minIndex + maxIndex) / 2)
|
|
664
684
|
local compareValue = self._compare(self._sortValue[self._keyList[mid]], sortValue)
|
|
665
|
-
|
|
666
|
-
error(string.format("Bad compareValue, expected number, got %q", type(compareValue)))
|
|
667
|
-
end
|
|
685
|
+
assert(type(compareValue) == "number", "Expecting number")
|
|
668
686
|
|
|
669
687
|
if self._isReversed then
|
|
670
688
|
compareValue = -compareValue
|
|
@@ -684,6 +702,16 @@ function ObservableSortedList:_lowBinarySearch(sortValue)
|
|
|
684
702
|
end
|
|
685
703
|
end
|
|
686
704
|
|
|
705
|
+
function ObservableSortedList:_debugSortValuesToString()
|
|
706
|
+
local values = {}
|
|
707
|
+
|
|
708
|
+
for _, key in pairs(self._keyList) do
|
|
709
|
+
table.insert(values, string.format("%4d", self._sortValue[key]))
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
return table.concat(values, ", ")
|
|
713
|
+
end
|
|
714
|
+
|
|
687
715
|
function ObservableSortedList:_debugVerifyIntegrity()
|
|
688
716
|
for i=2, #self._keyList do
|
|
689
717
|
local compare = self._compare(self._sortValue[self._keyList[i-1]], self._sortValue[self._keyList[i]])
|
|
@@ -702,14 +730,23 @@ function ObservableSortedList:_debugVerifyIntegrity()
|
|
|
702
730
|
end
|
|
703
731
|
end
|
|
704
732
|
|
|
705
|
-
function ObservableSortedList:
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
733
|
+
function ObservableSortedList:_fireSubs(list, index)
|
|
734
|
+
for _, sub in pairs(list) do
|
|
735
|
+
if sub:IsPending() then
|
|
736
|
+
task.spawn(function()
|
|
737
|
+
sub:Fire(index)
|
|
738
|
+
end)
|
|
739
|
+
end
|
|
710
740
|
end
|
|
741
|
+
end
|
|
711
742
|
|
|
712
|
-
|
|
743
|
+
function ObservableSortedList:_completeSubs(list)
|
|
744
|
+
for _, sub in pairs(list) do
|
|
745
|
+
if sub:IsPending() then
|
|
746
|
+
sub:Fire(nil)
|
|
747
|
+
sub:Complete()
|
|
748
|
+
end
|
|
749
|
+
end
|
|
713
750
|
end
|
|
714
751
|
|
|
715
752
|
--[=[
|