Skip to content

Commit f22c5b8

Browse files
Added support for hiding tabview when chat channel shown
1 parent 73d1f23 commit f22c5b8

File tree

4 files changed

+83
-2
lines changed

4 files changed

+83
-2
lines changed

Sources/StreamChatSwiftUI/ChatChannel/ChatChannelView.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@ import StreamChat
66
import SwiftUI
77

88
/// View for the chat channel.
9-
public struct ChatChannelView<Factory: ViewFactory>: View {
9+
public struct ChatChannelView<Factory: ViewFactory>: View, KeyboardReadable {
1010
@Injected(\.colors) private var colors
1111

1212
@StateObject private var viewModel: ChatChannelViewModel
1313

1414
@State private var messageDisplayInfo: MessageDisplayInfo?
15+
@State private var keyboardShown = false
16+
@State private var tabBarAvailable: Bool = false
1517

1618
private var factory: Factory
1719

@@ -94,11 +96,29 @@ public struct ChatChannelView<Factory: ViewFactory>: View {
9496
.edgesIgnoringSafeArea(.all)
9597
: nil
9698
)
99+
.onReceive(keyboardWillChangePublisher, perform: { visible in
100+
keyboardShown = visible
101+
})
97102
.onAppear {
98103
viewModel.onViewAppear()
99104
}
100105
.onDisappear {
101106
viewModel.onViewDissappear()
102107
}
108+
.background(
109+
Color.clear.background(
110+
TabBarAccessor { _ in
111+
self.tabBarAvailable = true
112+
}
113+
)
114+
.allowsHitTesting(false)
115+
)
116+
.padding(.bottom, keyboardShown || !tabBarAvailable ? 0 : bottomPadding)
117+
.ignoresSafeArea(.container, edges: tabBarAvailable ? .bottom : [])
118+
}
119+
120+
private var bottomPadding: CGFloat {
121+
let bottomPadding = topVC()?.view.safeAreaInsets.bottom ?? 0
122+
return bottomPadding
103123
}
104124
}

Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelHelperViews.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,33 @@ extension CGSize {
7474
/// Default size of the avatar used in the channel list.
7575
public static var defaultAvatarSize: CGSize = CGSize(width: 48, height: 48)
7676
}
77+
78+
/// Provides access to the the app's tab bar (if present).
79+
struct TabBarAccessor: UIViewControllerRepresentable {
80+
var callback: (UITabBar) -> Void
81+
private let proxyController = ViewController()
82+
83+
func makeUIViewController(context: UIViewControllerRepresentableContext<TabBarAccessor>) ->
84+
UIViewController {
85+
proxyController.callback = callback
86+
return proxyController
87+
}
88+
89+
func updateUIViewController(
90+
_ uiViewController: UIViewController,
91+
context: UIViewControllerRepresentableContext<TabBarAccessor>
92+
) {}
93+
94+
typealias UIViewControllerType = UIViewController
95+
96+
private class ViewController: UIViewController {
97+
var callback: (UITabBar) -> Void = { _ in }
98+
99+
override func viewWillAppear(_ animated: Bool) {
100+
super.viewWillAppear(animated)
101+
if let tabBar = tabBarController {
102+
callback(tabBar.tabBar)
103+
}
104+
}
105+
}
106+
}

Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListView.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public struct ChatChannelListView<Factory: ViewFactory>: View {
1212

1313
@StateObject private var viewModel: ChatChannelListViewModel
1414
@StateObject private var channelHeaderLoader = ChannelHeaderLoader()
15+
@State private var tabBar: UITabBar?
1516

1617
private let viewFactory: Factory
1718
private let title: String
@@ -124,12 +125,33 @@ public struct ChatChannelListView<Factory: ViewFactory>: View {
124125
.if(isIphone, transform: { view in
125126
view.navigationViewStyle(.stack)
126127
})
128+
.background(
129+
Color.clear.background(
130+
TabBarAccessor { tabBar in
131+
self.tabBar = tabBar
132+
}
133+
)
134+
.allowsHitTesting(false)
135+
)
136+
.onReceive(viewModel.$hideTabBar) { newValue in
137+
self.setupTabBarAppeareance()
138+
self.tabBar?.isHidden = newValue
139+
}
127140
}
128141

129142
private var isIphone: Bool {
130143
UIDevice.current.userInterfaceIdiom == .phone
131144
}
132145

146+
private func setupTabBarAppeareance() {
147+
if #available(iOS 15.0, *) {
148+
let tabBarAppearance: UITabBarAppearance = UITabBarAppearance()
149+
tabBarAppearance.configureWithDefaultBackground()
150+
UITabBar.appearance().standardAppearance = tabBarAppearance
151+
UITabBar.appearance().scrollEdgeAppearance = tabBarAppearance
152+
}
153+
}
154+
133155
@ViewBuilder
134156
private func customViewOverlay() -> some View {
135157
switch viewModel.customChannelPopupType {

Sources/StreamChatSwiftUI/ChatChannelList/ChatChannelListViewModel.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController
4141
}
4242

4343
@Published public var selectedChannel: ChannelSelectionInfo? {
44+
willSet {
45+
hideTabBar = newValue != nil
46+
}
4447
didSet {
4548
if oldValue != nil && selectedChannel == nil {
4649
// pop happened, apply the queued changes.
@@ -73,7 +76,12 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController
7376

7477
@Published public var alertShown = false
7578
@Published public var loading = false
76-
@Published public var customAlertShown = false
79+
@Published public var customAlertShown = false {
80+
didSet {
81+
hideTabBar = customAlertShown
82+
}
83+
}
84+
7785
@Published public var searchText = "" {
7886
didSet {
7987
handleSearchTextChange()
@@ -82,6 +90,7 @@ open class ChatChannelListViewModel: ObservableObject, ChatChannelListController
8290

8391
@Published public var loadingSearchResults = false
8492
@Published public var searchResults = [ChannelSelectionInfo]()
93+
@Published var hideTabBar = false
8594

8695
var isSearching: Bool {
8796
!searchText.isEmpty

0 commit comments

Comments
 (0)