feat: Hide/show the meetings UI depends on the feature flag - WPB-25683 - #5128
Conversation
There was a problem hiding this comment.
Pull request overview
This PR wires the Meetings UI visibility to a new UserSession.isMeetingsEnabled flag (derived from feature config), and propagates that through the main tab bar and sidebar so Meetings can be added after initial sync.
Changes:
- Added
UserSession.isMeetingsEnabledand implemented it inZMUserSession(plus mocks). - Updated
ZClientViewControllerto build/enable Meetings UI based onisMeetingsEnabled, including reacting to feature config updates. - Refactored Meetings tab bar item setup in
MainTabBarControllerand enabled lazy insertion of the Meetings tab when the UI becomes available.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift | Refactors Meetings tab bar item setup and supports lazy insertion of the Meetings tab when meetingsUI is set. |
| wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientViewController.swift | Switches Meetings visibility logic to userSession.isMeetingsEnabled and reacts to feature config changes to setup Meetings. |
| wire-ios/Wire-iOS/Sources/UserInterface/MainController/SidebarViewControllerBuilder.swift | Plumbs isMeetingsEnabled into sidebar construction to control Meetings visibility. |
| wire-ios/Tests/Mocks/UserSessionMock.swift | Adds isMeetingsEnabled to the test UserSession mock. |
| wire-ios-sync-engine/Support/Sourcery/generated/AutoMockable.manual.swift | Adds isMeetingsEnabled to the generated MockUserSession. |
| wire-ios-sync-engine/Source/UserSession/ZMUserSession/ZMUserSession.swift | Implements isMeetingsEnabled via feature config (currently also gated by developer flag). |
| wire-ios-sync-engine/Source/UserSession/UserSession.swift | Extends the UserSession protocol with isMeetingsEnabled. |
Suppressed comments (1)
WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift:273
setMeetingsUInow supports dynamically inserting the Meetings tab after initialization (whenshowMeetingswas false). There are existing unit tests for tab installation/release, but there isn't coverage for the new runtime-enable/runtime-disable flow (e.g. starting without Meetings, settingmeetingsUIto non-nil to insert the tab, then setting it back to nil to remove it). Adding a test inWireUI/Tests/WireMainNavigationUITests/Containers/MainTabBarControllerTests.swiftwould help prevent regressions in the feature-flag-driven hide/show behavior.
if meetingsNavigationController == nil, meetingsUI != nil {
let meetingsNavigationController = UINavigationController()
meetingsNavigationController.navigationBar.isTranslucent = false
self.meetingsNavigationController = meetingsNavigationController
viewControllers?.insert(meetingsNavigationController, at: 2)
setupMeetingsTabBarItem()
}
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Test Results3 246 tests 3 218 ✅ 5m 6s ⏱️ Results for commit 304b4cc. ♻️ This comment has been updated with latest results. Summary: workflow run #32029398781 |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 7 changed files in this pull request and generated no new comments.
Suppressed comments (3)
WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift:279
- When
meetingsUIis set tonil, the code only clears the navigation controller’s stack but keeps the Meetings tab inviewControllers. This leaves a visible Meetings tab that opens to an empty screen, which breaks the intended hide/show behavior when the feature flag is disabled. Remove the Meetings navigation controller from the tab bar when disabling (and reset selection if the user is currently on that tab).
_meetingsUI = meetingsUI
let viewControllers = [meetingsUI].compactMap(\.self)
meetingsNavigationController?.setViewControllers(viewControllers, animated: animated)
meetingsNavigationController?.view.layoutIfNeeded()
wire-ios/Wire-iOS/Sources/UserInterface/MainController/ZClientViewController.swift:312
clientSessionComponentis documented as guaranteed to exist for this view controller’s lifetime, butobserveFeatureConfigChanges()uses optional chaining (clientSessionComponent?). If that assumption is ever violated, this will silently drop the subscription and prevent the Files/Meetings tabs from updating, making the UI inconsistent and harder to debug. Prefer accessing it non-optionally so failures are explicit.
private func observeFeatureConfigChanges() {
subscription = clientSessionComponent?.featureConfigRepository
.observeFeatureStates()
.receive(on: DispatchQueue.main)
.sink { [weak self] featureState in
WireUI/Sources/WireMainNavigationUI/Containers/MainTabBarController.swift:272
- The Meetings tab is inserted at a hard-coded index (
at: 2), butselectedContentmaps between tab indices andMainTabBarControllerContent.rawValue. With the current enum ordering, placing Meetings at index 2 will make programmatic tab selection (e.g.selectedContent = .archive/.settings/.meetings) select the wrong tab once Meetings is present. The insertion order and theMainTabBarControllerContentraw values need to be aligned (orselectedContentneeds an index mapping that accounts for optional tabs).
let meetingsNavigationController = UINavigationController()
meetingsNavigationController.navigationBar.isTranslucent = false
self.meetingsNavigationController = meetingsNavigationController
viewControllers?.insert(meetingsNavigationController, at: 2)
setupMeetingsTabBarItem()
Issue
We should show/hide the Meeting tab depends on the “meetings“ feature flag.
Testing
Checklist
[WPB-XXX].UI accessibility checklist
If your PR includes UI changes, please utilize this checklist: