diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml index 924a62561..39280196e 100644 --- a/.github/workflows/ios.yml +++ b/.github/workflows/ios.yml @@ -20,7 +20,6 @@ on: - 'mise*.toml' - '.github/workflows/ios.yml' pull_request: - branches: [main] paths: - 'Sources/**' - 'Tests/**' diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 1fff29417..1f967df97 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -21,7 +21,6 @@ on: - 'Scripts/CI/**' - '.github/workflows/macos.yml' pull_request: - branches: [main] paths: - 'Sources/**' - 'Tests/**' diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 01bc24793..377aaa22f 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -20,7 +20,6 @@ on: - 'Package.swift' - '.github/workflows/ubuntu.yml' pull_request: - branches: [main] paths: - 'Sources/**' - 'Tests/**' diff --git a/Sources/OpenSwiftUICore/Data/State/StoredLocation.swift b/Sources/OpenSwiftUICore/Data/State/StoredLocation.swift index 9247bf6d6..96668716f 100644 --- a/Sources/OpenSwiftUICore/Data/State/StoredLocation.swift +++ b/Sources/OpenSwiftUICore/Data/State/StoredLocation.swift @@ -89,7 +89,7 @@ package class StoredLocationBase: AnyLocation, Location, @unchecke _openSwiftUIBaseClassAbstractMethod() } - fileprivate func commit(transaction: Transaction, mutation: BeginUpdate) { + fileprivate func commit(transaction: Transaction, id: Transaction.ID, mutation: BeginUpdate) { _openSwiftUIBaseClassAbstractMethod() } @@ -139,12 +139,13 @@ package class StoredLocationBase: AnyLocation, Location, @unchecke return } let transaction = transaction.current + let id = Transaction.id onMainThread { [weak self] in guard let self else { return } let update = BeginUpdate(box: self) - commit(transaction: transaction, mutation: update) + commit(transaction: transaction, id: id, mutation: update) } } @@ -174,9 +175,14 @@ final package class StoredLocation: StoredLocationBase, @unchecked host?.isUpdating ?? false } - override fileprivate func commit(transaction: Transaction, mutation: StoredLocationBase.BeginUpdate) { + override fileprivate func commit( + transaction: Transaction, + id: Transaction.ID, + mutation: StoredLocationBase.BeginUpdate + ) { host?.asyncTransaction( transaction, + id: id, mutation: mutation ) } @@ -185,3 +191,62 @@ final package class StoredLocation: StoredLocationBase, @unchecked $signal?.invalidateValue() } } + +// MARK: - ObservableLocation + +final package class ObservableLocation: StoredLocationBase, TransactionHostProvider, @unchecked Sendable { + private struct Observer { + weak var host: GraphHost? + var signal: WeakAttribute + } + + private var observers: [Observer] = [] + + package func addObserver(host: GraphHost, signal: WeakAttribute) { + observers.append(Observer(host: host, signal: signal)) + } + + package func removeObserver(signal: WeakAttribute) { + if let index = observers.firstIndex(where: { $0.signal == signal }) { + observers.remove(at: index) + } + } + + override fileprivate var isUpdating: Bool { + GraphHost.isUpdating + } + + override fileprivate func commit( + transaction: Transaction, + id: Transaction.ID, + mutation: StoredLocationBase.BeginUpdate + ) { + GraphHost.globalTransaction( + transaction, + id: id, + mutation: mutation, + hostProvider: self + ) + } + + override fileprivate func notifyObservers() { + var index = 0 + var count = observers.count + while index < count { + if let signal = observers[index].signal.attribute { + signal.invalidateValue() + index += 1 + } else { + count -= 1 + if index != count { + observers.swapAt(index, count) + } + observers.remove(at: count) + } + } + } + + package var mutationHost: GraphHost? { + observers.reduce(nil) { $0 ?? $1.host } + } +}