This repository has been archived by the owner on Apr 18, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #29 from hainayanda/second-rewrite
- Loading branch information
Showing
42 changed files
with
1,333 additions
and
1,312 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
// | ||
// AnyObservable.swift | ||
// Pharos | ||
// | ||
// Created by Nayanda on 16/11/22. | ||
// | ||
|
||
import Foundation | ||
|
||
// MARK: AnyObservable | ||
|
||
public protocol AnyObservable: AnyObject { | ||
var isAncestor: Bool { get } | ||
var parent: AnyObservable? { get } | ||
var source: AnyObservable? { get } | ||
var isValid: Bool { get } | ||
func release() | ||
func typeErased() -> Observable<Any> | ||
} | ||
|
||
typealias InvokableObservable = AnyObservable & InvokeChainable | ||
|
||
// MARK: AnyObservable + Extensions | ||
|
||
extension AnyObservable { | ||
@inlinable public var ancestor: AnyObservable? { | ||
isAncestor ? self: parent?.ancestor | ||
} | ||
|
||
@inlinable public var source: AnyObservable? { ancestor } | ||
|
||
@inlinable public var isValid: Bool { ancestor != nil } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// | ||
// Changes.swift | ||
// Pharos | ||
// | ||
// Created by Nayanda Haberty on 15/04/21. | ||
// | ||
|
||
import Foundation | ||
|
||
public struct Changes<State> { | ||
public let new: State | ||
public internal(set) var old: State? | ||
var consumers: [ObjectIdentifier] = [] | ||
let triggers: [ObjectIdentifier]? | ||
|
||
public init(new: State, old: State? = nil, triggers: [ObjectIdentifier]? = nil, consumers: [ObjectIdentifier] = []) { | ||
self.triggers = triggers | ||
self.new = new | ||
self.old = old | ||
self.consumers = consumers | ||
} | ||
|
||
func canBeConsumed(by source: AnyObject) -> Bool { | ||
guard !alreadyConsumed(by: source) else { return false } | ||
guard let triggers = triggers else { return true } | ||
let realSource = (source as? WrappingObserver)?.wrapped ?? source | ||
guard triggers.contains(ObjectIdentifier(realSource)) else { | ||
guard let parent = (realSource as? AnyObservable)?.parent else { return false } | ||
return triggers.contains(ObjectIdentifier(parent)) | ||
} | ||
return true | ||
} | ||
|
||
func alreadyConsumed(by source: AnyObject) -> Bool { | ||
consumers.contains(ObjectIdentifier(source)) | ||
} | ||
|
||
func consumed(by source: AnyObject) -> Changes { | ||
var mutableSelf = self | ||
mutableSelf.consumers.append(ObjectIdentifier(source)) | ||
return mutableSelf | ||
} | ||
|
||
func with(old: State?) -> Changes { | ||
var mutableSelf = self | ||
mutableSelf.old = old | ||
return mutableSelf | ||
} | ||
|
||
func mapped<NewState>(_ mapper: (State) -> NewState) -> Changes<NewState> { | ||
var newChanges = Changes<NewState>(new: mapper(new)) | ||
newChanges.consumers = consumers | ||
guard let old = self.old else { return newChanges } | ||
return newChanges.with(old: mapper(old)) | ||
} | ||
|
||
func compactMapped<NewState>(_ mapper: (State) -> NewState?) -> Changes<NewState>? { | ||
guard let newMapped = mapper(new) else { return nil } | ||
var newChanges = Changes<NewState>(new: newMapped) | ||
newChanges.consumers = consumers | ||
guard let old = self.old else { return newChanges } | ||
return newChanges.with(old: mapper(old)) | ||
} | ||
} | ||
|
||
extension Changes: Equatable where State: Equatable { | ||
@inlinable public var isChanging: Bool { !isNotChanging } | ||
@inlinable public var isNotChanging: Bool { new == old } | ||
|
||
@inlinable public static func == (lhs: Changes<State>, rhs: Changes<State>) -> Bool { | ||
lhs.new == rhs.new && lhs.old == rhs.old | ||
} | ||
} | ||
|
||
extension Changes: Hashable where State: Hashable { | ||
@inlinable public func hash(into hasher: inout Hasher) { | ||
hasher.combine(new) | ||
hasher.combine(old) | ||
} | ||
} | ||
|
||
extension Changes where State: AnyObject { | ||
@inlinable public var isSameInstance: Bool { new === old } | ||
@inlinable public var isNewInstance: Bool { !isSameInstance } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// | ||
// Invokable.swift | ||
// Pharos | ||
// | ||
// Created by Nayanda Haberty on 5/10/22. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol Invokable: AnyObject { | ||
func fire() | ||
} | ||
|
||
protocol InvokeChainable: Invokable { | ||
func signalFire(from triggers: [ObjectIdentifier]) | ||
} | ||
|
||
extension Invokable { | ||
@inlinable func fire(after delay: TimeInterval) { | ||
(DispatchQueue.current ?? DispatchQueue.main) | ||
.asyncAfter(deadline: .now() + delay) { [weak self] in | ||
self?.fire() | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// | ||
// InvokableGroup.swift | ||
// Pharos | ||
// | ||
// Created by Nayanda Haberty on 24/11/22. | ||
// | ||
|
||
import Foundation | ||
|
||
class InvokableGroup: Invokable { | ||
|
||
let invokables: [Invokable] | ||
|
||
init(invokables: [Invokable]) { | ||
self.invokables = invokables | ||
} | ||
|
||
@inlinable func fire() { | ||
invokables.first?.fire() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// | ||
// Observing.swift | ||
// Pharos | ||
// | ||
// Created by Nayanda on 16/11/22. | ||
// | ||
|
||
import Foundation | ||
|
||
// MARK: Observing | ||
|
||
protocol Observing { | ||
associatedtype Input | ||
|
||
@discardableResult | ||
func accept(_ changes: Changes<Input>) -> Bool | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// | ||
// Unwrapable.swift | ||
// Pharos | ||
// | ||
// Created by Nayanda Haberty on 16/11/22. | ||
// | ||
|
||
import Foundation | ||
|
||
// MARK: Unwrappable | ||
|
||
public protocol Unwrapable { | ||
associatedtype Wrapped | ||
|
||
func unwrap() -> Wrapped? | ||
} | ||
|
||
// MARK: Optional + Unwrapable | ||
|
||
extension Optional: Unwrapable { | ||
@inlinable public func unwrap() -> Wrapped? { | ||
self | ||
} | ||
} | ||
|
||
// MARK: Observable + Unwrappable AKA Optional | ||
|
||
extension Observable where Output: Unwrapable { | ||
/// Ignore all nil from this Observable | ||
/// - Returns: New Observable that ignores nil | ||
@inlinable public func compacted() -> Observable<Output.Wrapped> { | ||
compactMapped { $0.unwrap() } | ||
} | ||
} |
Oops, something went wrong.