feat: 添加COSManagerAdapter以支持新的TCCos组件

- 新增COSManagerAdapter类,保持与现有COSManager相同的接口,内部使用新的TCCos组件。
- 实现获取、刷新Token及上传图片的功能,确保与腾讯云COS的兼容性。
- 在CreateFeedView中重构内容输入、图片选择和发布按钮逻辑,提升用户体验。
- 更新EditFeedView以优化视图结构和状态管理,确保功能正常运行。
- 在多个视图中添加键盘状态管理,改善用户交互体验。
This commit is contained in:
edwinQQQ
2025-07-31 11:41:38 +08:00
parent 3d00e459e3
commit beda539e00
5 changed files with 209 additions and 456 deletions

View File

@@ -13,70 +13,68 @@ struct EditFeedView: View {
}
var body: some View {
WithPerceptionTracking {
GeometryReader { geometry in
ZStack {
backgroundView
mainContent(geometry: geometry)
if store.isUploadingImages {
uploadingImagesOverlay(progress: store.imageUploadProgress)
} else if store.isLoading {
loadingOverlay
}
}
.contentShape(Rectangle())
.onTapGesture {
if isKeyboardVisible {
hideKeyboard()
}
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { _ in
withAnimation(.easeInOut(duration: 0.3)) {
isKeyboardVisible = true
}
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
withAnimation(.easeInOut(duration: 0.3)) {
isKeyboardVisible = false
}
GeometryReader { geometry in
ZStack {
backgroundView
mainContent(geometry: geometry)
if store.isUploadingImages {
uploadingImagesOverlay(progress: store.imageUploadProgress)
} else if store.isLoading {
loadingOverlay
}
}
.navigationBarHidden(true)
.onAppear {
store.send(.clearError)
}
.onChange(of: store.shouldDismiss) {
if store.shouldDismiss {
onDismiss()
.contentShape(Rectangle())
.onTapGesture {
if isKeyboardVisible {
hideKeyboard()
}
}
.photosPicker(
isPresented: Binding(
get: { store.showPhotosPicker },
set: { _ in store.send(.photosPickerDismissed) }
),
selection: Binding(
get: { store.selectedPhotoItems },
set: { store.send(.photosPickerItemsChanged($0)) }
),
maxSelectionCount: 9,
matching: .images
)
.alert("删除图片", isPresented: Binding(
get: { store.showDeleteImageAlert },
set: { _ in store.send(.deleteImageAlertDismissed) }
)) {
Button("删除", role: .destructive) {
if let indexToDelete = store.imageToDeleteIndex {
store.send(.removeImage(indexToDelete))
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { _ in
withAnimation(.easeInOut(duration: 0.3)) {
isKeyboardVisible = true
}
Button("取消", role: .cancel) {
store.send(.deleteImageAlertDismissed)
}
} message: {
Text("确定要删除这张图片吗?")
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
withAnimation(.easeInOut(duration: 0.3)) {
isKeyboardVisible = false
}
}
}
.navigationBarHidden(true)
.onAppear {
store.send(.clearError)
}
.onChange(of: store.shouldDismiss) {
if store.shouldDismiss {
onDismiss()
}
}
.photosPicker(
isPresented: Binding(
get: { store.showPhotosPicker },
set: { _ in store.send(.photosPickerDismissed) }
),
selection: Binding(
get: { store.selectedPhotoItems },
set: { store.send(.photosPickerItemsChanged($0)) }
),
maxSelectionCount: 9,
matching: .images
)
.alert("删除图片", isPresented: Binding(
get: { store.showDeleteImageAlert },
set: { _ in store.send(.deleteImageAlertDismissed) }
)) {
Button("删除", role: .destructive) {
if let indexToDelete = store.imageToDeleteIndex {
store.send(.removeImage(indexToDelete))
}
}
Button("取消", role: .cancel) {
store.send(.deleteImageAlertDismissed)
}
} message: {
Text("确定要删除这张图片吗?")
}
}
@@ -86,127 +84,117 @@ struct EditFeedView: View {
}
private func mainContent(geometry: GeometryProxy) -> some View {
WithPerceptionTracking {
VStack(spacing: 0) {
topNavigationBar
ScrollView {
VStack(spacing: 20) {
textInputSection
imageSelectionSection
publishButton
}
.padding(.horizontal, 20)
.padding(.bottom, 40)
VStack(spacing: 0) {
topNavigationBar
ScrollView {
VStack(spacing: 20) {
textInputSection
imageSelectionSection
publishButton
}
.padding(.horizontal, 20)
.padding(.bottom, 40)
}
}
}
private var topNavigationBar: some View {
WithPerceptionTracking {
HStack {
Button(action: {
store.send(.clearDismissFlag)
onDismiss()
}) {
Image(systemName: "xmark")
.font(.system(size: 20, weight: .medium))
.foregroundColor(.white)
.frame(width: 44, height: 44)
}
Spacer()
Text("编辑动态")
.font(.system(size: 18, weight: .medium))
HStack {
Button(action: {
store.send(.clearDismissFlag)
onDismiss()
}) {
Image(systemName: "xmark")
.font(.system(size: 20, weight: .medium))
.foregroundColor(.white)
Spacer()
Color.clear
.frame(width: 44, height: 44)
}
.padding(.horizontal, 16)
.padding(.top, 8)
.padding(.bottom, 16)
Spacer()
Text("编辑动态")
.font(.system(size: 18, weight: .medium))
.foregroundColor(.white)
Spacer()
Color.clear
.frame(width: 44, height: 44)
}
.padding(.horizontal, 16)
.padding(.top, 8)
.padding(.bottom, 16)
}
private var textInputSection: some View {
WithPerceptionTracking {
VStack(alignment: .leading, spacing: 12) {
Text("分享你的想法...")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
TextEditor(text: Binding(
get: { store.content },
set: { store.send(.contentChanged($0)) }
))
.font(.system(size: 16))
VStack(alignment: .leading, spacing: 12) {
Text("分享你的想法...")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
.background(Color.clear)
.frame(minHeight: 120)
.padding(12)
.background(Color.white.opacity(0.1))
.cornerRadius(12)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(Color.white.opacity(0.2), lineWidth: 1)
)
HStack {
Spacer()
Text("\(store.content.count)/\(maxCount)")
.font(.system(size: 12))
.foregroundColor(.white.opacity(0.6))
}
TextEditor(text: Binding(
get: { store.content },
set: { store.send(.contentChanged($0)) }
))
.font(.system(size: 16))
.foregroundColor(.white)
.background(Color.clear)
.frame(minHeight: 120)
.padding(12)
.background(Color.white.opacity(0.1))
.cornerRadius(12)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(Color.white.opacity(0.2), lineWidth: 1)
)
HStack {
Spacer()
Text("\(store.content.count)/\(maxCount)")
.font(.system(size: 12))
.foregroundColor(.white.opacity(0.6))
}
}
}
private var imageSelectionSection: some View {
WithPerceptionTracking {
VStack(alignment: .leading, spacing: 12) {
Text("添加图片")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
ImageGrid(
images: store.processedImages,
onRemoveImage: { index in
store.send(.showDeleteImageAlert(index))
},
onAddImage: {
store.send(.addImageButtonTapped)
}
)
}
VStack(alignment: .leading, spacing: 12) {
Text("添加图片")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
ImageGrid(
images: store.processedImages,
onRemoveImage: { index in
store.send(.showDeleteImageAlert(index))
},
onAddImage: {
store.send(.addImageButtonTapped)
}
)
}
}
private var publishButton: some View {
WithPerceptionTracking {
Button(action: {
store.send(.publishButtonTapped)
}) {
if store.isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: .white))
.scaleEffect(1.2)
} else {
Text("发布")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
}
Button(action: {
store.send(.publishButtonTapped)
}) {
if store.isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: .white))
.scaleEffect(1.2)
} else {
Text("发布")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 16)
.background(store.content.isEmpty ? Color.gray : Color.blue)
.cornerRadius(12)
.disabled(store.isLoading || store.content.isEmpty)
}
.frame(maxWidth: .infinity)
.padding(.vertical, 16)
.background(store.content.isEmpty ? Color.gray : Color.blue)
.cornerRadius(12)
.disabled(store.isLoading || store.content.isEmpty)
}
private func uploadingImagesOverlay(progress: Double) -> some View {