fix(ios): preserve sidebar navigation after leaving terminal search
This commit is contained in:
1 parent
2502b76cd6
commit
6a84ab04b4
3 files changed
+45
-6
No files matched your search
@@ -2,11 +2,12 @@ import SwiftUI
|
||||
|
||||
struct MobileToolbarLayout: Equatable {
|
||||
var isTopBar = false
|
||||
var isSidebar = false
|
||||
var verticalEdge: HorizontalEdge?
|
||||
|
||||
var isVertical: Bool { verticalEdge != nil }
|
||||
var usesIconSwitcher: Bool { isTopBar || isVertical }
|
||||
var showsWorkspaceTabs: Bool { isTopBar || isVertical }
|
||||
var showsWorkspaceTabs: Bool { isTopBar || isSidebar || isVertical }
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
@@ -19,11 +20,12 @@ private struct MobileToolbarEnvironment: ViewModifier {
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if #available(iOS 27.1, *) {
|
||||
content.modifier(MobileVerticalToolbarEnvironment(isTopBar: placement == .topBar))
|
||||
content.modifier(
|
||||
MobileVerticalToolbarEnvironment(isTopBar: placement == .topBar, isSidebar: placement == .sidebar))
|
||||
} else {
|
||||
content.environment(
|
||||
\.mobileToolbarLayout,
|
||||
MobileToolbarLayout(isTopBar: placement == .topBar))
|
||||
MobileToolbarLayout(isTopBar: placement == .topBar, isSidebar: placement == .sidebar))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,12 +33,13 @@ private struct MobileToolbarEnvironment: ViewModifier {
|
||||
@available(iOS 27.1, *)
|
||||
private struct MobileVerticalToolbarEnvironment: ViewModifier {
|
||||
let isTopBar: Bool
|
||||
let isSidebar: Bool
|
||||
@Environment(\.toolbarVerticalEdge) private var edge
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content.environment(
|
||||
\.mobileToolbarLayout,
|
||||
MobileToolbarLayout(isTopBar: isTopBar, verticalEdge: edge))
|
||||
MobileToolbarLayout(isTopBar: isTopBar, isSidebar: isSidebar, verticalEdge: edge))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -145,7 +145,8 @@ struct MobileWorkspaceView: View {
|
||||
}
|
||||
.navigationTitle(workspace.descriptor.title)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar(toolbarLayout.showsWorkspaceTabs ? .visible : .hidden, for: .tabBar)
|
||||
// Retained, inactive workspaces must not hide another destination's navigation when folding.
|
||||
.toolbar(workspaceIsVisible && !toolbarLayout.showsWorkspaceTabs ? .hidden : .visible, for: .tabBar)
|
||||
.toolbar(removing: toolbarLayout.usesIconSwitcher ? .title : nil)
|
||||
.toolbar {
|
||||
if toolbarLayout.usesIconSwitcher {
|
||||
|
||||
@@ -9,6 +9,40 @@ import UIKit
|
||||
@Suite(.serialized, .requiresKeyWindow)
|
||||
@MainActor
|
||||
struct MobileTerminalSearchIntegrationTests {
|
||||
@Test func expandingVaultAfterWorkspaceSearchKeepsSidebarAvailable() async throws {
|
||||
let fixture = try SearchFixture(kind: .ssh, fullRoot: true)
|
||||
defer { fixture.close() }
|
||||
let scene = try #require(fixture.scene)
|
||||
fixture.resize(width: 430, height: 900, sizeClass: .compact)
|
||||
try await fixture.settle()
|
||||
let tabs = try #require(fixture.tabController)
|
||||
let search = try #require(fixture.searchController)
|
||||
search.isActive = true
|
||||
try await fixture.settle()
|
||||
scene.selectedDestination = .vault
|
||||
try await fixture.settle()
|
||||
|
||||
fixture.resize(width: 1024, height: 900, sizeClass: .regular)
|
||||
if #available(iOS 27.0, *) { tabs.sidebar.preferredPlacement = .sidebar }
|
||||
tabs.sidebar.isHidden = false
|
||||
try await fixture.settle()
|
||||
if #available(iOS 27.0, *) { #expect(tabs.sidebar.isAvailable) }
|
||||
#expect(!search.isActive)
|
||||
#expect(!tabs.sidebar.isHidden)
|
||||
#expect(!tabs.isTabBarHidden)
|
||||
#expect(scene.selectedDestination == .vault)
|
||||
|
||||
// The retained workspace must also keep navigation available in sidebar mode.
|
||||
scene.selectedDestination = .workspaces
|
||||
try await fixture.settle()
|
||||
#expect(!tabs.sidebar.isHidden)
|
||||
#expect(!tabs.isTabBarHidden)
|
||||
scene.selectedDestination = .vault
|
||||
try await fixture.settle()
|
||||
#expect(!tabs.sidebar.isHidden)
|
||||
#expect(!tabs.isTabBarHidden)
|
||||
}
|
||||
|
||||
@Test(arguments: [ConnectionHistoryEntry.Kind.ssh, .sftp])
|
||||
func leavingWorkspaceSearchRestoresVaultNavigationAcrossResizing(kind: ConnectionHistoryEntry.Kind) async throws {
|
||||
let fixture = try SearchFixture(kind: kind, fullRoot: true)
|
||||
@@ -278,8 +312,9 @@ private final class SearchFixture {
|
||||
|
||||
func settle() async throws { try await Task.sleep(for: .milliseconds(700)) }
|
||||
|
||||
func resize(width: CGFloat, height: CGFloat) {
|
||||
func resize(width: CGFloat, height: CGFloat, sizeClass: UIUserInterfaceSizeClass? = nil) {
|
||||
let frame = CGRect(x: 0, y: 0, width: width, height: height)
|
||||
if let sizeClass { host.traitOverrides.horizontalSizeClass = sizeClass }
|
||||
window.frame = frame
|
||||
host.view.frame = frame
|
||||
host.view.setNeedsLayout()
|
||||
|
||||
Reference in new issue
Block a user