Skip to content

Commit cd650a7

Browse files
committed
Further refined IPaginator, making it possible to do search pagination!
1 parent 997d29c commit cd650a7

7 files changed

Lines changed: 68 additions & 9 deletions

File tree

‎SpotifyAPI.Web/Clients/Interfaces/IPaginator.cs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ public interface IPaginator
99
{
1010
Task<List<T>> Paginate<T>(Paging<T> firstPage, IAPIConnector connector);
1111
Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IAPIConnector connector);
12+
13+
Task<List<T>> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper, IAPIConnector connector);
14+
Task<List<T>> Paginate<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper, IAPIConnector connector);
1215
}
1316
}

‎SpotifyAPI.Web/Clients/Interfaces/ISpotifyClient.cs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ public interface ISpotifyClient
2323
ITracksClient Tracks { get; }
2424

2525
Task<List<T>> Paginate<T>(Paging<T> firstPage);
26+
Task<List<T>> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper);
2627
Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage);
28+
Task<List<T>> Paginate<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper);
2729
Task<List<T>> Paginate<T>(Paging<T> firstPage, IPaginator paginator);
2830
Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator);
2931
}

‎SpotifyAPI.Web/Clients/SimplePaginator.cs‎

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ namespace SpotifyAPI.Web
77
{
88
public class SimplePaginator : IPaginator
99
{
10-
protected virtual bool ShouldContinue<T>(List<T> results, Paging<T> page)
10+
protected virtual Task<bool> ShouldContinue<T>(List<T> results, Paging<T> page)
1111
{
12-
return true;
12+
return Task.FromResult(true);
13+
}
14+
protected virtual Task<bool> ShouldContinue<T, TNext>(List<T> results, Paging<T, TNext> page)
15+
{
16+
return Task.FromResult(true);
1317
}
1418

1519
public async Task<List<T>> Paginate<T>(Paging<T> firstPage, IAPIConnector connector)
@@ -20,7 +24,7 @@ public async Task<List<T>> Paginate<T>(Paging<T> firstPage, IAPIConnector connec
2024
var page = firstPage;
2125
var results = new List<T>();
2226
results.AddRange(firstPage.Items);
23-
while (page.Next != null && ShouldContinue(results, page))
27+
while (page.Next != null && await ShouldContinue(results, page).ConfigureAwait(false))
2428
{
2529
page = await connector.Get<Paging<T>>(new Uri(page.Next, UriKind.Absolute)).ConfigureAwait(false);
2630
results.AddRange(page.Items);
@@ -36,5 +40,34 @@ public async Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IAPIC
3640
var firstPage = await getFirstPage().ConfigureAwait(false);
3741
return await Paginate(firstPage, connector).ConfigureAwait(false);
3842
}
43+
44+
public async Task<List<T>> Paginate<T, TNext>(
45+
Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper, IAPIConnector connector
46+
)
47+
{
48+
Ensure.ArgumentNotNull(firstPage, nameof(firstPage));
49+
Ensure.ArgumentNotNull(mapper, nameof(mapper));
50+
Ensure.ArgumentNotNull(connector, nameof(connector));
51+
52+
var page = firstPage;
53+
var results = new List<T>();
54+
results.AddRange(firstPage.Items);
55+
while (page.Next != null && await ShouldContinue(results, page).ConfigureAwait(false))
56+
{
57+
var next = await connector.Get<TNext>(new Uri(page.Next, UriKind.Absolute)).ConfigureAwait(false);
58+
page = mapper(next);
59+
results.AddRange(page.Items);
60+
}
61+
62+
return results;
63+
}
64+
65+
public async Task<List<T>> Paginate<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper, IAPIConnector connector)
66+
{
67+
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
68+
69+
var firstPage = await getFirstPage().ConfigureAwait(false);
70+
return await Paginate(firstPage, mapper, connector).ConfigureAwait(false);
71+
}
3972
}
4073
}

‎SpotifyAPI.Web/Clients/SpotifyClient.cs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ public Task<List<T>> Paginate<T>(Paging<T> firstPage)
4949
return DefaultPaginator.Paginate(firstPage, _apiConnector);
5050
}
5151

52+
public Task<List<T>> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper)
53+
{
54+
return DefaultPaginator.Paginate(firstPage, mapper, _apiConnector);
55+
}
56+
5257
public Task<List<T>> Paginate<T>(Paging<T> firstPage, IPaginator paginator)
5358
{
5459
Ensure.ArgumentNotNull(paginator, nameof(paginator));
@@ -61,6 +66,11 @@ public Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage)
6166
return DefaultPaginator.Paginate(getFirstPage, _apiConnector);
6267
}
6368

69+
public Task<List<T>> Paginate<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper)
70+
{
71+
return DefaultPaginator.Paginate(getFirstPage, mapper, _apiConnector);
72+
}
73+
6474
public Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator)
6575
{
6676
Ensure.ArgumentNotNull(paginator, nameof(paginator));

‎SpotifyAPI.Web/Http/APIConnector.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ object body
158158
Ensure.ArgumentNotNull(uri, nameof(uri));
159159
Ensure.ArgumentNotNull(method, nameof(method));
160160

161-
return new Request(parameters)
161+
return new Request(new Dictionary<string, string>(), parameters)
162162
{
163163
BaseAddress = _baseAddress,
164164
Endpoint = uri,

‎SpotifyAPI.Web/Models/Response/Paging.cs‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,15 @@ public class Paging<T>
1212
public string Previous { get; private set; }
1313
public int Total { get; private set; }
1414
}
15+
16+
public class Paging<T, TNext>
17+
{
18+
public string Href { get; private set; }
19+
public List<T> Items { get; private set; }
20+
public int Limit { get; private set; }
21+
public string Next { get; private set; }
22+
public int Offset { get; private set; }
23+
public string Previous { get; private set; }
24+
public int Total { get; private set; }
25+
}
1526
}

‎SpotifyAPI.Web/Models/Response/SearchResponse.cs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ namespace SpotifyAPI.Web
22
{
33
public class SearchResponse
44
{
5-
public Paging<FullArtist> Artists { get; private set; }
6-
public Paging<SimpleAlbum> Albums { get; private set; }
7-
public Paging<FullTrack> Tracks { get; private set; }
8-
public Paging<SimpleShow> Shows { get; private set; }
9-
public Paging<SimpleEpisode> Episodes { get; private set; }
5+
public Paging<FullArtist, SearchResponse> Artists { get; private set; }
6+
public Paging<SimpleAlbum, SearchResponse> Albums { get; private set; }
7+
public Paging<FullTrack, SearchResponse> Tracks { get; private set; }
8+
public Paging<SimpleShow, SearchResponse> Shows { get; private set; }
9+
public Paging<SimpleEpisode, SearchResponse> Episodes { get; private set; }
1010
}
1111
}

0 commit comments

Comments
 (0)