Files
e-party-iOS/yana/Features/AppSettingFeature.swift
edwinQQQ 815091a2ff feat: 新增返回按钮功能以优化设置页面导航
- 在AppSettingFeature中新增dismissTapped事件,处理返回操作。
- 更新MainFeature以监听dismissTapped事件,支持导航栈的pop操作。
- 在AppSettingView中实现返回按钮,提升用户体验与界面交互性。
- 隐藏导航栏以优化设置页面的视觉效果。
2025-07-25 14:43:27 +08:00

237 lines
9.2 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Foundation
import ComposableArchitecture
@Reducer
struct AppSettingFeature {
@ObservableState
struct State: Equatable {
var nickname: String = ""
var avatarURL: String? = nil
var userInfo: UserInfo? = nil
var isLoadingUserInfo: Bool = false
var userInfoError: String? = nil
// WebView
var showUserAgreement: Bool = false
var showPrivacyPolicy: Bool = false
// /
var isUploadingAvatar: Bool = false
var avatarUploadError: String? = nil
var isEditingNickname: Bool = false
var nicknameInput: String = ""
var isUpdatingUser: Bool = false
var updateUserError: String? = nil
// userInfoavatarURLnicknameinit
init(nickname: String = "", avatarURL: String? = nil, userInfo: UserInfo? = nil) {
self.nickname = nickname
self.avatarURL = avatarURL
self.userInfo = userInfo
}
}
enum Action: Equatable {
case onAppear
case editNicknameTapped
case logoutTapped
case dismissTapped
//
case loadUserInfo
case userInfoResponse(Result<UserInfo, APIError>)
// WebView
case personalInfoPermissionsTapped
case helpTapped
case clearCacheTapped
case checkUpdatesTapped
case aboutUsTapped
// WebView
case userAgreementDismissed
case privacyPolicyDismissed
// /
case avatarTapped
case avatarSelected(Data)
case avatarUploadResult(Result<String, APIError>)
case nicknameEditConfirmed(String)
case updateUser(Result<UpdateUserResponse, APIError>)
case nicknameInputChanged(String)
case nicknameEditAlert(Bool)
case testPushTapped
}
@Dependency(\.apiService) var apiService
func reduce(into state: inout State, action: Action) -> Effect<Action> {
switch action {
case .onAppear:
return .send(.loadUserInfo)
case .editNicknameTapped:
//
return .none
case .logoutTapped:
//
return .run { send in
await UserInfoManager.clearAllAuthenticationData()
// FeatureMainFeature
// .noneMainFeatureAppSettingFeature.Action.logoutTapped
}
case .dismissTapped:
// MainFeature navigationPath pop
return .none
case .loadUserInfo:
state.isLoadingUserInfo = true
state.userInfoError = nil
return .run { send in
// do {
if let userInfo = await UserInfoManager.getUserInfo() {
await send(.userInfoResponse(.success(userInfo)))
} else {
await send(.userInfoResponse(.failure(APIError.custom("用户信息不存在"))))
}
// } catch {
// let apiError: APIError
// if let error = error as? APIError {
// apiError = error
// } else {
// apiError = APIError.custom(error.localizedDescription)
// }
// await send(.userInfoResponse(.failure(apiError)))
// }
}
case let .userInfoResponse(.success(userInfo)):
state.userInfo = userInfo
state.nickname = userInfo.nick ?? ""
state.avatarURL = userInfo.avatar //
state.isLoadingUserInfo = false
return .none
case let .userInfoResponse(.failure(error)):
state.userInfoError = error.localizedDescription
state.isLoadingUserInfo = false
return .none
case .personalInfoPermissionsTapped:
state.showPrivacyPolicy = true
return .none
case .helpTapped:
state.showUserAgreement = true
return .none
case .clearCacheTapped:
//
return .none
case .checkUpdatesTapped:
//
return .none
case .aboutUsTapped:
//
return .none
case .userAgreementDismissed:
state.showUserAgreement = false
return .none
case .privacyPolicyDismissed:
state.showPrivacyPolicy = false
return .none
case .avatarTapped:
//
return .none
case let .avatarSelected(imageData):
state.isUploadingAvatar = true
state.avatarUploadError = nil
return .run { [avatarData = imageData] send in
guard let uiImage = UIImage(data: avatarData) else {
await send(.avatarUploadResult(.failure(APIError.custom("图片格式错误"))))
return
}
//
if let url = await COSManager.shared.uploadUIImage(uiImage, apiService: apiService) {
await send(.avatarUploadResult(.success(url)))
} else {
await send(.avatarUploadResult(.failure(APIError.custom("头像上传失败"))))
}
}
case let .avatarUploadResult(.success(url)):
state.isUploadingAvatar = false
// updateUser API avatar
state.isUpdatingUser = true
state.updateUserError = nil
guard let userInfo = state.userInfo else { return .none }
// avatarURLUI
state.avatarURL = url
return .run { send in
let ticket = await UserInfoManager.getCurrentUserTicket() ?? ""
let req = UpdateUserRequest(avatar: url, nick: nil, uid: userInfo.uid ?? 0, ticket: ticket)
do {
let resp: UpdateUserResponse = try await apiService.request(req)
await send(.updateUser(.success(resp)))
} catch {
let apiError = error as? APIError ?? APIError.custom(error.localizedDescription)
await send(.updateUser(.failure(apiError)))
}
}
case let .avatarUploadResult(.failure(error)):
state.isUploadingAvatar = false
state.avatarUploadError = error.localizedDescription
return .none
case .nicknameEditAlert(let show):
state.isEditingNickname = show
state.nicknameInput = state.nickname
return .none
case .nicknameInputChanged(let text):
state.nicknameInput = String(text.prefix(15))
return .none
case .nicknameEditConfirmed(let newNick):
guard let userInfo = state.userInfo else { return .none }
state.isUpdatingUser = true
state.updateUserError = nil
return .run { send in
let ticket = await UserInfoManager.getCurrentUserTicket() ?? ""
let req = UpdateUserRequest(avatar: nil, nick: newNick, uid: userInfo.uid ?? 0, ticket: ticket)
do {
let resp: UpdateUserResponse = try await apiService.request(req)
await send(.updateUser(.success(resp)))
} catch {
let apiError = error as? APIError ?? APIError.custom(error.localizedDescription)
await send(.updateUser(.failure(apiError)))
}
}
case .updateUser(.success(_)):
state.isUpdatingUser = false
// resp.data userinfo1
if let uid = state.userInfo?.uid {
return .run { send in
try? await Task.sleep(nanoseconds: 1_000_000_000)
if let newUser = await UserInfoManager.fetchUserInfoFromServer(uid: String(uid), apiService: apiService) {
await send(.userInfoResponse(.success(newUser)))
} else {
await send(.userInfoResponse(.failure(APIError.custom("获取最新用户信息失败"))))
}
}
}
state.isEditingNickname = false
return .none
case let .updateUser(.failure(error)):
state.isUpdatingUser = false
state.updateUserError = error.localizedDescription
return .none
case .testPushTapped:
return .none
}
}
}