-
Notifications
You must be signed in to change notification settings - Fork 424
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
Adds pixels to VPN tips #3629
Adds pixels to VPN tips #3629
Conversation
case networkProtectionWidgetTipShown | ||
case networkProtectionWidgetTipActioned | ||
case networkProtectionWidgetTipDismissed | ||
case networkProtectionWidgetTipIgnored |
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.
New pixels
var tipsModel: VPNTipsModel { | ||
statusModel.tipsModel | ||
} |
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.
Placing the tips in a model to separate view and other logic.
for await status in tipsModel.geoswitchingTip.statusUpdates { | ||
if case .invalidated(let reason) = status { | ||
if case .available = previousStatus { |
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.
This is a bit nasty. I copied this logic from macOS.
Tips don't have a simple action hook for when they're dismissed through the "X" button, unless we reimplement them from scratch.
Since I didn't want to recreate the standard tip UI, I am observing the tip status and when I detect a change from available
(should be shown to the user) to invalidated
(either closed or actioned) I'm firing a call to handle the event. This is mostly used for pixel-firing within tipsModel
.
@@ -138,7 +140,7 @@ final class NetworkProtectionStatusViewModel: ObservableObject { | |||
didSet { | |||
if #available(iOS 17.0, *) { | |||
if isNetPEnabled { | |||
VPNGeoswitchingTip.donateVPNConnectedEvent() | |||
VPNGeoswitchingTip.vpnEnabledOnce = true |
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.
Just a change to keep this as a flag, rather than an ever growing counter. We just need to know this happened once.
self.tipsModel = VPNTipsModel( | ||
isTipFeatureEnabled: featureFlagger.isFeatureOn(.networkProtectionUserTips), | ||
statusObserver: statusObserver, | ||
vpnSettings: settings) |
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.
Spawning the tips model.
@@ -577,30 +585,30 @@ final class NetworkProtectionStatusViewModel: ObservableObject { | |||
|
|||
// MARK: - UI Events handling | |||
|
|||
@available(iOS 17.0, *) | |||
@available(iOS 18.0, *) |
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.
This may seem confusing, but the VPN tips feature was initially meant for iOS 17, but due to some unexpected crashes that seem to be on Apple, we've decided to move them to iOS 18.
This just needed to be updated.
/// - The VPN is enabled when previous tip's status is invalidated. | ||
/// | ||
@Parameter | ||
static var isDistancedFromPreviousTip: Bool = false |
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.
"Distance" is a bit of a vague / abstract concept. This flag signals two things:
- The previous tip has been dismissed.
- The previous tip hasn't just been hidden.
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.
LGTM, one question:
Shouldn't we only call configure if the feature flag is enabled here?
controller.configureTipKit([ |
Here's the output of some of my tests:
Testing dismissed
Pixel fired m.vpn.tip.geoswitching.shown
Pixel fired m.vpn.tip.geoswitching.dismissed
Pixel fired m.vpn.tip.widget.shown
Pixel fired m.vpn.tip.widget.dismissed
Pixel fired m.vpn.tip.snooze.shown
Pixel fired m.vpn.tip.snooze.dismissed
-----
Testing actioned
Pixel fired m.vpn.tip.geoswitching.shown
Pixel fired m.vpn.tip.geoswitching.actioned
Pixel fired m.vpn.tip.widget.shown
Pixel fired m.vpn.tip.widget.actioned
Pixel fired m.vpn.tip.snooze.shown
Pixel fired m.vpn.tip.snooze.actioned
----
Testing ignore
Pixel fired m.vpn.tip.geoswitching.shown
Pixel fired m.vpn.tip.geoswitching.ignored
Pixel fired m.vpn.tip.geoswitching.shown
Pixel fired m.vpn.tip.geoswitching.ignored
Pixel fired m.vpn.tip.geoswitching.shown
Pixel fired m.vpn.tip.geoswitching.dismissed
Pixel fired m.vpn.tip.widget.shown
Pixel fired m.vpn.tip.widget.ignored
Pixel fired m.vpn.tip.widget.shown
Pixel fired m.vpn.tip.widget.ignored
Pixel fired m.vpn.tip.widget.shown
Pixel fired m.vpn.tip.widget.dismissed
Pixel fired m.vpn.tip.snooze.shown
Pixel fired m.vpn.tip.snooze.ignored
This was actually fine, although I understand where the question is coming from - I flagged it during our call 😅 The feature flag guard is a few lines above that point. |
Task/Issue URL: https://app.asana.com/0/1206580121312550/1208856370909429/f
Description
Add pixels for VPN tips in iOS.
Testing
Based on the previous description you should get different pixels depending on how you interact with the tip:
The pixels you can get with this tip are:
The pixels you can get with this tip are:
Definition of Done (Internal Only):
Internal references:
Software Engineering Expectations
Technical Design Template