From aa25690bbf44bf91adc3fc5e3a1afd984247620b Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Aug 2024 15:17:48 +0200 Subject: [PATCH 1/4] chore: Support the propertiesSanitizer config --- CHANGELOG.md | 2 + PostHog.xcodeproj/project.pbxproj | 12 +++ PostHog/PostHogConfig.swift | 4 + PostHog/PostHogPropertiesSanitizer.swift | 34 ++++++++ PostHog/PostHogSDK.swift | 52 +++++++++--- PostHog/Replay/PostHogReplayIntegration.swift | 4 +- PostHogExample/AppDelegate.swift | 3 +- PostHogExample/ContentView2.swift | 80 +++++++++++++++++++ PostHogExample/PostHogExampleApp.swift | 2 +- PostHogTests/ExampleSanitizer.swift | 23 ++++++ PostHogTests/PostHogSDKTest.swift | 20 ++++- 11 files changed, 218 insertions(+), 18 deletions(-) create mode 100644 PostHog/PostHogPropertiesSanitizer.swift create mode 100644 PostHogExample/ContentView2.swift create mode 100644 PostHogTests/ExampleSanitizer.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d9e790ec..b23a99b96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## Next +- chore: Support the `propertiesSanitizer` config ([#150](https://github.com/PostHog/posthog-ios/pull/150)) + ## 3.6.3 - 2024-07-26 - recording: fix: respect session replay project settings from app start ([#150](https://github.com/PostHog/posthog-ios/pull/150)) diff --git a/PostHog.xcodeproj/project.pbxproj b/PostHog.xcodeproj/project.pbxproj index fbd0d057c..29a8b65da 100644 --- a/PostHog.xcodeproj/project.pbxproj +++ b/PostHog.xcodeproj/project.pbxproj @@ -67,7 +67,10 @@ 69278D472AE6BC7200BB541A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 69278D462AE6BC7200BB541A /* main.m */; }; 69278D4B2AE6BC9000BB541A /* PostHog.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AC745B5296D6FE60025C109 /* PostHog.framework */; }; 69278D4C2AE6BC9000BB541A /* PostHog.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3AC745B5296D6FE60025C109 /* PostHog.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 693E977B2C625208004B1030 /* PostHogPropertiesSanitizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E977A2C625208004B1030 /* PostHogPropertiesSanitizer.swift */; }; + 693E977D2C6257F9004B1030 /* ExampleSanitizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E977C2C6257F9004B1030 /* ExampleSanitizer.swift */; }; 6955CB732C517651008EFD8D /* CGSize+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6955CB722C517651008EFD8D /* CGSize+Util.swift */; }; + 6955CB832C5AB517008EFD8D /* ContentView2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6955CB822C5AB517008EFD8D /* ContentView2.swift */; }; 69779BEC2AE68E6900D7A48E /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69779BEB2AE68E6900D7A48E /* UIViewController.swift */; }; 6992AA832AFE51A000087600 /* PostHogExampleTvOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6992AA822AFE51A000087600 /* PostHogExampleTvOSApp.swift */; }; 6992AA852AFE51A000087600 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6992AA842AFE51A000087600 /* ContentView.swift */; }; @@ -316,7 +319,10 @@ 69278D432AE6BC7200BB541A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 69278D452AE6BC7200BB541A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 69278D462AE6BC7200BB541A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 693E977A2C625208004B1030 /* PostHogPropertiesSanitizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogPropertiesSanitizer.swift; sourceTree = ""; }; + 693E977C2C6257F9004B1030 /* ExampleSanitizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleSanitizer.swift; sourceTree = ""; }; 6955CB722C517651008EFD8D /* CGSize+Util.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGSize+Util.swift"; sourceTree = ""; }; + 6955CB822C5AB517008EFD8D /* ContentView2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView2.swift; sourceTree = ""; }; 69779BEB2AE68E6900D7A48E /* UIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; 6992AA802AFE51A000087600 /* PostHogExampleTvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PostHogExampleTvOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6992AA822AFE51A000087600 /* PostHogExampleTvOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogExampleTvOSApp.swift; sourceTree = ""; }; @@ -455,6 +461,7 @@ 3AA34CFB296D951A003398F4 /* ContentView.swift */, 3AA34CFD296D951B003398F4 /* Assets.xcassets */, 3AA34CFF296D951B003398F4 /* Preview Content */, + 6955CB822C5AB517008EFD8D /* ContentView2.swift */, ); path = PostHogExample; sourceTree = ""; @@ -541,6 +548,7 @@ 69779BEB2AE68E6900D7A48E /* UIViewController.swift */, 690FF0C42AEFAE8200A0B06B /* PostHogLegacyQueue.swift */, 69F518372BB2BA0100F52C14 /* PostHogSwizzler.swift */, + 693E977A2C625208004B1030 /* PostHogPropertiesSanitizer.swift */, ); path = PostHog; sourceTree = ""; @@ -559,6 +567,7 @@ 690FF0E82AEFD3BD00A0B06B /* PostHogQueueTest.swift */, 690FF0F42AF0F06100A0B06B /* PostHogSDKTest.swift */, 699C5FEE2C20242A007DB818 /* UUIDTest.swift */, + 693E977C2C6257F9004B1030 /* ExampleSanitizer.swift */, ); path = PostHogTests; sourceTree = ""; @@ -1045,6 +1054,7 @@ 3AA34D17296D9993003398F4 /* AppDelegate.swift in Sources */, 3AA34CFC296D951A003398F4 /* ContentView.swift in Sources */, 3AE3FB2C2991320300AFFC18 /* Api.swift in Sources */, + 6955CB832C5AB517008EFD8D /* ContentView2.swift in Sources */, 3A0F108329C47940002C0084 /* UIViewExample.swift in Sources */, 3AA34CFA296D951A003398F4 /* PostHogExampleApp.swift in Sources */, ); @@ -1080,6 +1090,7 @@ 69F5181A2BAC81FC00F52C14 /* UITextInputTraits+Util.swift in Sources */, 69F517E82BAC675800F52C14 /* RRWireframe.swift in Sources */, 3A0F108529C9ABB6002C0084 /* ReadWriteLock.swift in Sources */, + 693E977B2C625208004B1030 /* PostHogPropertiesSanitizer.swift in Sources */, 3AE3FB3D29924E8200AFFC18 /* PostHogSDK.swift in Sources */, 69F517F32BAC734300F52C14 /* UIColor+Util.swift in Sources */, 3AE3FB3F29924F4F00AFFC18 /* PostHogConfig.swift in Sources */, @@ -1114,6 +1125,7 @@ 690FF0BB2AEF8B8200A0B06B /* PostHogContextTest.swift in Sources */, 690FF0E32AEFD12900A0B06B /* PostHogConfigTest.swift in Sources */, 3A62647129CAF67B007E8C07 /* PostHogSessionManagerTest.swift in Sources */, + 693E977D2C6257F9004B1030 /* ExampleSanitizer.swift in Sources */, 690FF0DF2AEFBC5700A0B06B /* PostHogLegacyQueueTest.swift in Sources */, 690FF0BD2AEF93F400A0B06B /* PostHogFeatureFlagsTest.swift in Sources */, 690FF0E92AEFD3BD00A0B06B /* PostHogQueueTest.swift in Sources */, diff --git a/PostHog/PostHogConfig.swift b/PostHog/PostHogConfig.swift index b05e715f4..78487e9df 100644 --- a/PostHog/PostHogConfig.swift +++ b/PostHog/PostHogConfig.swift @@ -27,6 +27,10 @@ import Foundation @objc public var debug: Bool = false @objc public var optOut: Bool = false @objc public var getAnonymousId: ((UUID) -> UUID) = { uuid in uuid } + /// Hook that allows to sanitize the event properties + /// The hook is called before the event is cached or sent over the wire + @objc public var propertiesSanitizer: PostHogPropertiesSanitizer? + /// Internal var snapshotEndpoint: String = "/s/" diff --git a/PostHog/PostHogPropertiesSanitizer.swift b/PostHog/PostHogPropertiesSanitizer.swift new file mode 100644 index 000000000..789f19793 --- /dev/null +++ b/PostHog/PostHogPropertiesSanitizer.swift @@ -0,0 +1,34 @@ +// +// PostHogPropertiesSanitizer.swift +// PostHog +// +// Created by Manoel Aranda Neto on 06.08.24. +// + +import Foundation + +/// Protocol to sanitize the event properties +@objc(PostHogPropertiesSanitizer) public protocol PostHogPropertiesSanitizer { + /// Sanitizes the event properties + /// - Parameter properties: the event properties to sanitize + /// - Returns: the sanitized properties + /// + /// Obs: `inout` cannot be used in Swift protocols, so you need to clone the properties + /// + /// ```swift + /// private class ExampleSanitizer: PostHogPropertiesSanitizer { + /// public func sanitize(_ properties: [String: Any]) -> [String: Any] { + /// var sanitizedProperties = properties + /// // Perform sanitization + /// // For example, removing keys with empty values + /// for (key, value) in properties { + /// if let stringValue = value as? String, stringValue.isEmpty { + /// sanitizedProperties.removeValue(forKey: key) + /// } + /// } + /// return sanitizedProperties + /// } + /// } + /// ``` + @objc func sanitize(_ properties: [String: Any]) -> [String: Any] +} diff --git a/PostHog/PostHogSDK.swift b/PostHog/PostHogSDK.swift index 09fc25997..47c4f04c8 100644 --- a/PostHog/PostHogSDK.swift +++ b/PostHog/PostHogSDK.swift @@ -379,13 +379,16 @@ private let sessionChangeThreshold: TimeInterval = 60 * 30 } let oldDistinctId = getDistinctId() + let properties = buildProperties(distinctId: distinctId, properties: [ + "distinct_id": distinctId, + "$anon_distinct_id": getAnonymousId(), + ], userProperties: sanitizeDicionary(userProperties), userPropertiesSetOnce: sanitizeDicionary(userPropertiesSetOnce)) + let sanitizedProperties = sanitizeProperties(properties) + queue.add(PostHogEvent( event: "$identify", distinctId: distinctId, - properties: buildProperties(distinctId: distinctId, properties: [ - "distinct_id": distinctId, - "$anon_distinct_id": getAnonymousId(), - ], userProperties: sanitizeDicionary(userProperties), userPropertiesSetOnce: sanitizeDicionary(userPropertiesSetOnce)) + properties: sanitizedProperties )) if distinctId != oldDistinctId { @@ -469,15 +472,19 @@ private let sessionChangeThreshold: TimeInterval = 60 * 30 } let distinctId = getDistinctId() + + let properties = buildProperties(distinctId: distinctId, + properties: sanitizeDicionary(properties), + userProperties: sanitizeDicionary(userProperties), + userPropertiesSetOnce: sanitizeDicionary(userPropertiesSetOnce), + groups: groups, + appendSharedProps: !snapshotEvent) + let sanitizedProperties = sanitizeProperties(properties) + let posthogEvent = PostHogEvent( event: event, distinctId: distinctId, - properties: buildProperties(distinctId: distinctId, - properties: sanitizeDicionary(properties), - userProperties: sanitizeDicionary(userProperties), - userPropertiesSetOnce: sanitizeDicionary(userPropertiesSetOnce), - groups: groups, - appendSharedProps: !snapshotEvent) + properties: sanitizedProperties ) // Replay has its own queue @@ -515,13 +522,24 @@ private let sessionChangeThreshold: TimeInterval = 60 * 30 ].merging(sanitizeDicionary(properties) ?? [:]) { prop, _ in prop } let distinctId = getDistinctId() + + let properties = buildProperties(distinctId: distinctId, properties: props) + let sanitizedProperties = sanitizeProperties(properties) + queue.add(PostHogEvent( event: "$screen", distinctId: distinctId, - properties: buildProperties(distinctId: distinctId, properties: props) + properties: sanitizedProperties )) } + private func sanitizeProperties(_ properties: [String: Any]) -> [String: Any] { + if let sanitizer = config.propertiesSanitizer { + return sanitizer.sanitize(properties) + } + return properties + } + @objc public func alias(_ alias: String) { if !isEnabled() { return @@ -538,10 +556,14 @@ private let sessionChangeThreshold: TimeInterval = 60 * 30 let props = ["alias": alias] let distinctId = getDistinctId() + + let properties = buildProperties(distinctId: distinctId, properties: props) + let sanitizedProperties = sanitizeProperties(properties) + queue.add(PostHogEvent( event: "$create_alias", distinctId: distinctId, - properties: buildProperties(distinctId: distinctId, properties: props) + properties: sanitizedProperties )) } @@ -597,10 +619,14 @@ private let sessionChangeThreshold: TimeInterval = 60 * 30 // Same as .group but without associating the current user with the group let distinctId = getDistinctId() + + let properties = buildProperties(distinctId: distinctId, properties: props) + let sanitizedProperties = sanitizeProperties(properties) + queue.add(PostHogEvent( event: "$groupidentify", distinctId: distinctId, - properties: buildProperties(distinctId: distinctId, properties: props) + properties: sanitizedProperties )) } diff --git a/PostHog/Replay/PostHogReplayIntegration.swift b/PostHog/Replay/PostHogReplayIntegration.swift index c37db19f5..0ed05c2fc 100644 --- a/PostHog/Replay/PostHogReplayIntegration.swift +++ b/PostHog/Replay/PostHogReplayIntegration.swift @@ -25,9 +25,9 @@ // SwiftUI image types // https://stackoverflow.com/questions/57554590/how-to-get-all-the-subviews-of-a-window-or-view-in-latest-swiftui-app // https://stackoverflow.com/questions/58336045/how-to-detect-swiftui-usage-programmatically-in-an-ios-application - private let swiftUIImageTypes = ["_TtCOCV7SwiftUI11DisplayList11ViewUpdater8Platform13CGDrawingView", + private let swiftUIImageTypes = ["_TtCOCV7SwiftUI11DisplayList11ViewUpdater8Platform13CGDrawingView", // 0 "_TtC7SwiftUIP33_A34643117F00277B93DEBAB70EC0697122_UIShapeHitTestingView", - "SwiftUI._UIGraphicsView", + "SwiftUI._UIGraphicsView", // 0 "SwiftUI.ImageLayer"].compactMap { NSClassFromString($0) } init(_ config: PostHogConfig) { diff --git a/PostHogExample/AppDelegate.swift b/PostHogExample/AppDelegate.swift index 31153eed5..f57710622 100644 --- a/PostHogExample/AppDelegate.swift +++ b/PostHogExample/AppDelegate.swift @@ -23,8 +23,9 @@ class AppDelegate: NSObject, UIApplicationDelegate { config.sendFeatureFlagEvent = false config.sessionReplay = true config.sessionReplayConfig.screenshotMode = true - config.sessionReplayConfig.maskAllTextInputs = true + config.sessionReplayConfig.maskAllTextInputs = false config.sessionReplayConfig.maskAllImages = true + config.optOut = true PostHogSDK.shared.setup(config) // PostHogSDK.shared.debug() diff --git a/PostHogExample/ContentView2.swift b/PostHogExample/ContentView2.swift new file mode 100644 index 000000000..015883f59 --- /dev/null +++ b/PostHogExample/ContentView2.swift @@ -0,0 +1,80 @@ +import SwiftUI + +struct ContentView2: View { + @State private var email: String = "" + @State private var password: String = "" + @State private var isLoggedIn: Bool = false + + var body: some View { + NavigationView { + if isLoggedIn { + WelcomeView(isLoggedIn: $isLoggedIn) + } else { + VStack { +// TextField("Email", text: $email) +// .padding() +// .keyboardType(.emailAddress) +// .accessibilityLabel("ph-no-capture") +// .autocapitalization(.none) +// .border(Color.gray) + +// SecureField("Password", text: $password) +// .padding() +// .border(Color.gray) + Text("Welcome!") + .font(.largeTitle) + // .accessibilityIdentifier("ph-no-capture") + .padding() + +// Button(action: { +// // Simple login logic + //// if !email.isEmpty && !password.isEmpty { + //// isLoggedIn = true + //// } +// isLoggedIn = true +// }) { +// Text("Login") +// .frame(maxWidth: .infinity) +// .padding() +// .background(Color.blue) +// .foregroundColor(.white) +// .cornerRadius(10) +// } +// .padding(.top, 20) + } + .padding() + .navigationTitle("Login") + } + } + } +} + +struct WelcomeView: View { + @Binding var isLoggedIn: Bool + + var body: some View { + VStack { + Text("Welcome!") + .font(.largeTitle) +// .accessibilityIdentifier("ph-no-capture") + .padding() + +// Button(action: { +// isLoggedIn = false +// }) { +// Text("Logout") +// .frame(maxWidth: .infinity) +// .padding() +// .background(Color.red) +// .foregroundColor(.white) +// .cornerRadius(10) +// } +// .padding(.top, 20) + } + .padding() + } +} + +#Preview { + ContentView() +} diff --git a/PostHogExample/PostHogExampleApp.swift b/PostHogExample/PostHogExampleApp.swift index a9251a797..e75641751 100644 --- a/PostHogExample/PostHogExampleApp.swift +++ b/PostHogExample/PostHogExampleApp.swift @@ -13,7 +13,7 @@ struct PostHogExampleApp: App { var body: some Scene { WindowGroup { - ContentView() + ContentView2() } } } diff --git a/PostHogTests/ExampleSanitizer.swift b/PostHogTests/ExampleSanitizer.swift new file mode 100644 index 000000000..9e2f03999 --- /dev/null +++ b/PostHogTests/ExampleSanitizer.swift @@ -0,0 +1,23 @@ +// +// ExampleSanitizer.swift +// PostHogTests +// +// Created by Manoel Aranda Neto on 06.08.24. +// + +import Foundation +import PostHog + +class ExampleSanitizer: PostHogPropertiesSanitizer { + public func sanitize(_ properties: [String: Any]) -> [String: Any] { + var sanitizedProperties = properties + // Perform sanitization + // For example, removing keys with empty values + for (key, value) in properties { + if let stringValue = value as? String, stringValue.isEmpty { + sanitizedProperties.removeValue(forKey: key) + } + } + return sanitizedProperties + } +} diff --git a/PostHogTests/PostHogSDKTest.swift b/PostHogTests/PostHogSDKTest.swift index e7eecfdcb..98d917d62 100644 --- a/PostHogTests/PostHogSDKTest.swift +++ b/PostHogTests/PostHogSDKTest.swift @@ -16,7 +16,8 @@ class PostHogSDKTest: QuickSpec { sendFeatureFlagEvent: Bool = false, captureApplicationLifecycleEvents: Bool = false, flushAt: Int = 1, - optOut: Bool = false) -> PostHogSDK + optOut: Bool = false, + propertiesSanitizer: PostHogPropertiesSanitizer? = nil) -> PostHogSDK { let config = PostHogConfig(apiKey: "123", host: "http://localhost:9001") config.flushAt = flushAt @@ -26,6 +27,7 @@ class PostHogSDKTest: QuickSpec { config.disableQueueTimerForTesting = true config.captureApplicationLifecycleEvents = captureApplicationLifecycleEvents config.optOut = optOut + config.propertiesSanitizer = propertiesSanitizer return PostHogSDK.with(config) } @@ -704,6 +706,22 @@ class PostHogSDKTest: QuickSpec { expect(FileManager.default.fileExists(atPath: appFolder.path)) == true } + + it("client sanitize properties") { + let sanitizer = ExampleSanitizer() + let sut = self.getSut(propertiesSanitizer: sanitizer) + + let props: [String: Any] = ["empty": ""] + + sut.capture("event", properties: props) + + let events = getBatchedEvents(server) + + expect(events[0].properties["empty"] as? String).to(beNil()) + + sut.reset() + sut.close() + } } } From 51c82941a555f660d9a61402c0683b58c547bce7 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Aug 2024 15:18:22 +0200 Subject: [PATCH 2/4] fix --- PostHog.xcodeproj/project.pbxproj | 4 -- PostHogExample/ContentView2.swift | 80 ------------------------------- 2 files changed, 84 deletions(-) delete mode 100644 PostHogExample/ContentView2.swift diff --git a/PostHog.xcodeproj/project.pbxproj b/PostHog.xcodeproj/project.pbxproj index 29a8b65da..86bc090a3 100644 --- a/PostHog.xcodeproj/project.pbxproj +++ b/PostHog.xcodeproj/project.pbxproj @@ -70,7 +70,6 @@ 693E977B2C625208004B1030 /* PostHogPropertiesSanitizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E977A2C625208004B1030 /* PostHogPropertiesSanitizer.swift */; }; 693E977D2C6257F9004B1030 /* ExampleSanitizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 693E977C2C6257F9004B1030 /* ExampleSanitizer.swift */; }; 6955CB732C517651008EFD8D /* CGSize+Util.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6955CB722C517651008EFD8D /* CGSize+Util.swift */; }; - 6955CB832C5AB517008EFD8D /* ContentView2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6955CB822C5AB517008EFD8D /* ContentView2.swift */; }; 69779BEC2AE68E6900D7A48E /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 69779BEB2AE68E6900D7A48E /* UIViewController.swift */; }; 6992AA832AFE51A000087600 /* PostHogExampleTvOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6992AA822AFE51A000087600 /* PostHogExampleTvOSApp.swift */; }; 6992AA852AFE51A000087600 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6992AA842AFE51A000087600 /* ContentView.swift */; }; @@ -322,7 +321,6 @@ 693E977A2C625208004B1030 /* PostHogPropertiesSanitizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogPropertiesSanitizer.swift; sourceTree = ""; }; 693E977C2C6257F9004B1030 /* ExampleSanitizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleSanitizer.swift; sourceTree = ""; }; 6955CB722C517651008EFD8D /* CGSize+Util.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CGSize+Util.swift"; sourceTree = ""; }; - 6955CB822C5AB517008EFD8D /* ContentView2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView2.swift; sourceTree = ""; }; 69779BEB2AE68E6900D7A48E /* UIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; 6992AA802AFE51A000087600 /* PostHogExampleTvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PostHogExampleTvOS.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6992AA822AFE51A000087600 /* PostHogExampleTvOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogExampleTvOSApp.swift; sourceTree = ""; }; @@ -461,7 +459,6 @@ 3AA34CFB296D951A003398F4 /* ContentView.swift */, 3AA34CFD296D951B003398F4 /* Assets.xcassets */, 3AA34CFF296D951B003398F4 /* Preview Content */, - 6955CB822C5AB517008EFD8D /* ContentView2.swift */, ); path = PostHogExample; sourceTree = ""; @@ -1054,7 +1051,6 @@ 3AA34D17296D9993003398F4 /* AppDelegate.swift in Sources */, 3AA34CFC296D951A003398F4 /* ContentView.swift in Sources */, 3AE3FB2C2991320300AFFC18 /* Api.swift in Sources */, - 6955CB832C5AB517008EFD8D /* ContentView2.swift in Sources */, 3A0F108329C47940002C0084 /* UIViewExample.swift in Sources */, 3AA34CFA296D951A003398F4 /* PostHogExampleApp.swift in Sources */, ); diff --git a/PostHogExample/ContentView2.swift b/PostHogExample/ContentView2.swift deleted file mode 100644 index 015883f59..000000000 --- a/PostHogExample/ContentView2.swift +++ /dev/null @@ -1,80 +0,0 @@ -import SwiftUI - -struct ContentView2: View { - @State private var email: String = "" - @State private var password: String = "" - @State private var isLoggedIn: Bool = false - - var body: some View { - NavigationView { - if isLoggedIn { - WelcomeView(isLoggedIn: $isLoggedIn) - } else { - VStack { -// TextField("Email", text: $email) -// .padding() -// .keyboardType(.emailAddress) -// .accessibilityLabel("ph-no-capture") -// .autocapitalization(.none) -// .border(Color.gray) - -// SecureField("Password", text: $password) -// .padding() -// .border(Color.gray) - Text("Welcome!") - .font(.largeTitle) - // .accessibilityIdentifier("ph-no-capture") - .padding() - -// Button(action: { -// // Simple login logic - //// if !email.isEmpty && !password.isEmpty { - //// isLoggedIn = true - //// } -// isLoggedIn = true -// }) { -// Text("Login") -// .frame(maxWidth: .infinity) -// .padding() -// .background(Color.blue) -// .foregroundColor(.white) -// .cornerRadius(10) -// } -// .padding(.top, 20) - } - .padding() - .navigationTitle("Login") - } - } - } -} - -struct WelcomeView: View { - @Binding var isLoggedIn: Bool - - var body: some View { - VStack { - Text("Welcome!") - .font(.largeTitle) -// .accessibilityIdentifier("ph-no-capture") - .padding() - -// Button(action: { -// isLoggedIn = false -// }) { -// Text("Logout") -// .frame(maxWidth: .infinity) -// .padding() -// .background(Color.red) -// .foregroundColor(.white) -// .cornerRadius(10) -// } -// .padding(.top, 20) - } - .padding() - } -} - -#Preview { - ContentView() -} From 1e9b8df0edd112fcfa66a55ff7d619757b2026d6 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Aug 2024 15:19:29 +0200 Subject: [PATCH 3/4] pr id --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b23a99b96..92abe0e3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ## Next -- chore: Support the `propertiesSanitizer` config ([#150](https://github.com/PostHog/posthog-ios/pull/150)) +- chore: Support the `propertiesSanitizer` config ([#154](https://github.com/PostHog/posthog-ios/pull/154)) ## 3.6.3 - 2024-07-26 From 555fb52bb2fbbc70aeee07e43b69c8b5277c163c Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Tue, 6 Aug 2024 15:21:00 +0200 Subject: [PATCH 4/4] fix --- PostHog/Replay/PostHogReplayIntegration.swift | 4 ++-- PostHogExample/AppDelegate.swift | 3 +-- PostHogExample/PostHogExampleApp.swift | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/PostHog/Replay/PostHogReplayIntegration.swift b/PostHog/Replay/PostHogReplayIntegration.swift index 0ed05c2fc..c37db19f5 100644 --- a/PostHog/Replay/PostHogReplayIntegration.swift +++ b/PostHog/Replay/PostHogReplayIntegration.swift @@ -25,9 +25,9 @@ // SwiftUI image types // https://stackoverflow.com/questions/57554590/how-to-get-all-the-subviews-of-a-window-or-view-in-latest-swiftui-app // https://stackoverflow.com/questions/58336045/how-to-detect-swiftui-usage-programmatically-in-an-ios-application - private let swiftUIImageTypes = ["_TtCOCV7SwiftUI11DisplayList11ViewUpdater8Platform13CGDrawingView", // 0 + private let swiftUIImageTypes = ["_TtCOCV7SwiftUI11DisplayList11ViewUpdater8Platform13CGDrawingView", "_TtC7SwiftUIP33_A34643117F00277B93DEBAB70EC0697122_UIShapeHitTestingView", - "SwiftUI._UIGraphicsView", // 0 + "SwiftUI._UIGraphicsView", "SwiftUI.ImageLayer"].compactMap { NSClassFromString($0) } init(_ config: PostHogConfig) { diff --git a/PostHogExample/AppDelegate.swift b/PostHogExample/AppDelegate.swift index f57710622..31153eed5 100644 --- a/PostHogExample/AppDelegate.swift +++ b/PostHogExample/AppDelegate.swift @@ -23,9 +23,8 @@ class AppDelegate: NSObject, UIApplicationDelegate { config.sendFeatureFlagEvent = false config.sessionReplay = true config.sessionReplayConfig.screenshotMode = true - config.sessionReplayConfig.maskAllTextInputs = false + config.sessionReplayConfig.maskAllTextInputs = true config.sessionReplayConfig.maskAllImages = true - config.optOut = true PostHogSDK.shared.setup(config) // PostHogSDK.shared.debug() diff --git a/PostHogExample/PostHogExampleApp.swift b/PostHogExample/PostHogExampleApp.swift index e75641751..a9251a797 100644 --- a/PostHogExample/PostHogExampleApp.swift +++ b/PostHogExample/PostHogExampleApp.swift @@ -13,7 +13,7 @@ struct PostHogExampleApp: App { var body: some Scene { WindowGroup { - ContentView2() + ContentView() } } }