InstantPage V2: support nested <details> blocks
A details block nested inside another rendered (title + chevron) but could not expand: its body is hosted by a fresh InstantPageV2View whose detailsTapped closure was never wired (only the top-level view's is, by the bubble), so the nested title's tap hit a nil closure and was dropped. Wire the body view's detailsTapped to chain through this view's onTitleTapped, which makeItemView already routes to the owning view's detailsTapped -> the bubble's toggle handler; this chains up through arbitrary nesting depth. Also make the bubble's defaultExpanded(forDetailsIndex:) recurse into expanded bodies so a nested details whose model default is expanded toggles from the correct state (the flat top-level scan missed nested indices). Known pre-existing limitation (unchanged): V2 keys expansion state by a flat DFS index, so expanding a nested details can shift sibling indices. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a4cddb74d6
commit
0d5b051820
2 changed files with 22 additions and 4 deletions
|
|
@ -1803,6 +1803,13 @@ final class InstantPageV2DetailsView: UIView, InstantPageItemView {
|
|||
self.addSubview(body)
|
||||
self.bodyView = body
|
||||
}
|
||||
// Forward taps on details NESTED inside this body up to the same toggle handler this
|
||||
// view uses: makeItemView wired our onTitleTapped to the owning InstantPageV2View's
|
||||
// detailsTapped, so chaining through onTitleTapped reaches the bubble's toggle handler.
|
||||
// Without this, a nested details' tap hits the body view's nil detailsTapped and is dropped.
|
||||
body.detailsTapped = { [weak self] index in
|
||||
self?.onTitleTapped?(index)
|
||||
}
|
||||
body.update(layout: innerLayout, theme: theme, animation: animation)
|
||||
body.frame = CGRect(
|
||||
origin: CGPoint(x: 0.0, y: item.titleFrame.maxY),
|
||||
|
|
|
|||
|
|
@ -164,12 +164,23 @@ public class ChatMessageRichDataBubbleContentNode: ChatMessageBubbleContentNode
|
|||
|
||||
private func defaultExpanded(forDetailsIndex index: Int) -> Bool {
|
||||
guard let layout = self.currentPageLayout?.layout else { return false }
|
||||
for item in layout.items {
|
||||
if case let .details(d) = item, d.index == index {
|
||||
return d.defaultExpanded
|
||||
func search(_ items: [InstantPageV2LaidOutItem]) -> Bool? {
|
||||
for item in items {
|
||||
if case let .details(d) = item {
|
||||
if d.index == index {
|
||||
return d.defaultExpanded
|
||||
}
|
||||
// Recurse into an expanded parent's body so NESTED details indices resolve too;
|
||||
// the flat top-level scan missed them, leaving the toggle's "current state"
|
||||
// computation wrong for a nested details whose model default is expanded.
|
||||
if let inner = d.innerLayout, let found = search(inner.items) {
|
||||
return found
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return false
|
||||
return search(layout.items) ?? false
|
||||
}
|
||||
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue