@@ -46,6 +46,14 @@ class DefaultStoresManager: StoresManager {
4646 ///
4747 private let cardPresentPaymentOnboardingStateCache : CardPresentPaymentOnboardingStateCache
4848
49+ /// Tracks site IDs that are eligible for app password support to prevent duplicate analytics events
50+ ///
51+ private var trackedEligibleSites : Set < Int64 > = [ ]
52+
53+ /// Network switching notification observers
54+ ///
55+ private var networkNotificationObservers : [ NSObjectProtocol ] ?
56+
4957 /// SessionManager: Persistent Storage for Session-Y Properties.
5058 /// This property is thread safe
5159 private( set) var sessionManager : SessionManagerProtocol {
@@ -148,6 +156,9 @@ class DefaultStoresManager: StoresManager {
148156 self . cardPresentPaymentOnboardingStateCache = cardPresentPaymentOnboardingStateCache
149157
150158 isLoggedIn = isAuthenticated
159+ if isLoggedIn, case . some( . wpcom) = sessionManager. defaultCredentials {
160+ startObservingNetworkNotifications ( )
161+ }
151162 }
152163
153164 /// This should only be invoked after all the ServiceLocator dependencies in this function are initialized to avoid circular reference.
@@ -182,9 +193,11 @@ class DefaultStoresManager: StoresManager {
182193 if case . wpcom = credentials {
183194 listenToWPCOMInvalidWPCOMTokenNotification ( )
184195 applicationPasswordGenerationFailureObserver = nil
196+ startObservingNetworkNotifications ( )
185197 } else {
186198 listenToApplicationPasswordGenerationFailureNotification ( )
187199 invalidWPCOMTokenNotificationObserver = nil
200+ stopObservingNetworkNotifications ( )
188201 }
189202
190203 return self
@@ -265,6 +278,8 @@ class DefaultStoresManager: StoresManager {
265278 func deauthenticate( ) -> StoresManager {
266279 applicationPasswordGenerationFailureObserver = nil
267280 invalidWPCOMTokenNotificationObserver = nil
281+ stopObservingNetworkNotifications ( )
282+ trackedEligibleSites. removeAll ( )
268283
269284 if isAuthenticated {
270285 let resetAction = CardPresentPaymentAction . reset
@@ -823,6 +838,62 @@ private extension DefaultStoresManager {
823838 systemPlugins: systemPlugins)
824839 }
825840 }
841+
842+ /// Sets up network switching notification observers
843+ ///
844+ func startObservingNetworkNotifications( ) {
845+ let eligibleSiteObserver = notificationCenter. addObserver (
846+ forName: . JetpackSiteEligibleForAppPasswordSupport,
847+ object: nil ,
848+ queue: . main) { [ weak self] note in
849+ self ? . trackJetpackSiteEligible ( note: note)
850+ }
851+
852+ let siteFlaggedObserver = notificationCenter. addObserver (
853+ forName: . JetpackSiteFlaggedUnsupportedForApplicationPassword,
854+ object: nil ,
855+ queue: . main) { [ weak self] note in
856+ self ? . trackJetpackSiteFlagged ( note: note)
857+ }
858+
859+ networkNotificationObservers = [ eligibleSiteObserver, siteFlaggedObserver]
860+ }
861+
862+ /// Removes network switching notification observers
863+ ///
864+ func stopObservingNetworkNotifications( ) {
865+ networkNotificationObservers? . forEach { observer in
866+ notificationCenter. removeObserver ( observer)
867+ }
868+ networkNotificationObservers = nil
869+ }
870+
871+ /// Tracks Jetpack site eligible for app password support with deduplication
872+ ///
873+ func trackJetpackSiteEligible( note: Notification ) {
874+ guard let siteID = note. object as? Int64 ,
875+ sessionManager. defaultSite? . siteID == siteID else {
876+ return
877+ }
878+ // Only track if we haven't already tracked this site
879+ if !trackedEligibleSites. contains ( siteID) {
880+ trackedEligibleSites. insert ( siteID)
881+ ServiceLocator . analytics. track ( . jetpackSiteEligibleForAppPasswordSupport)
882+ }
883+ }
884+
885+ /// Tracks Jetpack site flagged as unsupported and removes from eligible tracking
886+ ///
887+ private func trackJetpackSiteFlagged( note: Notification ) {
888+ guard let properties = note. object as? [ String : Any ] else {
889+ return
890+ }
891+ // Get the current site ID and remove from tracked sites
892+ if let siteID = sessionManager. defaultStoreID {
893+ trackedEligibleSites. remove ( siteID)
894+ }
895+ ServiceLocator . analytics. track ( . jetpackSiteFlaggedUnsupportedForAppPasswords, withProperties: properties)
896+ }
826897}
827898
828899
0 commit comments