Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 057a69d

Browse files
committed
Added conditional sticky items.
Added a method that creates an observable collection that tracks an ITrackingCollection and adds a sticky item to the top of the collection when a related selection is null.
1 parent d19859d commit 057a69d

File tree

3 files changed

+162
-0
lines changed

3 files changed

+162
-0
lines changed

src/GitHub.Exports.Reactive/Collections/TrackingCollection.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,46 @@ public static ObservableCollection<T> CreateListenerCollection<T>(this ITracking
100100
};
101101
return col;
102102
}
103+
104+
/// <summary>
105+
/// Creates an observable collection that tracks an <see cref="ITrackingCollection{T}"/>
106+
/// and adds a sticky item to the top of the collection when a related selection is null.
107+
/// </summary>
108+
/// <typeparam name="T">The type of items in the collection.</typeparam>
109+
/// <param name="tcol">The source tracking collection</param>
110+
/// <param name="stickieItemOnTop">The sticky item to add to the top of the collection.</param>
111+
/// <param name="selection">
112+
/// The current selection. If null or equal to the sticky item then the sticky item will be
113+
/// added to the collection.
114+
/// </param>
115+
/// <returns>An <see cref="ObservableCollection{T}"/>.</returns>
116+
public static ObservableCollection<T> CreateListenerCollection<T>(this ITrackingCollection<T> tcol,
117+
T stickieItemOnTop,
118+
IObservable<T> selection)
119+
where T : class, ICopyable<T>
120+
{
121+
Debug.Assert(stickieItemOnTop != null, "stickieItemOnTop may not be null in CreateListenerCollection");
122+
Debug.Assert(selection != null, "selection may not be null in CreateListenerCollection");
123+
124+
var result = tcol.CreateListenerCollection(new[] { stickieItemOnTop });
125+
var addedStickieItem = true;
126+
127+
selection.Subscribe(x =>
128+
{
129+
if ((x == null || object.Equals(x, stickieItemOnTop)) && addedStickieItem)
130+
{
131+
result.Remove(stickieItemOnTop);
132+
addedStickieItem = false;
133+
}
134+
else if (x != null && !addedStickieItem)
135+
{
136+
result.Insert(0, stickieItemOnTop);
137+
addedStickieItem = true;
138+
}
139+
});
140+
141+
return result;
142+
}
103143
}
104144

105145
/// <summary>
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
using System;
2+
using System.Linq;
3+
using System.Reactive.Linq;
4+
using System.Reactive.Subjects;
5+
using GitHub.Collections;
6+
using NUnit.Framework;
7+
8+
[TestFixture]
9+
public class ListenerCollectionTests : TestBase
10+
{
11+
#if !DISABLE_REACTIVE_UI
12+
[TestFixtureSetUp]
13+
public void Setup()
14+
{
15+
Splat.ModeDetector.Current.SetInUnitTestRunner(true);
16+
}
17+
#endif
18+
19+
[Test]
20+
public void StickyItemShouldNotBePresentAfterCreationWhenSelectionNull()
21+
{
22+
var source = CreateSource();
23+
var stickie = new Thing();
24+
var selection = Observable.Return<Thing>(null);
25+
var target = source.CreateListenerCollection(stickie, selection);
26+
27+
CollectionAssert.AreEqual(source, target);
28+
}
29+
30+
[Test]
31+
public void StickyItemShouldBePresentAfterCreationWhenSelectionNotNull()
32+
{
33+
var source = CreateSource();
34+
var stickie = new Thing();
35+
var selection = Observable.Return(source[0]);
36+
var target = source.CreateListenerCollection(stickie, selection);
37+
38+
var expected = new[] { stickie }.Concat(source);
39+
CollectionAssert.AreEqual(expected, target);
40+
}
41+
42+
[Test]
43+
public void StickyItemShouldNotBePresentAfterCreationWhenSelectionIsStickyItem()
44+
{
45+
var source = CreateSource();
46+
var stickie = new Thing();
47+
var selection = Observable.Return(stickie);
48+
var target = source.CreateListenerCollection(stickie, selection);
49+
50+
CollectionAssert.AreEqual(source, target);
51+
}
52+
53+
[Test]
54+
public void StickyItemShouldNotBePresentAfterCreationWhenSelectionEqualsStickyItem()
55+
{
56+
var source = CreateSource();
57+
var stickie = new Thing();
58+
var selection = Observable.Return(new Thing());
59+
var target = source.CreateListenerCollection(stickie, selection);
60+
61+
CollectionAssert.AreEqual(source, target);
62+
}
63+
64+
[Test]
65+
public void StickyItemShouldBeAddedWhenSelectionChangesFromNull()
66+
{
67+
var source = CreateSource();
68+
var selection = new BehaviorSubject<Thing>(null);
69+
var stickie = new Thing();
70+
var target = source.CreateListenerCollection(stickie, selection);
71+
72+
CollectionAssert.AreEqual(source, target);
73+
74+
selection.OnNext(source[0]);
75+
76+
var expected = new[] { stickie }.Concat(source);
77+
CollectionAssert.AreEqual(expected, target);
78+
}
79+
80+
[Test]
81+
public void StickyItemShouldBeRemovedWhenSelectionChangesToNull()
82+
{
83+
var source = CreateSource();
84+
var stickie = new Thing();
85+
var selection = new BehaviorSubject<Thing>(source[0]);
86+
var target = source.CreateListenerCollection(stickie, selection);
87+
88+
var expected = new[] { stickie }.Concat(source);
89+
CollectionAssert.AreEqual(expected, target);
90+
91+
selection.OnNext(null);
92+
93+
CollectionAssert.AreEqual(source, target);
94+
}
95+
96+
[Test]
97+
public void StickyItemShouldBeRemovedWhenSelectionChangesToStickyItem()
98+
{
99+
var source = CreateSource();
100+
var stickie = new Thing();
101+
var selection = new BehaviorSubject<Thing>(source[0]);
102+
var target = source.CreateListenerCollection(stickie, selection);
103+
104+
var expected = new[] { stickie }.Concat(source);
105+
CollectionAssert.AreEqual(expected, target);
106+
107+
selection.OnNext(stickie);
108+
109+
CollectionAssert.AreEqual(source, target);
110+
}
111+
112+
TrackingCollection<Thing> CreateSource()
113+
{
114+
var result = new TrackingCollection<Thing>(Observable.Empty<Thing>());
115+
result.Subscribe();
116+
result.AddItem(new Thing(1, "item1", DateTimeOffset.MinValue));
117+
result.AddItem(new Thing(2, "item2", DateTimeOffset.MinValue));
118+
result.AddItem(new Thing(3, "item3", DateTimeOffset.MinValue));
119+
return result;
120+
}
121+
}

src/TrackingCollectionTests/TrackingCollectionTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
<Compile Include="ITestOutputHelper.cs" />
101101
<Compile Include="TestBase.cs" />
102102
<Compile Include="Thing.cs" />
103+
<Compile Include="ListenerCollectionTests.cs" />
103104
<Compile Include="TrackingCollectionTests.cs" />
104105
<Compile Include="Properties\AssemblyInfo.cs" />
105106
</ItemGroup>

0 commit comments

Comments
 (0)