mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-02 12:07:55 +00:00
Posthog: report SessionSecurityState (#2795)
* Posthog: report SessionSecurityState * Review quick change --------- Co-authored-by: Mauro <34335419+Velin92@users.noreply.github.com>
This commit is contained in:
@@ -431,6 +431,7 @@
|
||||
6860721DB3091BE08164C132 /* MapAssets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B48B7AD4908C5C374517B892 /* MapAssets.xcassets */; };
|
||||
68AC3C84E2B438036B174E30 /* EmoteRoomTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 471EB7D96AFEA8D787659686 /* EmoteRoomTimelineView.swift */; };
|
||||
695825D20A761C678809345D /* MessageForwardingScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52135BD9E0E7A091688F627A /* MessageForwardingScreenModels.swift */; };
|
||||
69A9B430397C15075D86193F /* UserPropertiesExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */; };
|
||||
69B3C6010B42010F591FC3CB /* RoomRolesAndPermissionsScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7C1AF829F12FDC99717082D9 /* RoomRolesAndPermissionsScreenViewModel.swift */; };
|
||||
69BCBB4FB2DC3D61A28D3FD8 /* TimelineStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC2C9E0E15C79BBDA80F0A2 /* TimelineStyle.swift */; };
|
||||
69C7B956B74BEC3DB88224EA /* NavigationSplitCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */; };
|
||||
@@ -1533,6 +1534,7 @@
|
||||
6663BFB9FDB8752562CD12CA /* AuthenticationStartScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticationStartScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||
667DD3A9D932D7D9EB380CAA /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = sk; path = sk.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
|
||||
669F35C505ACE1110589F875 /* MediaUploadingPreprocessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaUploadingPreprocessor.swift; sourceTree = "<group>"; };
|
||||
66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPropertiesExt.swift; sourceTree = "<group>"; };
|
||||
66F2402D738694F98729A441 /* RoomTimelineProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomTimelineProvider.swift; sourceTree = "<group>"; };
|
||||
6722709BD6178E10B70C9641 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/SAS.strings; sourceTree = "<group>"; };
|
||||
68010886142843705E342645 /* ProgressMaskModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressMaskModifier.swift; sourceTree = "<group>"; };
|
||||
@@ -3120,6 +3122,7 @@
|
||||
5CEEAE1BFAACD6C96B6DB731 /* PHGPostHogProtocol.swift */,
|
||||
1715E3D7F53C0748AA50C91C /* PostHogAnalyticsClient.swift */,
|
||||
752A0EB49BF5BCEA37EDF7A3 /* Signposter.swift */,
|
||||
66AFD800AF033D8B0D11191A /* UserPropertiesExt.swift */,
|
||||
3A304097A59704AC9B869EC6 /* Helpers */,
|
||||
);
|
||||
path = Analytics;
|
||||
@@ -6555,6 +6558,7 @@
|
||||
D4CB979EB4FE26AAD9F9A72B /* UserProfileScreenModels.swift in Sources */,
|
||||
AC1DB27A4134470846BE49F6 /* UserProfileScreenViewModel.swift in Sources */,
|
||||
46A183C6125A669AEB005699 /* UserProfileScreenViewModelProtocol.swift in Sources */,
|
||||
69A9B430397C15075D86193F /* UserPropertiesExt.swift in Sources */,
|
||||
8AB8ED1051216546CB35FA0E /* UserSession.swift in Sources */,
|
||||
4A618590DEB72C4F186BFED4 /* UserSessionFlowCoordinator.swift in Sources */,
|
||||
3113065AABBC14CEAE6843FA /* UserSessionFlowCoordinatorStateMachine.swift in Sources */,
|
||||
@@ -7378,7 +7382,7 @@
|
||||
repositoryURL = "https://github.com/matrix-org/matrix-analytics-events";
|
||||
requirement = {
|
||||
kind = upToNextMinorVersion;
|
||||
minimumVersion = 0.20.0;
|
||||
minimumVersion = 0.21.0;
|
||||
};
|
||||
};
|
||||
C13F55E4518415CB4C278E73 /* XCRemoteSwiftPackageReference "DTCoreText" */ = {
|
||||
|
||||
@@ -121,8 +121,8 @@
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/matrix-org/matrix-analytics-events",
|
||||
"state" : {
|
||||
"revision" : "e4e49896331c9dcf7346c90529a9aad7944a3259",
|
||||
"version" : "0.20.0"
|
||||
"revision" : "f10d044b9eaf35871bbb61cdfdb8f93a04e429e0",
|
||||
"version" : "0.21.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -203,6 +203,45 @@ class AnalyticsClientMock: AnalyticsClientProtocol {
|
||||
screenReceivedInvocations.append(event)
|
||||
screenClosure?(event)
|
||||
}
|
||||
//MARK: - updateUserProperties
|
||||
|
||||
var updateUserPropertiesUnderlyingCallsCount = 0
|
||||
var updateUserPropertiesCallsCount: Int {
|
||||
get {
|
||||
if Thread.isMainThread {
|
||||
return updateUserPropertiesUnderlyingCallsCount
|
||||
} else {
|
||||
var returnValue: Int? = nil
|
||||
DispatchQueue.main.sync {
|
||||
returnValue = updateUserPropertiesUnderlyingCallsCount
|
||||
}
|
||||
|
||||
return returnValue!
|
||||
}
|
||||
}
|
||||
set {
|
||||
if Thread.isMainThread {
|
||||
updateUserPropertiesUnderlyingCallsCount = newValue
|
||||
} else {
|
||||
DispatchQueue.main.sync {
|
||||
updateUserPropertiesUnderlyingCallsCount = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var updateUserPropertiesCalled: Bool {
|
||||
return updateUserPropertiesCallsCount > 0
|
||||
}
|
||||
var updateUserPropertiesReceivedEvent: AnalyticsEvent.UserProperties?
|
||||
var updateUserPropertiesReceivedInvocations: [AnalyticsEvent.UserProperties] = []
|
||||
var updateUserPropertiesClosure: ((AnalyticsEvent.UserProperties) -> Void)?
|
||||
|
||||
func updateUserProperties(_ event: AnalyticsEvent.UserProperties) {
|
||||
updateUserPropertiesCallsCount += 1
|
||||
updateUserPropertiesReceivedEvent = event
|
||||
updateUserPropertiesReceivedInvocations.append(event)
|
||||
updateUserPropertiesClosure?(event)
|
||||
}
|
||||
}
|
||||
class AppLockServiceMock: AppLockServiceProtocol {
|
||||
var isMandatory: Bool {
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import AnalyticsEvents
|
||||
import Combine
|
||||
import SwiftUI
|
||||
|
||||
@@ -86,6 +87,21 @@ class HomeScreenViewModel: HomeScreenViewModelType, HomeScreenViewModelProtocol
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
userSession.sessionSecurityStatePublisher
|
||||
.receive(on: DispatchQueue.main)
|
||||
.filter { state in
|
||||
state.verificationState != .unknown
|
||||
&& state.recoveryState != .settingUp
|
||||
&& state.recoveryState != .unknown
|
||||
}
|
||||
.sink { [weak self] state in
|
||||
guard let self else { return }
|
||||
|
||||
self.analyticsService.updateUserProperties(AnalyticsEvent.newVerificationStateUserProperty(verificationState: state.verificationState, recoveryState: state.recoveryState))
|
||||
self.analyticsService.trackSessionSecurityState(state)
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
selectedRoomPublisher
|
||||
.weakAssign(to: \.state.selectedRoomID, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
@@ -38,6 +38,10 @@ protocol AnalyticsClientProtocol {
|
||||
/// Capture the supplied analytics screen event.
|
||||
/// - Parameter event: The screen event to capture.
|
||||
func screen(_ event: AnalyticsScreenProtocol)
|
||||
|
||||
/// Updates the user properties
|
||||
/// - Parameter userProperties: The properties event to capture.
|
||||
func updateUserProperties(_ event: AnalyticsEvent.UserProperties)
|
||||
}
|
||||
|
||||
// sourcery: AutoMockable
|
||||
|
||||
@@ -223,4 +223,39 @@ extension AnalyticsService {
|
||||
let role = role.map(AnalyticsEvent.RoomModeration.Role.init)
|
||||
capture(event: AnalyticsEvent.RoomModeration(action: action, role: role))
|
||||
}
|
||||
|
||||
func trackSessionSecurityState(_ state: SessionSecurityState) {
|
||||
let analyticsVerificationState: AnalyticsEvent.CryptoSessionStateChange.VerificationState
|
||||
|
||||
switch state.verificationState {
|
||||
case .unknown:
|
||||
return
|
||||
case .verified:
|
||||
analyticsVerificationState = .Verified
|
||||
case .unverified:
|
||||
analyticsVerificationState = .NotVerified
|
||||
}
|
||||
|
||||
let analyticsRecoveryState: AnalyticsEvent.CryptoSessionStateChange.RecoveryState
|
||||
|
||||
switch state.recoveryState {
|
||||
case .enabled:
|
||||
analyticsRecoveryState = .Enabled
|
||||
case .disabled:
|
||||
analyticsRecoveryState = .Disabled
|
||||
case .incomplete:
|
||||
analyticsRecoveryState = .Incomplete
|
||||
case .unknown:
|
||||
return
|
||||
case .settingUp:
|
||||
return
|
||||
}
|
||||
|
||||
let event = AnalyticsEvent.CryptoSessionStateChange(recoveryState: analyticsRecoveryState, verificationState: analyticsVerificationState)
|
||||
client.capture(event)
|
||||
}
|
||||
|
||||
func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) {
|
||||
client.updateUserProperties(userProperties)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,9 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol {
|
||||
self.pendingUserProperties = AnalyticsEvent.UserProperties(allChatsActiveFilter: userProperties.allChatsActiveFilter ?? pendingUserProperties.allChatsActiveFilter,
|
||||
ftueUseCaseSelection: userProperties.ftueUseCaseSelection ?? pendingUserProperties.ftueUseCaseSelection,
|
||||
numFavouriteRooms: userProperties.numFavouriteRooms ?? pendingUserProperties.numFavouriteRooms,
|
||||
numSpaces: userProperties.numSpaces ?? pendingUserProperties.numSpaces)
|
||||
numSpaces: userProperties.numSpaces ?? pendingUserProperties.numSpaces,
|
||||
recoveryState: userProperties.recoveryState ?? pendingUserProperties.recoveryState,
|
||||
verificationState: userProperties.verificationState ?? pendingUserProperties.verificationState)
|
||||
}
|
||||
|
||||
func updateSuperProperties(_ updatedProperties: AnalyticsEvent.SuperProperties) {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// Copyright 2024 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import AnalyticsEvents
|
||||
import Foundation
|
||||
|
||||
extension AnalyticsEvent {
|
||||
static func newVerificationStateUserProperty(verificationState: SessionVerificationState, recoveryState: SecureBackupRecoveryState) -> UserProperties {
|
||||
let analyticsVerificationState: AnalyticsEvent.UserProperties.VerificationState? = switch verificationState {
|
||||
case .unknown:
|
||||
nil
|
||||
case .verified:
|
||||
.Verified
|
||||
case .unverified:
|
||||
.NotVerified
|
||||
}
|
||||
|
||||
let analyticsRecoveryState: AnalyticsEvent.UserProperties.RecoveryState? = switch recoveryState {
|
||||
case .enabled:
|
||||
.Enabled
|
||||
case .disabled:
|
||||
.Disabled
|
||||
case .incomplete:
|
||||
.Incomplete
|
||||
case .unknown:
|
||||
nil
|
||||
case .settingUp:
|
||||
nil
|
||||
}
|
||||
|
||||
return UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: nil, numFavouriteRooms: nil, numSpaces: nil, recoveryState: analyticsRecoveryState, verificationState: analyticsVerificationState)
|
||||
}
|
||||
}
|
||||
@@ -142,13 +142,15 @@ class AnalyticsTests: XCTestCase {
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil,
|
||||
ftueUseCaseSelection: .PersonalMessaging,
|
||||
numFavouriteRooms: 4,
|
||||
numSpaces: 5))
|
||||
numSpaces: 5, recoveryState: .Disabled, verificationState: .Verified))
|
||||
|
||||
// Then the properties should be cached
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.numFavouriteRooms, 4, "The number of favorite rooms should match.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.numSpaces, 5, "The number of spaces should match.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.verificationState, AnalyticsEvent.UserProperties.VerificationState.Verified, "The verification state should match.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.recoveryState, AnalyticsEvent.UserProperties.RecoveryState.Disabled, "The recovery state should match.")
|
||||
}
|
||||
|
||||
func testMergingUserProperties() {
|
||||
@@ -156,7 +158,7 @@ class AnalyticsTests: XCTestCase {
|
||||
let client = PostHogAnalyticsClient()
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging,
|
||||
numFavouriteRooms: nil,
|
||||
numSpaces: nil))
|
||||
numSpaces: nil, recoveryState: nil, verificationState: nil))
|
||||
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.")
|
||||
@@ -166,7 +168,7 @@ class AnalyticsTests: XCTestCase {
|
||||
// When updating the number of spaced
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: nil,
|
||||
numFavouriteRooms: 4,
|
||||
numSpaces: 5))
|
||||
numSpaces: 5, recoveryState: nil, verificationState: nil))
|
||||
|
||||
// Then the new properties should be updated and the existing properties should remain unchanged
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
@@ -183,7 +185,7 @@ class AnalyticsTests: XCTestCase {
|
||||
|
||||
client.updateUserProperties(AnalyticsEvent.UserProperties(allChatsActiveFilter: nil, ftueUseCaseSelection: .PersonalMessaging,
|
||||
numFavouriteRooms: nil,
|
||||
numSpaces: nil))
|
||||
numSpaces: nil, recoveryState: nil, verificationState: nil))
|
||||
|
||||
XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.")
|
||||
XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.")
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ packages:
|
||||
# path: ../compound-ios
|
||||
AnalyticsEvents:
|
||||
url: https://github.com/matrix-org/matrix-analytics-events
|
||||
minorVersion: 0.20.0
|
||||
minorVersion: 0.21.0
|
||||
# path: ../matrix-analytics-events
|
||||
Emojibase:
|
||||
url: https://github.com/matrix-org/emojibase-bindings
|
||||
|
||||
Reference in New Issue
Block a user