-
Notifications
You must be signed in to change notification settings - Fork 48
Replace custom tab bar with native iOS TabView #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Replace the custom bottom tab bar implementation with iOS native TabView component using SF Symbols icons. Changes: - Replace custom TabBar widget with native SwiftUI TabView - Use SF Symbols for tab icons (newspaper, safari, bell, person) - Add badge support for unread message count - Remove .hide() modifiers from page views (TabView handles visibility) - Move data loading logic to onAppear in each page view - Integrate TopBar within each tab using pageWithTopBar helper Cleanup: - Delete TabBar.swift (custom tab bar implementation) - Remove custom tab icon assets (feed_tab, explore_tab, message_tab, me_tab) - Removed ~150 lines of custom UI code Benefits: - Native iOS look and feel with standard tab bar behavior - Uses system SF Symbols icons instead of custom assets - Cleaner, more maintainable codebase - Better integration with iOS accessibility features - Automatic handling of safe areas and device variations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Coverage Report ❌Current coverage: 0% |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Replaces the custom bottom TabBar with the native SwiftUI TabView to simplify implementation and leverage system behaviors (icons, badges, safe areas).
- Introduces TabView with SF Symbols and per-tab top bar wrapper.
- Removes custom .hide() based tab selection gating and shifts initial data loading to onAppear in pages.
- Cleans up obsolete custom tab bar file and image assets.
Reviewed Changes
Copilot reviewed 10 out of 22 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| V2er/View/MainPage.swift | Adds native TabView with tab items and helper wrapping each page with TopBar. |
| V2er/View/Feed/FeedPage.swift | Removes .hide usage; adds onAppear fetch trigger. |
| V2er/View/Explore/ExplorePage.swift | Removes .hide; adds onAppear conditional fetch. |
| V2er/View/Message/MessagePage.swift | Removes .hide; adds onAppear conditional fetch. |
| V2er/View/Me/MePage.swift | Removes .hide call for profile tab. |
| V2er/View/Widget/TabBar.swift | Deletes custom tab bar implementation (now replaced). |
| V2er/Assets.xcassets/*_tab.imageset | Deletes obsolete custom tab icon assets. |
Comments suppressed due to low confidence (1)
V2er/View/Me/MePage.swift:1
- With this hide call removed, the isSelected logic in MePage (used only to support hiding) becomes unused; consider removing the isSelected computed property to reduce dead code.
//
| TabView(selection: selectedTab) { | ||
| // Feed Tab | ||
| pageWithTopBar( | ||
| FeedPage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the parameter label 'selecedTab' to 'selectedTab' to avoid propagating the typo; update the corresponding parameter name in each page's initializer.
|
|
||
| // Explore Tab | ||
| pageWithTopBar( | ||
| ExplorePage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the parameter label 'selecedTab' to 'selectedTab' to avoid propagating the typo; update the corresponding parameter name in each page's initializer.
|
|
||
| // Message Tab | ||
| pageWithTopBar( | ||
| MessagePage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the parameter label 'selecedTab' to 'selectedTab' to avoid propagating the typo; update the corresponding parameter name in each page's initializer.
|
|
||
| // Me Tab | ||
| pageWithTopBar( | ||
| MePage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct the parameter label 'selecedTab' to 'selectedTab' to avoid propagating the typo; update the corresponding parameter name in each page's initializer.
| .onAppear { | ||
| log("FeedPage.onAppear") | ||
| if !state.hasLoadedOnce { | ||
| dispatch(FeedActions.FetchData.Start(autoLoad: true)) | ||
| } |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fetch is already conditionally dispatched inside the existing isSelected computed property; adding the same conditional fetch in onAppear risks double dispatch and duplicate network requests. Remove one of the two triggers (prefer a single source, e.g. keep onAppear and simplify isSelected or vice versa).
| .onAppear { | ||
| if !state.hasLoadedOnce { | ||
| dispatch(ExploreActions.FetchData.Start(autoLoad: true)) | ||
| } | ||
| } |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExplorePage already dispatches the same initial fetch inside isSelected when the tab becomes active; this added onAppear block duplicates that logic and can cause redundant requests. Consolidate to a single initiation point.
| .onAppear { | |
| if !state.hasLoadedOnce { | |
| dispatch(ExploreActions.FetchData.Start(autoLoad: true)) | |
| } | |
| } |
| .onAppear { | ||
| if !state.hasLoadedOnce { | ||
| dispatch(MessageActions.FetchStart(autoLoad: true)) | ||
| } | ||
| } |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MessagePage also conditionally dispatches the same fetch in isSelected; retaining both paths may cause duplicate initial loads. Remove one of them to avoid unnecessary network calls.
Remove all references to the deleted TabBar.swift file from the Xcode project.pbxproj file to fix build failure. - Remove PBXBuildFile reference - Remove PBXFileReference - Remove from Widget group children - Remove from PBXSourcesBuildPhase Fixes CI build error: "Build input file cannot be found: TabBar.swift" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Coverage Report ❌Current coverage: 0% |
Restore the TabId enum definition that was removed with TabBar.swift. The enum is now defined in GlobalState.swift where it's primarily used. Fixes build errors: "cannot find type 'TabId' in scope" 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Code Coverage Report ❌Current coverage: 0% |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 12 out of 24 changed files in this pull request and generated 5 comments.
| TabView(selection: selectedTab) { | ||
| // Feed Tab | ||
| pageWithTopBar( | ||
| FeedPage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name 'selecedTab' is misspelled; rename to 'selectedTab' for clarity and consistency.
|
|
||
| // Explore Tab | ||
| pageWithTopBar( | ||
| ExplorePage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name 'selecedTab' is misspelled; rename to 'selectedTab' for clarity and consistency.
|
|
||
| // Message Tab | ||
| pageWithTopBar( | ||
| MessagePage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name 'selecedTab' is misspelled; rename to 'selectedTab' for clarity and consistency.
|
|
||
| // Me Tab | ||
| pageWithTopBar( | ||
| MePage(selecedTab: state.selectedTab) |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name 'selecedTab' is misspelled; rename to 'selectedTab' for clarity and consistency.
| .onAppear { | ||
| log("FeedPage.onAppear") | ||
| if !state.hasLoadedOnce { | ||
| dispatch(FeedActions.FetchData.Start(autoLoad: true)) | ||
| } | ||
| } |
Copilot
AI
Oct 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initial fetch is already triggered in the existing isSelected computed property; this added onAppear block can cause duplicate dispatches (two initial network requests). Remove either the isSelected-triggered fetch or this onAppear block.
| .onAppear { | |
| log("FeedPage.onAppear") | |
| if !state.hasLoadedOnce { | |
| dispatch(FeedActions.FetchData.Start(autoLoad: true)) | |
| } | |
| } |
Summary
Replace the custom bottom tab bar implementation with iOS native TabView component using SF Symbols icons.
Changes Made
Core Implementation
newspapersafaribellwith badge supportpersonpageWithTopBarhelper functionCode Updates
.hide()modifier, move data loading toonAppear.hide()modifier, addonAppearfor data loading.hide()modifier, move data loading toonAppear.hide()modifierResource Cleanup
TabBar.swift(custom tab bar implementation, ~150 lines)feed_tab.imageset(3 PNG files + JSON)explore_tab.imageset(3 PNG files + JSON)message_tab.imageset(3 PNG files + JSON)me_tab.imageset(3 PNG files + JSON)Benefits
✨ User Experience
📦 Code Quality
🔧 Technical
Testing
Screenshots
Screenshots will be added after manual testing on device
🤖 Generated with Claude Code