Hide the tab bar whilst we're working on it and add some tests.

This commit is contained in:
Doug
2025-07-30 15:50:39 +01:00
committed by Doug
parent dac804309e
commit 6133a563cf
4 changed files with 135 additions and 3 deletions

View File

@@ -1238,6 +1238,7 @@
EDB6915EC953BB2A44AA608E /* EditRoomAddressScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906451FB8CF27C628152BF7A /* EditRoomAddressScreenViewModelTests.swift */; };
EDD45A73B688B87D84B9C2E9 /* AccessibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6D867A7FBB70C6EFDBCBC5 /* AccessibilityTests.swift */; };
EDF8919F15DE0FF00EF99E70 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0F5567A7EF6F2AB9473236F6 /* DocumentPicker.swift */; };
EE17B7154DCA50677D931A94 /* NavigationTabCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2B67DC84B42D86035FCFF6F8 /* NavigationTabCoordinatorTests.swift */; };
EE4E2C1922BBF5169E213555 /* PillAttachmentViewProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1B53D6C5C0D14B04D3AB3F6E /* PillAttachmentViewProvider.swift */; };
EE56238683BC3ECA9BA00684 /* GlobalSearchScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA4D639E27D5882A6A71AECF /* GlobalSearchScreenViewModelTests.swift */; };
EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */; };
@@ -1664,6 +1665,7 @@
2AE83A3DD63BCFBB956FE5CB /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = nl; path = nl.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
2AF715D4FD4710EBB637D661 /* SettingsScreenViewModelProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreenViewModelProtocol.swift; sourceTree = "<group>"; };
2B1FB56520A847DD2532D5C8 /* VideoMediaEventsTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoMediaEventsTimelineView.swift; sourceTree = "<group>"; };
2B67DC84B42D86035FCFF6F8 /* NavigationTabCoordinatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationTabCoordinatorTests.swift; sourceTree = "<group>"; };
2B9BCACD0CC4CB8E37F17732 /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = lt; path = lt.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
2BA894BC09972DC45E497D37 /* TimelineInteractionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineInteractionHandler.swift; sourceTree = "<group>"; };
2BB385E148DE55C85C0A02D6 /* SoftLogoutScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SoftLogoutScreenModels.swift; sourceTree = "<group>"; };
@@ -4444,6 +4446,7 @@
F875D71347DC81EAE7687446 /* NavigationRootCoordinatorTests.swift */,
78913D6E120D46138E97C107 /* NavigationSplitCoordinatorTests.swift */,
9C698E30698EC59302A8EEBD /* NavigationStackCoordinatorTests.swift */,
2B67DC84B42D86035FCFF6F8 /* NavigationTabCoordinatorTests.swift */,
8544F7058D31DBEB8DBFF0F5 /* NotificationSettingsEditScreenViewModelTests.swift */,
514363244AE7D68080D44C6F /* NotificationSettingsScreenViewModelTests.swift */,
FA3EB5B1848CF4F64E63C6B7 /* PermalinkTests.swift */,
@@ -7071,6 +7074,7 @@
981853650217B6C8ECDD998C /* NavigationRootCoordinatorTests.swift in Sources */,
69C7B956B74BEC3DB88224EA /* NavigationSplitCoordinatorTests.swift in Sources */,
4BB282209EA82015D0DF8F89 /* NavigationStackCoordinatorTests.swift in Sources */,
EE17B7154DCA50677D931A94 /* NavigationTabCoordinatorTests.swift in Sources */,
1B2DADC008EE211AF1DA5292 /* NotificationManagerTests.swift in Sources */,
C11939FDC40716C4387275A4 /* NotificationSettingsEditScreenViewModelTests.swift in Sources */,
E3AC72E3E58F364EF15C1CC7 /* NotificationSettingsScreenViewModelTests.swift in Sources */,

View File

@@ -15,6 +15,7 @@ import SwiftUI
let title: String
let icon: KeyPath<CompoundIcons, Image>
let selectedIcon: KeyPath<CompoundIcons, Image>
var dismissalCallback: (() -> Void)?
}
// MARK: Tabs
@@ -56,7 +57,10 @@ import SwiftUI
transaction.disablesAnimations = !animated
withTransaction(transaction) {
tabModules = tabs.map { TabModule(module: .init($0.coordinator), title: $0.title, icon: $0.icon, selectedIcon: $0.selectedIcon) }
tabModules = tabs.map { TabModule(module: .init($0.coordinator, dismissalCallback: $0.dismissalCallback),
title: $0.title,
icon: $0.icon,
selectedIcon: $0.selectedIcon) }
}
}
@@ -199,6 +203,7 @@ private struct NavigationTabCoordinatorView: View {
}
.tag(module.id)
.id(module.id)
.toolbar(.hidden, for: .tabBar)
}
}
.sheet(item: $navigationTabCoordinator.sheetModule) { module in

View File

@@ -81,8 +81,8 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
isNewLogin: isNewLogin)
navigationTabCoordinator.setTabs([
.init(coordinator: chatsSplitCoordinator, title: L10n.screenHomeTabChats, icon: \.chat, selectedIcon: \.chatSolid),
.init(coordinator: BlankFormCoordinator(), title: L10n.screenHomeTabSpaces, icon: \.space, selectedIcon: \.spaceSolid)
.init(coordinator: chatsSplitCoordinator, title: L10n.screenHomeTabChats, icon: \.chat, selectedIcon: \.chatSolid)
// .init(coordinator: BlankFormCoordinator(), title: L10n.screenHomeTabSpaces, icon: \.space, selectedIcon: \.spaceSolid)
])
setupObservers()

View File

@@ -0,0 +1,123 @@
//
// Copyright 2022-2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import XCTest
@testable import ElementX
@MainActor
class NavigationTabCoordinatorTests: XCTestCase {
private var navigationTabCoordinator: NavigationTabCoordinator!
override func setUp() {
navigationTabCoordinator = NavigationTabCoordinator()
}
func testTabs() {
XCTAssertTrue(navigationTabCoordinator.tabCoordinators.isEmpty)
let someCoordinator = SomeTestCoordinator()
navigationTabCoordinator.setTabs([.init(coordinator: someCoordinator, title: "Whatever", icon: \.help, selectedIcon: \.helpSolid)])
assertCoordinatorsEqual(navigationTabCoordinator.tabCoordinators, [someCoordinator])
let chatsCoordinator = SomeTestCoordinator()
let spacesCoordinator = SomeTestCoordinator()
navigationTabCoordinator.setTabs([
.init(coordinator: chatsCoordinator, title: "Chats", icon: \.chat, selectedIcon: \.chatSolid),
.init(coordinator: spacesCoordinator, title: "Spaces", icon: \.space, selectedIcon: \.spaceSolid)
])
assertCoordinatorsEqual(navigationTabCoordinator.tabCoordinators, [chatsCoordinator, spacesCoordinator])
}
func testSingleSheet() {
let tabCoordinator = SomeTestCoordinator()
navigationTabCoordinator.setTabs([.init(coordinator: tabCoordinator, title: "Tab", icon: \.help, selectedIcon: \.helpSolid)])
let coordinator = SomeTestCoordinator()
navigationTabCoordinator.setSheetCoordinator(coordinator)
assertCoordinatorsEqual(navigationTabCoordinator.tabCoordinators, [tabCoordinator])
assertCoordinatorsEqual(coordinator, navigationTabCoordinator.sheetCoordinator)
navigationTabCoordinator.setSheetCoordinator(nil)
assertCoordinatorsEqual(navigationTabCoordinator.tabCoordinators, [tabCoordinator])
XCTAssertNil(navigationTabCoordinator.sheetCoordinator)
}
func testMultipleSheets() {
let tabCoordinator = SomeTestCoordinator()
navigationTabCoordinator.setTabs([.init(coordinator: tabCoordinator, title: "Tab", icon: \.help, selectedIcon: \.helpSolid)])
let sheetCoordinator = SomeTestCoordinator()
navigationTabCoordinator.setSheetCoordinator(sheetCoordinator)
assertCoordinatorsEqual(navigationTabCoordinator.tabCoordinators, [tabCoordinator])
assertCoordinatorsEqual(sheetCoordinator, navigationTabCoordinator.sheetCoordinator)
let someOtherSheetCoordinator = SomeTestCoordinator()
navigationTabCoordinator.setSheetCoordinator(someOtherSheetCoordinator)
assertCoordinatorsEqual(navigationTabCoordinator.tabCoordinators, [tabCoordinator])
assertCoordinatorsEqual(someOtherSheetCoordinator, navigationTabCoordinator.sheetCoordinator)
}
func testTabDismissalCallbacks() {
let chatsCoordinator = SomeTestCoordinator()
let spacesCoordinator = SomeTestCoordinator()
let expectation = expectation(description: "Wait for callback")
expectation.expectedFulfillmentCount = 2
navigationTabCoordinator.setTabs([
.init(coordinator: chatsCoordinator, title: "Chats", icon: \.chat, selectedIcon: \.chatSolid) { expectation.fulfill() },
.init(coordinator: spacesCoordinator, title: "Spaces", icon: \.space, selectedIcon: \.spaceSolid) { expectation.fulfill() }
])
assertCoordinatorsEqual(navigationTabCoordinator.tabCoordinators, [chatsCoordinator, spacesCoordinator])
navigationTabCoordinator.setTabs([.init(coordinator: SomeTestCoordinator(), title: "Whatever", icon: \.help, selectedIcon: \.helpSolid)])
waitForExpectations(timeout: 1.0)
}
func testSheetDismissalCallback() {
let coordinator = SomeTestCoordinator()
let expectation = expectation(description: "Wait for callback")
navigationTabCoordinator.setSheetCoordinator(coordinator) {
expectation.fulfill()
}
navigationTabCoordinator.setSheetCoordinator(nil)
waitForExpectations(timeout: 1.0)
}
// MARK: - Private
private func assertCoordinatorsEqual(_ lhs: CoordinatorProtocol?, _ rhs: CoordinatorProtocol?) {
guard let lhs = lhs as? SomeTestCoordinator,
let rhs = rhs as? SomeTestCoordinator else {
XCTFail("Coordinators are not the same")
return
}
XCTAssertEqual(lhs.id, rhs.id)
}
private func assertCoordinatorsEqual(_ lhs: [CoordinatorProtocol], _ rhs: [CoordinatorProtocol]) {
guard lhs.count == rhs.count else {
XCTFail("Coordinators are not the same")
return
}
for (index, coordinator) in lhs.enumerated() {
assertCoordinatorsEqual(coordinator, rhs[index])
}
}
}
private class SomeTestCoordinator: CoordinatorProtocol {
let id = UUID()
}