feat: 实现DetailView头像点击功能并优化MeView
- 在DetailView中添加头像点击功能,支持展示非当前用户的主页。 - 更新OptimizedDynamicCardView以支持头像点击回调。 - 修改DetailFeature以管理用户主页显示状态。 - 在MeView中添加关闭按钮支持,优化用户体验。 - 确保其他页面的兼容性,未影响现有功能。
This commit is contained in:
68
issues/DetailView头像点击功能.md
Normal file
68
issues/DetailView头像点击功能.md
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# DetailView头像点击功能实现
|
||||||
|
|
||||||
|
## 需求分析
|
||||||
|
在DetailView中点击OptimizedDynamicCardView的头像时,如果是非当前用户的动态,则present一个MeView并传入该动态的uid作为displayUID。
|
||||||
|
|
||||||
|
## 实施计划
|
||||||
|
|
||||||
|
### 修改文件
|
||||||
|
1. **OptimizedDynamicCardView.swift**:添加头像点击回调参数
|
||||||
|
2. **DetailFeature.swift**:添加显示用户主页的状态管理
|
||||||
|
3. **DetailView.swift**:添加MeView的present逻辑
|
||||||
|
4. **MeView.swift**:更新OptimizedDynamicCardView调用,添加关闭按钮支持
|
||||||
|
5. **FeedListView.swift**:更新OptimizedDynamicCardView调用
|
||||||
|
6. **MainView.swift**:更新MeView调用
|
||||||
|
|
||||||
|
### 核心功能设计
|
||||||
|
1. **OptimizedDynamicCardView**:
|
||||||
|
- 添加`onAvatarTap: (() -> Void)?`参数
|
||||||
|
- 在头像上添加点击手势
|
||||||
|
- 移除头像的`allowsHitTesting(false)`
|
||||||
|
|
||||||
|
2. **DetailFeature**:
|
||||||
|
- 添加`showUserProfile: Bool`状态
|
||||||
|
- 添加`targetUserId: Int`状态
|
||||||
|
- 添加`showUserProfile(Int)`和`hideUserProfile` Action
|
||||||
|
|
||||||
|
3. **DetailView**:
|
||||||
|
- 在OptimizedDynamicCardView中添加头像点击回调
|
||||||
|
- 判断是否为当前用户动态
|
||||||
|
- 使用sheet替代fullScreenCover,支持下拉关闭
|
||||||
|
- 添加presentationDetents和presentationDragIndicator
|
||||||
|
|
||||||
|
4. **MeView**:
|
||||||
|
- 添加`showCloseButton: Bool`参数
|
||||||
|
- 在present时显示关闭按钮
|
||||||
|
- 在MainView中不显示关闭按钮
|
||||||
|
|
||||||
|
### 实施步骤
|
||||||
|
1. ✅ 修改OptimizedDynamicCardView添加头像点击回调
|
||||||
|
2. ✅ 修改DetailFeature添加用户主页状态管理
|
||||||
|
3. ✅ 修改DetailView添加MeView present逻辑
|
||||||
|
4. ✅ 更新其他使用OptimizedDynamicCardView的地方
|
||||||
|
5. ✅ 改进present方式,使用sheet替代fullScreenCover
|
||||||
|
6. ✅ 添加MeView关闭按钮支持
|
||||||
|
|
||||||
|
### 功能特点
|
||||||
|
- **智能判断**:只有点击非当前用户的头像才会显示用户主页
|
||||||
|
- **复用MeView**:利用之前实现的displayUID功能
|
||||||
|
- **用户体验**:使用sheet支持下拉关闭,更符合iOS设计规范
|
||||||
|
- **关闭按钮**:在present时提供明确的关闭方式
|
||||||
|
- **向后兼容**:其他页面的OptimizedDynamicCardView不受影响
|
||||||
|
|
||||||
|
## 完成状态
|
||||||
|
- [x] OptimizedDynamicCardView头像点击功能
|
||||||
|
- [x] DetailFeature状态管理
|
||||||
|
- [x] DetailView MeView present逻辑
|
||||||
|
- [x] 其他页面兼容性更新
|
||||||
|
- [x] 改进present方式(sheet替代fullScreenCover)
|
||||||
|
- [x] MeView关闭按钮支持
|
||||||
|
|
||||||
|
## 测试要点
|
||||||
|
1. 在DetailView中点击当前用户头像,不触发任何操作
|
||||||
|
2. 在DetailView中点击其他用户头像,正确显示该用户的主页
|
||||||
|
3. 用户主页支持下拉关闭
|
||||||
|
4. 用户主页显示关闭按钮,点击可关闭
|
||||||
|
5. MainView中的MeView不显示关闭按钮
|
||||||
|
6. 其他页面的OptimizedDynamicCardView正常工作
|
||||||
|
7. MeView正确显示指定用户的信息
|
@@ -17,10 +17,11 @@
|
|||||||
|
|
||||||
### 核心组件设计
|
### 核心组件设计
|
||||||
1. **UserIDDisplay组件**:
|
1. **UserIDDisplay组件**:
|
||||||
- 参数:uid (Int), fontSize (CGFloat), textColor (Color)
|
- 参数:uid (Int), fontSize (CGFloat), textColor (Color), isDisplayCopy (Bool)
|
||||||
- 功能:显示"ID: xxx",右侧复制图标,点击复制ID
|
- 功能:显示"ID: xxx",可选的复制图标,点击复制ID
|
||||||
- 样式:数字不使用逗号分割
|
- 样式:数字不使用逗号分割
|
||||||
- 反馈:点击后显示"已复制"提示
|
- 反馈:点击后显示"已复制"提示
|
||||||
|
- 配置:isDisplayCopy控制是否显示复制图标和启用复制功能
|
||||||
|
|
||||||
2. **头像样式调整**:
|
2. **头像样式调整**:
|
||||||
- 尺寸:130x130
|
- 尺寸:130x130
|
||||||
@@ -44,11 +45,12 @@
|
|||||||
- [x] OptimizedDynamicCardView组件更新
|
- [x] OptimizedDynamicCardView组件更新
|
||||||
- [x] 复制功能实现
|
- [x] 复制功能实现
|
||||||
- [x] 视觉反馈实现
|
- [x] 视觉反馈实现
|
||||||
|
- [x] 复制图标显示控制功能
|
||||||
|
|
||||||
## 测试要点
|
## 测试要点
|
||||||
1. 头像尺寸和边框显示正确
|
1. 头像尺寸和边框显示正确
|
||||||
2. ID显示格式正确(无逗号分割)
|
2. ID显示格式正确(无逗号分割)
|
||||||
3. 复制图标显示正确
|
3. 复制图标显示控制正确(MeView显示,其他页面不显示)
|
||||||
4. 点击复制功能正常
|
4. 点击复制功能正常
|
||||||
5. 复制成功反馈显示
|
5. 复制成功反馈显示
|
||||||
6. 组件在不同场景下复用正常
|
6. 组件在不同场景下复用正常
|
@@ -22,6 +22,10 @@ struct DetailFeature {
|
|||||||
// 新增:是否需要关闭DetailView
|
// 新增:是否需要关闭DetailView
|
||||||
var shouldDismiss = false
|
var shouldDismiss = false
|
||||||
|
|
||||||
|
// 新增:显示用户主页相关状态
|
||||||
|
var showUserProfile = false
|
||||||
|
var targetUserId: Int = 0
|
||||||
|
|
||||||
init(moment: MomentsInfo) {
|
init(moment: MomentsInfo) {
|
||||||
self.moment = moment
|
self.moment = moment
|
||||||
}
|
}
|
||||||
@@ -41,6 +45,10 @@ struct DetailFeature {
|
|||||||
// 新增:当前用户ID相关actions
|
// 新增:当前用户ID相关actions
|
||||||
case loadCurrentUserId
|
case loadCurrentUserId
|
||||||
case currentUserIdLoaded(String?)
|
case currentUserIdLoaded(String?)
|
||||||
|
|
||||||
|
// 新增:用户主页相关actions
|
||||||
|
case showUserProfile(Int)
|
||||||
|
case hideUserProfile
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some ReducerOf<Self> {
|
var body: some ReducerOf<Self> {
|
||||||
@@ -190,6 +198,15 @@ struct DetailFeature {
|
|||||||
debugInfoSync("🔍 DetailFeature: 请求关闭DetailView")
|
debugInfoSync("🔍 DetailFeature: 请求关闭DetailView")
|
||||||
state.shouldDismiss = true
|
state.shouldDismiss = true
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
case let .showUserProfile(userId):
|
||||||
|
state.targetUserId = userId
|
||||||
|
state.showUserProfile = true
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .hideUserProfile:
|
||||||
|
state.showUserProfile = false
|
||||||
|
return .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,7 +12,7 @@ struct MainFeature {
|
|||||||
struct State: Equatable {
|
struct State: Equatable {
|
||||||
var selectedTab: Tab = .feed
|
var selectedTab: Tab = .feed
|
||||||
var feedList: FeedListFeature.State = .init()
|
var feedList: FeedListFeature.State = .init()
|
||||||
var me: MeFeature.State = .init()
|
var me: MeFeature.State
|
||||||
var accountModel: AccountModel? = nil
|
var accountModel: AccountModel? = nil
|
||||||
// 新增:导航路径和设置页面 State
|
// 新增:导航路径和设置页面 State
|
||||||
var navigationPath: [Destination] = []
|
var navigationPath: [Destination] = []
|
||||||
@@ -20,8 +20,10 @@ struct MainFeature {
|
|||||||
// 新增:登出标志
|
// 新增:登出标志
|
||||||
var isLoggedOut: Bool = false
|
var isLoggedOut: Bool = false
|
||||||
|
|
||||||
init() {
|
init(accountModel: AccountModel? = nil) {
|
||||||
// 默认初始化
|
self.accountModel = accountModel
|
||||||
|
let uid = accountModel?.uid.flatMap { Int($0) } ?? 0
|
||||||
|
self.me = MeFeature.State(displayUID: uid > 0 ? uid : nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,9 +66,9 @@ struct MainFeature {
|
|||||||
state.selectedTab = tab
|
state.selectedTab = tab
|
||||||
state.navigationPath = []
|
state.navigationPath = []
|
||||||
if tab == .other, let uidStr = state.accountModel?.uid, let uid = Int(uidStr), uid > 0 {
|
if tab == .other, let uidStr = state.accountModel?.uid, let uid = Int(uidStr), uid > 0 {
|
||||||
if state.me.uid != uid {
|
if state.me.displayUID != uid {
|
||||||
state.me.uid = uid
|
state.me.displayUID = uid
|
||||||
state.me.isFirstLoad = true // 仅当用户切换时才重置首次加载
|
state.me.isFirstLoad = true
|
||||||
}
|
}
|
||||||
return .send(.me(.onAppear))
|
return .send(.me(.onAppear))
|
||||||
}
|
}
|
||||||
@@ -86,8 +88,8 @@ struct MainFeature {
|
|||||||
state.accountModel = accountModel
|
state.accountModel = accountModel
|
||||||
// 如果当前选中的是 MeView 标签页,且有有效的 uid,则触发数据加载
|
// 如果当前选中的是 MeView 标签页,且有有效的 uid,则触发数据加载
|
||||||
if state.selectedTab == .other, let uidStr = accountModel?.uid, let uid = Int(uidStr), uid > 0 {
|
if state.selectedTab == .other, let uidStr = accountModel?.uid, let uid = Int(uidStr), uid > 0 {
|
||||||
if state.me.uid != uid {
|
if state.me.displayUID != uid {
|
||||||
state.me.uid = uid
|
state.me.displayUID = uid
|
||||||
state.me.isFirstLoad = true
|
state.me.isFirstLoad = true
|
||||||
}
|
}
|
||||||
return .send(.me(.onAppear))
|
return .send(.me(.onAppear))
|
||||||
|
@@ -19,12 +19,24 @@ struct MeFeature {
|
|||||||
var page: Int = 1
|
var page: Int = 1
|
||||||
var pageSize: Int = 20
|
var pageSize: Int = 20
|
||||||
var uid: Int = 0
|
var uid: Int = 0
|
||||||
|
// 新增:显示指定用户ID,如果为nil则显示当前登录用户
|
||||||
|
var displayUID: Int?
|
||||||
// 新增:DetailView相关状态
|
// 新增:DetailView相关状态
|
||||||
var showDetail: Bool = false
|
var showDetail: Bool = false
|
||||||
var selectedMoment: MomentsInfo?
|
var selectedMoment: MomentsInfo?
|
||||||
|
|
||||||
init() {
|
init(displayUID: Int? = nil) {
|
||||||
// 默认初始化
|
self.displayUID = displayUID
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取实际要显示的用户ID
|
||||||
|
var effectiveUID: Int {
|
||||||
|
return displayUID ?? uid
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否显示其他用户
|
||||||
|
var isDisplayingOtherUser: Bool {
|
||||||
|
return displayUID != nil && displayUID != uid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,18 +60,18 @@ struct MeFeature {
|
|||||||
state.isFirstLoad = false
|
state.isFirstLoad = false
|
||||||
return .send(.refresh)
|
return .send(.refresh)
|
||||||
case .refresh:
|
case .refresh:
|
||||||
guard state.uid > 0 else { return .none }
|
guard state.effectiveUID > 0 else { return .none }
|
||||||
state.isRefreshing = true
|
state.isRefreshing = true
|
||||||
state.page = 1
|
state.page = 1
|
||||||
state.hasMore = true
|
state.hasMore = true
|
||||||
return .merge(
|
return .merge(
|
||||||
fetchUserInfo(uid: state.uid),
|
fetchUserInfo(uid: state.effectiveUID),
|
||||||
fetchMoments(uid: state.uid, page: 1, pageSize: state.pageSize)
|
fetchMoments(uid: state.effectiveUID, page: 1, pageSize: state.pageSize)
|
||||||
)
|
)
|
||||||
case .loadMore:
|
case .loadMore:
|
||||||
guard state.uid > 0, state.hasMore, !state.isLoadingMore else { return .none }
|
guard state.effectiveUID > 0, state.hasMore, !state.isLoadingMore else { return .none }
|
||||||
state.isLoadingMore = true
|
state.isLoadingMore = true
|
||||||
return fetchMoments(uid: state.uid, page: state.page + 1, pageSize: state.pageSize)
|
return fetchMoments(uid: state.effectiveUID, page: state.page + 1, pageSize: state.pageSize)
|
||||||
case let .userInfoResponse(result):
|
case let .userInfoResponse(result):
|
||||||
state.isLoadingUserInfo = false
|
state.isLoadingUserInfo = false
|
||||||
state.isRefreshing = false
|
state.isRefreshing = false
|
||||||
@@ -106,15 +118,11 @@ struct MeFeature {
|
|||||||
|
|
||||||
private func fetchUserInfo(uid: Int) -> Effect<Action> {
|
private func fetchUserInfo(uid: Int) -> Effect<Action> {
|
||||||
.run { send in
|
.run { send in
|
||||||
// do {
|
if let userInfo = await UserInfoManager.fetchUserInfoFromServer(uid: String(uid), apiService: apiService) {
|
||||||
if let userInfo = await UserInfoManager.fetchUserInfoFromServer(uid: String(uid), apiService: apiService) {
|
await send(.userInfoResponse(.success(userInfo)))
|
||||||
await send(.userInfoResponse(.success(userInfo)))
|
} else {
|
||||||
} else {
|
await send(.userInfoResponse(.failure(.noData)))
|
||||||
await send(.userInfoResponse(.failure(.noData)))
|
}
|
||||||
}
|
|
||||||
// } catch {
|
|
||||||
// await send(.userInfoResponse(.failure(error as? APIError ?? .unknown(error.localizedDescription))))
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,18 +13,21 @@ struct OptimizedDynamicCardView: View {
|
|||||||
let onLikeTap: (_ dynamicId: Int, _ uid: Int, _ likedUid: Int, _ worldId: Int) -> Void
|
let onLikeTap: (_ dynamicId: Int, _ uid: Int, _ likedUid: Int, _ worldId: Int) -> Void
|
||||||
// 新增:卡片点击回调
|
// 新增:卡片点击回调
|
||||||
let onCardTap: (() -> Void)?
|
let onCardTap: (() -> Void)?
|
||||||
|
// 新增:头像点击回调
|
||||||
|
let onAvatarTap: (() -> Void)?
|
||||||
// 新增:详情页模式,点击卡片不跳转
|
// 新增:详情页模式,点击卡片不跳转
|
||||||
let isDetailMode: Bool
|
let isDetailMode: Bool
|
||||||
// 新增:点赞loading状态
|
// 新增:点赞loading状态
|
||||||
let isLikeLoading: Bool
|
let isLikeLoading: Bool
|
||||||
|
|
||||||
init(moment: MomentsInfo, allMoments: [MomentsInfo], currentIndex: Int, onImageTap: @escaping (_ images: [String], _ index: Int) -> Void, onLikeTap: @escaping (_ dynamicId: Int, _ uid: Int, _ likedUid: Int, _ worldId: Int) -> Void, onCardTap: (() -> Void)? = nil, isDetailMode: Bool = false, isLikeLoading: Bool = false) {
|
init(moment: MomentsInfo, allMoments: [MomentsInfo], currentIndex: Int, onImageTap: @escaping (_ images: [String], _ index: Int) -> Void, onLikeTap: @escaping (_ dynamicId: Int, _ uid: Int, _ likedUid: Int, _ worldId: Int) -> Void, onCardTap: (() -> Void)? = nil, onAvatarTap: (() -> Void)? = nil, isDetailMode: Bool = false, isLikeLoading: Bool = false) {
|
||||||
self.moment = moment
|
self.moment = moment
|
||||||
self.allMoments = allMoments
|
self.allMoments = allMoments
|
||||||
self.currentIndex = currentIndex
|
self.currentIndex = currentIndex
|
||||||
self.onImageTap = onImageTap
|
self.onImageTap = onImageTap
|
||||||
self.onLikeTap = onLikeTap
|
self.onLikeTap = onLikeTap
|
||||||
self.onCardTap = onCardTap
|
self.onCardTap = onCardTap
|
||||||
|
self.onAvatarTap = onAvatarTap
|
||||||
self.isDetailMode = isDetailMode
|
self.isDetailMode = isDetailMode
|
||||||
self.isLikeLoading = isLikeLoading
|
self.isLikeLoading = isLikeLoading
|
||||||
}
|
}
|
||||||
@@ -62,7 +65,11 @@ struct OptimizedDynamicCardView: View {
|
|||||||
}
|
}
|
||||||
.frame(width: 40, height: 40)
|
.frame(width: 40, height: 40)
|
||||||
.clipShape(Circle())
|
.clipShape(Circle())
|
||||||
.allowsHitTesting(false) // 不拦截点击事件
|
.onTapGesture {
|
||||||
|
if let onAvatarTap = onAvatarTap {
|
||||||
|
onAvatarTap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 2) {
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
Text(moment.nick)
|
Text(moment.nick)
|
||||||
|
@@ -4,13 +4,15 @@ struct UserIDDisplay: View {
|
|||||||
let uid: Int
|
let uid: Int
|
||||||
let fontSize: CGFloat
|
let fontSize: CGFloat
|
||||||
let textColor: Color
|
let textColor: Color
|
||||||
|
let isDisplayCopy: Bool
|
||||||
|
|
||||||
@State private var showCopiedFeedback: Bool = false
|
@State private var showCopiedFeedback: Bool = false
|
||||||
|
|
||||||
init(uid: Int, fontSize: CGFloat = 14, textColor: Color = .white.opacity(0.7)) {
|
init(uid: Int, fontSize: CGFloat = 14, textColor: Color = .white.opacity(0.7), isDisplayCopy: Bool = false) {
|
||||||
self.uid = uid
|
self.uid = uid
|
||||||
self.fontSize = fontSize
|
self.fontSize = fontSize
|
||||||
self.textColor = textColor
|
self.textColor = textColor
|
||||||
|
self.isDisplayCopy = isDisplayCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
@@ -19,17 +21,21 @@ struct UserIDDisplay: View {
|
|||||||
.font(.system(size: fontSize))
|
.font(.system(size: fontSize))
|
||||||
.foregroundColor(textColor)
|
.foregroundColor(textColor)
|
||||||
|
|
||||||
Image("icon_copy")
|
if isDisplayCopy {
|
||||||
.resizable()
|
Image("icon_copy")
|
||||||
.frame(width: 14, height: 14)
|
.resizable()
|
||||||
.foregroundColor(textColor)
|
.frame(width: 14, height: 14)
|
||||||
|
.foregroundColor(textColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
copyToClipboard()
|
if isDisplayCopy {
|
||||||
|
copyToClipboard()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.overlay(
|
.overlay(
|
||||||
Group {
|
Group {
|
||||||
if showCopiedFeedback {
|
if isDisplayCopy && showCopiedFeedback {
|
||||||
Text("已复制")
|
Text("已复制")
|
||||||
.font(.system(size: 12))
|
.font(.system(size: 12))
|
||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
@@ -61,8 +67,8 @@ struct UserIDDisplay: View {
|
|||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
VStack(spacing: 20) {
|
VStack(spacing: 20) {
|
||||||
UserIDDisplay(uid: 123456789)
|
UserIDDisplay(uid: 123456789, isDisplayCopy: true)
|
||||||
UserIDDisplay(uid: 987654321, fontSize: 16, textColor: .black)
|
UserIDDisplay(uid: 987654321, fontSize: 16, textColor: .black, isDisplayCopy: false)
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
@@ -51,6 +51,12 @@ struct DetailView: View {
|
|||||||
store.send(.likeDynamic(dynamicId, uid, likedUid, worldId))
|
store.send(.likeDynamic(dynamicId, uid, likedUid, worldId))
|
||||||
},
|
},
|
||||||
onCardTap: nil, // 详情页不需要卡片点击
|
onCardTap: nil, // 详情页不需要卡片点击
|
||||||
|
onAvatarTap: {
|
||||||
|
// 如果点击的是非当前用户的头像,则显示用户主页
|
||||||
|
if !isCurrentUserDynamic {
|
||||||
|
store.send(.showUserProfile(store.moment.uid))
|
||||||
|
}
|
||||||
|
},
|
||||||
isDetailMode: true, // 详情页模式,点击卡片不跳转
|
isDetailMode: true, // 详情页模式,点击卡片不跳转
|
||||||
isLikeLoading: store.isLikeLoading
|
isLikeLoading: store.isLikeLoading
|
||||||
)
|
)
|
||||||
@@ -91,7 +97,23 @@ struct DetailView: View {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.sheet(isPresented: Binding(
|
||||||
|
get: { store.showUserProfile },
|
||||||
|
set: { _ in store.send(.hideUserProfile) }
|
||||||
|
)) {
|
||||||
|
WithPerceptionTracking {
|
||||||
|
let meStore = Store(
|
||||||
|
initialState: MeFeature.State(displayUID: store.targetUserId)
|
||||||
|
) {
|
||||||
|
MeFeature()
|
||||||
|
}
|
||||||
|
|
||||||
|
MeView(store: meStore, showCloseButton: true)
|
||||||
|
.presentationDetents([.large])
|
||||||
|
.presentationDragIndicator(.visible)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断是否为当前用户的动态
|
// 判断是否为当前用户的动态
|
||||||
|
@@ -96,6 +96,7 @@ struct MomentCardView: View {
|
|||||||
onImageTap: onImageTap,
|
onImageTap: onImageTap,
|
||||||
onLikeTap: onLikeTap,
|
onLikeTap: onLikeTap,
|
||||||
onCardTap: onTap,
|
onCardTap: onTap,
|
||||||
|
onAvatarTap: nil, // FeedListView中暂时不需要头像点击功能
|
||||||
isDetailMode: false,
|
isDetailMode: false,
|
||||||
isLikeLoading: isLikeLoading
|
isLikeLoading: isLikeLoading
|
||||||
)
|
)
|
||||||
|
@@ -124,7 +124,8 @@ struct MainContentView: View {
|
|||||||
store: store.scope(
|
store: store.scope(
|
||||||
state: \.me,
|
state: \.me,
|
||||||
action: \.me
|
action: \.me
|
||||||
)
|
),
|
||||||
|
showCloseButton: false // MainView中不需要关闭按钮
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
EmptyView()
|
EmptyView()
|
||||||
|
@@ -6,6 +6,15 @@ struct MeView: View {
|
|||||||
// 新增:图片预览状态
|
// 新增:图片预览状态
|
||||||
@State private var previewItem: PreviewItem? = nil
|
@State private var previewItem: PreviewItem? = nil
|
||||||
@State private var previewCurrentIndex: Int = 0
|
@State private var previewCurrentIndex: Int = 0
|
||||||
|
// 新增:是否显示关闭按钮
|
||||||
|
let showCloseButton: Bool
|
||||||
|
// 新增:dismiss环境变量
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
init(store: StoreOf<MeFeature>, showCloseButton: Bool = false) {
|
||||||
|
self.store = store
|
||||||
|
self.showCloseButton = showCloseButton
|
||||||
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
WithPerceptionTracking {
|
WithPerceptionTracking {
|
||||||
@@ -22,16 +31,35 @@ struct MeView: View {
|
|||||||
// 顶部栏,右上角设置按钮
|
// 顶部栏,右上角设置按钮
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
Spacer()
|
// 新增:关闭按钮(仅在present时显示)
|
||||||
Button(action: {
|
if showCloseButton {
|
||||||
store.send(.settingButtonTapped)
|
Button(action: {
|
||||||
}) {
|
dismiss()
|
||||||
Image(systemName: "gearshape")
|
}) {
|
||||||
.font(.system(size: 33, weight: .medium))
|
Image(systemName: "xmark")
|
||||||
.foregroundColor(.white)
|
.font(.system(size: 20, weight: .medium))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.frame(width: 44, height: 44)
|
||||||
|
.background(Color.black.opacity(0.3))
|
||||||
|
.clipShape(Circle())
|
||||||
|
}
|
||||||
|
.padding(.leading, 16)
|
||||||
|
.padding(.top, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
if !store.isDisplayingOtherUser {
|
||||||
|
Button(action: {
|
||||||
|
store.send(.settingButtonTapped)
|
||||||
|
}) {
|
||||||
|
Image(systemName: "gearshape")
|
||||||
|
.font(.system(size: 33, weight: .medium))
|
||||||
|
.foregroundColor(.white)
|
||||||
|
}
|
||||||
|
.padding(.trailing, 16)
|
||||||
|
.padding(.top, 8)
|
||||||
}
|
}
|
||||||
.padding(.trailing, 16)
|
|
||||||
.padding(.top, 8)
|
|
||||||
}
|
}
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
@@ -111,7 +139,7 @@ struct MeView: View {
|
|||||||
.foregroundColor(.white)
|
.foregroundColor(.white)
|
||||||
|
|
||||||
// 用户ID
|
// 用户ID
|
||||||
UserIDDisplay(uid: store.userInfo?.uid ?? 0)
|
UserIDDisplay(uid: store.userInfo?.uid ?? 0, isDisplayCopy: true)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 32)
|
.padding(.horizontal, 32)
|
||||||
}
|
}
|
||||||
@@ -184,7 +212,8 @@ struct MeView: View {
|
|||||||
},
|
},
|
||||||
onCardTap: {
|
onCardTap: {
|
||||||
store.send(.showDetail(moment))
|
store.send(.showDetail(moment))
|
||||||
}
|
},
|
||||||
|
onAvatarTap: nil // MeView中不需要头像点击功能
|
||||||
)
|
)
|
||||||
.padding(.horizontal, 12)
|
.padding(.horizontal, 12)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user