Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MBL-1022: Add blocking mutation to iOS client #1890

Merged
merged 5 commits into from Nov 29, 2023

Conversation

amy-at-kickstarter
Copy link
Contributor

@amy-at-kickstarter amy-at-kickstarter commented Nov 27, 2023

📲 What

Add BlockUser mutation to the app.

🤔 Why

So we can implement blocking in the UI!

@@ -6716,7 +6841,7 @@ public enum GraphAPI {
}

public struct Node: GraphQLSelectionSet {
public static let possibleTypes: [String] = ["Backing", "Reward", "Photo", "RewardItem", "Project", "Comment", "User", "Address", "Conversation", "Message", "CuratedPage", "Location", "Organization", "UserUrl", "Category", "AiDisclosure", "BusinessAddress", "ProjectFeaturedImage", "Flagging", "Video", "VideoTrack", "VideoTrackCue", "ProjectProfile", "AttachedAudio", "AttachedVideo", "Tag", "CreatorInterview", "InterviewAnswer", "InterviewQuestion", "CreatorPrompt", "FreeformPost", "ShippingRule", "Checkout", "Order", "OrderAddress", "Survey"]
public static let possibleTypes: [String] = ["Backing", "Reward", "Photo", "RewardItem", "Project", "Comment", "User", "Address", "Conversation", "Message", "CuratedPage", "Location", "Organization", "UserUrl", "Category", "AiDisclosure", "BusinessAddress", "Flagging", "Video", "VideoTrack", "VideoTrackCue", "ProjectProfile", "AttachedAudio", "AttachedVideo", "Tag", "CreatorInterview", "InterviewAnswer", "InterviewQuestion", "CreatorPrompt", "FreeformPost", "ShippingRule", "Checkout", "Order", "OrderAddress", "Survey"]
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There were a few other changes in the GraphQL schema since it was last updated, so I assume these are part of that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One point worth noting - right now we only update the schema when we need to update it on the client. But we should really be updating it any time changes to the web schema are pushed out - otherwise, we risk getting out of sync, and (say) using a feature that no longer actually exists on the web.

Obviously I'd hope that someone working on the web side would point this out to us before merging that change! But nice to enforce the same thing through code, not just socially.

return GraphQL.shared.client
.perform(mutation: GraphAPI.BlockUserMutation(input: GraphAPI.BlockUserInput(blockUserId: userId)))
.flatMap { _ in
SignalProducer(value: EmptyResponseEnvelope())
Copy link
Contributor Author

Choose a reason for hiding this comment

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

So BlockUser can return two fields: success and currentUser { blockedUsers } . However, based on my current understanding of the client designs, we don't need to read either of these fields: we'll fetch isBlocked directly on other User objects.

Is that correct? Based on that assumption I figured I'd take the simplest route out and return an EmptyResponseEnvelope.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep exactly. We only need to know if it was successful right now.

public func blockUser(userId: String)
-> SignalProducer<EmptyResponseEnvelope, ErrorEnvelope> {
return GraphQL.shared.client
.perform(mutation: GraphAPI.BlockUserMutation(input: GraphAPI.BlockUserInput(blockUserId: userId)))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

GraphAPI.BlockUserMutation wants us to pass it a GraphQLID type, which can also be a String. It's not obvious to me if we'll need to turn the ID into a base64-encoded value, like a proper GraphQL identifier, or if it will be happy taking a plain, string-based user ID like "12345".

Copy link
Contributor

Choose a reason for hiding this comment

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

Let's follow the same "adapter" pattern that we're using elsewhere here. We can create an extension on GraphAPI.BlockUserInput for creating the input type. Extracting this allows us to test it more easily. See GraphAPI.WatchProjectInput.from(_ input:... for an example

Copy link

codecov bot commented Nov 27, 2023

Codecov Report

Attention: 7 lines in your changes are missing coverage. Please review.

Comparison is base (a164c48) 87.76% compared to head (670994a) 83.72%.

Files Patch % Lines
KsApi/Service.swift 0.00% 5 Missing ⚠️
KsApi/MockService.swift 0.00% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1890      +/-   ##
==========================================
- Coverage   87.76%   83.72%   -4.04%     
==========================================
  Files         858     1225     +367     
  Lines       77001   111519   +34518     
  Branches    20418    29673    +9255     
==========================================
+ Hits        67583    93374   +25791     
- Misses       8677    17125    +8448     
- Partials      741     1020     +279     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

@scottkicks scottkicks left a comment

Choose a reason for hiding this comment

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

Nice first run through! There's just a couple of things we need to add to stick to the existing pattern and keep things well tested. I added inline comments and you can use the linked PR below as a guide.

Let's create a BlockUserInput type to inject into our Service method as well as a .from(_ input...) helper extension to make it easier on ourselves to bundle up the expected properties once we implement this. Check out this PR out as a reference

Oh and we can add some tests around the input and extension as well 😄

public func blockUser(userId: String)
-> SignalProducer<EmptyResponseEnvelope, ErrorEnvelope> {
return GraphQL.shared.client
.perform(mutation: GraphAPI.BlockUserMutation(input: GraphAPI.BlockUserInput(blockUserId: userId)))
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's follow the same "adapter" pattern that we're using elsewhere here. We can create an extension on GraphAPI.BlockUserInput for creating the input type. Extracting this allows us to test it more easily. See GraphAPI.WatchProjectInput.from(_ input:... for an example

return GraphQL.shared.client
.perform(mutation: GraphAPI.BlockUserMutation(input: GraphAPI.BlockUserInput(blockUserId: userId)))
.flatMap { _ in
SignalProducer(value: EmptyResponseEnvelope())
Copy link
Contributor

Choose a reason for hiding this comment

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

Yep exactly. We only need to know if it was successful right now.

@@ -380,6 +380,8 @@ public protocol ServiceType {

func fetchBackedProjects(cursor: String?, limit: Int?)
-> SignalProducer<FetchProjectsEnvelope, ErrorEnvelope>

func blockUser(userId: String) -> SignalProducer<EmptyResponseEnvelope, ErrorEnvelope>
Copy link
Contributor

Choose a reason for hiding this comment

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

So, this will be func blockUser(input: BlockUserInput) -> SignalProducer<EmptyResponseEnvelope, ErrorEnvelope>

@nativeksr
Copy link
Collaborator

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

@@ -0,0 +1,5 @@
import Foundation
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@scottkicks Can you explain a little more about this input adapter pattern? Happy to follow it for now, but at least for a very teeny input like this, it doesn't seem obviously beneficial. I'm curious to hear more about why we've been using this pattern instead of using the GraphAPI.XYZInput objects directly.

@scottkicks
Copy link
Contributor

scottkicks commented Nov 29, 2023

@amy-at-kickstarter Until we can say this current mutation works and is testable as expected, we might want to hold off on merging this. In case Santiago has to make further changes. ref: https://kickstarter.slack.com/archives/C05HX9GS0CD/p1701219627599909?thread_ts=1701184665.560489&cid=C05HX9GS0CD

@amy-at-kickstarter amy-at-kickstarter merged commit 3279b51 into main Nov 29, 2023
7 checks passed
@amy-at-kickstarter amy-at-kickstarter deleted the feat/adyer/mbl-1022/block-mutation branch November 29, 2023 19:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants