Skip to content

Commit

Permalink
Add PPro unified feedback form (#3248)
Browse files Browse the repository at this point in the history
<!--
Note: This checklist is a reminder of our shared engineering
expectations. Feel free to change it, although assigning a GitHub
reviewer and the items in bold are required.

⚠️ If you're an external contributor, please file an issue first before
working on a PR, as we can't guarantee that we will accept your changes
if they haven't been discussed ahead of time. Thanks!
-->

Task/Issue URL:
https://app.asana.com/0/414235014887631/1207701941801991/f
Tech Design URL:
CC:

**Description**:

<!--
If at any point it isn't actively being worked on/ready for
review/otherwise moving forward strongly consider closing it (or not
opening it in the first place). If you decide not to close it, use Draft
PR while work is still in progress or use `DO NOT MERGE` label to
clarify the PRs state and comment with more information.
-->

This adds PPro unified feedback form to iOS

**Steps to test this PR**:
1. Check Settings > Share Feedback, the existing flow should work
2. Make sure you have a PPro subscription
3. Go to Settings > Subscription Settings, the last menu item should be
FAQs and Support
4. Go to Settings > VPN > Share VPN Feedback, the existing flow should
work
5. Log in as internal user, use this for the privacy config:
http://www.jsonblob.com/api/1274015132613992448
6. Settings > Send Feedback should now let you choose between the
current browser feedback and PPro feedback form. Play with the form and
see if it works
7. Settings > Subscription Settings, the last menu item should now be
Send Feedback, again check if the flow works
8. Settings > VPN > Send feedback, this should use the new unified flow.

Smoke test these pixels as you go through the flow:
https://app.asana.com/0/72649045549333/1207816523739193/f

<!--
Before submitting a PR, please ensure you have tested the combinations
you expect the reviewer to test, then delete configurations you *know*
do not need explicit testing.

Using a simulator where a physical device is unavailable is acceptable.
-->

**Definition of Done (Internal Only)**:

* [ ] Does this PR satisfy our [Definition of
Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)?

**Copy Testing**:

* [ ] Use of correct apostrophes in new copy, ie `’` rather than `'`

**Orientation Testing**:

* [ ] Portrait
* [ ] Landscape

**Device Testing**:

* [ ] iPhone SE (1st Gen)
* [ ] iPhone 8
* [ ] iPhone X
* [ ] iPhone 14 Pro
* [ ] iPad

**OS Testing**:

* [ ] iOS 15
* [ ] iOS 16
* [ ] iOS 17

**Theme Testing**:

* [ ] Light theme
* [ ] Dark theme

---
###### Internal references:
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
  • Loading branch information
quanganhdo authored Aug 27, 2024
1 parent 5ca931e commit 29f8770
Show file tree
Hide file tree
Showing 22 changed files with 1,497 additions and 41 deletions.
3 changes: 2 additions & 1 deletion Core/Pixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,8 @@ public class Pixel {
headers: headers)
let request = APIRequest(configuration: configuration, urlSession: .session(useMainThreadCallbackQueue: true))
request.fetch { _, error in
os_log("Pixel fired %{public}s %{public}s", log: .generalLog, type: .debug, pixelName, "\(params)")
os_log("Pixel fired %{public}s %{public}s", log: .generalLog, type: .debug,
pixelName.replacingOccurrences(of: "_", with: "."), "\(params)")
onComplete(error)
}
}
Expand Down
22 changes: 22 additions & 0 deletions Core/PixelEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,17 @@ extension Pixel {
case duckPlayerSettingNeverOverlayYoutube
case duckPlayerContingencySettingsDisplayed
case duckPlayerContingencyLearnMoreClicked

// MARK: Unified Feedback Form
case pproFeedbackFeatureRequest(description: String, source: String)
case pproFeedbackGeneralFeedback(description: String, source: String)
case pproFeedbackReportIssue(source: String, category: String, subcategory: String, description: String, metadata: String)
case pproFeedbackFormShow
case pproFeedbackActionsScreenShow(source: String)
case pproFeedbackCategoryScreenShow(source: String, reportType: String)
case pproFeedbackSubcategoryScreenShow(source: String, reportType: String, category: String)
case pproFeedbackSubmitScreenShow(source: String, reportType: String, category: String, subcategory: String)
case pproFeedbackSubmitScreenFAQClick(source: String, reportType: String, category: String, subcategory: String)
}

}
Expand Down Expand Up @@ -1551,6 +1562,17 @@ extension Pixel.Event {
case .duckPlayerSettingNeverOverlayYoutube: return "duckplayer_setting_never_overlay_youtube"
case .duckPlayerContingencySettingsDisplayed: return "duckplayer_ios_contingency_settings-displayed"
case .duckPlayerContingencyLearnMoreClicked: return "duckplayer_ios_contingency_learn-more-clicked"

// MARK: Unified Feedback Form
case .pproFeedbackFeatureRequest: return "m_ppro_feedback_feature-request"
case .pproFeedbackGeneralFeedback: return "m_ppro_feedback_general-feedback"
case .pproFeedbackReportIssue: return "m_ppro_feedback_report-issue"
case .pproFeedbackFormShow: return "m_ppro_feedback_general-screen_show"
case .pproFeedbackActionsScreenShow: return "m_ppro_feedback_actions-screen_show"
case .pproFeedbackCategoryScreenShow: return "m_ppro_feedback_category-screen_show"
case .pproFeedbackSubcategoryScreenShow: return "m_ppro_feedback_subcategory-screen_show"
case .pproFeedbackSubmitScreenShow: return "m_ppro_feedback_submit-screen_show"
case .pproFeedbackSubmitScreenFAQClick: return "m_ppro_feedback_submit-screen-faq_click"
}
}
}
Expand Down
36 changes: 36 additions & 0 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,7 @@
B6BA95E828924730004ABA20 /* JSAlertController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B6BA95E728924730004ABA20 /* JSAlertController.storyboard */; };
B6CB93E5286445AB0090FEB4 /* Base64DownloadSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6CB93E4286445AB0090FEB4 /* Base64DownloadSession.swift */; };
BBFF18B12C76448100C48D7D /* QuerySubmittedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBFF18B02C76448100C48D7D /* QuerySubmittedTests.swift */; };
BD10B8AA2C7629740033115D /* Logger+Subscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD10B8A92C7629740033115D /* Logger+Subscription.swift */; };
BD15DB852B959CFD00821457 /* BundleExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD15DB842B959CFD00821457 /* BundleExtension.swift */; };
BD2F39EB2C19F955005B19E7 /* NetworkProtectionDNSSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD2F39EA2C19F955005B19E7 /* NetworkProtectionDNSSettingsView.swift */; };
BD862E032B30DA170073E2EE /* VPNFeedbackFormViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BD862E022B30DA170073E2EE /* VPNFeedbackFormViewModel.swift */; };
Expand All @@ -796,6 +797,12 @@
BDD3B3552B8EF8DB005857A8 /* NetworkProtectionUNNotificationPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE3766DD2AC5945500AAB575 /* NetworkProtectionUNNotificationPresenter.swift */; };
BDE219E62C406D19005D5884 /* PrivacyProDataReporting.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE219E52C406D19005D5884 /* PrivacyProDataReporting.swift */; };
BDE219EA2C457B46005D5884 /* PrivacyProDataReporterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE219E92C457B46005D5884 /* PrivacyProDataReporterTests.swift */; };
BDE91CD62C6294020005CB74 /* FeedbackCategoryProviding.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE91CD52C6294020005CB74 /* FeedbackCategoryProviding.swift */; };
BDE91CD82C629A910005CB74 /* UnifiedFeedbackSender.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE91CD72C629A910005CB74 /* UnifiedFeedbackSender.swift */; };
BDE91CDA2C62A70B0005CB74 /* UnifiedMetadataCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE91CD92C62A70B0005CB74 /* UnifiedMetadataCollector.swift */; };
BDE91CDC2C62AA3A0005CB74 /* DefaultMetadataCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE91CDB2C62AA3A0005CB74 /* DefaultMetadataCollector.swift */; };
BDE91CDE2C62B90F0005CB74 /* UnifiedFeedbackRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE91CDD2C62B90F0005CB74 /* UnifiedFeedbackRootView.swift */; };
BDE91CE02C6515420005CB74 /* UnifiedFeedbackFormViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDE91CDF2C6515410005CB74 /* UnifiedFeedbackFormViewModel.swift */; };
BDF8D0022C1B87F4003E3B27 /* NetworkProtectionDNSSettingsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDF8D0012C1B87F4003E3B27 /* NetworkProtectionDNSSettingsViewModel.swift */; };
BDFF031D2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF031C2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift */; };
BDFF03212BA3D3CF00F324C9 /* NetworkProtectionVisibilityForTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDFF03202BA3D3CF00F324C9 /* NetworkProtectionVisibilityForTunnelProvider.swift */; };
Expand Down Expand Up @@ -2534,6 +2541,7 @@
B6DFE6CF2BC7E47500A9CE59 /* SwiftLintTool.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SwiftLintTool.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
B6DFE6D92BC7E61B00A9CE59 /* SwiftLintToolBundleConfiguration.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SwiftLintToolBundleConfiguration.xcconfig; sourceTree = "<group>"; };
BBFF18B02C76448100C48D7D /* QuerySubmittedTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuerySubmittedTests.swift; sourceTree = "<group>"; };
BD10B8A92C7629740033115D /* Logger+Subscription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Logger+Subscription.swift"; sourceTree = "<group>"; };
BD15DB842B959CFD00821457 /* BundleExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleExtension.swift; sourceTree = "<group>"; };
BD2F39EA2C19F955005B19E7 /* NetworkProtectionDNSSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDNSSettingsView.swift; sourceTree = "<group>"; };
BD862E022B30DA170073E2EE /* VPNFeedbackFormViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNFeedbackFormViewModel.swift; sourceTree = "<group>"; };
Expand All @@ -2544,6 +2552,12 @@
BDC234F62B27F51100D3C798 /* UniquePixel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UniquePixel.swift; sourceTree = "<group>"; };
BDE219E52C406D19005D5884 /* PrivacyProDataReporting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyProDataReporting.swift; sourceTree = "<group>"; };
BDE219E92C457B46005D5884 /* PrivacyProDataReporterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PrivacyProDataReporterTests.swift; sourceTree = "<group>"; };
BDE91CD52C6294020005CB74 /* FeedbackCategoryProviding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackCategoryProviding.swift; sourceTree = "<group>"; };
BDE91CD72C629A910005CB74 /* UnifiedFeedbackSender.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnifiedFeedbackSender.swift; sourceTree = "<group>"; };
BDE91CD92C62A70B0005CB74 /* UnifiedMetadataCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnifiedMetadataCollector.swift; sourceTree = "<group>"; };
BDE91CDB2C62AA3A0005CB74 /* DefaultMetadataCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultMetadataCollector.swift; sourceTree = "<group>"; };
BDE91CDD2C62B90F0005CB74 /* UnifiedFeedbackRootView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnifiedFeedbackRootView.swift; sourceTree = "<group>"; };
BDE91CDF2C6515410005CB74 /* UnifiedFeedbackFormViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnifiedFeedbackFormViewModel.swift; sourceTree = "<group>"; };
BDF8D0012C1B87F4003E3B27 /* NetworkProtectionDNSSettingsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDNSSettingsViewModel.swift; sourceTree = "<group>"; };
BDFF03192BA39C5A00F324C9 /* NetworkProtectionFeatureVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionFeatureVisibility.swift; sourceTree = "<group>"; };
BDFF031C2BA3D2BD00F324C9 /* DefaultNetworkProtectionVisibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultNetworkProtectionVisibility.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4828,6 +4842,19 @@
path = Feedback;
sourceTree = "<group>";
};
BDE91CD42C6292BF0005CB74 /* Feedback */ = {
isa = PBXGroup;
children = (
BDE91CD52C6294020005CB74 /* FeedbackCategoryProviding.swift */,
BDE91CD72C629A910005CB74 /* UnifiedFeedbackSender.swift */,
BDE91CD92C62A70B0005CB74 /* UnifiedMetadataCollector.swift */,
BDE91CDB2C62AA3A0005CB74 /* DefaultMetadataCollector.swift */,
BDE91CDD2C62B90F0005CB74 /* UnifiedFeedbackRootView.swift */,
BDE91CDF2C6515410005CB74 /* UnifiedFeedbackFormViewModel.swift */,
);
path = Feedback;
sourceTree = "<group>";
};
BDFF031F2BA3D3AD00F324C9 /* Feature Visibility */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -5049,6 +5076,7 @@
D664C7922B289AA000CBFA76 /* Subscription */ = {
isa = PBXGroup;
children = (
BDE91CD42C6292BF0005CB74 /* Feedback */,
F1FDC92F2BF4E0B3006B1435 /* SubscriptionEnvironment+Default.swift */,
D60170BB2BA32DD6001911B5 /* Subscription.swift */,
D6D95CE42B6DA3F200960317 /* AsyncHeadlessWebview */,
Expand Down Expand Up @@ -5081,6 +5109,7 @@
D664C7962B289AA000CBFA76 /* Extensions */ = {
isa = PBXGroup;
children = (
BD10B8A92C7629740033115D /* Logger+Subscription.swift */,
F1FDC9342BF51E41006B1435 /* VPNSettings+Environment.swift */,
D664C7982B289AA000CBFA76 /* WKUserContentController+Handler.swift */,
);
Expand Down Expand Up @@ -7005,6 +7034,7 @@
files = (
EE4FB1862A28CE7200E5CBA7 /* NetworkProtectionStatusView.swift in Sources */,
C17B59592A03AAD30055F2D1 /* PasswordGenerationPromptViewModel.swift in Sources */,
BDE91CDE2C62B90F0005CB74 /* UnifiedFeedbackRootView.swift in Sources */,
D65625A12C232F5E006EF297 /* SettingsDuckPlayerView.swift in Sources */,
D6FEB8B52B74994000C3615F /* HeadlessWebViewCoordinator.swift in Sources */,
6FE1273D2C204C2500EB5724 /* FavoritesView.swift in Sources */,
Expand Down Expand Up @@ -7140,6 +7170,7 @@
D65625952C22D382006EF297 /* TabViewController.swift in Sources */,
8C4838B5221C8F7F008A6739 /* GestureToolbarButton.swift in Sources */,
310ECFDD282A8BB0005029B3 /* EnableAutofillSettingsTableViewCell.swift in Sources */,
BDE91CD62C6294020005CB74 /* FeedbackCategoryProviding.swift in Sources */,
6F9FFE2A2C57ADB100A238BE /* EditableShortcutsView.swift in Sources */,
1E908BF329827C480008C8F3 /* AutoconsentManagement.swift in Sources */,
D6D95CE32B6D9F8800960317 /* AsyncHeadlessWebViewModel.swift in Sources */,
Expand Down Expand Up @@ -7228,6 +7259,7 @@
85F2FFCF2211F8E5006BB258 /* TabSwitcherViewController+KeyCommands.swift in Sources */,
3157B43327F497E90042D3D7 /* SaveLoginView.swift in Sources */,
F17922E01E71BB59006E3D97 /* AutocompleteViewControllerDelegate.swift in Sources */,
BDE91CDC2C62AA3A0005CB74 /* DefaultMetadataCollector.swift in Sources */,
D664C7C82B289AA200CBFA76 /* SubscriptionFlowView.swift in Sources */,
EE458D142ABB652900FC651A /* NetworkProtectionDebugUtilities.swift in Sources */,
8528AE7C212EF4A200D0BD74 /* AppRatingPrompt.swift in Sources */,
Expand Down Expand Up @@ -7325,6 +7357,7 @@
F13B4BC01F180D8A00814661 /* TabsModel.swift in Sources */,
BD862E052B30DB250073E2EE /* VPNFeedbackCategory.swift in Sources */,
85AE6690209724120014CF04 /* NotificationView.swift in Sources */,
BDE91CE02C6515420005CB74 /* UnifiedFeedbackFormViewModel.swift in Sources */,
1EA51376286596A000493C6A /* PrivacyIconLogic.swift in Sources */,
980891A92238504B00313A70 /* UILabelExtension.swift in Sources */,
6FD8E51E2C5B84DE00345670 /* NewTabPageIntroMessageView.swift in Sources */,
Expand Down Expand Up @@ -7363,6 +7396,7 @@
85C861E628FF1B5F00189466 /* HomeViewSectionRenderersExtension.swift in Sources */,
CB825C922C071B1400BCC586 /* AlertView.swift in Sources */,
1DDF40292BA04FCD006850D9 /* SettingsPrivacyProtectionsView.swift in Sources */,
BDE91CD82C629A910005CB74 /* UnifiedFeedbackSender.swift in Sources */,
6F64AA5F2C49463C00CF4489 /* ShortcutsModel.swift in Sources */,
F1D477C61F2126CC0031ED49 /* OmniBarState.swift in Sources */,
85F2FFCD2211F615006BB258 /* MainViewController+KeyCommands.swift in Sources */,
Expand Down Expand Up @@ -7461,6 +7495,7 @@
85F98F92296F32BD00742F4A /* SyncSettingsViewController.swift in Sources */,
84E341961E2F7EFB00BDBA6F /* AppDelegate.swift in Sources */,
310D091D2799F57200DC0060 /* Download.swift in Sources */,
BDE91CDA2C62A70B0005CB74 /* UnifiedMetadataCollector.swift in Sources */,
C13F3F6C2B7F88470083BE40 /* AuthConfirmationPromptViewModel.swift in Sources */,
1EEF124E2850EADE003DDE57 /* PrivacyIconView.swift in Sources */,
9FB027122C2526DD009EA190 /* OnboardingView+IntroDialogContent.swift in Sources */,
Expand Down Expand Up @@ -7532,6 +7567,7 @@
D664C7B92B289AA200CBFA76 /* WKUserContentController+Handler.swift in Sources */,
1E8AD1D727C2E24E00ABA377 /* DownloadsListRowViewModel.swift in Sources */,
9FEA222E2C324ECD006B03BF /* ViewVisibility.swift in Sources */,
BD10B8AA2C7629740033115D /* Logger+Subscription.swift in Sources */,
1E865AF0272042DB001C74F3 /* TextSizeSettingsViewController.swift in Sources */,
D6E0C1892B7A2E0D00D5E1E9 /* DesktopDownloadViewModel.swift in Sources */,
8524CC9A246DA81700E59D45 /* FullscreenDaxDialogViewController.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/Feedback/VPNFeedbackFormViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ final class VPNFeedbackFormViewModel: ObservableObject {
viewState = .feedbackSending

do {
let metadata = await metadataCollector.collectMetadata()
let metadata = await metadataCollector.collectVPNMetadata()
try await feedbackSender.send(metadata: metadata, category: category, userText: feedbackFormText)
viewState = .feedbackSent
return true
Expand Down
30 changes: 16 additions & 14 deletions DuckDuckGo/Feedback/VPNMetadataCollector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,22 +93,10 @@ struct VPNMetadata: Encodable {

return String(data: encodedMetadata, encoding: .utf8)
}

func toBase64() -> String {
let encoder = JSONEncoder()
encoder.outputFormatting = [.sortedKeys]

do {
let encodedMetadata = try encoder.encode(self)
return encodedMetadata.base64EncodedString()
} catch {
return "Failed to encode metadata to JSON, error message: \(error.localizedDescription)"
}
}
}

protocol VPNMetadataCollector {
func collectMetadata() async -> VPNMetadata
func collectVPNMetadata() async -> VPNMetadata
}

final class DefaultVPNMetadataCollector: VPNMetadataCollector {
Expand All @@ -130,7 +118,7 @@ final class DefaultVPNMetadataCollector: VPNMetadataCollector {
self.defaults = defaults
}

func collectMetadata() async -> VPNMetadata {
func collectVPNMetadata() async -> VPNMetadata {
let appInfoMetadata = collectAppInfoMetadata()
let deviceInfoMetadata = collectDeviceInfoMetadata()
let networkInfoMetadata = await collectNetworkInformation()
Expand Down Expand Up @@ -282,3 +270,17 @@ private extension NSError {
}

}

// MARK: - Unified feedback form support

extension VPNMetadata: UnifiedFeedbackMetadata {}

extension DefaultVPNMetadataCollector: UnifiedMetadataCollector {
convenience init() {
self.init(statusObserver: AppDependencyProvider.shared.connectionObserver)
}

func collectMetadata() async -> VPNMetadata? {
await collectVPNMetadata()
}
}
15 changes: 15 additions & 0 deletions DuckDuckGo/MainViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class MainViewController: UIViewController {
private var settingsDeepLinkcancellables = Set<AnyCancellable>()
private let tunnelDefaults = UserDefaults.networkProtectionGroupDefaults
private var vpnCancellables = Set<AnyCancellable>()
private var feedbackCancellable: AnyCancellable?

let privacyProDataReporter: PrivacyProDataReporting

Expand Down Expand Up @@ -285,6 +286,7 @@ class MainViewController: UIViewController {
subscribeToURLInterceptorNotifications()
subscribeToSettingsDeeplinkNotifications()
subscribeToNetworkProtectionEvents()
subscribeToUnifiedFeedbackNotifications()

findInPageView.delegate = self
findInPageBottomLayoutConstraint.constant = 0
Expand Down Expand Up @@ -1548,6 +1550,19 @@ class MainViewController: UIViewController {
nil, .deliverImmediately)
}

private func subscribeToUnifiedFeedbackNotifications() {
feedbackCancellable = NotificationCenter.default.publisher(for: .unifiedFeedbackNotification)
.receive(on: DispatchQueue.main)
.sink { _ in
DispatchQueue.main.async { [weak self] in
guard let navigationController = self?.presentedViewController as? UINavigationController else { return }
navigationController.popToRootViewController(animated: true)
ActionMessageView.present(message: UserText.vpnFeedbackFormSubmittedMessage,
presentationLocation: .withoutBottomBar)
}
}
}

private func onNetworkProtectionEntitlementMessagingChange() {
if tunnelDefaults.showEntitlementAlert {
presentExpiredEntitlementAlert()
Expand Down
Loading

0 comments on commit 29f8770

Please sign in to comment.