Skip to content

Commit fa983fc

Browse files
Update stencils for presets (#583)
* Update stencils for presets * Remove extraneous “Window” * Update Root preset * Use Hello World string * Use “Root View Controller” string * Add line breaks * Use convenience method * Access dependencies on component for app preset * Inject analytics properties for presets * Inject dynamic component dependency in app preset * Exclude parent scope in app preset * Inject flow properties for presets * Inject flow properties for presets * Move flow_properties loops inside conditionals
1 parent bdf1895 commit fa983fc

File tree

50 files changed

+713
-394
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+713
-394
lines changed

Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/Builder-SwiftUI.stencil

+2-2
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ internal final class {{ node_name }}BuilderImp: AbstractBuilder
177177
{% if analytics_properties %}
178178
let analytics: {{ node_name }}AnalyticsImp = .init(
179179
{% for property in analytics_properties %}
180-
{{ property.name }}: component.dependency.{{ property.name }}{% if not forloop.last %}{{ ',' }}
180+
{{ property.name }}: component{% if node_name != "App" %}.dependency{% endif %}.{{ property.name }}{% if not forloop.last %}{{ ',' }}
181181
{% endif %}
182182
{% endfor +%}
183183
)
@@ -202,7 +202,7 @@ internal final class {{ node_name }}BuilderImp: AbstractBuilder
202202
context: context,
203203
viewController: viewController{% if flow_properties %}{{ ',' }}
204204
{% for property in flow_properties %}
205-
{{ property.name }}: component.dependency.{{ property.name }}{% if not forloop.last %}{{ ',' }}
205+
{{ property.name }}: component{% if node_name != "App" %}.dependency{% endif %}.{{ property.name }}{% if not forloop.last %}{{ ',' }}
206206
{% endif %}
207207
{% endfor %}
208208
{% endif +%}

Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/Builder.stencil

+82-8
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ import {{ import }}
1414
@MainActor
1515
{% if owns_view %}
1616
internal protocol {{ node_name }}Flow: {{ view_controllable_flow_type }} {}
17+
{% elif node_name == "Scene" %}
18+
internal protocol {{ node_name }}Flow: Flow {
19+
func getViewController() -> Window{{ node_name }}ViewControllable
20+
}
1721
{% else %}
1822
internal protocol {{ node_name }}Flow: Flow {}
1923
{% endif %}
24+
{% if node_name != "App" %}
2025

2126
/**
2227
PURPOSE:
@@ -33,6 +38,7 @@ public protocol {{ node_name }}Dependency: Dependency {
3338
{% else %}
3439
public protocol {{ node_name }}Dependency: Dependency {}
3540
{% endif %}
41+
{% endif %}
3642

3743
/**
3844
PURPOSE:
@@ -42,6 +48,10 @@ public protocol {{ node_name }}Dependency: Dependency {}
4248
*/
4349
{% if owns_view %}
4450
internal typealias {{ node_name }}DynamicBuildDependency = {{ node_name }}Listener
51+
{% elif node_name == "App" %}
52+
internal typealias {{ node_name }}DynamicBuildDependency = Void
53+
{% elif node_name == "Scene" %}
54+
internal typealias {{ node_name }}DynamicBuildDependency = ({{ node_name }}Listener, Window{{ node_name }}ViewControllable)
4555
{% else %}
4656
internal typealias {{ node_name }}DynamicBuildDependency = ({{ node_name }}Listener, {{ node_name }}ViewControllable)
4757
{% endif %}
@@ -60,10 +70,14 @@ internal typealias {{ node_name }}DynamicComponentDependency = Void
6070
PURPOSE:
6171
Declares dependencies that are owned by this Node.
6272
*/
73+
{% if node_name == "App" %}
74+
public final class {{ node_name }}Component: BootstrapComponent {
75+
{% else %}
6376
public final class {{ node_name }}Component: Component
6477
<
6578
{{ node_name }}Dependency
6679
> {
80+
{% endif %}
6781

6882
/*
6983
Dependencies
@@ -89,6 +103,10 @@ public final class {{ node_name }}Component: Component
89103
}
90104

91105
*/
106+
{% if node_name == "App" %}
107+
108+
fileprivate let appService: AppService = AppServiceImp()
109+
{% endif %}
92110

93111
{% if is_periphery_comment_enabled %}
94112
// periphery:ignore
@@ -102,15 +120,25 @@ public final class {{ node_name }}Component: Component
102120
///
103121
/// Remove `dynamicDependency` default parameter when its type is not `Void`.
104122
///
123+
{% if node_name == "App" %}
124+
/// - Parameter dynamicDependency: The dynamic component dependency
125+
{% else %}
105126
/// - Parameters:
106127
/// - parent: The parent scope
107128
/// - dynamicDependency: The dynamic component dependency
129+
{% endif %}
108130
internal init(
131+
{% if node_name != "App" %}
109132
parent: Scope,
133+
{% endif %}
110134
dynamicDependency: {{ node_name }}DynamicComponentDependency = ()
111135
) {
112136
self.dynamicDependency = dynamicDependency
137+
{% if node_name == "App" %}
138+
super.init()
139+
{% else %}
113140
super.init(parent: parent)
141+
{% endif %}
114142
}
115143

116144
/*
@@ -124,6 +152,22 @@ public final class {{ node_name }}Component: Component
124152
}
125153

126154
*/
155+
{% if node_name == "App" %}
156+
157+
fileprivate func sceneComponentFactory() -> SceneComponent {
158+
SceneComponent(parent: self)
159+
}
160+
{% elif node_name == "Scene" %}
161+
162+
fileprivate func windowComponentFactory() -> WindowComponent {
163+
WindowComponent(parent: self)
164+
}
165+
{% elif node_name == "Window" %}
166+
167+
fileprivate func rootComponentFactory() -> RootComponent {
168+
RootComponent(parent: self)
169+
}
170+
{% endif %}
127171
}
128172

129173
// MARK: - Builder
@@ -138,10 +182,19 @@ public final class {{ node_name }}Component: Component
138182
/// @mockable
139183
@MainActor
140184
internal protocol {{ node_name }}Builder: AnyObject {
185+
{% if node_name == "App" %}
186+
func build() -> {{ node_name }}Flow
187+
{% elif node_name == "Scene" %}
188+
func build(
189+
withListener listener: {{ node_name }}Listener,
190+
viewController: Window{{ node_name }}ViewControllable
191+
) -> {{ node_name }}Flow
192+
{% else %}
141193
func build(
142194
withListener listener: {{ node_name }}Listener{% if not owns_view %}{{ ',' }}
143195
viewController: {{ node_name }}ViewControllable{% endif +%}
144196
) -> {{ node_name }}Flow
197+
{% endif %}
145198
}
146199

147200
{% if is_periphery_comment_enabled %}
@@ -165,18 +218,29 @@ internal final class {{ node_name }}BuilderImp: AbstractBuilder
165218
/// The dynamic dependencies can be tuples or structs containing multiple values when necessary.
166219
{% if owns_view %}
167220
/// - Parameter listener: An object that can listen for signals from the Node
168-
{% else %}
221+
{% elif node_name != "App" %}
169222
/// - Parameters:
170223
/// - listener: An object that can listen for signals from the Node
171224
/// - viewController: The injected view controller
172225
{% endif %}
173226
/// - Returns: The Flow instance
227+
{% if node_name == "App" %}
228+
internal func build() -> {{ node_name }}Flow {
229+
{% elif node_name == "Scene" %}
230+
internal func build(
231+
withListener listener: {{ node_name }}Listener,
232+
viewController: Window{{ node_name }}ViewControllable
233+
) -> {{ node_name }}Flow {
234+
{% else %}
174235
internal func build(
175236
withListener listener: {{ node_name }}Listener{% if not owns_view %}{{ ',' }}
176237
viewController: {{ node_name }}ViewControllable{% endif +%}
177238
) -> {{ node_name }}Flow {
239+
{% endif %}
178240
{% if owns_view %}
179241
let dynamicBuildDependency: {{ node_name }}DynamicBuildDependency = listener
242+
{% elif node_name == "App" %}
243+
let dynamicBuildDependency: {{ node_name }}DynamicBuildDependency = ()
180244
{% else %}
181245
let dynamicBuildDependency: {{ node_name }}DynamicBuildDependency = (listener, viewController)
182246
{% endif %}
@@ -195,14 +259,18 @@ internal final class {{ node_name }}BuilderImp: AbstractBuilder
195259
) -> {{ node_name }}Flow {
196260
{% if owns_view %}
197261
let listener: {{ node_name }}Listener = dynamicBuildDependency
198-
{% else %}
262+
{% elif node_name != "App" %}
199263
let listener: {{ node_name }}Listener = dynamicBuildDependency.0
264+
{% if node_name == "Scene" %}
265+
let viewController: Window{{ node_name }}ViewControllable = dynamicBuildDependency.1
266+
{% else %}
200267
let viewController: {{ node_name }}ViewControllable = dynamicBuildDependency.1
201268
{% endif %}
269+
{% endif %}
202270
{% if analytics_properties %}
203271
let analytics: {{ node_name }}AnalyticsImp = .init(
204272
{% for property in analytics_properties %}
205-
{{ property.name }}: component.dependency.{{ property.name }}{% if not forloop.last %}{{ ',' }}
273+
{{ property.name }}: component{% if node_name != "App" %}.dependency{% endif %}.{{ property.name }}{% if not forloop.last %}{{ ',' }}
206274
{% endif %}
207275
{% endfor +%}
208276
)
@@ -211,9 +279,12 @@ internal final class {{ node_name }}BuilderImp: AbstractBuilder
211279
{% endif %}
212280
let context: {{ node_name }}ContextImp = .init(
213281
workers: [],
214-
analytics: analytics
282+
analytics: analytics{% if node_name == "App" %}{{ ',' }}
283+
windowSceneState: component.appService.windowSceneState{% endif +%}
215284
)
285+
{% if node_name != "App" %}
216286
context.listener = listener
287+
{% endif %}
217288
{% if owns_view %}
218289
let viewStateFactory: {{ node_name }}ViewStateFactory = .init()
219290
let viewController: {{ node_name }}ViewController = .init(
@@ -223,13 +294,16 @@ internal final class {{ node_name }}BuilderImp: AbstractBuilder
223294
viewController.receiver = context
224295
{% endif %}
225296
let flow: {{ node_name }}FlowImp = .init(
226-
context: context,
227-
viewController: viewController{% if flow_properties %}{{ ',' }}
297+
context: context{% if node_name != "App" %}{{ ',' }}
298+
viewController: viewController{% endif +%}{% if flow_properties %}{{ ',' }}
228299
{% for property in flow_properties %}
229-
{{ property.name }}: component.dependency.{{ property.name }}{% if not forloop.last %}{{ ',' }}
300+
{{ property.name }}: component{% if node_name != "App" %}.dependency{% endif %}.{{ property.name }}{% if not forloop.last %}{{ ',' }}
230301
{% endif %}
231302
{% endfor %}
232-
{% endif +%}
303+
{% endif +%}{% if node_name == "App" %}{{ ',' }}
304+
sceneBuilder: SceneBuilderImp(componentFactory: component.sceneComponentFactory){% endif +%}{% if node_name == "Scene" %}{{ ',' }}
305+
windowBuilder: WindowBuilderImp(componentFactory: component.windowComponentFactory){% endif +%}{% if node_name == "Window" %}{{ ',' }}
306+
rootBuilder: RootBuilderImp(componentFactory: component.rootComponentFactory){% endif +%}
233307
)
234308
context.flow = flow
235309
return flow

Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/Context.stencil

+47-3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import {{ import }}
66
{% endfor %}
77
{% endif %}
8+
{% if node_name != "App" %}
89

910
/**
1011
PURPOSE:
@@ -13,6 +14,7 @@ import {{ import }}
1314
/// @mockable
1415
@MainActor
1516
internal protocol {{ node_name }}Listener: AnyObject {}
17+
{% endif %}
1618

1719
/**
1820
PURPOSE:
@@ -21,7 +23,12 @@ internal protocol {{ node_name }}Listener: AnyObject {}
2123
*/
2224
/// @mockable
2325
@MainActor
24-
{% if node_name == "Root" %}
26+
{% if node_name == "App" %}
27+
internal protocol {{ node_name }}FlowInterface: Flow {
28+
func attachScene(_ viewController: WindowSceneViewControllable)
29+
func detachScene(_ viewController: WindowSceneViewControllable)
30+
}
31+
{% elif node_name == "Root" %}
2532
internal protocol {{ node_name }}FlowInterface: Flow {
2633
func didBecomeReady()
2734
}
@@ -52,27 +59,35 @@ internal final class {{ node_name }}ContextImp: AbstractContext {
5259
{% endif %}
5360
/// The Flow instance.
5461
internal weak var flow: {{ node_name }}FlowInterface?
62+
{% if node_name != "App" %}
5563

5664
{% if is_periphery_comment_enabled %}
5765
// periphery:ignore
5866
{% endif %}
5967
/// The Listener instance.
6068
internal weak var listener: {{ node_name }}Listener?
69+
{% endif %}
70+
{% if node_name != "App" and node_name != "Scene" and node_name != "Window" %}
6171

6272
{% if is_periphery_comment_enabled and not owns_view %}
6373
// periphery:ignore
6474
{% endif %}
6575
/// The State instance.
6676
@Published
6777
internal private(set) var state: {{ node_name }}State
78+
{% endif %}
6879

6980
{% if is_periphery_comment_enabled %}
7081
// periphery:ignore
7182
{% endif %}
7283
/// The Analytics instance.
7384
private let analytics: {{ node_name }}Analytics
74-
{% if node_name == "Root" %}
85+
{% if node_name == "App" %}
7586

87+
private let windowSceneState: AnyPublisher<WindowSceneState, Never>
88+
{% elif node_name == "Root" %}
89+
90+
// swiftlint:disable:next redundant_type_annotation
7691
private var isReady: Bool = false
7792
{% endif %}
7893

@@ -82,18 +97,47 @@ internal final class {{ node_name }}ContextImp: AbstractContext {
8297
/// - analytics: The Analytics instance
8398
internal init(
8499
workers: [Worker],
85-
analytics: {{ node_name }}Analytics
100+
analytics: {{ node_name }}Analytics{% if node_name == "App" %}{{ ',' }}
101+
windowSceneState: AnyPublisher<WindowSceneState, Never>{% endif +%}
86102
) {
103+
{% if node_name == "Root" %}
104+
self.state = {{ node_name }}State(name: "{{ node_name }} View Controller")
105+
{% elif node_name != "App" and node_name != "Scene" and node_name != "Window" %}
87106
self.state = {{ node_name }}State()
107+
{% endif %}
88108
self.analytics = analytics
109+
{% if node_name == "App" %}
110+
self.windowSceneState = windowSceneState
111+
{% endif %}
89112
super.init(workers: workers)
90113
}
91114

92115
/// Implement logic to execute when the Context becomes active.
116+
{% if node_name == "App" %}
117+
override internal func didBecomeActive() {
118+
subscribe(to: windowSceneState)
119+
}
120+
{% else %}
93121
override internal func didBecomeActive() {}
122+
{% endif %}
94123

95124
/// Implement logic to execute when the Context will become inactive.
96125
override internal func willResignActive() {}
126+
{% if node_name == "App" %}
127+
128+
private func subscribe(to windowSceneState: AnyPublisher<WindowSceneState, Never>) {
129+
windowSceneState
130+
.filter(\.isAdded)
131+
.map(\.windowScene)
132+
.sink { [weak self] in self?.flow?.attachScene($0) }
133+
.store(in: &cancellables)
134+
windowSceneState
135+
.filter(\.isRemoved)
136+
.map(\.windowScene)
137+
.sink { [weak self] in self?.flow?.detachScene($0) }
138+
.store(in: &cancellables)
139+
}
140+
{% endif %}
97141
}
98142

99143
extension {{ node_name }}ContextImp: {{ node_name }}ContextInterface {}

0 commit comments

Comments
 (0)