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

Commit 6ae3f7d

Browse files
viktoraslBasThomas
authored andcommitted
Pagination for repo branches list (#2620)
* Pagination for repo branches list * Use strong ref in repo branches fetch completion
1 parent 572596c commit 6ae3f7d

File tree

4 files changed

+121
-30
lines changed

4 files changed

+121
-30
lines changed

Classes/Repository/RepositoryBranches/GitHubClient+RepositoryBranches.swift

+37-14
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,54 @@
77
//
88

99
import GitHubAPI
10+
import Apollo
11+
12+
private extension FetchRepositoryBranchesQuery.Data {
13+
14+
func branches() -> [String] {
15+
var branches: [String] = []
16+
repository?.refs.map { edges in
17+
edges.edges.map { edge in
18+
branches += edge.compactMap {
19+
$0?.node?.name
20+
}
21+
}
22+
}
23+
return branches
24+
}
25+
26+
func nextPageToken() -> String? {
27+
guard repository?.refs?.pageInfo.hasNextPage == true else { return nil }
28+
return repository?.refs?.pageInfo.endCursor
29+
}
30+
31+
}
1032

1133
extension GithubClient {
1234

35+
struct RepositoryBranchesPayload {
36+
let branches: [String]
37+
let nextPage: String?
38+
}
39+
1340
func fetchRepositoryBranches(owner: String,
1441
repo: String,
15-
completion: @escaping (Result<([String])>) -> Void
42+
nextPage: String?,
43+
completion: @escaping (Result<RepositoryBranchesPayload>) -> Void
1644
) {
17-
let query = FetchRepositoryBranchesQuery(owner: owner, name: repo)
18-
client.query(query, result: { $0.repository }, completion: { result in
45+
let query = FetchRepositoryBranchesQuery(owner: owner, name: repo, after: nextPage)
46+
client.query(query, result: { $0 }, completion: { result in
1947

2048
switch result {
2149
case .failure(let error):
2250
completion(.error(error))
2351

24-
case .success(let repository):
25-
var branches: [String] = []
26-
repository.refs.map { edges in
27-
edges.edges.map { edge in
28-
branches += edge.compactMap {
29-
$0?.node?.name
30-
}
31-
}
32-
}
33-
34-
completion(.success(branches))
52+
case .success(let data):
53+
let payload = RepositoryBranchesPayload(
54+
branches: data.branches(),
55+
nextPage: data.nextPageToken()
56+
)
57+
completion(.success(payload))
3558
}
3659
})
3760
}

Classes/Repository/RepositoryBranches/RepositoryBranchesViewController.swift

+10-8
Original file line numberDiff line numberDiff line change
@@ -70,22 +70,24 @@ RepositoryBranchSectionControllerDelegate {
7070
}
7171

7272
override func fetch(page: String?) {
73-
client.fetchRepositoryBranches(owner: owner,
74-
repo: repo
75-
) { [weak self] result in
73+
client.fetchRepositoryBranches(
74+
owner: owner,
75+
repo: repo,
76+
nextPage: page as String?
77+
) { [weak self] result in
7678
guard let strongSelf = self else { return }
7779
switch result {
78-
case .success(let branches):
79-
self?.branches = RepositoryBranchesViewController.arrangeBranches(
80+
case .success(let payload):
81+
strongSelf.branches = RepositoryBranchesViewController.arrangeBranches(
8082
selectedBranch: strongSelf.selectedBranch,
8183
defaultBranch: strongSelf.defaultBranch,
82-
branches: branches
84+
branches: strongSelf.branches + payload.branches
8385
)
84-
86+
strongSelf.update(page: payload.nextPage, animated: true)
8587
case .error(let error):
8688
Squawk.show(error: error)
89+
strongSelf.error(animated: trueUnlessReduceMotionEnabled)
8790
}
88-
self?.update(animated: true)
8991
}
9092
}
9193

gql/API.swift

+68-6
Original file line numberDiff line numberDiff line change
@@ -14898,18 +14898,20 @@ public final class RemoveReactionMutation: GraphQLMutation {
1489814898

1489914899
public final class FetchRepositoryBranchesQuery: GraphQLQuery {
1490014900
public static let operationString =
14901-
"query fetchRepositoryBranches($owner: String!, $name: String!) {\n repository(owner: $owner, name: $name) {\n __typename\n refs(first: 50, refPrefix: \"refs/heads/\") {\n __typename\n edges {\n __typename\n node {\n __typename\n name\n }\n }\n }\n }\n}"
14901+
"query fetchRepositoryBranches($owner: String!, $name: String!, $after: String) {\n repository(owner: $owner, name: $name) {\n __typename\n refs(first: 50, after: $after, refPrefix: \"refs/heads/\") {\n __typename\n edges {\n __typename\n node {\n __typename\n name\n }\n }\n pageInfo {\n __typename\n hasNextPage\n endCursor\n }\n }\n }\n}"
1490214902

1490314903
public var owner: String
1490414904
public var name: String
14905+
public var after: String?
1490514906

14906-
public init(owner: String, name: String) {
14907+
public init(owner: String, name: String, after: String? = nil) {
1490714908
self.owner = owner
1490814909
self.name = name
14910+
self.after = after
1490914911
}
1491014912

1491114913
public var variables: GraphQLMap? {
14912-
return ["owner": owner, "name": name]
14914+
return ["owner": owner, "name": name, "after": after]
1491314915
}
1491414916

1491514917
public struct Data: GraphQLSelectionSet {
@@ -14944,7 +14946,7 @@ public final class FetchRepositoryBranchesQuery: GraphQLQuery {
1494414946

1494514947
public static let selections: [GraphQLSelection] = [
1494614948
GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
14947-
GraphQLField("refs", arguments: ["first": 50, "refPrefix": "refs/heads/"], type: .object(Ref.selections)),
14949+
GraphQLField("refs", arguments: ["first": 50, "after": GraphQLVariable("after"), "refPrefix": "refs/heads/"], type: .object(Ref.selections)),
1494814950
]
1494914951

1495014952
public var snapshot: Snapshot
@@ -14982,6 +14984,7 @@ public final class FetchRepositoryBranchesQuery: GraphQLQuery {
1498214984
public static let selections: [GraphQLSelection] = [
1498314985
GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
1498414986
GraphQLField("edges", type: .list(.object(Edge.selections))),
14987+
GraphQLField("pageInfo", type: .nonNull(.object(PageInfo.selections))),
1498514988
]
1498614989

1498714990
public var snapshot: Snapshot
@@ -14990,8 +14993,8 @@ public final class FetchRepositoryBranchesQuery: GraphQLQuery {
1499014993
self.snapshot = snapshot
1499114994
}
1499214995

14993-
public init(edges: [Edge?]? = nil) {
14994-
self.init(snapshot: ["__typename": "RefConnection", "edges": edges.flatMap { (value: [Edge?]) -> [Snapshot?] in value.map { (value: Edge?) -> Snapshot? in value.flatMap { (value: Edge) -> Snapshot in value.snapshot } } }])
14996+
public init(edges: [Edge?]? = nil, pageInfo: PageInfo) {
14997+
self.init(snapshot: ["__typename": "RefConnection", "edges": edges.flatMap { (value: [Edge?]) -> [Snapshot?] in value.map { (value: Edge?) -> Snapshot? in value.flatMap { (value: Edge) -> Snapshot in value.snapshot } } }, "pageInfo": pageInfo.snapshot])
1499514998
}
1499614999

1499715000
public var __typename: String {
@@ -15013,6 +15016,16 @@ public final class FetchRepositoryBranchesQuery: GraphQLQuery {
1501315016
}
1501415017
}
1501515018

15019+
/// Information to aid in pagination.
15020+
public var pageInfo: PageInfo {
15021+
get {
15022+
return PageInfo(snapshot: snapshot["pageInfo"]! as! Snapshot)
15023+
}
15024+
set {
15025+
snapshot.updateValue(newValue.snapshot, forKey: "pageInfo")
15026+
}
15027+
}
15028+
1501615029
public struct Edge: GraphQLSelectionSet {
1501715030
public static let possibleTypes = ["RefEdge"]
1501815031

@@ -15088,6 +15101,55 @@ public final class FetchRepositoryBranchesQuery: GraphQLQuery {
1508815101
}
1508915102
}
1509015103
}
15104+
15105+
public struct PageInfo: GraphQLSelectionSet {
15106+
public static let possibleTypes = ["PageInfo"]
15107+
15108+
public static let selections: [GraphQLSelection] = [
15109+
GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
15110+
GraphQLField("hasNextPage", type: .nonNull(.scalar(Bool.self))),
15111+
GraphQLField("endCursor", type: .scalar(String.self)),
15112+
]
15113+
15114+
public var snapshot: Snapshot
15115+
15116+
public init(snapshot: Snapshot) {
15117+
self.snapshot = snapshot
15118+
}
15119+
15120+
public init(hasNextPage: Bool, endCursor: String? = nil) {
15121+
self.init(snapshot: ["__typename": "PageInfo", "hasNextPage": hasNextPage, "endCursor": endCursor])
15122+
}
15123+
15124+
public var __typename: String {
15125+
get {
15126+
return snapshot["__typename"]! as! String
15127+
}
15128+
set {
15129+
snapshot.updateValue(newValue, forKey: "__typename")
15130+
}
15131+
}
15132+
15133+
/// When paginating forwards, are there more items?
15134+
public var hasNextPage: Bool {
15135+
get {
15136+
return snapshot["hasNextPage"]! as! Bool
15137+
}
15138+
set {
15139+
snapshot.updateValue(newValue, forKey: "hasNextPage")
15140+
}
15141+
}
15142+
15143+
/// When paginating forwards, the cursor to continue.
15144+
public var endCursor: String? {
15145+
get {
15146+
return snapshot["endCursor"] as? String
15147+
}
15148+
set {
15149+
snapshot.updateValue(newValue, forKey: "endCursor")
15150+
}
15151+
}
15152+
}
1509115153
}
1509215154
}
1509315155
}

gql/RepoBranches.graphql

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
query fetchRepositoryBranches($owner:String!, $name:String!) {
1+
query fetchRepositoryBranches($owner:String!, $name:String!, $after: String) {
22
repository(owner: $owner, name: $name) {
3-
refs(first: 50, refPrefix:"refs/heads/") {
3+
refs(first: 50, after: $after, refPrefix:"refs/heads/") {
44
edges {
55
node {
66
name
77
}
88
}
9+
pageInfo {
10+
hasNextPage
11+
endCursor
12+
}
913
}
1014
}
1115
}

0 commit comments

Comments
 (0)