Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .swiftpm/xcode/xcshareddata/xcschemes/Reactor.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "Reactor"
BuildableName = "Reactor"
BlueprintName = "Reactor"
ReferencedContainer = "container:">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "Reactor"
BuildableName = "Reactor"
BlueprintName = "Reactor"
ReferencedContainer = "container:">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1620"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B4ECB0AB2A1250AE00B0CAAE"
BuildableName = "AsyncReactorExample.app"
BlueprintName = "AsyncReactorExample"
ReferencedContainer = "container:AsyncReactorExample.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B4ECB0AB2A1250AE00B0CAAE"
BuildableName = "AsyncReactorExample.app"
BlueprintName = "AsyncReactorExample"
ReferencedContainer = "container:AsyncReactorExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "B4ECB0AB2A1250AE00B0CAAE"
BuildableName = "AsyncReactorExample.app"
BlueprintName = "AsyncReactorExample"
ReferencedContainer = "container:AsyncReactorExample.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
8 changes: 3 additions & 5 deletions Example/AsyncReactorExample/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ struct ContentView: View {
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
ContentView()
}
#Preview {
NavigationStack {
ContentView()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ struct RepositoryDescriptionSheet: View {
}
}

struct RepositoryDescriptionSheet_Previews: PreviewProvider {
static var previews: some View {
RepositoryDescriptionSheet(description: "Description")
}
#Preview {
RepositoryDescriptionSheet(description: "Description")
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,9 @@ struct RepositoryDetailView: View {
}
}

struct RepositoryDetailView_Previews: PreviewProvider {
static var previews: some View {
NavigationStack {
RepositoryDetailView(repository: Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ultricies nisi elit, non imperdiet nibh euismod in. Sed sit amet tincidunt arcu, nec ornare nisl. Pellentesque sollicitudin quam quis elit tempus, et interdum lorem tristique. Nunc rhoncus ornare efficitur. Ut tellus libero, pretium sit amet dolor a, maximus scelerisque sem. Phasellus posuere aliquam purus. Mauris justo tellus, molestie ut eros at, lobortis luctus nulla. Nullam libero leo, sagittis ac orci nec, viverra faucibus lacus. Phasellus faucibus ipsum nec velit mattis tincidunt. Phasellus nulla mauris, lobortis ac quam non, consectetur viverra odio. Praesent sed venenatis nulla. Praesent non maximus sem, quis ultricies ligula. Aliquam eleifend non velit eget venenatis. Vivamus aliquet, nisl vestibulum cursus aliquet, neque justo feugiat magna, eu suscipit turpis mi id orci.", htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")))
}
.environmentObject(RepositoryDetailReactor())
#Preview {
NavigationStack {
RepositoryDetailView(repository: Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse ultricies nisi elit, non imperdiet nibh euismod in. Sed sit amet tincidunt arcu, nec ornare nisl. Pellentesque sollicitudin quam quis elit tempus, et interdum lorem tristique. Nunc rhoncus ornare efficitur. Ut tellus libero, pretium sit amet dolor a, maximus scelerisque sem. Phasellus posuere aliquam purus. Mauris justo tellus, molestie ut eros at, lobortis luctus nulla. Nullam libero leo, sagittis ac orci nec, viverra faucibus lacus. Phasellus faucibus ipsum nec velit mattis tincidunt. Phasellus nulla mauris, lobortis ac quam non, consectetur viverra odio. Praesent sed venenatis nulla. Praesent non maximus sem, quis ultricies ligula. Aliquam eleifend non velit eget venenatis. Vivamus aliquet, nisl vestibulum cursus aliquet, neque justo feugiat magna, eu suscipit turpis mi id orci.", htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")))
}
.environmentObject(RepositoryDetailReactor())
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@ struct RepositoryItem: View {
}
}

struct RepositoryItem_Previews: PreviewProvider {
static var previews: some View {
RepositoryItem(repository: Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "", htmlUrl: "google.com", watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")))
}
#Preview {
RepositoryItem(repository: Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "", htmlUrl: "google.com", watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")))
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ struct RepositoryList: View {
}
}

struct RepositoryList_Previews: PreviewProvider {
static var previews: some View {
RepositoryList(repositories: [
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "",htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")),
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "",htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")),
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "",htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")),
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "", htmlUrl: "google.com",watchersCount: 1, forks: 1,visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4"))
])
}
#Preview {
RepositoryList(repositories: [
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "",htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")),
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "",htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")),
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "",htmlUrl: "google.com",watchersCount: 1, forks: 1, visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4")),
Repository(id: 0, name: "Test Repo", fullName: "github/Test Repo", description: "", htmlUrl: "google.com",watchersCount: 1, forks: 1,visibility: "public", owner: Repository.Owner(avatarUrl: "https://avatars.githubusercontent.com/u/60294?v=4"))
])
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ enum SortOptions: String, CaseIterable, Identifiable {
}

class RepositorySearchReactor: AsyncReactor {
enum Action {
enum AsyncAction {
case onHidePrivateToggle
case enterQuery(String)
case load
Expand Down Expand Up @@ -66,7 +66,7 @@ class RepositorySearchReactor: AsyncReactor {
}
}

func action(_ action: Action) async {
func action(_ action: AsyncAction) async {
switch action {
case .onHidePrivateToggle:
state.hidePrivate.toggle()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ struct RepositorySearchView: View {
@EnvironmentObject
private var reactor: RepositorySearchReactor

@ActionBinding(RepositorySearchReactor.self, keyPath: \.hidePrivate, action: RepositorySearchReactor.SyncAction.toggleHidePrivate)
@ActionBinding(
RepositorySearchReactor.self,
keyPath: \.hidePrivate,
action: RepositorySearchReactor.SyncAction.toggleHidePrivate
)
private var hidePrivate: Bool

@ActionBinding(RepositorySearchReactor.self, keyPath: \.query, cancelId: .init(id: "enterQuery", mode: .inFlight), action: RepositorySearchReactor.Action.enterQuery)
@ActionBinding(
RepositorySearchReactor.self,
keyPath: \.query,
cancelId: .init(id: "enterQuery", mode: .inFlight),
action: RepositorySearchReactor.AsyncAction.enterQuery
)
private var query: String

@ActionBinding(RepositorySearchReactor.self, keyPath: \.sortBy, action: RepositorySearchReactor.Action.onSortOptionSelected)
@ActionBinding(
RepositorySearchReactor.self,
keyPath: \.sortBy,
action: RepositorySearchReactor.AsyncAction.onSortOptionSelected
)
private var sortOption: SortOptions

var body: some View {
Expand Down Expand Up @@ -78,11 +91,8 @@ struct RepositorySearchView: View {
}
}

struct RepositorySearchView_Previews: PreviewProvider {
static var previews: some View {
ReactorView(RepositorySearchReactor()) {
RepositorySearchView()
}
#Preview {
ReactorView(RepositorySearchReactor()) {
RepositorySearchView()
}
}

43 changes: 35 additions & 8 deletions Sources/AsyncReactor/AsyncReactor+SwiftUI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,48 @@ public struct ActionBinding<Reactor: AsyncReactor, Action, Value>: DynamicProper

let cancelId: CancelId?

public init(_ reactorType: Reactor.Type, keyPath: KeyPath<Reactor.State, Value>, cancelId: CancelId? = nil, action: @escaping (Value) -> Reactor.Action) where Action == Reactor.Action {
public init(
_ reactorType: Reactor.Type,
keyPath: KeyPath<Reactor.State, Value>,
cancelId: CancelId? = nil,
action: @escaping (Value) -> Reactor.AsyncAction
) where Action == Reactor.AsyncAction {
target = EnvironmentObject()
self.keyPath = keyPath
self.action = action
self.cancelId = cancelId
}

public init(_ reactorType: Reactor.Type, keyPath: KeyPath<Reactor.State, Value>, cancelId: CancelId? = nil, action: @escaping @autoclosure () -> Reactor.Action) where Action == Reactor.Action {
self.init(reactorType, keyPath: keyPath, cancelId: cancelId, action: { _ in action() })
public init(
_ reactorType: Reactor.Type,
keyPath: KeyPath<Reactor.State, Value>,
cancelId: CancelId? = nil,
action: @escaping @autoclosure () -> Reactor.AsyncAction
) where Action == Reactor.AsyncAction {
self.init(
reactorType,
keyPath: keyPath,
cancelId: cancelId,
action: { _ in action() }
)
}

public init(_ reactorType: Reactor.Type, keyPath: KeyPath<Reactor.State, Value>, action: @escaping (Value) -> Reactor.SyncAction) where Action == Reactor.SyncAction {
public init(
_ reactorType: Reactor.Type,
keyPath: KeyPath<Reactor.State, Value>,
action: @escaping (Value) -> Reactor.SyncAction
) where Action == Reactor.SyncAction {
target = EnvironmentObject()
self.keyPath = keyPath
self.action = action
cancelId = nil
}

public init(_ reactorType: Reactor.Type, keyPath: KeyPath<Reactor.State, Value>, action: @escaping @autoclosure () -> Reactor.SyncAction) where Action == Reactor.SyncAction {
public init(
_ reactorType: Reactor.Type,
keyPath: KeyPath<Reactor.State, Value>,
action: @escaping @autoclosure () -> Reactor.SyncAction
) where Action == Reactor.SyncAction {
self.init(reactorType, keyPath: keyPath, action: { _ in action() })
}

Expand All @@ -51,7 +74,7 @@ public struct ActionBinding<Reactor: AsyncReactor, Action, Value>: DynamicProper
public var projectedValue: Binding<Value> {
get {
func bindAction() -> Binding<Value> {
target.wrappedValue.bind(keyPath, cancelId: cancelId, action: action as! (Value) -> Reactor.Action)
target.wrappedValue.bind(keyPath, cancelId: cancelId, action: action as! (Value) -> Reactor.AsyncAction)
}

func bindSyncAction() -> Binding<Value> {
Expand All @@ -60,7 +83,7 @@ public struct ActionBinding<Reactor: AsyncReactor, Action, Value>: DynamicProper

if Action.self == Reactor.SyncAction.self {
return bindSyncAction()
} else if Action.self == Reactor.Action.self {
} else if Action.self == Reactor.AsyncAction.self {
return bindAction()
} else {
fatalError("this should never happen :)")
Expand All @@ -76,7 +99,11 @@ public struct ReactorView<Content: View, R: AsyncReactor>: View {
@StateObject
private var reactor: R

public init(_ reactor: @escaping @autoclosure () -> R, definesLifecycle: Bool = true, @ViewBuilder content: () -> Content) {
public init(
_ reactor: @escaping @autoclosure () -> R,
definesLifecycle: Bool = true,
@ViewBuilder content: () -> Content
) {
_reactor = StateObject(wrappedValue: reactor())
self.content = content()
self.definesLifecycle = definesLifecycle
Expand Down
Loading