- Added ChatListViewModel to manage chat list state and server search. - Created ChatRowView for displaying individual chat rows. - Developed SearchView and SearchViewModel for user search functionality. - Introduced MainTabView for tab-based navigation between chats and settings. - Implemented OnboardingPager for onboarding experience. - Created SettingsView and SettingsViewModel for user settings management. - Added SplashView for initial app launch experience.
88 lines
2.7 KiB
Swift
88 lines
2.7 KiB
Swift
import SwiftUI
|
|
|
|
/// Main container view with tab-based navigation.
|
|
struct MainTabView: View {
|
|
var onLogout: (() -> Void)?
|
|
@State private var selectedTab: RosettaTab = .chats
|
|
|
|
var body: some View {
|
|
ZStack(alignment: .bottom) {
|
|
RosettaColors.Adaptive.background
|
|
.ignoresSafeArea()
|
|
|
|
Group {
|
|
switch selectedTab {
|
|
case .chats:
|
|
ChatListView()
|
|
case .settings:
|
|
SettingsView(onLogout: onLogout)
|
|
case .search:
|
|
SearchView()
|
|
}
|
|
}
|
|
|
|
RosettaTabBar(
|
|
selectedTab: selectedTab,
|
|
onTabSelected: { tab in
|
|
withAnimation(.easeInOut(duration: 0.15)) {
|
|
selectedTab = tab
|
|
}
|
|
},
|
|
badges: tabBadges
|
|
)
|
|
.ignoresSafeArea(.keyboard)
|
|
}
|
|
}
|
|
|
|
private var tabBadges: [TabBadge] {
|
|
var result: [TabBadge] = []
|
|
let unread = DialogRepository.shared.sortedDialogs
|
|
.filter { !$0.isMuted }
|
|
.reduce(0) { $0 + $1.unreadCount }
|
|
if unread > 0 {
|
|
result.append(TabBadge(tab: .chats, text: unread > 999 ? "\(unread / 1000)K" : "\(unread)"))
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
// MARK: - Placeholder
|
|
|
|
struct PlaceholderTabView: View {
|
|
let title: String
|
|
let icon: String
|
|
|
|
var body: some View {
|
|
NavigationStack {
|
|
ZStack {
|
|
RosettaColors.Adaptive.background
|
|
.ignoresSafeArea()
|
|
|
|
VStack(spacing: 16) {
|
|
Image(systemName: icon)
|
|
.font(.system(size: 52))
|
|
.foregroundStyle(RosettaColors.Adaptive.textSecondary.opacity(0.5))
|
|
|
|
Text(title)
|
|
.font(.system(size: 17, weight: .semibold))
|
|
.foregroundStyle(RosettaColors.Adaptive.textSecondary)
|
|
|
|
Text("Coming soon")
|
|
.font(.system(size: 15))
|
|
.foregroundStyle(RosettaColors.Adaptive.textTertiary)
|
|
}
|
|
}
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .principal) {
|
|
Text(title)
|
|
.font(.system(size: 17, weight: .semibold))
|
|
.foregroundStyle(RosettaColors.Adaptive.text)
|
|
}
|
|
}
|
|
.toolbarBackground(.ultraThinMaterial, for: .navigationBar)
|
|
.toolbarBackground(.visible, for: .navigationBar)
|
|
}
|
|
}
|
|
}
|