Files
e-party-iOS/yana/Views/CreateFeedView.swift
edwinQQQ ba991598be feat: 更新CreateFeed功能及相关视图组件
- 在CreateFeedFeature中新增isPresented依赖,确保在适当的上下文中执行视图关闭操作。
- 在FeedFeature中优化状态管理,简化CreateFeedView的呈现逻辑。
- 新增FeedListFeature和MainFeature,整合FeedListView和底部导航功能,提升用户体验。
- 更新HomeView和SplashView以集成MainView,确保应用结构一致性。
- 在多个视图中调整状态管理和导航逻辑,增强可维护性和用户体验。
2025-07-21 19:10:31 +08:00

240 lines
10 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 SwiftUI
import ComposableArchitecture
import PhotosUI
struct CreateFeedView: View {
let store: StoreOf<CreateFeedFeature>
@State private var keyboardHeight: CGFloat = 0
var body: some View {
NavigationStack {
GeometryReader { geometry in
VStack(spacing: 0) {
//
Color(hex: 0x0C0527)
.ignoresSafeArea()
// ScrollView
VStack(spacing: 20) {
//
VStack(alignment: .leading, spacing: 12) {
//
ZStack(alignment: .topLeading) {
RoundedRectangle(cornerRadius: 12)
.fill(Color.white.opacity(0.1))
.frame(height: 200) // 200
if store.content.isEmpty {
Text("Enter Content")
.foregroundColor(.white.opacity(0.5))
.padding(.horizontal, 16)
.padding(.vertical, 12)
}
TextEditor(text: .init(
get: { store.content },
set: { store.send(.contentChanged($0)) }
))
.foregroundColor(.white)
.background(Color.clear)
.padding(.horizontal, 12)
.padding(.vertical, 8)
.scrollContentBackground(.hidden)
.frame(height: 200) // 200
}
//
HStack {
Spacer()
Text("\(store.characterCount)/500")
.font(.system(size: 12))
.foregroundColor(
store.characterCount > 500 ? .red : .white.opacity(0.6)
)
}
}
.padding(.horizontal, 20)
.padding(.top, 20)
//
VStack(alignment: .leading, spacing: 12) {
if !store.processedImages.isEmpty || store.canAddMoreImages {
ModernImageSelectionGrid(
images: store.processedImages,
selectedItems: store.selectedImages,
canAddMore: store.canAddMoreImages,
onItemsChanged: { items in
store.send(.photosPickerItemsChanged(items))
},
onRemoveImage: { index in
store.send(.removeImage(index))
}
)
}
}
.padding(.horizontal, 20)
//
if store.isLoading {
HStack {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: .white))
Text("处理图片中...")
.font(.system(size: 14))
.foregroundColor(.white.opacity(0.8))
}
.padding(.top, 10)
}
//
if let error = store.errorMessage {
Text(error)
.font(.system(size: 14))
.foregroundColor(.red)
.padding(.horizontal, 20)
.multilineTextAlignment(.center)
}
//
Color.clear.frame(height: max(keyboardHeight, geometry.safeAreaInsets.bottom) + 100)
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.ignoresSafeArea(.keyboard, edges: .bottom)
// -
VStack {
Button(action: {
store.send(.publishButtonTapped)
}) {
HStack {
if store.isLoading {
ProgressView()
.progressViewStyle(CircularProgressViewStyle(tint: .white))
.scaleEffect(0.8)
Text("发布中...")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
} else {
Text("发布")
.font(.system(size: 16, weight: .medium))
.foregroundColor(.white)
}
}
.frame(maxWidth: .infinity)
.frame(height: 50)
.background(
Color(hex: 0x0C0527)
)
.cornerRadius(25)
.disabled(store.isLoading || !store.canPublish)
.opacity(store.isLoading || !store.canPublish ? 0.6 : 1.0)
}
.padding(.horizontal, 20)
.padding(.bottom, max(keyboardHeight, geometry.safeAreaInsets.bottom) + 20)
}
.background(
Color(hex: 0x0C0527)
)
}
}
.navigationTitle("图文发布")
.navigationBarTitleDisplayMode(.inline)
.toolbarBackground(.hidden, for: .navigationBar)
.navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: {
store.send(.dismissView)
}) {
Image(systemName: "xmark")
.font(.system(size: 18, weight: .medium))
.foregroundColor(.white)
}
}
//
}
}
.preferredColorScheme(.dark)
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
keyboardHeight = keyboardFrame.height
}
}
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
keyboardHeight = 0
}
}
}
// MARK: - iOS 16+
struct ModernImageSelectionGrid: View {
let images: [UIImage]
let selectedItems: [PhotosPickerItem]
let canAddMore: Bool
let onItemsChanged: ([PhotosPickerItem]) -> Void
let onRemoveImage: (Int) -> Void
private let columns = Array(repeating: GridItem(.flexible(), spacing: 8), count: 3)
var body: some View {
WithPerceptionTracking {
LazyVGrid(columns: columns, spacing: 8) {
//
ForEach(Array(images.enumerated()), id: \.offset) { index, image in
ZStack(alignment: .topTrailing) {
Image(uiImage: image)
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: 100)
.clipped()
.cornerRadius(8)
//
Button(action: {
onRemoveImage(index)
}) {
Image(systemName: "xmark.circle.fill")
.font(.system(size: 20))
.foregroundColor(.white)
.background(Color.black.opacity(0.6))
.clipShape(Circle())
}
.padding(4)
}
}
//
if canAddMore {
PhotosPicker(
selection: .init(
get: { selectedItems },
set: onItemsChanged
),
maxSelectionCount: 9,
matching: .images
) {
RoundedRectangle(cornerRadius: 8)
.fill(Color.white.opacity(0.1))
.frame(height: 100)
.overlay(
Image(systemName: "plus")
.font(.system(size: 40))
.foregroundColor(.white.opacity(0.6))
)
}
}
}
}
}
}
// MARK: -
//#Preview {
// CreateFeedView(
// store: Store(initialState: CreateFeedFeature.State()) {
// CreateFeedFeature()
// }
// )
//}