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

Subscribe/Unsubscribe #2482

Open
wants to merge 7 commits 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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 33 additions & 1 deletion Classes/Issues/GithubClient+Issues.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,8 @@ extension GithubClient {
viewerCanAdminister: canAdmin,
defaultBranch: repository.defaultBranchRef?.name ?? "master",
fileChanges: issueType.fileChanges,
mergeModel: issueType.mergeModel(availableTypes: availableMergeTypes)
mergeModel: issueType.mergeModel(availableTypes: availableMergeTypes),
subscriptionState: issueType.subscriptionState
)

DispatchQueue.main.async {
Expand Down Expand Up @@ -297,6 +298,37 @@ extension GithubClient {
}
}

func setSubscription(
previous: IssueResult,
subscribe: Bool,
completion: ((Result<SubscriptionState?>) -> Void)? = nil
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, what would it mean if the state is nil? Would that be an actual success?

) {

let state: SubscriptionState = subscribe
? .subscribed
: .unsubscribed

let optimisticResult = previous.updated(subscriptionState: state)

let cache = self.cache
cache.set(value: optimisticResult)

let mutation = UpdateSubscriptionMutation(subscribable_Id: previous.id, subscription_state: state)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change these parameters to camelCase?


client.mutate(mutation, result: { data in
data.updateSubscription?.subscribable
}, completion: { result in
switch result {
case .success(let subscribable):
completion?(.success(subscribable.viewerSubscription))
case .failure(let error):
cache.set(value: previous)
completion?(.error(error))
Squawk.show(error: error)
}
})
}

enum CollaboratorPermission: String {
case admin
case write
Expand Down
4 changes: 4 additions & 0 deletions Classes/Issues/Issue+IssueType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import IGListKit

extension IssueOrPullRequestQuery.Data.Repository.IssueOrPullRequest.AsIssue: IssueType {

var subscriptionState: SubscriptionState {
return viewerSubscription ?? .unsubscribed
}

var pullRequest: Bool {
return false
}
Expand Down
45 changes: 35 additions & 10 deletions Classes/Issues/IssueManagingContextController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,12 @@ final class IssueManagingContextController: NSObject, ContextMenuDelegate {
case lock
case reopen
case close
case subscribe
case unsubscribe
}

var actions: [Action] {
if case .none = permissions { return [] }

guard let result = self.result else { return [] }

var actions = [Action]()
Expand All @@ -97,21 +99,30 @@ final class IssueManagingContextController: NSObject, ContextMenuDelegate {
if result.pullRequest {
actions.append(.reviewers)
}
}

if result.subscriptionState == .subscribed {
actions.append(.unsubscribe)
} else {
actions.append(.subscribe)
}

if case .collaborator = permissions {
if result.labels.locked {
actions.append(.unlock)
} else {
actions.append(.lock)
}
}

switch result.labels.status.status {
case .closed:
actions.append(.reopen)
case .open:
actions.append(.close)
case .merged: break
if permissions == .collaborator || permissions == .author {
switch result.labels.status.status {
case .closed:
actions.append(.reopen)
case .open:
actions.append(.close)
case .merged: break
}
}

return actions
}

Expand Down Expand Up @@ -144,13 +155,19 @@ final class IssueManagingContextController: NSObject, ContextMenuDelegate {
case .close:
title = Constants.Strings.close
iconName = "x"
case .subscribe:
title = Constants.Strings.subscribe
iconName = "unmute"
case .unsubscribe:
title = Constants.Strings.unsubscribe
iconName = "mute"
}

// Lock always has the divider above it assuming you're a collaborator.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should update this comment.

// If you aren't a collaborator (Lock does not show), close has the divider above it.
let separator: Bool
switch action {
case .lock, .unlock: separator = true
case .subscribe, .unsubscribe: separator = true
case .reopen, .close: separator = permissions != .collaborator
default: separator = false
}
Expand Down Expand Up @@ -186,6 +203,8 @@ final class IssueManagingContextController: NSObject, ContextMenuDelegate {
case .lock: strongSelf.lock(true)
case .reopen: strongSelf.close(false)
case .close: strongSelf.close(true)
case .subscribe: strongSelf.subscribe(true)
case .unsubscribe: strongSelf.subscribe(false)
}
}
}
Expand Down Expand Up @@ -271,6 +290,12 @@ final class IssueManagingContextController: NSObject, ContextMenuDelegate {
)
}

func subscribe(_ doSubscribe: Bool) {
guard let previous = result else { return }
delegate?.willMutateModel(from: self)
client.setSubscription(previous: previous, subscribe: doSubscribe)
Haptic.triggerNotification(.success)
}
func close(_ doClose: Bool) {
guard let previous = result else { return }
delegate?.willMutateModel(from: self)
Expand Down
13 changes: 9 additions & 4 deletions Classes/Issues/IssueResult.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ struct IssueResult: Cachable {
let defaultBranch: String
let fileChanges: FileChanges?
let mergeModel: IssueMergeModel?
let subscriptionState: SubscriptionState

var timelineViewModels: [ListDiffable] {
return timelinePages.reduce([], { $0 + $1.viewModels })
Expand Down Expand Up @@ -77,7 +78,8 @@ struct IssueResult: Cachable {
hasIssuesEnabled: Bool? = nil,
viewerCanAdminister: Bool? = nil,
defaultBranch: String? = nil,
mergeModel: IssueMergeModel? = nil
mergeModel: IssueMergeModel? = nil,
subscriptionState: SubscriptionState? = nil
) -> IssueResult {
return IssueResult(
id: id ?? self.id,
Expand All @@ -95,7 +97,8 @@ struct IssueResult: Cachable {
viewerCanAdminister: viewerCanAdminister ?? self.viewerCanAdminister,
defaultBranch: defaultBranch ?? self.defaultBranch,
fileChanges: fileChanges,
mergeModel: mergeModel ?? self.mergeModel
mergeModel: mergeModel ?? self.mergeModel,
subscriptionState: subscriptionState ?? self.subscriptionState
)
}

Expand All @@ -119,7 +122,8 @@ struct IssueResult: Cachable {
viewerCanAdminister: self.viewerCanAdminister,
defaultBranch: self.defaultBranch,
fileChanges: self.fileChanges,
mergeModel: self.mergeModel
mergeModel: self.mergeModel,
subscriptionState: self.subscriptionState
)
}

Expand All @@ -143,7 +147,8 @@ struct IssueResult: Cachable {
viewerCanAdminister: self.viewerCanAdminister,
defaultBranch: self.defaultBranch,
fileChanges: self.fileChanges,
mergeModel: self.mergeModel
mergeModel: self.mergeModel,
subscriptionState: self.subscriptionState
)
}

Expand Down
2 changes: 2 additions & 0 deletions Classes/Issues/IssueType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ protocol IssueType {
var headPaging: HeadPaging { get }
var viewerCanUpdate: Bool { get }
var fileChanges: FileChanges? { get }
var subscriptionState: SubscriptionState { get }


var reviewRequestModel: IssueAssigneesModel? { get }
func mergeModel(availableTypes: [IssueMergeType]) -> IssueMergeModel?
Expand Down
4 changes: 4 additions & 0 deletions Classes/Issues/PullRequest+IssueType.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import StyledTextKit

extension IssueOrPullRequestQuery.Data.Repository.IssueOrPullRequest.AsPullRequest: IssueType {

var subscriptionState: SubscriptionState {
return viewerSubscription ?? .unsubscribed
}

var pullRequest: Bool {
return true
}
Expand Down
2 changes: 2 additions & 0 deletions Classes/Views/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ enum Constants {
static let reviewers = NSLocalizedString("Reviewers", comment: "")
static let clear = NSLocalizedString("Clear", comment: "")
static let preview = NSLocalizedString("Preview", comment: "")
static let subscribe = NSLocalizedString("Subscribe", comment: "")
static let unsubscribe = NSLocalizedString("Unsubscribe", comment: "")
static let overview = NSLocalizedString("Overview", comment: "")
}
}
4 changes: 1 addition & 3 deletions FreetimeTests/SplitViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,7 @@ class SplitViewTests: XCTestCase {
client: GithubClient(userSession: nil),
repo: RepositoryDetails(
owner: "Foo",
name: "Bar",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was this changed? 🤔

defaultBranch: "Baz",
hasIssuesEnabled: false
name: "Bar"
))

let detail2 = IssuesViewController(
Expand Down
342 changes: 333 additions & 9 deletions gql/API.swift

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions gql/Fragments.graphql
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
fragment subscribableFields on Subscribable {
id
viewerCanSubscribe
viewerSubscription
}

fragment reactionFields on Reactable {
viewerCanReact
reactionGroups {
Expand Down
2 changes: 2 additions & 0 deletions gql/IssueOrPullRequest.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ query IssueOrPullRequest($owner: String!, $repo: String!, $number: Int!, $page_s
}
issueOrPullRequest(number: $number) {
... on Issue {
viewerSubscription
timeline(last: $page_size, before: $before) {
pageInfo{...headPaging}
nodes {
Expand Down Expand Up @@ -182,6 +183,7 @@ query IssueOrPullRequest($owner: String!, $repo: String!, $number: Int!, $page_s
title
}
... on PullRequest {
viewerSubscription
timeline(last: $page_size, before: $before) {
pageInfo{...headPaging}
nodes {
Expand Down
7 changes: 7 additions & 0 deletions gql/UpdateSubscription.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
mutation UpdateSubscription($subscribable_Id: ID!, $subscription_state: SubscriptionState!) {
updateSubscription(input:{subscribableId: $subscribable_Id, state: $subscription_state}) {
subscribable{
...subscribableFields
}
}
}