Skip to content

Commit 380f5b4

Browse files
committed
Add contextual modifier resolution for callback-carrying modifiers
1 parent f63a2d5 commit 380f5b4

1 file changed

Lines changed: 23 additions & 2 deletions

File tree

AndroidSwiftUICore/Sources/AndroidSwiftUICore/Evaluator.swift

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,26 @@ public protocol _ModifierProvider {
7474
var _modifiedContent: any View { get }
7575
}
7676

77+
/// A modifier provider that needs the resolve context to emit its node — e.g.
78+
/// to register a callback. The evaluator prefers this over the context-free
79+
/// `_modifierNode` property when a provider conforms to it.
80+
public protocol _ContextualModifierProvider {
81+
func _modifierNode(in context: ResolveContext) -> ModifierNode
82+
}
83+
84+
/// A modifier whose emitted node embeds a callback registered against the
85+
/// resolve context (e.g. `onTapGesture`, `onAppear`, `onChange`).
86+
public protocol _CallbackModifier {
87+
func _callbackNode(in context: ResolveContext) -> ModifierNode
88+
}
89+
90+
extension _ModifierProvider {
91+
/// The emitted node, using the resolve context when the provider needs it.
92+
func resolvedModifierNode(in context: ResolveContext) -> ModifierNode {
93+
(self as? _ContextualModifierProvider)?._modifierNode(in: context) ?? _modifierNode
94+
}
95+
}
96+
7797
/// A group that flattens into a sequence of sibling nodes (TupleView, ForEach,
7898
/// conditionals, optionals).
7999
public protocol _GroupView {
@@ -123,7 +143,7 @@ public enum Evaluator {
123143
case let modifier as _ModifierProvider:
124144
// identity-transparent: resolve content at the SAME path, then prepend
125145
var node = resolve(modifier._modifiedContent, context)
126-
node.modifiers.insert(modifier._modifierNode, at: 0)
146+
node.modifiers.insert(modifier.resolvedModifierNode(in: context), at: 0)
127147
return node
128148
case let effect as _ResolutionEffectView:
129149
var context = context
@@ -171,8 +191,9 @@ public enum Evaluator {
171191
var before = nodes.count
172192
flatten(modifier._modifiedContent, into: &nodes, context: context)
173193
// apply the modifier to each node the content produced
194+
let modifierNode = modifier.resolvedModifierNode(in: context)
174195
while before < nodes.count {
175-
nodes[before].modifiers.insert(modifier._modifierNode, at: 0)
196+
nodes[before].modifiers.insert(modifierNode, at: 0)
176197
before += 1
177198
}
178199
case let anyView as AnyView:

0 commit comments

Comments
 (0)