@quenty/observablecollection 12.20.0 → 12.20.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 +11 -0
- package/package.json +15 -15
- package/src/Shared/ObservableCountingMap.lua +102 -81
- package/src/Shared/ObservableList.lua +91 -70
- package/src/Shared/ObservableMap.lua +100 -78
- package/src/Shared/ObservableMapList.lua +2 -2
- package/src/Shared/ObservableMapSet.lua +83 -41
- package/src/Shared/ObservableSet.lua +61 -34
- package/src/Shared/SortedList/ObservableSortedList.lua +128 -58
- package/src/Shared/SortedList/ObservableSortedList.story.lua +1 -1
- package/src/Shared/SortedList/SortFunctionUtils.lua +25 -8
- package/src/Shared/SortedList/SortedNode.lua +231 -116
- package/src/Shared/SortedList/SortedNodeValue.lua +17 -6
- package/src/Shared/Utils/ListIndexUtils.lua +9 -2
- package/test/scripts/Server/ServerMain.server.lua +1 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
--strict
|
|
1
2
|
--[=[
|
|
2
3
|
A list that can be observed for blend and other components and maintains sorting order.
|
|
3
4
|
|
|
@@ -35,16 +36,38 @@ local ObservableSortedList = {}
|
|
|
35
36
|
ObservableSortedList.ClassName = "ObservableSortedList"
|
|
36
37
|
ObservableSortedList.__index = ObservableSortedList
|
|
37
38
|
|
|
39
|
+
export type CompareFunction<T> = (T, T) -> number
|
|
40
|
+
|
|
41
|
+
export type ObservableSortedList<T> = typeof(setmetatable(
|
|
42
|
+
{} :: {
|
|
43
|
+
_maid: Maid.Maid,
|
|
44
|
+
_root: SortedNode.SortedNode<T>?,
|
|
45
|
+
_nodesAdded: { [SortedNode.SortedNode<T>]: boolean },
|
|
46
|
+
_nodesRemoved: { [SortedNode.SortedNode<T>]: boolean },
|
|
47
|
+
_lowestIndexChanged: number?,
|
|
48
|
+
_compare: CompareFunction<T>,
|
|
49
|
+
_countValue: ValueObject.ValueObject<number>,
|
|
50
|
+
_indexObservers: any,
|
|
51
|
+
_nodeIndexObservables: any,
|
|
52
|
+
_mainObservables: any,
|
|
53
|
+
ItemAdded: Signal.Signal<T, number, SortedNode.SortedNode<T>>,
|
|
54
|
+
ItemRemoved: Signal.Signal<T, SortedNode.SortedNode<T>>,
|
|
55
|
+
OrderChanged: Signal.Signal<()>,
|
|
56
|
+
CountChanged: Signal.Signal<number>,
|
|
57
|
+
},
|
|
58
|
+
ObservableSortedList
|
|
59
|
+
))
|
|
60
|
+
|
|
38
61
|
--[=[
|
|
39
62
|
Constructs a new ObservableSortedList
|
|
40
63
|
@param isReversed boolean
|
|
41
64
|
@param compare function
|
|
42
65
|
@return ObservableSortedList<T>
|
|
43
66
|
]=]
|
|
44
|
-
function ObservableSortedList.new(isReversed
|
|
67
|
+
function ObservableSortedList.new<T>(isReversed: boolean?, compare: CompareFunction<T>): ObservableSortedList<T>
|
|
45
68
|
assert(type(isReversed) == "boolean" or isReversed == nil, "Bad isReversed")
|
|
46
69
|
|
|
47
|
-
local self = setmetatable({}, ObservableSortedList)
|
|
70
|
+
local self = setmetatable({} :: any, ObservableSortedList)
|
|
48
71
|
|
|
49
72
|
self._maid = Maid.new()
|
|
50
73
|
|
|
@@ -61,7 +84,7 @@ function ObservableSortedList.new(isReversed, compare)
|
|
|
61
84
|
|
|
62
85
|
self._countValue = self._maid:Add(ValueObject.new(0, "number"))
|
|
63
86
|
|
|
64
|
-
--[=[
|
|
87
|
+
--[=[
|
|
65
88
|
Fires when an item is added
|
|
66
89
|
|
|
67
90
|
@readonly
|
|
@@ -70,7 +93,7 @@ function ObservableSortedList.new(isReversed, compare)
|
|
|
70
93
|
]=]
|
|
71
94
|
self.ItemAdded = self._maid:Add(Signal.new())
|
|
72
95
|
|
|
73
|
-
--[=[
|
|
96
|
+
--[=[
|
|
74
97
|
Fires when an item is removed.
|
|
75
98
|
|
|
76
99
|
@readonly
|
|
@@ -79,7 +102,7 @@ function ObservableSortedList.new(isReversed, compare)
|
|
|
79
102
|
]=]
|
|
80
103
|
self.ItemRemoved = self._maid:Add(Signal.new())
|
|
81
104
|
|
|
82
|
-
--[=[
|
|
105
|
+
--[=[
|
|
83
106
|
Fires when the order could have changed
|
|
84
107
|
|
|
85
108
|
@readonly
|
|
@@ -88,8 +111,7 @@ function ObservableSortedList.new(isReversed, compare)
|
|
|
88
111
|
]=]
|
|
89
112
|
self.OrderChanged = self._maid:Add(Signal.new())
|
|
90
113
|
|
|
91
|
-
|
|
92
|
-
--[=[
|
|
114
|
+
--[=[
|
|
93
115
|
Fires when the count changes
|
|
94
116
|
|
|
95
117
|
@readonly
|
|
@@ -106,7 +128,7 @@ end
|
|
|
106
128
|
@param value any
|
|
107
129
|
@return boolean
|
|
108
130
|
]=]
|
|
109
|
-
function ObservableSortedList.isObservableSortedList(value)
|
|
131
|
+
function ObservableSortedList.isObservableSortedList(value: any): boolean
|
|
110
132
|
return DuckTypeUtils.isImplementation(ObservableSortedList, value)
|
|
111
133
|
end
|
|
112
134
|
|
|
@@ -115,11 +137,11 @@ end
|
|
|
115
137
|
|
|
116
138
|
@return Observable<{ T }>
|
|
117
139
|
]=]
|
|
118
|
-
function ObservableSortedList
|
|
140
|
+
function ObservableSortedList.Observe<T>(self: ObservableSortedList<T>): Observable.Observable<{ T }>
|
|
119
141
|
return self._mainObservables:Observe("list"):Pipe({
|
|
120
142
|
Rx.start(function()
|
|
121
143
|
return self:GetList()
|
|
122
|
-
end)
|
|
144
|
+
end),
|
|
123
145
|
})
|
|
124
146
|
end
|
|
125
147
|
|
|
@@ -128,7 +150,7 @@ end
|
|
|
128
150
|
|
|
129
151
|
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
130
152
|
]=]
|
|
131
|
-
function ObservableSortedList
|
|
153
|
+
function ObservableSortedList.__iter<T>(self: ObservableSortedList<T>): SortFunctionUtils.WrappedIterator<number, T>
|
|
132
154
|
if self._root then
|
|
133
155
|
return self._root:IterateData()
|
|
134
156
|
else
|
|
@@ -143,15 +165,21 @@ end
|
|
|
143
165
|
@param finish number
|
|
144
166
|
@return (T) -> ((T, nextIndex: any) -> ...any, T?)
|
|
145
167
|
]=]
|
|
146
|
-
function ObservableSortedList
|
|
168
|
+
function ObservableSortedList.IterateRange<T>(
|
|
169
|
+
self: ObservableSortedList<T>,
|
|
170
|
+
start: number,
|
|
171
|
+
finish: number
|
|
172
|
+
): SortFunctionUtils.WrappedIterator<number, T>
|
|
147
173
|
return coroutine.wrap(function()
|
|
148
|
-
for index, node in self:_iterateNodesRange(start, finish) do
|
|
174
|
+
for index: number, node in self:_iterateNodesRange(start, finish) do
|
|
149
175
|
coroutine.yield(index, node.data)
|
|
150
176
|
end
|
|
151
|
-
end)
|
|
177
|
+
end) :: any
|
|
152
178
|
end
|
|
153
179
|
|
|
154
|
-
function ObservableSortedList
|
|
180
|
+
function ObservableSortedList._iterateNodes<T>(
|
|
181
|
+
self: ObservableSortedList<T>
|
|
182
|
+
): SortFunctionUtils.WrappedIterator<number, SortedNode.SortedNode<T>>
|
|
155
183
|
if self._root then
|
|
156
184
|
return self._root:IterateNodes()
|
|
157
185
|
else
|
|
@@ -159,7 +187,11 @@ function ObservableSortedList:_iterateNodes()
|
|
|
159
187
|
end
|
|
160
188
|
end
|
|
161
189
|
|
|
162
|
-
function ObservableSortedList
|
|
190
|
+
function ObservableSortedList._iterateNodesRange<T>(
|
|
191
|
+
self: ObservableSortedList<T>,
|
|
192
|
+
start: number,
|
|
193
|
+
finish: number
|
|
194
|
+
): SortFunctionUtils.WrappedIterator<number, SortedNode.SortedNode<T>>
|
|
163
195
|
if self._root then
|
|
164
196
|
return self._root:IterateNodesRange(start, finish)
|
|
165
197
|
else
|
|
@@ -167,7 +199,7 @@ function ObservableSortedList:_iterateNodesRange(start, finish)
|
|
|
167
199
|
end
|
|
168
200
|
end
|
|
169
201
|
|
|
170
|
-
function ObservableSortedList
|
|
202
|
+
function ObservableSortedList._containsNode<T>(self: ObservableSortedList<T>, node: SortedNode.SortedNode<T>): boolean
|
|
171
203
|
assert(SortedNode.isSortedNode(node), "Bad node")
|
|
172
204
|
|
|
173
205
|
if self._root then
|
|
@@ -177,7 +209,10 @@ function ObservableSortedList:_containsNode(node)
|
|
|
177
209
|
end
|
|
178
210
|
end
|
|
179
211
|
|
|
180
|
-
function ObservableSortedList
|
|
212
|
+
function ObservableSortedList._findNodeForDataLinearSearchSlow<T>(
|
|
213
|
+
self: ObservableSortedList<T>,
|
|
214
|
+
data: T
|
|
215
|
+
): SortedNode.SortedNode<T>?
|
|
181
216
|
if self._root then
|
|
182
217
|
return self._root:FindFirstNodeForData(data)
|
|
183
218
|
else
|
|
@@ -185,7 +220,7 @@ function ObservableSortedList:_findNodeForDataLinearSearchSlow(data)
|
|
|
185
220
|
end
|
|
186
221
|
end
|
|
187
222
|
|
|
188
|
-
function ObservableSortedList
|
|
223
|
+
function ObservableSortedList._findNodeAtIndex<T>(self: ObservableSortedList<T>, index: number): SortedNode.SortedNode<T>?
|
|
189
224
|
assert(type(index) == "number", "Bad index")
|
|
190
225
|
|
|
191
226
|
if self._root then
|
|
@@ -195,7 +230,7 @@ function ObservableSortedList:_findNodeAtIndex(index)
|
|
|
195
230
|
end
|
|
196
231
|
end
|
|
197
232
|
|
|
198
|
-
function ObservableSortedList
|
|
233
|
+
function ObservableSortedList._findNodeIndex<T>(self: ObservableSortedList<T>, node: SortedNode.SortedNode<T>): number?
|
|
199
234
|
assert(SortedNode.isSortedNode(node), "Bad node")
|
|
200
235
|
|
|
201
236
|
if self._root then
|
|
@@ -211,11 +246,11 @@ end
|
|
|
211
246
|
@param content T
|
|
212
247
|
@return Symbol
|
|
213
248
|
]=]
|
|
214
|
-
function ObservableSortedList
|
|
249
|
+
function ObservableSortedList.FindFirstKey<T>(self: ObservableSortedList<T>, content: T): SortedNode.SortedNode<T>?
|
|
215
250
|
return self:_findNodeForDataLinearSearchSlow(content)
|
|
216
251
|
end
|
|
217
252
|
|
|
218
|
-
function ObservableSortedList
|
|
253
|
+
function ObservableSortedList.PrintDebug<T>(self: ObservableSortedList<T>)
|
|
219
254
|
print(self._root)
|
|
220
255
|
end
|
|
221
256
|
|
|
@@ -225,7 +260,7 @@ end
|
|
|
225
260
|
@param content T
|
|
226
261
|
@return boolean
|
|
227
262
|
]=]
|
|
228
|
-
function ObservableSortedList
|
|
263
|
+
function ObservableSortedList.Contains<T>(self: ObservableSortedList<T>, content): boolean
|
|
229
264
|
assert(content ~= nil, "Bad content")
|
|
230
265
|
|
|
231
266
|
-- TODO: Speed up
|
|
@@ -236,14 +271,16 @@ end
|
|
|
236
271
|
Observes all items in the list
|
|
237
272
|
@return Observable<Brio<T, Symbol>>
|
|
238
273
|
]=]
|
|
239
|
-
function ObservableSortedList
|
|
274
|
+
function ObservableSortedList.ObserveItemsBrio<T>(
|
|
275
|
+
self: ObservableSortedList<T>
|
|
276
|
+
): Observable.Observable<Brio.Brio<T, SortedNode.SortedNode<T>>>
|
|
240
277
|
return Observable.new(function(sub)
|
|
241
278
|
local maid = Maid.new()
|
|
242
279
|
|
|
243
280
|
-- TODO: Optimize this so we don't have to make so many brios and connect
|
|
244
281
|
-- to so many events
|
|
245
282
|
|
|
246
|
-
local function handleItem(data, _index, node)
|
|
283
|
+
local function handleItem(data: T, _index, node)
|
|
247
284
|
local brio = Brio.new(data, node)
|
|
248
285
|
maid[node] = brio
|
|
249
286
|
sub:Fire(brio)
|
|
@@ -267,7 +304,7 @@ function ObservableSortedList:ObserveItemsBrio()
|
|
|
267
304
|
end)
|
|
268
305
|
|
|
269
306
|
return maid
|
|
270
|
-
end)
|
|
307
|
+
end) :: any
|
|
271
308
|
end
|
|
272
309
|
|
|
273
310
|
--[=[
|
|
@@ -277,12 +314,20 @@ end
|
|
|
277
314
|
@param indexToObserve number
|
|
278
315
|
@return Observable<number>
|
|
279
316
|
]=]
|
|
280
|
-
function ObservableSortedList
|
|
317
|
+
function ObservableSortedList.ObserveIndex<T>(
|
|
318
|
+
self: ObservableSortedList<T>,
|
|
319
|
+
indexToObserve: number
|
|
320
|
+
): Observable.Observable<number>
|
|
281
321
|
assert(type(indexToObserve) == "number", "Bad indexToObserve")
|
|
282
322
|
|
|
283
323
|
local node = self:_findNodeAtIndex(indexToObserve)
|
|
284
324
|
if not node then
|
|
285
|
-
error(
|
|
325
|
+
error(
|
|
326
|
+
string.format(
|
|
327
|
+
"[ObservableSortedList.ObserveIndex] - No entry at index %d, cannot observe changes",
|
|
328
|
+
indexToObserve
|
|
329
|
+
)
|
|
330
|
+
)
|
|
286
331
|
end
|
|
287
332
|
|
|
288
333
|
return self:ObserveIndexByKey(node)
|
|
@@ -295,7 +340,10 @@ end
|
|
|
295
340
|
@param indexToObserve number
|
|
296
341
|
@return Observable<(T, Key)>
|
|
297
342
|
]=]
|
|
298
|
-
function ObservableSortedList
|
|
343
|
+
function ObservableSortedList.ObserveAtIndex<T>(
|
|
344
|
+
self: ObservableSortedList<T>,
|
|
345
|
+
indexToObserve: number
|
|
346
|
+
): Observable.Observable<T, SortedNode.SortedNode<T>>
|
|
299
347
|
assert(type(indexToObserve) == "number", "Bad indexToObserve")
|
|
300
348
|
|
|
301
349
|
return self._indexObservers:Observe(indexToObserve, function(sub)
|
|
@@ -305,7 +353,7 @@ function ObservableSortedList:ObserveAtIndex(indexToObserve)
|
|
|
305
353
|
else
|
|
306
354
|
sub:Fire(nil, nil)
|
|
307
355
|
end
|
|
308
|
-
end)
|
|
356
|
+
end) :: any
|
|
309
357
|
end
|
|
310
358
|
|
|
311
359
|
--[=[
|
|
@@ -315,7 +363,10 @@ end
|
|
|
315
363
|
@param node SortedNode
|
|
316
364
|
@return Observable<number>
|
|
317
365
|
]=]
|
|
318
|
-
function ObservableSortedList
|
|
366
|
+
function ObservableSortedList.ObserveIndexByKey<T>(
|
|
367
|
+
self: ObservableSortedList<T>,
|
|
368
|
+
node: SortedNode.SortedNode<T>
|
|
369
|
+
): Observable.Observable<number?>
|
|
319
370
|
assert(SortedNode.isSortedNode(node), "Bad node")
|
|
320
371
|
|
|
321
372
|
return self._nodeIndexObservables:Observe(node, function(sub)
|
|
@@ -323,7 +374,7 @@ function ObservableSortedList:ObserveIndexByKey(node)
|
|
|
323
374
|
if currentIndex then
|
|
324
375
|
sub:Fire(currentIndex)
|
|
325
376
|
end
|
|
326
|
-
end)
|
|
377
|
+
end) :: any
|
|
327
378
|
end
|
|
328
379
|
|
|
329
380
|
--[=[
|
|
@@ -332,7 +383,7 @@ end
|
|
|
332
383
|
@param node SortedNode
|
|
333
384
|
@return number
|
|
334
385
|
]=]
|
|
335
|
-
function ObservableSortedList
|
|
386
|
+
function ObservableSortedList.GetIndexByKey<T>(self: ObservableSortedList<T>, node: SortedNode.SortedNode<T>): number?
|
|
336
387
|
assert(SortedNode.isSortedNode(node), "Bad node")
|
|
337
388
|
|
|
338
389
|
return self:_findNodeIndex(node)
|
|
@@ -342,7 +393,7 @@ end
|
|
|
342
393
|
Gets the count of items in the list
|
|
343
394
|
@return number
|
|
344
395
|
]=]
|
|
345
|
-
function ObservableSortedList
|
|
396
|
+
function ObservableSortedList.GetCount<T>(self: ObservableSortedList<T>): number
|
|
346
397
|
return self._countValue.Value or 0
|
|
347
398
|
end
|
|
348
399
|
|
|
@@ -352,7 +403,7 @@ ObservableSortedList.__len = ObservableSortedList.GetCount
|
|
|
352
403
|
Gets a list of all entries.
|
|
353
404
|
@return { T }
|
|
354
405
|
]=]
|
|
355
|
-
function ObservableSortedList
|
|
406
|
+
function ObservableSortedList.GetList<T>(self: ObservableSortedList<T>): { T }
|
|
356
407
|
local list = table.create(self._countValue.Value)
|
|
357
408
|
for index, data in self:__iter() do
|
|
358
409
|
list[index] = data
|
|
@@ -364,7 +415,7 @@ end
|
|
|
364
415
|
Observes the count of the list
|
|
365
416
|
@return Observable<number>
|
|
366
417
|
]=]
|
|
367
|
-
function ObservableSortedList
|
|
418
|
+
function ObservableSortedList.ObserveCount<T>(self: ObservableSortedList<T>): Observable.Observable<number>
|
|
368
419
|
return self._countValue:Observe()
|
|
369
420
|
end
|
|
370
421
|
|
|
@@ -374,7 +425,11 @@ end
|
|
|
374
425
|
@param observeValue Observable<Comparable> | Comparable
|
|
375
426
|
@return callback -- Call to remove
|
|
376
427
|
]=]
|
|
377
|
-
function ObservableSortedList
|
|
428
|
+
function ObservableSortedList.Add<T>(
|
|
429
|
+
self: ObservableSortedList<T>,
|
|
430
|
+
data: T,
|
|
431
|
+
observeValue: Observable.Observable<number> | number
|
|
432
|
+
): () -> ()
|
|
378
433
|
assert(data ~= nil, "Bad data")
|
|
379
434
|
assert(Observable.isObservable(observeValue) or observeValue ~= nil, "Bad observeValue")
|
|
380
435
|
|
|
@@ -384,7 +439,7 @@ function ObservableSortedList:Add(data, observeValue)
|
|
|
384
439
|
local maid = Maid.new()
|
|
385
440
|
|
|
386
441
|
if Observable.isObservable(observeValue) then
|
|
387
|
-
maid:GiveTask(observeValue:Subscribe(function(sortValue)
|
|
442
|
+
maid:GiveTask((observeValue :: any):Subscribe(function(sortValue: number)
|
|
388
443
|
self:_assignSortValue(node, sortValue)
|
|
389
444
|
end))
|
|
390
445
|
elseif observeValue ~= nil then
|
|
@@ -406,9 +461,13 @@ function ObservableSortedList:Add(data, observeValue)
|
|
|
406
461
|
end
|
|
407
462
|
end
|
|
408
463
|
|
|
409
|
-
function ObservableSortedList
|
|
464
|
+
function ObservableSortedList._assignSortValue<T>(
|
|
465
|
+
self: ObservableSortedList<T>,
|
|
466
|
+
node: SortedNode.SortedNode<T>,
|
|
467
|
+
value: number?
|
|
468
|
+
): ()
|
|
410
469
|
if SortedNodeValue.isSortedNodeValue(node.value) then
|
|
411
|
-
if node.value:GetValue() == value then
|
|
470
|
+
if (node.value :: any):GetValue() == value then
|
|
412
471
|
return
|
|
413
472
|
end
|
|
414
473
|
elseif node.value == value then
|
|
@@ -435,7 +494,7 @@ function ObservableSortedList:_assignSortValue(node, value)
|
|
|
435
494
|
end
|
|
436
495
|
|
|
437
496
|
if self._compare ~= nil then
|
|
438
|
-
value = SortedNodeValue.new(value, self._compare)
|
|
497
|
+
value = SortedNodeValue.new(value, self._compare) :: any
|
|
439
498
|
end
|
|
440
499
|
|
|
441
500
|
-- our value changing didn't change anything
|
|
@@ -460,7 +519,7 @@ function ObservableSortedList:_assignSortValue(node, value)
|
|
|
460
519
|
self:_queueFireEvents()
|
|
461
520
|
end
|
|
462
521
|
|
|
463
|
-
function ObservableSortedList
|
|
522
|
+
function ObservableSortedList._applyLowestIndexChanged<T>(self: ObservableSortedList<T>, index: number)
|
|
464
523
|
if self._lowestIndexChanged == nil then
|
|
465
524
|
self._lowestIndexChanged = index
|
|
466
525
|
return
|
|
@@ -471,7 +530,7 @@ function ObservableSortedList:_applyLowestIndexChanged(index)
|
|
|
471
530
|
end
|
|
472
531
|
end
|
|
473
532
|
|
|
474
|
-
function ObservableSortedList
|
|
533
|
+
function ObservableSortedList._queueFireEvents<T>(self: ObservableSortedList<T>)
|
|
475
534
|
if self._maid._fireEvents then
|
|
476
535
|
return
|
|
477
536
|
end
|
|
@@ -482,7 +541,7 @@ function ObservableSortedList:_queueFireEvents()
|
|
|
482
541
|
end)
|
|
483
542
|
end
|
|
484
543
|
|
|
485
|
-
function ObservableSortedList
|
|
544
|
+
function ObservableSortedList._fireEvents<T>(self: ObservableSortedList<T>)
|
|
486
545
|
-- print(self._root)
|
|
487
546
|
|
|
488
547
|
local lowestIndexChanged = self._lowestIndexChanged
|
|
@@ -500,7 +559,9 @@ function ObservableSortedList:_fireEvents()
|
|
|
500
559
|
-- Fire count changed first
|
|
501
560
|
self._countValue.Value = newCount
|
|
502
561
|
|
|
503
|
-
if not self.Destroy then
|
|
562
|
+
if not self.Destroy then
|
|
563
|
+
return
|
|
564
|
+
end
|
|
504
565
|
|
|
505
566
|
-- TODO: Prevent Rx.of(itemAdded) stuff in our UI
|
|
506
567
|
for node in nodesAdded do
|
|
@@ -509,37 +570,46 @@ function ObservableSortedList:_fireEvents()
|
|
|
509
570
|
self.ItemAdded:Fire(node.data, index, node)
|
|
510
571
|
end
|
|
511
572
|
|
|
512
|
-
if not self.Destroy then
|
|
573
|
+
if not self.Destroy then
|
|
574
|
+
return
|
|
575
|
+
end
|
|
513
576
|
|
|
514
577
|
for node in nodesRemoved do
|
|
515
578
|
self.ItemRemoved:Fire(node.data, node)
|
|
516
579
|
end
|
|
517
580
|
|
|
518
|
-
if not self.Destroy then
|
|
581
|
+
if not self.Destroy then
|
|
582
|
+
return
|
|
583
|
+
end
|
|
519
584
|
|
|
520
585
|
self.OrderChanged:Fire()
|
|
521
586
|
|
|
522
|
-
if not self.Destroy then
|
|
587
|
+
if not self.Destroy then
|
|
588
|
+
return
|
|
589
|
+
end
|
|
523
590
|
|
|
524
591
|
do
|
|
592
|
+
local descendantCount = self._root and self._root.descendantCount or 0
|
|
525
593
|
for index, node in self:_iterateNodesRange(lowestIndexChanged) do
|
|
526
594
|
-- TODO: Handle negative observations to avoid refiring upon insertion
|
|
527
595
|
-- TODO: Handle our state changing while we're firing
|
|
528
596
|
-- TODO: Avoid looping over nodes if we don't need to (track observations in node itself?)
|
|
529
|
-
local negative = ListIndexUtils.toNegativeIndex(
|
|
597
|
+
local negative = ListIndexUtils.toNegativeIndex(descendantCount, index)
|
|
530
598
|
self._nodeIndexObservables:Fire(node, index)
|
|
531
599
|
self._indexObservers:Fire(index, node.data, node)
|
|
532
600
|
self._indexObservers:Fire(negative, node.data, node)
|
|
533
601
|
end
|
|
534
602
|
|
|
535
|
-
for index=newCount+1, lastCount do
|
|
603
|
+
for index = newCount + 1, lastCount do
|
|
536
604
|
self._indexObservers:Fire(index, nil, nil)
|
|
537
605
|
end
|
|
538
606
|
|
|
539
607
|
-- TODO: Fire negatives beyond range
|
|
540
608
|
end
|
|
541
609
|
|
|
542
|
-
if not self.Destroy then
|
|
610
|
+
if not self.Destroy then
|
|
611
|
+
return
|
|
612
|
+
end
|
|
543
613
|
|
|
544
614
|
if self._mainObservables:HasSubscriptions("list") then
|
|
545
615
|
-- TODO: Reuse list
|
|
@@ -548,7 +618,7 @@ function ObservableSortedList:_fireEvents()
|
|
|
548
618
|
end
|
|
549
619
|
end
|
|
550
620
|
|
|
551
|
-
function ObservableSortedList
|
|
621
|
+
function ObservableSortedList._insertNode<T>(self: ObservableSortedList<T>, node: SortedNode.SortedNode<T>)
|
|
552
622
|
assert(SortedNode.isSortedNode(node), "Bad SortedNode")
|
|
553
623
|
|
|
554
624
|
if self._root == nil then
|
|
@@ -559,7 +629,7 @@ function ObservableSortedList:_insertNode(node)
|
|
|
559
629
|
end
|
|
560
630
|
end
|
|
561
631
|
|
|
562
|
-
function ObservableSortedList
|
|
632
|
+
function ObservableSortedList._removeNode<T>(self: ObservableSortedList<T>, nodeToRemove: SortedNode.SortedNode<T>)
|
|
563
633
|
assert(SortedNode.isSortedNode(nodeToRemove), "Bad SortedNode")
|
|
564
634
|
|
|
565
635
|
if self._root ~= nil then
|
|
@@ -572,7 +642,7 @@ end
|
|
|
572
642
|
@param index number
|
|
573
643
|
@return T?
|
|
574
644
|
]=]
|
|
575
|
-
function ObservableSortedList
|
|
645
|
+
function ObservableSortedList.Get<T>(self: ObservableSortedList<T>, index: number): T?
|
|
576
646
|
assert(type(index) == "number", "Bad index")
|
|
577
647
|
|
|
578
648
|
local node = self:_findNodeAtIndex(index)
|
|
@@ -588,18 +658,18 @@ end
|
|
|
588
658
|
@param node SortedNode
|
|
589
659
|
@return T
|
|
590
660
|
]=]
|
|
591
|
-
function ObservableSortedList
|
|
661
|
+
function ObservableSortedList.RemoveByKey<T>(self: ObservableSortedList<T>, node: SortedNode.SortedNode<T>)
|
|
592
662
|
assert(SortedNode.isSortedNode(node), "Bad node")
|
|
593
663
|
|
|
594
|
-
self._maid[node] = nil
|
|
664
|
+
self._maid[node :: any] = nil
|
|
595
665
|
end
|
|
596
666
|
|
|
597
667
|
--[=[
|
|
598
668
|
Cleans up the ObservableSortedList and sets the metatable to nil.
|
|
599
669
|
]=]
|
|
600
|
-
function ObservableSortedList
|
|
670
|
+
function ObservableSortedList.Destroy<T>(self: ObservableSortedList<T>)
|
|
601
671
|
self._maid:DoCleaning()
|
|
602
|
-
setmetatable(self, nil)
|
|
672
|
+
setmetatable(self :: any, nil)
|
|
603
673
|
end
|
|
604
674
|
|
|
605
675
|
return ObservableSortedList
|
|
@@ -48,7 +48,7 @@ return function(target)
|
|
|
48
48
|
local results = {}
|
|
49
49
|
local inOrder = true
|
|
50
50
|
local lastValue = nil
|
|
51
|
-
for _, item in
|
|
51
|
+
for _, item in observableSortedList:GetList() do
|
|
52
52
|
if lastValue then
|
|
53
53
|
if item.scoreValue.Value < lastValue then
|
|
54
54
|
inOrder = false
|
|
@@ -1,20 +1,37 @@
|
|
|
1
|
+
--!strict
|
|
1
2
|
--[=[
|
|
2
3
|
@class SortFunctionUtils
|
|
3
4
|
]=]
|
|
4
5
|
|
|
5
|
-
local require = require(script.Parent.loader).load(script)
|
|
6
|
-
|
|
7
6
|
local SortFunctionUtils = {}
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
export type SortFunction<T> = (a: T, b: T) -> number
|
|
9
|
+
|
|
10
|
+
export type WrappedIterator<T...> = (...any) -> T...
|
|
11
|
+
|
|
12
|
+
--[=[
|
|
13
|
+
Reverses a given sort function
|
|
14
|
+
|
|
15
|
+
@param compare (a: T, b: T) -> number
|
|
16
|
+
@return (a: T, b: T) -> number
|
|
17
|
+
]=]
|
|
18
|
+
function SortFunctionUtils.reverse<T>(compare: SortFunction<T>?): SortFunction<T>
|
|
19
|
+
local comparison = compare or SortFunctionUtils.default
|
|
20
|
+
return function(a: T, b: T): number
|
|
21
|
+
return (comparison :: any)(b, a)
|
|
13
22
|
end
|
|
14
23
|
end
|
|
15
24
|
|
|
16
|
-
--
|
|
17
|
-
|
|
25
|
+
--[=[
|
|
26
|
+
Sorts a given list of items using the given compare function
|
|
27
|
+
|
|
28
|
+
Higher numbers last
|
|
29
|
+
|
|
30
|
+
@param a T
|
|
31
|
+
@param b T
|
|
32
|
+
@return number
|
|
33
|
+
]=]
|
|
34
|
+
function SortFunctionUtils.default(a: any, b: any): number
|
|
18
35
|
-- equivalent of `return a - b` except it supports comparison of strings and stuff
|
|
19
36
|
if b > a then
|
|
20
37
|
return -1
|