feat: 添加腾讯云COS Token管理功能及相关视图更新

- 在APIEndpoints.swift中新增tcToken端点以支持腾讯云COS Token获取。
- 在APIModels.swift中新增TcTokenRequest和TcTokenResponse模型,处理Token请求和响应。
- 在COSManager.swift中实现Token的获取、缓存和过期管理逻辑,提升API请求的安全性。
- 在LanguageSettingsView中添加调试功能,允许测试COS Token获取。
- 在多个视图中更新状态管理和导航逻辑,确保用户体验一致性。
- 在FeedFeature和HomeFeature中优化状态管理,简化视图逻辑。
This commit is contained in:
edwinQQQ
2025-07-18 20:50:25 +08:00
parent fb7ae9e0ad
commit 9a49d591c3
17 changed files with 1090 additions and 767 deletions

View File

@@ -11,12 +11,11 @@ struct FeedFeature {
var error: String?
var nextDynamicId: Int = 0
//
// -
var isInitialized = false
// CreateFeedView
var isShowingCreateFeed = false
var createFeedState: CreateFeedFeature.State? = nil
// CreateFeedView -
var isCreateFeedPresented = false
}
enum Action {
@@ -27,11 +26,10 @@ struct FeedFeature {
case clearError
case retryLoad
// CreateFeedView Action
// CreateFeedView Action -
case showCreateFeed
case dismissCreateFeed
case createFeedCompleted
indirect case createFeed(CreateFeedFeature.Action)
case createFeedDismissed
}
@Dependency(\.apiService) var apiService
@@ -40,15 +38,19 @@ struct FeedFeature {
Reduce { state, action in
switch action {
case .onAppear:
#if DEBUG
return .none
#endif
//
guard !state.isInitialized else { return .none }
state.isInitialized = true
//
guard !state.isInitialized else {
return .none
}
return .send(.loadLatestMoments)
case .loadLatestMoments:
//
guard !state.isLoading else {
return .none
}
//
state.isLoading = true
state.error = nil
@@ -58,7 +60,6 @@ struct FeedFeature {
pageSize: 20,
types: [.text, .picture]
)
return .run { send in
await send(.momentsResponse(TaskResult {
try await apiService.request(request)
@@ -87,50 +88,38 @@ struct FeedFeature {
case let .momentsResponse(.success(response)):
state.isLoading = false
//
debugInfoSync("📱 FeedFeature: API 响应成功")
debugInfoSync("📱 FeedFeature: response.code = \(response.code)")
debugInfoSync("📱 FeedFeature: response.message = \(response.message)")
debugInfoSync("📱 FeedFeature: response.data = \(response.data != nil ? "有数据" : "无数据")")
//
if !state.isInitialized {
state.isInitialized = true
}
//
guard response.code == 200, let data = response.data else {
let errorMsg = response.message.isEmpty ? "获取动态失败" : response.message
state.error = errorMsg
debugErrorSync("❌ FeedFeature: API 响应失败 - code: \(response.code), message: \(errorMsg)")
return .none
}
//
debugInfoSync("📱 FeedFeature: data.dynamicList.count = \(data.dynamicList.count)")
debugInfoSync("📱 FeedFeature: data.nextDynamicId = \(data.nextDynamicId)")
//
let isRefresh = state.nextDynamicId == 0
debugInfoSync("📱 FeedFeature: isRefresh = \(isRefresh)")
if isRefresh {
//
state.moments = data.dynamicList
debugInfoSync(" FeedFeature: 刷新数据moments.count = \(state.moments.count)")
} else {
//
let oldCount = state.moments.count
state.moments.append(contentsOf: data.dynamicList)
debugInfoSync(" FeedFeature: 加载更多moments.count: \(oldCount) -> \(state.moments.count)")
}
//
state.nextDynamicId = data.nextDynamicId
state.hasMoreData = !data.dynamicList.isEmpty
debugInfoSync("📱 FeedFeature: 更新完成 - nextDynamicId: \(state.nextDynamicId), hasMoreData: \(state.hasMoreData)")
return .none
case let .momentsResponse(.failure(error)):
state.isLoading = false
state.error = error.localizedDescription
debugErrorSync("❌ FeedFeature: API 请求失败 - \(error.localizedDescription)")
return .none
case .clearError:
@@ -145,30 +134,20 @@ struct FeedFeature {
return .send(.loadMoreMoments)
}
// CreateFeedView Action -
case .showCreateFeed:
state.isShowingCreateFeed = true
// createFeedState
state.createFeedState = CreateFeedFeature.State()
return .none
case .dismissCreateFeed:
state.isShowingCreateFeed = false
state.createFeedState = nil
state.isCreateFeedPresented = true
return .none
case .createFeedCompleted:
state.isShowingCreateFeed = false
state.createFeedState = nil
//
state.isCreateFeedPresented = false
return .send(.loadLatestMoments)
case .createFeed:
// Action reducer
case .createFeedDismissed:
state.isCreateFeedPresented = false
return .none
}
}
// reducer
self.ifLet(\.createFeedState, action: \.createFeed) {
CreateFeedFeature()
}
}
}