
- 在DetailView中添加头像点击功能,支持展示非当前用户的主页。 - 更新OptimizedDynamicCardView以支持头像点击回调。 - 修改DetailFeature以管理用户主页显示状态。 - 在MeView中添加关闭按钮支持,优化用户体验。 - 确保其他页面的兼容性,未影响现有功能。
136 lines
4.5 KiB
Swift
136 lines
4.5 KiB
Swift
import SwiftUI
|
|
import ComposableArchitecture
|
|
|
|
struct MainView: View {
|
|
let store: StoreOf<MainFeature>
|
|
var onLogout: (() -> Void)? = nil
|
|
|
|
var body: some View {
|
|
WithPerceptionTracking {
|
|
InternalMainView(store: store)
|
|
.onChange(of: store.isLoggedOut) { _, isLoggedOut in
|
|
if isLoggedOut {
|
|
onLogout?()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct InternalMainView: View {
|
|
let store: StoreOf<MainFeature>
|
|
@State private var path: [MainFeature.Destination] = []
|
|
init(store: StoreOf<MainFeature>) {
|
|
self.store = store
|
|
_path = State(initialValue: store.withState { $0.navigationPath })
|
|
}
|
|
var body: some View {
|
|
WithPerceptionTracking {
|
|
NavigationStack(path: $path) {
|
|
GeometryReader { geometry in
|
|
contentView(geometry: geometry)
|
|
.navigationDestination(for: MainFeature.Destination.self) { destination in
|
|
DestinationView(destination: destination, store: self.store)
|
|
}
|
|
.onChange(of: path) { _, path in
|
|
store.send(.navigationPathChanged(path))
|
|
}
|
|
.onChange(of: store.navigationPath) { _, navigationPath in
|
|
if path != navigationPath {
|
|
path = navigationPath
|
|
}
|
|
}
|
|
.onAppear {
|
|
store.send(.onAppear)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct DestinationView: View {
|
|
let destination: MainFeature.Destination
|
|
let store: StoreOf<MainFeature>
|
|
|
|
var body: some View {
|
|
switch destination {
|
|
case .appSetting:
|
|
IfLetStore(
|
|
store.scope(state: \.appSettingState, action: \.appSettingAction),
|
|
then: { store in
|
|
WithPerceptionTracking {
|
|
AppSettingView(store: store)
|
|
}
|
|
},
|
|
else: { Text("appSettingState is nil") }
|
|
)
|
|
case .testView:
|
|
TestView()
|
|
}
|
|
}
|
|
}
|
|
|
|
private func contentView(geometry: GeometryProxy) -> some View {
|
|
WithPerceptionTracking {
|
|
ZStack {
|
|
// 背景图片
|
|
Image("bg")
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.clipped()
|
|
.ignoresSafeArea(.all)
|
|
// 主内容
|
|
MainContentView(
|
|
store: store,
|
|
selectedTab: store.selectedTab
|
|
)
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
.padding(.bottom, 80) // 为底部导航栏留出空间
|
|
|
|
// 底部导航栏 - 固定在底部
|
|
VStack {
|
|
Spacer()
|
|
BottomTabView(selectedTab: Binding(
|
|
get: { Tab(rawValue: store.selectedTab.rawValue) ?? .feed },
|
|
set: { newTab in
|
|
store.send(.selectTab(MainFeature.Tab(rawValue: newTab.rawValue) ?? .feed))
|
|
}
|
|
))
|
|
}
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
|
|
.padding(.bottom, 100)
|
|
.ignoresSafeArea(.keyboard, edges: .bottom)
|
|
|
|
// 添加API Loading和错误处理视图
|
|
APILoadingEffectView()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct MainContentView: View {
|
|
let store: StoreOf<MainFeature>
|
|
let selectedTab: MainFeature.Tab
|
|
var body: some View {
|
|
Group {
|
|
if selectedTab == .feed {
|
|
FeedListView(store: store.scope(
|
|
state: \.feedList,
|
|
action: \.feedList
|
|
))
|
|
} else if selectedTab == .other {
|
|
MeView(
|
|
store: store.scope(
|
|
state: \.me,
|
|
action: \.me
|
|
),
|
|
showCloseButton: false // MainView中不需要关闭按钮
|
|
)
|
|
} else {
|
|
EmptyView()
|
|
}
|
|
}
|
|
}
|
|
}
|