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

Repo overview header including watchers, stars & forks #2624

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions Classes/Repository/RepositoryOverviewHeaderViewModels.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//
// RepositoryOverviewHeaderViewModels.swift
// Freetime
//
// Created by Viktoras Laukevicius on 23/01/2019.
// Copyright © 2019 Ryan Nystrom. All rights reserved.
//

import UIKit
import IGListKit
import StyledTextKit

struct RepositoryOverviewHeaderModel {
let watchersCount: Int
let starsCount: Int
let forksCount: Int
}

private extension Int {
var localizedDecimal: String {
return NumberFormatter.localizedString(from: NSNumber(value: self), number: .decimal)
}
}

func RepositoryOverviewHeaderViewModels(
model: RepositoryOverviewHeaderModel,
width: CGFloat,
contentSizeCategory: UIContentSizeCategory
) -> [ListDiffable] {
let watchersCount = model.watchersCount.localizedDecimal
let starsCount = model.starsCount.localizedDecimal
let forksCount = model.forksCount.localizedDecimal
let iconsStyle = Styles.Text.h2
let textStyle = Styles.Text.secondaryBold
let builder = StyledTextBuilder(styledText: StyledText(
style: iconsStyle.with(foreground: Styles.Colors.Gray.medium.color)
))
.save()
let baselineOffset = (iconsStyle.preferredFont.lineHeight - textStyle.preferredFont.lineHeight) / 4.0
let elements = [
(UIImage(named: "eye")!, watchersCount),
(UIImage(named: "star")!, starsCount),
(UIImage(named: "repo-forked")!, forksCount)
]
for (image, countText) in elements {
builder
.add(image: image)
.add(styledText: StyledText(text: " \(countText) ", style: textStyle.with(attributes: [
.baselineOffset: baselineOffset
])
))
.restore()
.save()
}

let hdr = StyledTextRenderer(
string: builder.build(),
contentSizeCategory: contentSizeCategory,
inset: .zero
).warm(width: width)
return [hdr]
}
12 changes: 10 additions & 2 deletions Classes/Repository/RepositoryOverviewViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ IndicatorInfoProvider {
private let client: RepositoryClient
private var readme: RepositoryReadmeModel?
private var branch: String
private let headerModel: RepositoryOverviewHeaderModel

init(client: GithubClient, repo: RepositoryDetails, branch: String) {
init(client: GithubClient, repo: RepositoryDetails, branch: String, headerModel: RepositoryOverviewHeaderModel) {
self.repo = repo
self.branch = branch
self.client = RepositoryClient(githubClient: client, owner: repo.owner, name: repo.name)
self.headerModel = headerModel
super.init(
emptyErrorMessage: NSLocalizedString("Cannot load README.", comment: "")
)
Expand Down Expand Up @@ -57,13 +59,19 @@ IndicatorInfoProvider {
let width = view.safeContentWidth(with: feed.collectionView)
let contentSizeCategory = UIContentSizeCategory.preferred
let branch = self.branch
let headerModel = self.headerModel

client.githubClient.client
.send(V3RepositoryReadmeRequest(owner: repo.owner, repo: repo.name, branch: branch)) { [weak self] result in
switch result {
case .success(let response):
DispatchQueue.global().async {

let header = RepositoryOverviewHeaderViewModels(
model: headerModel,
width: width,
contentSizeCategory: contentSizeCategory
)
let models = MarkdownModels(
response.data.content,
owner: repo.owner,
Expand All @@ -74,7 +82,7 @@ IndicatorInfoProvider {
isRoot: false,
branch: branch
)
let model = RepositoryReadmeModel(models: models)
let model = RepositoryReadmeModel(models: header + models)
DispatchQueue.main.async { [weak self] in
self?.readme = model
self?.update(animated: trueUnlessReduceMotionEnabled)
Expand Down
12 changes: 10 additions & 2 deletions Classes/Repository/RepositoryViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ EmptyViewDelegate {
let hasIssuesEnabled: Bool
let defaultBranch: String
let graphQLID: String
let headerModel: RepositoryOverviewHeaderModel
}

private enum State {
Expand Down Expand Up @@ -128,7 +129,8 @@ EmptyViewDelegate {
controllers.append(RepositoryOverviewViewController(
client: client,
repo: repo,
branch: branch ?? details.defaultBranch
branch: branch ?? details.defaultBranch,
headerModel: details.headerModel
))
if details.hasIssuesEnabled {
controllers.append(RepositoryIssuesViewController(
Expand Down Expand Up @@ -173,10 +175,16 @@ EmptyViewDelegate {
Squawk.show(error: error)
case .success(let data):
if let repo = data.repository {
let headerModel = RepositoryOverviewHeaderModel(
watchersCount: repo.watchers.totalCount,
starsCount: repo.stargazers.totalCount,
forksCount: repo.forkCount
)
let details = Details(
hasIssuesEnabled: repo.hasIssuesEnabled,
defaultBranch: repo.defaultBranchRef?.name ?? "master",
graphQLID: repo.id
graphQLID: repo.id,
headerModel: headerModel
)
self?.state = .value(details)
} else {
Expand Down
4 changes: 4 additions & 0 deletions Freetime.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
03A0EC6321F8F60B008C9CE2 /* RepositoryOverviewHeaderViewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03A0EC6221F8F60B008C9CE2 /* RepositoryOverviewHeaderViewModels.swift */; };
0F9440FD32236514CD7215E9 /* Pods_Freetime.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ECF622FFD773FDA73297C0D0 /* Pods_Freetime.framework */; };
15F28F992108DBA6006421B6 /* SplashView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F28F982108DBA6006421B6 /* SplashView.swift */; };
290056F3210028B20046EAE5 /* UIViewController+MenuDone.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290056F2210028B20046EAE5 /* UIViewController+MenuDone.swift */; };
Expand Down Expand Up @@ -593,6 +594,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
03A0EC6221F8F60B008C9CE2 /* RepositoryOverviewHeaderViewModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepositoryOverviewHeaderViewModels.swift; sourceTree = "<group>"; };
07C7DC5A7A907BE73BCA95AC /* Pods-FreetimeTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FreetimeTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-FreetimeTests/Pods-FreetimeTests.debug.xcconfig"; sourceTree = "<group>"; };
0F26A46A43D11F8D04E17D4A /* Pods-FreetimeWatch Extension.testflight.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FreetimeWatch Extension.testflight.xcconfig"; path = "Pods/Target Support Files/Pods-FreetimeWatch Extension/Pods-FreetimeWatch Extension.testflight.xcconfig"; sourceTree = "<group>"; };
15F28F982108DBA6006421B6 /* SplashView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2249,6 +2251,7 @@
986B87331F2CAE9800AAB55C /* RepositoryIssueSummaryType.swift */,
2905AFAC1F7357C50015AE32 /* RepositoryIssuesViewController.swift */,
29FE635E21AE2E2F00A07A86 /* RepositoryLoadingViewController.swift */,
03A0EC6221F8F60B008C9CE2 /* RepositoryOverviewHeaderViewModels.swift */,
2905AFAA1F7357B40015AE32 /* RepositoryOverviewViewController.swift */,
29EDFE811F661562005BCCEB /* RepositoryReadmeModel.swift */,
29EDFE831F661776005BCCEB /* RepositoryReadmeSectionController.swift */,
Expand Down Expand Up @@ -2981,6 +2984,7 @@
986B87191F2B875800AAB55C /* GithubClient+Search.swift in Sources */,
29C0E7071ECBC6C50051D756 /* GithubClient.swift in Sources */,
15F28F992108DBA6006421B6 /* SplashView.swift in Sources */,
03A0EC6321F8F60B008C9CE2 /* RepositoryOverviewHeaderViewModels.swift in Sources */,
2986B35A1FD30F0B00E3CFC6 /* IssueManagingModel.swift in Sources */,
2981A8A41EFE9FC700E25EF1 /* GithubEmoji.swift in Sources */,
2924C18B20D5B3A100FCFCFF /* LabelMenuCell.swift in Sources */,
Expand Down
115 changes: 112 additions & 3 deletions gql/API.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16961,7 +16961,7 @@ public final class RepoSearchPagesQuery: GraphQLQuery {

public final class RepositoryInfoQuery: GraphQLQuery {
public static let operationString =
"query RepositoryInfo($owner: String!, $name: String!) {\n repository(owner: $owner, name: $name) {\n __typename\n id\n defaultBranchRef {\n __typename\n name\n }\n hasIssuesEnabled\n }\n}"
"query RepositoryInfo($owner: String!, $name: String!) {\n repository(owner: $owner, name: $name) {\n __typename\n id\n defaultBranchRef {\n __typename\n name\n }\n hasIssuesEnabled\n watchers {\n __typename\n totalCount\n }\n stargazers {\n __typename\n totalCount\n }\n forkCount\n }\n}"

public var owner: String
public var name: String
Expand Down Expand Up @@ -17010,6 +17010,9 @@ public final class RepositoryInfoQuery: GraphQLQuery {
GraphQLField("id", type: .nonNull(.scalar(GraphQLID.self))),
GraphQLField("defaultBranchRef", type: .object(DefaultBranchRef.selections)),
GraphQLField("hasIssuesEnabled", type: .nonNull(.scalar(Bool.self))),
GraphQLField("watchers", type: .nonNull(.object(Watcher.selections))),
GraphQLField("stargazers", type: .nonNull(.object(Stargazer.selections))),
GraphQLField("forkCount", type: .nonNull(.scalar(Int.self))),
]

public var snapshot: Snapshot
Expand All @@ -17018,8 +17021,8 @@ public final class RepositoryInfoQuery: GraphQLQuery {
self.snapshot = snapshot
}

public init(id: GraphQLID, defaultBranchRef: DefaultBranchRef? = nil, hasIssuesEnabled: Bool) {
self.init(snapshot: ["__typename": "Repository", "id": id, "defaultBranchRef": defaultBranchRef.flatMap { (value: DefaultBranchRef) -> Snapshot in value.snapshot }, "hasIssuesEnabled": hasIssuesEnabled])
public init(id: GraphQLID, defaultBranchRef: DefaultBranchRef? = nil, hasIssuesEnabled: Bool, watchers: Watcher, stargazers: Stargazer, forkCount: Int) {
self.init(snapshot: ["__typename": "Repository", "id": id, "defaultBranchRef": defaultBranchRef.flatMap { (value: DefaultBranchRef) -> Snapshot in value.snapshot }, "hasIssuesEnabled": hasIssuesEnabled, "watchers": watchers.snapshot, "stargazers": stargazers.snapshot, "forkCount": forkCount])
}

public var __typename: String {
Expand Down Expand Up @@ -17060,6 +17063,36 @@ public final class RepositoryInfoQuery: GraphQLQuery {
}
}

/// A list of users watching the repository.
public var watchers: Watcher {
get {
return Watcher(snapshot: snapshot["watchers"]! as! Snapshot)
}
set {
snapshot.updateValue(newValue.snapshot, forKey: "watchers")
}
}

/// A list of users who have starred this starrable.
public var stargazers: Stargazer {
get {
return Stargazer(snapshot: snapshot["stargazers"]! as! Snapshot)
}
set {
snapshot.updateValue(newValue.snapshot, forKey: "stargazers")
}
}

/// Returns how many forks there are of this repository in the whole network.
public var forkCount: Int {
get {
return snapshot["forkCount"]! as! Int
}
set {
snapshot.updateValue(newValue, forKey: "forkCount")
}
}

public struct DefaultBranchRef: GraphQLSelectionSet {
public static let possibleTypes = ["Ref"]

Expand Down Expand Up @@ -17097,6 +17130,82 @@ public final class RepositoryInfoQuery: GraphQLQuery {
}
}
}

public struct Watcher: GraphQLSelectionSet {
public static let possibleTypes = ["UserConnection"]

public static let selections: [GraphQLSelection] = [
GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
GraphQLField("totalCount", type: .nonNull(.scalar(Int.self))),
]

public var snapshot: Snapshot

public init(snapshot: Snapshot) {
self.snapshot = snapshot
}

public init(totalCount: Int) {
self.init(snapshot: ["__typename": "UserConnection", "totalCount": totalCount])
}

public var __typename: String {
get {
return snapshot["__typename"]! as! String
}
set {
snapshot.updateValue(newValue, forKey: "__typename")
}
}

/// Identifies the total count of items in the connection.
public var totalCount: Int {
get {
return snapshot["totalCount"]! as! Int
}
set {
snapshot.updateValue(newValue, forKey: "totalCount")
}
}
}

public struct Stargazer: GraphQLSelectionSet {
public static let possibleTypes = ["StargazerConnection"]

public static let selections: [GraphQLSelection] = [
GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
GraphQLField("totalCount", type: .nonNull(.scalar(Int.self))),
]

public var snapshot: Snapshot

public init(snapshot: Snapshot) {
self.snapshot = snapshot
}

public init(totalCount: Int) {
self.init(snapshot: ["__typename": "StargazerConnection", "totalCount": totalCount])
}

public var __typename: String {
get {
return snapshot["__typename"]! as! String
}
set {
snapshot.updateValue(newValue, forKey: "__typename")
}
}

/// Identifies the total count of items in the connection.
public var totalCount: Int {
get {
return snapshot["totalCount"]! as! Int
}
set {
snapshot.updateValue(newValue, forKey: "totalCount")
}
}
}
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions gql/RepositoryInfo.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,12 @@ query RepositoryInfo($owner: String!, $name: String!) {
name
}
hasIssuesEnabled
watchers {
totalCount
}
stargazers {
totalCount
}
forkCount
}
}