-
Notifications
You must be signed in to change notification settings - Fork 121
[IPPInAppFeedback] Banner dismiss logic #8657
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
Conversation
You can test the changes from this Pull Request by:
|
# Conflicts: # WooCommerce/Classes/ViewRelated/Orders/OrderListViewController.swift # WooCommerce/Classes/ViewRelated/Orders/OrderListViewModel.swift
|
👋 @toupper I'd appreciate an "early" review on this one before is fully ready for review, as I'm unsure how to deal with the case of "Dismisses the IPP banner upon survey completion", happy to get any pointer on what would work for this case. For context:
We seem to use the first option across other surveys, but I'm failing to understand how are we dealing with the logic that needs to happen when a user submits the survey from the modal view. This will be needed for tracking FeedbackStatus as well. Edit: This is resolved with 523fe0a (Reference: p1674118095143339?thread_ts=1674101250.398509&cid=CGPNUU63E-slack-CGPNUU63E). We'll be dismissing the banner right away upon tapping, and then we'll figure out if we need to show it again or not via checking the FeedbackStatus |
|
|
||
| private func createIPPFeedbackTopBanner() -> TopBannerView { | ||
| let shareIPPFeedbackAction = TopBannerViewModel.ActionButton(title: Localization.shareFeedbackButton, action: { _ in | ||
| self.displayIPPFeedbackBannerSurvey() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to add [weak self] for these references? Also for other self usage within a block in this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We definitely do 🙇 , added both on 70d9cbd
| self.present(surveyNavigation, animated: true, completion: nil) | ||
| } | ||
|
|
||
| private func dismissIPPFeedbackBannerSurvey() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to be more precise, I would rename this function to actually reflect what's happening inside. Perhaps something like func showIPPFeedbackDismissAlert() ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the method internals changed but I didn't change the name. Modified on 909bea5
| static let estimatedHeaderHeight = CGFloat(43) | ||
| static let estimatedRowHeight = CGFloat(86) | ||
| static let placeholderRowsPerSection = [3] | ||
| static let remindAfterDays = 7 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would be more specific here, what is it that we are using this value for? IPP Feedback or something else? Also, this pertains to view model logic, as mentioned before.
| } | ||
|
|
||
| private func remindMeLaterTapped() { | ||
| viewModel.dismissIPPFeedbackBanner(remindLater: true, remindAfter: Settings.remindAfterDays) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The remindLater and remindAfter logic seem to fit better in the view model logic, I would move that there while keeping the UI actions here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense, moved to the view model on 80a1b1b
| stores.dispatch(action) | ||
| } | ||
|
|
||
| func dismissIPPFeedbackBanner(remindLater: Bool, remindAfter: Int?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned before, remindLater and remindAfter shouldn't be exposed to the view, but kept here inside the view model logic. We can also test it that way.
| loadCouponManagementFeatureSwitchState(onCompletion: onCompletion) | ||
| case .setFeatureAnnouncementDismissed(campaign: let campaign, remindLater: let remindLater, onCompletion: let completion): | ||
| setFeatureAnnouncementDismissed(campaign: campaign, remindLater: remindLater, onCompletion: completion) | ||
| case .setFeatureAnnouncementDismissed(campaign: let campaign, remindLater: let remindLater, remindAfter: let remindAfter, onCompletion: let completion): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would encapsulate remindLater and remindLater in one value, I don't think we need both here. If we have both we can give place to inconsistent states, e.g., remindLater false and remindAfter to 5 days. For instance, we can solve this as follows:
- We can have only
remindAfter, where 0 means it shouldn't be reminded. Or, remindAftercan be an optional, beingnilmeaning it shouldn't be reminded. I prefer this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much cleaner indeed, changes here: 2177584 Now we have a unique Optional parameter remindAfterDays rather than two.
| loadCouponManagementFeatureSwitchState(onCompletion: onCompletion) | ||
| case .setFeatureAnnouncementDismissed(campaign: let campaign, remindLater: let remindLater, onCompletion: let completion): | ||
| setFeatureAnnouncementDismissed(campaign: campaign, remindLater: remindLater, onCompletion: completion) | ||
| case .setFeatureAnnouncementDismissed(campaign: let campaign, remindLater: let remindLater, remindAfter: let remindAfter, onCompletion: let completion): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If keep remindAfter, it would be valuable to specify what time unit are we expecting: remindAfterDays
|
Great job @iamgabrielma! I left some comments there, let me know what you think of that. Once we are done with that, I will test the flow 👍 |
| XCTAssert(Calendar.current.isDate(actualRemindAfter, inSameDayAs: twoWeeksTime)) | ||
| } | ||
|
|
||
| func test_setFeatureAnnouncementDismissed_with_remindAfter_seven_days_stores_reminder_date_in_one_week() throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be great to use the agreed test function naming syntax here as well:
test_setFeatureAnnouncementDismissed_when_remindAfter_is_seven_days_stores_reminder_then_date_saved_date_is_one_week
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right! Changed f8a2586
We’re modifying the action by removing the parameters remindLater, and remindAfter in favor of an unique remindAfterDays parameter. If this is nil, no reminder is set. Otherwise the number of days will be set.
By making remindAfterDays an Optional Int, we need to edit storeDismissedSetting as well to either save the current date if is true (by passing 0, so adds 0 days to the current date) or nil if is false
| } | ||
|
|
||
| func test_setFeatureAnnouncementDismissed_with_remindLater_true_stores_reminder_date_in_two_weeks() throws { | ||
| func test_setFeatureAnnouncementDismissed_with_remindAfterDays_two_weeks_stores_reminder_date_in_two_weeks() throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| func test_setFeatureAnnouncementDismissed_with_remindAfterDays_two_weeks_stores_reminder_date_in_two_weeks() throws { | |
| func test_setFeatureAnnouncementDismissed_when_remindAfterDays_two_weeks_then_stores_reminder_date_in_two_weeks() throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_setFeatureAnnouncementDismissed_when_remindAfterDays_is_two_weeks_then_stores_reminder_date_is_two_weeks()
|
Thanks for the review @toupper ! I made the changes and this is ready for review 🙇 |
| // MARK: - In-Person Payments Feedback Banner | ||
|
|
||
| extension OrderListViewModel { | ||
| func dismissIPPFeedbackBanner(remindAfterDays: Int?) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice change moving the logic to the view model! However, the remindAfterDays logic can be contained in the view model; the view doesn't need to know about when are we going to show it again. With that, we can remove this parameter remindAfterDays from this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed here the remaining use of remindAfterDays: d5e02a2 to a new method, so this is entirely contained in the view model now 👍
| } | ||
|
|
||
| func test_setFeatureAnnouncementDismissed_with_remindLater_true_stores_reminder_date_in_two_weeks() throws { | ||
| func test_setFeatureAnnouncementDismissed_with_remindAfterDays_two_weeks_stores_reminder_date_in_two_weeks() throws { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test_setFeatureAnnouncementDismissed_when_remindAfterDays_is_two_weeks_then_stores_reminder_date_is_two_weeks()
| stores.dispatch(updateBannerVisibility) | ||
| } | ||
|
|
||
| func remindMeLaterTapped() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can name this function more specifically for the IPP Feedback Banner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed on 9884f22
|
Great job! LGTM |
Closes: #8589
Part of #8530
Description
This PR adds the logic to dismiss the IPP feedback banner.
TODO
Changes
setFeatureAnnouncementDismissedAppSettingsStore/AppSettingsAction to accept a newremindAfterparameter, this allows us to specify a number of days for the reminder to be triggered (previous default to 14)UIAlertControllerto be shown when the IPP banner is dismissed, with 2 buttons: "Remind me later", and "Don't show again"..dismissed, and the feedback visibility to be reminded later or never.Testing instructions
Screenshots
RELEASE-NOTES.txtif necessary.