feat: Implement chat list and search functionality
- 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.
This commit is contained in:
79
Rosetta/Features/Onboarding/OnboardingPager.swift
Normal file
79
Rosetta/Features/Onboarding/OnboardingPager.swift
Normal file
@@ -0,0 +1,79 @@
|
||||
import SwiftUI
|
||||
|
||||
/// UIPageViewController wrapper that handles paging entirely in UIKit.
|
||||
/// SwiftUI state is only updated after a page fully settles — zero overhead during swipe.
|
||||
struct OnboardingPager<Page: View>: UIViewControllerRepresentable {
|
||||
@Binding var currentIndex: Int
|
||||
let count: Int
|
||||
let buildPage: (Int) -> Page
|
||||
|
||||
func makeCoordinator() -> Coordinator { Coordinator(self) }
|
||||
|
||||
func makeUIViewController(context: Context) -> UIPageViewController {
|
||||
let vc = UIPageViewController(
|
||||
transitionStyle: .scroll,
|
||||
navigationOrientation: .horizontal
|
||||
)
|
||||
vc.view.backgroundColor = .clear
|
||||
vc.dataSource = context.coordinator
|
||||
vc.delegate = context.coordinator
|
||||
vc.setViewControllers(
|
||||
[context.coordinator.controllers[currentIndex]],
|
||||
direction: .forward,
|
||||
animated: false
|
||||
)
|
||||
// Make the inner scroll view transparent
|
||||
for sub in vc.view.subviews {
|
||||
(sub as? UIScrollView)?.backgroundColor = .clear
|
||||
}
|
||||
return vc
|
||||
}
|
||||
|
||||
func updateUIViewController(_ vc: UIPageViewController, context: Context) {
|
||||
context.coordinator.parent = self
|
||||
}
|
||||
|
||||
// MARK: - Coordinator
|
||||
|
||||
final class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
|
||||
var parent: OnboardingPager
|
||||
let controllers: [UIHostingController<Page>]
|
||||
|
||||
init(_ parent: OnboardingPager) {
|
||||
self.parent = parent
|
||||
// Create hosting controllers without triggering view loading
|
||||
self.controllers = (0..<parent.count).map { i in
|
||||
UIHostingController(rootView: parent.buildPage(i))
|
||||
}
|
||||
}
|
||||
|
||||
func pageViewController(
|
||||
_ pvc: UIPageViewController,
|
||||
viewControllerBefore vc: UIViewController
|
||||
) -> UIViewController? {
|
||||
guard let idx = controllers.firstIndex(where: { $0 === vc }), idx > 0 else { return nil }
|
||||
return controllers[idx - 1]
|
||||
}
|
||||
|
||||
func pageViewController(
|
||||
_ pvc: UIPageViewController,
|
||||
viewControllerAfter vc: UIViewController
|
||||
) -> UIViewController? {
|
||||
guard let idx = controllers.firstIndex(where: { $0 === vc }),
|
||||
idx < parent.count - 1 else { return nil }
|
||||
return controllers[idx + 1]
|
||||
}
|
||||
|
||||
func pageViewController(
|
||||
_ pvc: UIPageViewController,
|
||||
didFinishAnimating finished: Bool,
|
||||
previousViewControllers: [UIViewController],
|
||||
transitionCompleted completed: Bool
|
||||
) {
|
||||
guard completed,
|
||||
let current = pvc.viewControllers?.first,
|
||||
let idx = controllers.firstIndex(where: { $0 === current }) else { return }
|
||||
parent.currentIndex = idx
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user