Skip to content

Commit 357f284

Browse files
authored
Internal refactoring (#61)
* Refactor internal APIs * Add modifier context * Update docc
1 parent b3dd595 commit 357f284

20 files changed

+183
-140
lines changed

Sources/Atoms/Atom/ModifiedAtom.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/// An atom type that applies a modifier to an atom.
22
///
33
/// Use ``Atom/modifier(_:)`` instead of using this atom directly.
4-
public struct ModifiedAtom<Node: Atom, Modifier: AtomModifier>: Atom where Node.Loader.Value == Modifier.Value {
4+
public struct ModifiedAtom<Node: Atom, Modifier: AtomModifier>: Atom where Node.Loader.Value == Modifier.BaseValue {
55
/// A type representing the stable identity of this atom.
66
public struct Key: Hashable {
77
private let atomKey: Node.Key

Sources/Atoms/Atoms.docc/Atoms.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,9 @@ SwiftUI Atom Properties offers practical capabilities to manage the complexity o
5656
- ``AtomWatchableContext``
5757
- ``AtomTransactionContext``
5858
- ``AtomViewContext``
59-
- ``AtomUpdatedContext``
6059
- ``AtomTestContext``
60+
- ``AtomUpdatedContext``
61+
- ``AtomModifierContext``
6162

6263
### Internal System
6364

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/// A context structure for notifying modifier value updates.
2+
@MainActor
3+
public struct AtomModifierContext<Value> {
4+
internal let _transaction: Transaction
5+
internal let _update: @MainActor (Value) -> Void
6+
7+
internal init(
8+
transaction: Transaction,
9+
update: @escaping @MainActor (Value) -> Void
10+
) {
11+
_transaction = transaction
12+
_update = update
13+
}
14+
15+
/// Notifies value updates.
16+
///
17+
/// - Parameter value: An updated value.
18+
public func update(with value: Value) {
19+
_update(value)
20+
}
21+
22+
/// Add a termination action to be performed when atom value is updated or released.
23+
///
24+
/// - Parameter termination: A termination action.
25+
public func addTermination(_ termination: @MainActor @escaping () -> Void) {
26+
_transaction.addTermination(termination)
27+
}
28+
}

Sources/Atoms/Core/Loader/AsyncSequenceAtomLoader.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public struct AsyncSequenceAtomLoader<Node: AsyncSequenceAtom>: RefreshableAtomL
1313
}
1414

1515
/// Returns a new value for the corresponding atom.
16-
public func get(context: Context) -> Value {
16+
public func value(context: Context) -> Value {
1717
let sequence = context.transaction(atom.sequence)
1818
let task = Task {
1919
do {
@@ -35,8 +35,8 @@ public struct AsyncSequenceAtomLoader<Node: AsyncSequenceAtom>: RefreshableAtomL
3535
return .suspending
3636
}
3737

38-
/// Refreshes and awaits until the asynchronous is finished and returns a final value.
39-
public func handle(context: Context, with value: Value) -> Value {
38+
/// Associates given value and handle updates and cancellations.
39+
public func associateOverridden(value: Value, context: Context) -> Value {
4040
value
4141
}
4242

@@ -70,7 +70,7 @@ public struct AsyncSequenceAtomLoader<Node: AsyncSequenceAtom>: RefreshableAtomL
7070

7171
/// Refreshes and awaits for the passed value to be finished to yield values
7272
/// and returns a final value.
73-
public func refresh(context: Context, with value: Value) async -> Value {
73+
public func refreshOverridden(value: Value, context: Context) async -> Value {
7474
value
7575
}
7676
}

Sources/Atoms/Core/Loader/AtomLoader.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ public protocol AtomLoader {
1111
typealias Context = AtomLoaderContext<Value, Coordinator>
1212

1313
/// Returns a new value for the corresponding atom.
14-
func get(context: Context) -> Value
14+
func value(context: Context) -> Value
1515

16-
/// Handles updates or cancellation of the passed value.
17-
func handle(context: Context, with value: Value) -> Value
16+
/// Associates given value and handle updates and cancellations.
17+
func associateOverridden(value: Value, context: Context) -> Value
1818

1919
/// Returns a boolean value indicating whether it should notify updates to downstream
2020
/// by checking the equivalence of the given old value and new value.
21-
func shouldNotifyUpdate(newValue: Value, oldValue: Value) -> Bool
21+
func shouldUpdate(newValue: Value, oldValue: Value) -> Bool
2222
}
2323

2424
public extension AtomLoader {
25-
func shouldNotifyUpdate(newValue: Value, oldValue: Value) -> Bool {
25+
func shouldUpdate(newValue: Value, oldValue: Value) -> Bool {
2626
true
2727
}
2828
}
@@ -35,7 +35,7 @@ public protocol RefreshableAtomLoader: AtomLoader {
3535

3636
/// Refreshes and awaits for the passed value to be finished to yield values
3737
/// and returns a final value.
38-
func refresh(context: Context, with value: Value) async -> Value
38+
func refreshOverridden(value: Value, context: Context) async -> Value
3939
}
4040

4141
/// A loader protocol that represents an actual implementation of the corresponding atom

Sources/Atoms/Core/Loader/AtomLoaderContext.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
/// The context structure that to interact with an atom store.
22
@MainActor
33
public struct AtomLoaderContext<Value, Coordinator> {
4-
@usableFromInline
54
internal let _store: StoreContext
6-
@usableFromInline
75
internal let _transaction: Transaction
8-
@usableFromInline
96
internal let _coordinator: Coordinator
10-
@usableFromInline
117
internal let _update: @MainActor (Value, Bool) -> Void
128

139
internal init(
@@ -22,6 +18,12 @@ public struct AtomLoaderContext<Value, Coordinator> {
2218
_update = update
2319
}
2420

21+
internal var modifierContext: AtomModifierContext<Value> {
22+
AtomModifierContext(transaction: _transaction) { value in
23+
update(with: value)
24+
}
25+
}
26+
2527
internal func update(with value: Value, needsEnsureValueUpdate: Bool = false) {
2628
_update(value, needsEnsureValueUpdate)
2729
}
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/// A loader protocol that represents an actual implementation of `ModifiedAtom`.
2-
public struct ModifiedAtomLoader<Node: Atom, Modifier: AtomModifier>: AtomLoader where Node.Loader.Value == Modifier.Value {
2+
public struct ModifiedAtomLoader<Node: Atom, Modifier: AtomModifier>: AtomLoader where Node.Loader.Value == Modifier.BaseValue {
33
/// A type of value to provide.
4-
public typealias Value = Modifier.ModifiedValue
4+
public typealias Value = Modifier.Value
55

66
/// A type to coordinate with the atom.
77
public typealias Coordinator = Void
@@ -15,19 +15,19 @@ public struct ModifiedAtomLoader<Node: Atom, Modifier: AtomModifier>: AtomLoader
1515
}
1616

1717
/// Returns a new value for the corresponding atom.
18-
public func get(context: Context) -> Value {
18+
public func value(context: Context) -> Value {
1919
let value = context.transaction { $0.watch(atom) }
20-
return modifier.value(context: context, with: value)
20+
return modifier.modify(value: value, context: context.modifierContext)
2121
}
2222

23-
/// Handles updates or cancellation of the passed value.
24-
public func handle(context: Context, with value: Modifier.ModifiedValue) -> Modifier.ModifiedValue {
25-
modifier.handle(context: context, with: value)
23+
/// Associates given value and handle updates and cancellations.
24+
public func associateOverridden(value: Value, context: Context) -> Value {
25+
modifier.associateOverridden(value: value, context: context.modifierContext)
2626
}
2727

2828
/// Returns a boolean value indicating whether it should notify updates to downstream
2929
/// by checking the equivalence of the given old value and new value.
30-
public func shouldNotifyUpdate(newValue: Modifier.ModifiedValue, oldValue: Modifier.ModifiedValue) -> Bool {
31-
modifier.shouldNotifyUpdate(newValue: newValue, oldValue: oldValue)
30+
public func shouldUpdate(newValue: Value, oldValue: Value) -> Bool {
31+
modifier.shouldUpdate(newValue: newValue, oldValue: oldValue)
3232
}
3333
}

Sources/Atoms/Core/Loader/ObservableObjectAtomLoader.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,23 @@ public struct ObservableObjectAtomLoader<Node: ObservableObjectAtom>: AtomLoader
1616
}
1717

1818
/// Returns a new value for the corresponding atom.
19-
public func get(context: Context) -> Value {
19+
public func value(context: Context) -> Value {
2020
let object = context.transaction(atom.object)
21-
return handle(context: context, with: object)
21+
return associateOverridden(value: object, context: context)
2222
}
2323

24-
/// Handles updates or cancellation of the passed value.
25-
public func handle(context: Context, with object: Value) -> Value {
26-
let cancellable = object.objectWillChange.sink { [weak object] _ in
27-
guard let object else {
24+
/// Associates given value and handle updates and cancellations.
25+
public func associateOverridden(value: Value, context: Context) -> Value {
26+
let cancellable = value.objectWillChange.sink { [weak value] _ in
27+
guard let value else {
2828
return
2929
}
3030

31-
context.update(with: object, needsEnsureValueUpdate: true)
31+
context.update(with: value, needsEnsureValueUpdate: true)
3232
}
3333

3434
context.addTermination(cancellable.cancel)
3535

36-
return object
36+
return value
3737
}
3838
}

Sources/Atoms/Core/Loader/PublisherAtomLoader.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public struct PublisherAtomLoader<Node: PublisherAtom>: RefreshableAtomLoader {
1515
}
1616

1717
/// Returns a new value for the corresponding atom.
18-
public func get(context: Context) -> Value {
18+
public func value(context: Context) -> Value {
1919
let results = context.transaction(atom.publisher).results
2020
let task = Task {
2121
for await result in results {
@@ -30,8 +30,8 @@ public struct PublisherAtomLoader<Node: PublisherAtom>: RefreshableAtomLoader {
3030
return .suspending
3131
}
3232

33-
/// Handles updates or cancellation of the passed value.
34-
public func handle(context: Context, with value: Value) -> Value {
33+
/// Associates given value and handle updates and cancellations.
34+
public func associateOverridden(value: Value, context: Context) -> Value {
3535
value
3636
}
3737

@@ -59,7 +59,7 @@ public struct PublisherAtomLoader<Node: PublisherAtom>: RefreshableAtomLoader {
5959

6060
/// Refreshes and awaits for the passed value to be finished to yield values
6161
/// and returns a final value.
62-
public func refresh(context: Context, with value: Value) async -> Value {
62+
public func refreshOverridden(value: Value, context: Context) async -> Value {
6363
value
6464
}
6565
}

Sources/Atoms/Core/Loader/StateAtomLoader.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ public struct StateAtomLoader<Node: StateAtom>: AtomLoader {
1313
}
1414

1515
/// Returns a new value for the corresponding atom.
16-
public func get(context: Context) -> Value {
16+
public func value(context: Context) -> Value {
1717
context.transaction(atom.defaultValue)
1818
}
1919

20-
/// Handles updates or cancellation of the passed value.
21-
public func handle(context: Context, with value: Value) -> Value {
20+
/// Associates given value and handle updates and cancellations.
21+
public func associateOverridden(value: Value, context: Context) -> Value {
2222
value
2323
}
2424
}

0 commit comments

Comments
 (0)