Skip to content

Commit d145a75

Browse files
isaacclaude
andcommitted
iPhone Duo: the chat list's search field stays on screen in unfolded landscape
With no status bar height, SearchDisplayController starts a list-mode search bar 20pt above the top, which suits the legacy fields: they are drawn at the bottom of the bar. The glass field is drawn at the top of its frame, in the navigation bar's search row, already below the status bar, so the offset put it 20pt above the row. In the Duo's unfolded landscape the list pane has no status bar (the clock is in the detail pane's corner), and the active field sat at window y -12, half off the screen. A glass bar now starts at the row's top, its bottom where it was, so the results' inset is unchanged. Any status bar height above 0, the legacy fields and `.navigation` mode lay out as before. Verified on the Duo simulator, unfolded landscape: the field at window y 8 (was -12, from an lldb frame dump), and the open animation, captured at 10x slow, settles there without a jump. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 336db35 commit d145a75

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

‎submodules/SearchUI/Sources/SearchDisplayController.swift‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ public enum SearchDisplayControllerMode {
1111
case navigation
1212
}
1313

14+
/// The search bar's frame in `.list` mode. With no status bar height the bar starts 20pt above the top, which suits the
15+
/// legacy fields, drawn at the bar's bottom. A glass field is drawn at the top of its frame, in a search row already
16+
/// placed below the status bar, so its frame starts at the row's top instead (offset, the field sat 20pt above the row:
17+
/// iPhone Duo's unfolded landscape, whose list pane has no status bar). The frame's bottom stays where it was.
18+
private func listSearchBarFrame(navigationBarFrame: CGRect, fieldStyle: SearchBarStyle) -> CGRect {
19+
if case .glass = fieldStyle, navigationBarFrame.minY < 0.0 {
20+
return CGRect(x: navigationBarFrame.minX, y: 0.0, width: navigationBarFrame.width, height: navigationBarFrame.maxY)
21+
}
22+
return navigationBarFrame
23+
}
24+
1425
public final class SearchDisplayController {
1526
private final class BackgroundNode: ASDisplayNode {
1627
var isTransparent: Bool = false
@@ -189,7 +200,7 @@ public final class SearchDisplayController {
189200
searchBarFrame = CGRect(x: 0.0, y: 0.0, width: layout.size.width, height: 54.0)
190201
}
191202
} else {
192-
searchBarFrame = navigationBarFrame
203+
searchBarFrame = listSearchBarFrame(navigationBarFrame: navigationBarFrame, fieldStyle: searchBar.fieldStyle)
193204
navigationBarHeight = navigationBarFrame.maxY + 8.0
194205
}
195206
transition.updateFrame(node: searchBar, frame: searchBarFrame)
@@ -286,7 +297,11 @@ public final class SearchDisplayController {
286297
}
287298

288299
if !self.searchBarIsExternal, let searchBar = self.searchBar {
289-
searchBar.frame = navigationBarFrame
300+
if case .list = self.mode {
301+
searchBar.frame = listSearchBarFrame(navigationBarFrame: navigationBarFrame, fieldStyle: searchBar.fieldStyle)
302+
} else {
303+
searchBar.frame = navigationBarFrame
304+
}
290305
insertSubnode(searchBar, true)
291306
searchBar.layout()
292307

0 commit comments

Comments
 (0)