Skip to content

Commit

Permalink
lots of fixes after testing
Browse files Browse the repository at this point in the history
  • Loading branch information
ndurell committed Nov 7, 2024
1 parent 59a5daa commit 35aff37
Show file tree
Hide file tree
Showing 51 changed files with 111 additions and 123 deletions.
1 change: 0 additions & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"originHash" : "8ef972f340bf89ccd4a56e634f9243c952510d9d3b7f8a894414454b4618f0ec",
"pins" : [
{
"identity" : "combine-schedulers",
Expand Down
18 changes: 9 additions & 9 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ let package = Package(
name: "KlaviyoSwift",
dependencies: [
"KlaviyoCore",
"ComposableArchitecture",
"KComposableArchitecture",
"AnyCodable"
],
path: "Sources/KlaviyoSwift",
Expand All @@ -52,7 +52,7 @@ let package = Package(
"KCustomDump",
.product(name: "CombineSchedulers", package: "combine-schedulers"),
"KlaviyoCore",
"ComposableArchitecture",
"KComposableArchitecture",
"KIssueReporting",
"KCasePaths",
.product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay")
Expand Down Expand Up @@ -80,26 +80,26 @@ let package = Package(

// Vendorized Things
.target(
name: "ComposableArchitecture",
name: "KComposableArchitecture",
dependencies: [
"KCustomDump",
"IdentifiedCollections",
"KIdentifiedCollections",
"KConcurrencyExtras",
"KPerception",
"KCasePaths"
],
path: "Sources/ComposableArchitecture"),
.target(
name: "OrderedCollections",
dependencies: ["InternalCollectionsUtilities"],
name: "KOrderedCollections",
dependencies: ["KInternalCollectionsUtilities"],
path: "Sources/OrderedCollections"),
.target(
name: "InternalCollectionsUtilities",
name: "KInternalCollectionsUtilities",
dependencies: [],
path: "Sources/InternalCollectionsUtilities"),
.target(
name: "IdentifiedCollections",
dependencies: ["OrderedCollections"],
name: "KIdentifiedCollections",
dependencies: ["KOrderedCollections"],
path: "Sources/IdentifiedCollections"),
.target(
name: "AnyCodable",
Expand Down
18 changes: 9 additions & 9 deletions [email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ let package = Package(
dependencies: [
"AnyCodable",
"KlaviyoCore",
"ComposableArchitecture"
"KComposableArchitecture"
],
path: "Sources/KlaviyoSwift",
resources: [.copy("PrivacyInfo.xcprivacy")]),
Expand All @@ -51,7 +51,7 @@ let package = Package(
"KCustomDump",
.product(name: "CombineSchedulers", package: "combine-schedulers"),
"KlaviyoCore",
"ComposableArchitecture",
"KComposableArchitecture",
"KIssueReporting",
"KCasePaths",
.product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay")
Expand Down Expand Up @@ -79,26 +79,26 @@ let package = Package(

// Vendorized Things
.target(
name: "ComposableArchitecture",
name: "KComposableArchitecture",
dependencies: [
"KCustomDump",
"IdentifiedCollections",
"KIdentifiedCollections",
"KConcurrencyExtras",
"KPerception",
"KCasePaths"
],
path: "Sources/ComposableArchitecture"),
.target(
name: "OrderedCollections",
dependencies: ["InternalCollectionsUtilities"],
name: "KOrderedCollections",
dependencies: ["KInternalCollectionsUtilities"],
path: "Sources/OrderedCollections"),
.target(
name: "InternalCollectionsUtilities",
name: "KInternalCollectionsUtilities",
dependencies: [],
path: "Sources/InternalCollectionsUtilities"),
.target(
name: "IdentifiedCollections",
dependencies: ["OrderedCollections"],
name: "KIdentifiedCollections",
dependencies: ["KOrderedCollections"],
path: "Sources/IdentifiedCollections"),
.target(
name: "AnyCodable",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Foundation
import OrderedCollections
import KOrderedCollections

@inlinable
func areOrderedSetsDuplicates<T>(_ lhs: OrderedSet<T>, _ rhs: OrderedSet<T>) -> Bool {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Foundation
import IdentifiedCollections
import KIdentifiedCollections
import KPerception

/// A type that emits notifications to observers when underlying data changes.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

extension IdentifiedArray: Encodable where Element: Encodable {
@inlinable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

extension IdentifiedArray: Collection {
@inlinable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

extension IdentifiedArray: _IdentifiedCollection {
/// A read-only collection view for the ids contained in this array, as an `OrderedSet`.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

extension IdentifiedArray {
/// Creates a new array from the elements in the given sequence, which must not contain duplicate
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

extension IdentifiedArray {
/// Append a new member to the end of the array, if the array doesn't already contain it.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

extension IdentifiedArray: MutableCollection {
@inlinable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

@available(iOS 13, macOS 10.15, tvOS 13, watchOS 6, *)
extension IdentifiedArray: RangeReplaceableCollection
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import OrderedCollections
import KOrderedCollections

/// An ordered collection of identifiable elements.
///
Expand Down
2 changes: 2 additions & 0 deletions Sources/KlaviyoCore/AppLifeCycleEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import Combine
import Foundation
import KComposableArchitecture
import UIKit

public enum LifeCycleErrors: Error {
Expand Down Expand Up @@ -54,6 +55,7 @@ public struct AppLifeCycleEvents {
.map { _ in LifeCycleEvents.backgrounded }
// The below is a bit convoluted since network status can be nil.
let reachability = notificationPublisher(ReachabilityChangedNotification)
.receive(on: UIScheduler.shared)
.compactMap { _ in
let status = reachabilityStatus() ?? .reachableViaWWAN
return LifeCycleEvents.reachabilityChanged(status: status)
Expand Down
15 changes: 10 additions & 5 deletions Sources/KlaviyoCore/KlaviyoEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ public struct KlaviyoEnvironment: Sendable {
timeZone: { TimeZone.autoupdatingCurrent.identifier },
klaviyoAPI: KlaviyoAPI(),
timer: { interval in
let timerActor = TimerActor()
return AsyncStream { continuation in
AsyncStream { continuation in
let timerActor = TimerActor()
Task {
// Start the timer via the TimerActor
#if swift(>=6)
Expand Down Expand Up @@ -201,21 +201,26 @@ public struct DataDecoder: Sendable {
}

actor TimerActor {
private var timer: Timer?
private var timer: DispatchSourceTimer?

func startTimer(interval: TimeInterval, continuation: AsyncStream<Date>.Continuation) {
// Ensure any previous timer is invalidated
stopTimer()

// Create a new Timer and fire it
timer = Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { _ in
// Create a new DispatchSourceTimer and start it
let newTimer = DispatchSource.makeTimerSource(queue: .global())
newTimer.schedule(deadline: .now(), repeating: interval)
newTimer.setEventHandler {
continuation.yield(Date())
}
newTimer.resume()
timer = newTimer
}

func stopTimer() {
// Invalidate the existing timer if there is one
timer?.invalidate()
timer?.cancel()
timer = nil
}
}
3 changes: 2 additions & 1 deletion Sources/KlaviyoSwift/Klaviyo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ func dispatchStoreAction(action: KlaviyoAction) async {
///
/// From there you can you can call the additional methods below to track events and profile.
@MainActor
public final class KlaviyoSDK {
public struct KlaviyoSDK {
public init() {}
private var state: KlaviyoState {
klaviyoSwiftEnvironment.state()
}
Expand Down
33 changes: 3 additions & 30 deletions Sources/KlaviyoSwift/KlaviyoSwiftEnvironment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Combine
import Foundation
@_spi(Internals) import ComposableArchitecture // to access internal state
@_spi(Internals) import KComposableArchitecture // to access internal state
import KlaviyoCore
import UIKit

Expand All @@ -19,7 +19,7 @@ struct KlaviyoSwiftEnvironment: Sendable {
var send: @MainActor (KlaviyoAction) async -> StoreTask
var state: @MainActor () -> KlaviyoState
var statePublisher: @MainActor () -> AnyPublisher<KlaviyoState, Never>
var stateChangePublisher: @MainActor () -> AsyncStream<KlaviyoAction>
var stateChangePublisher: @MainActor () -> AsyncStream<Never>
var lifeCyclePublisher: @MainActor () -> AsyncStream<KlaviyoAction>
var getBackgroundSetting: @MainActor () -> PushBackground
var networkSession: @MainActor () -> NetworkSession
Expand All @@ -37,34 +37,7 @@ struct KlaviyoSwiftEnvironment: Sendable {
store.publisher.eraseToAnyPublisher()
},
stateChangePublisher: {
let publisher = StateChangePublisher().publisher()
return AsyncStream<KlaviyoAction> { continuation in

Task {
let cancellableStore = CancellableStore()
let cancellable = publisher.sink { value in
continuation.yield(value)
}
Task {
#if swift(>=6)
cancellableStore.store(cancellable)
#else
await cancellableStore.store(cancellable)
#endif
}

// Handle cancellation
continuation.onTermination = { @Sendable _ in
Task {
#if swift(>=6)
cancellableStore.cancel()
#else
await cancellableStore.cancel()
#endif
}
}
}
}
StateChangePublisher().publisher()
}, lifeCyclePublisher: {
let publisher = AppLifeCycleEvents.production.lifeCycleEvents(environment.notificationCenterPublisher, environment.startReachability, environment.stopReachability, environment.reachabilityStatus).map(\.transformToKlaviyoAction).eraseToAnyPublisher()
return AsyncStream<KlaviyoAction> { continuation in
Expand Down
44 changes: 25 additions & 19 deletions Sources/KlaviyoSwift/StateManagement/StateChangePublisher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import UIKit

@_spi(KlaviyoPrivate)
@MainActor
public struct StateChangePublisher {
public struct StateChangePublisher: Sendable {
static var debouncedPublisher: (AnyPublisher<KlaviyoState, Never>) -> AnyPublisher<KlaviyoState, Never> = { publisher in
publisher
.debounce(for: .seconds(1), scheduler: DispatchQueue.global())
Expand All @@ -26,18 +26,19 @@ public struct StateChangePublisher {
}

// publisher to listen for state and persist them on an interval.
// does not emit action but mapped that way so it can be used in the store.
var publisher: @MainActor () -> AnyPublisher<KlaviyoAction, Never> = {
debouncedPublisher(createStatePublisher())
.flatMap { state -> Empty<KlaviyoAction, Never> in
saveKlaviyoState(state: state)
return Empty<KlaviyoAction, Never>()
// does not emit anything
var publisher: @MainActor () -> AsyncStream<Never> = {
AsyncStream { _ in
Task {
for await state in debouncedPublisher(createStatePublisher()).values {
saveKlaviyoState(state: state)
}
}
.eraseToAnyPublisher()
}
}

@_spi(KlaviyoPrivate)
public struct PrivateState {
public struct PrivateState: Sendable {
public var email: String?
public var anonymousId: String?
public var phoneNumber: String?
Expand All @@ -46,16 +47,21 @@ public struct StateChangePublisher {
}

@_spi(KlaviyoPrivate)
public static func internalStatePublisher() -> AnyPublisher<PrivateState, Never> {
createStatePublisher()
.map { state in
PrivateState(
email: state.email,
anonymousId: state.anonymousId,
phoneNumber: state.phoneNumber,
externalId: state.externalId,
pushToken: state.pushTokenData?.pushToken)
@MainActor
public static func internalStatePublisher() -> AsyncStream<PrivateState> {
let publisher = StateChangePublisher.createStatePublisher()
return AsyncStream { continuation in
Task {
for await state in publisher
.subscribe(on: DispatchQueue.main).values {
continuation.yield(PrivateState(
email: state.email,
anonymousId: state.anonymousId,
phoneNumber: state.phoneNumber,
externalId: state.externalId,
pushToken: state.pushTokenData?.pushToken))
}
}
.eraseToAnyPublisher()
}
}
}
12 changes: 7 additions & 5 deletions Sources/KlaviyoSwift/StateManagement/StateManagement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
//

import AnyCodable
import ComposableArchitecture
import Foundation
import KComposableArchitecture
import KlaviyoCore

enum StateManagementConstants {
Expand Down Expand Up @@ -201,14 +201,16 @@ struct KlaviyoReducer: Reducer {
await send(.start)
}
.merge(with: .run { send in
for await action in await klaviyoSwiftEnvironment.lifeCyclePublisher() {
let lifeCyclePublisher = await MainActor.run { klaviyoSwiftEnvironment.lifeCyclePublisher()
}
for await action in lifeCyclePublisher {
await send(action)
}
})
.merge(with: .run { send in
for await action in await klaviyoSwiftEnvironment.stateChangePublisher() {
await send(action)
.merge(with: .run { _ in
let publisher = await MainActor.run { klaviyoSwiftEnvironment.stateChangePublisher()
}
for await _ in publisher {}
})

case let .setEmail(email, appContextInfo):
Expand Down
Loading

0 comments on commit 35aff37

Please sign in to comment.