feat: 反馈页面

This commit is contained in:
jinyaqiu 2025-09-01 15:19:25 +08:00
parent 85bd75b03a
commit c5cb87b90b
4 changed files with 96 additions and 58 deletions

View File

@ -645,16 +645,14 @@ struct BlindBoxView: View {
Button(action: { Button(action: {
// BlindOutcomeView // BlindOutcomeView
if mediaType == .video, !videoURL.isEmpty, let url = URL(string: videoURL) { if mediaType == .video, !videoURL.isEmpty, let url = URL(string: videoURL) {
Router.shared.navigate(to: .blindOutcome(media: .video(url, nil))) Router.shared.navigate(to: .blindOutcome(media: .video(url, nil), time: blindGenerate?.videoGenerateTime ?? "hhsdshjsjdhn", description:blindGenerate?.description ?? "informationinformationinformationinformationinformationinformation"))
} else if mediaType == .image, let image = displayImage { } else if mediaType == .image, let image = displayImage {
Router.shared.navigate(to: .blindOutcome(media: .image(image))) Router.shared.navigate(to: .blindOutcome(media: .image(image), time: blindGenerate?.videoGenerateTime ?? "hhsdshjsjdhn", description:blindGenerate?.description ?? "informationinformationinformationinformationinformationinformation"))
} }
}) { }) {
Image(systemName: "chevron.left.circle.fill") Image(systemName: "chevron.left")
.font(.system(size: 36)) .font(.system(size: 24))
.foregroundColor(.black) .foregroundColor(.black)
.padding(12)
.clipShape(Circle())
} }
Spacer() Spacer()
} }

View File

@ -8,13 +8,14 @@ enum AppRoute: Hashable {
case feedbackDetail(type: FeedbackView.FeedbackType) case feedbackDetail(type: FeedbackView.FeedbackType)
case mediaUpload case mediaUpload
case blindBox(mediaType: BlindBoxView.BlindBoxMediaType) case blindBox(mediaType: BlindBoxView.BlindBoxMediaType)
case blindOutcome(media: MediaType) case blindOutcome(media: MediaType, time: String? = nil, description: String? = nil)
case memories case memories
case subscribe case subscribe
case userInfo case userInfo
case account case account
case about case about
case permissionManagement case permissionManagement
case feedback
@ViewBuilder @ViewBuilder
var view: some View { var view: some View {
@ -31,8 +32,8 @@ enum AppRoute: Hashable {
MediaUploadView() MediaUploadView()
case .blindBox(let mediaType): case .blindBox(let mediaType):
BlindBoxView(mediaType: mediaType) BlindBoxView(mediaType: mediaType)
case .blindOutcome(let media): case .blindOutcome(let media, let time, let description):
BlindOutcomeView(media: media) BlindOutcomeView(media: media, time: time, description: description)
case .memories: case .memories:
MemoriesView() MemoriesView()
case .subscribe: case .subscribe:
@ -45,6 +46,8 @@ enum AppRoute: Hashable {
AboutUsView() AboutUsView()
case .permissionManagement: case .permissionManagement:
PermissionManagementView() PermissionManagementView()
case .feedback:
FeedbackView()
} }
} }
} }

View File

@ -5,11 +5,19 @@ import os.log
/// A view that displays either an image or a video with fullscreen support /// A view that displays either an image or a video with fullscreen support
struct BlindOutcomeView: View { struct BlindOutcomeView: View {
let media: MediaType let media: MediaType
let time: String?
let description: String?
@Environment(\.presentationMode) var presentationMode @Environment(\.presentationMode) var presentationMode
@State private var isFullscreen = false @State private var isFullscreen = false
@State private var isPlaying = false @State private var isPlaying = false
@State private var showIPListModal = false @State private var showIPListModal = false
init(media: MediaType, time: String? = nil, description: String? = nil) {
self.media = media
self.time = time
self.description = description
}
var body: some View { var body: some View {
NavigationView { NavigationView {
ZStack { ZStack {
@ -54,12 +62,14 @@ struct BlindOutcomeView: View {
// Media content // Media content
GeometryReader { geometry in GeometryReader { geometry in
VStack(spacing: 16) {
ZStack { ZStack {
// //
RoundedRectangle(cornerRadius: 12) RoundedRectangle(cornerRadius: 12)
.fill(Color.white) .fill(Color.white)
.shadow(color: Color.black.opacity(0.1), radius: 8, x: 0, y: 2) .shadow(color: Color.black.opacity(0.1), radius: 8, x: 0, y: 2)
VStack(spacing: 0) {
switch media { switch media {
case .image(let uiImage): case .image(let uiImage):
Image(uiImage: uiImage) Image(uiImage: uiImage)
@ -67,7 +77,6 @@ struct BlindOutcomeView: View {
.scaledToFit() .scaledToFit()
.cornerRadius(10) .cornerRadius(10)
.padding(4) .padding(4)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.onTapGesture { .onTapGesture {
withAnimation { withAnimation {
isFullscreen.toggle() isFullscreen.toggle()
@ -80,7 +89,6 @@ struct BlindOutcomeView: View {
VideoPlayer(player: player) VideoPlayer(player: player)
.cornerRadius(10) .cornerRadius(10)
.padding(4) .padding(4)
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.onAppear { .onAppear {
player.play() player.play()
isPlaying = true isPlaying = true
@ -90,15 +98,36 @@ struct BlindOutcomeView: View {
isPlaying = false isPlaying = false
} }
} }
VStack(alignment: .leading, spacing: 8) {
if let description = description, !description.isEmpty {
VStack(alignment: .leading, spacing: 2) {
Text("Description")
.font(Typography.font(for: .body, family: .quicksandBold))
.foregroundColor(.themeTextMessageMain)
Text(description)
.font(.system(size: 12))
.foregroundColor(Color.themeTextMessageMain)
.fixedSize(horizontal: false, vertical: true)
}
.padding(.horizontal, 12)
.padding(.bottom, 12)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(.top, 8)
}
} }
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.padding(.bottom, 20) .padding(.bottom, 20)
} }
.frame(height: UIScreen.main.bounds.height / 2)
.padding(.horizontal) .padding(.horizontal)
Spacer() Spacer()
// Button below media // Button at bottom
VStack(spacing: 16) { VStack {
Spacer()
Button(action: { Button(action: {
// video // video
if case .video = media { if case .video = media {
@ -106,7 +135,7 @@ struct BlindOutcomeView: View {
showIPListModal = true showIPListModal = true
} }
} else { } else {
Router.shared.navigate(to: .mediaUpload) Router.shared.navigate(to: .feedbackView)
} }
}) { }) {
Text("Continue") Text("Continue")
@ -117,9 +146,9 @@ struct BlindOutcomeView: View {
.background(Color.themePrimary) .background(Color.themePrimary)
.cornerRadius(26) .cornerRadius(26)
} }
.padding() .padding(.horizontal)
} }
.frame(maxWidth: .infinity, maxHeight: .infinity) .padding(.bottom, 20)
} }
} }
.navigationBarHidden(true) // .navigationBarHidden(true) //
@ -350,12 +379,20 @@ private struct VideoControls: View {
// MARK: - Preview // MARK: - Preview
struct BlindOutcomeView_Previews: PreviewProvider { struct BlindOutcomeView_Previews: PreviewProvider {
static var previews: some View { static var previews: some View {
// Preview with image // Preview with image and details
BlindOutcomeView(media: .image(UIImage(systemName: "photo")!)) BlindOutcomeView(
media: .image(UIImage(systemName: "photo")!),
time: "2:30",
description: "This is a sample description for the preview. It shows how the text will wrap and display below the media content."
)
// Preview with video // Preview with video and details
if let url = URL(string: "https://example.com/sample.mp4") { if let url = URL(string: "https://example.com/sample.mp4") {
BlindOutcomeView(media: .video(url, nil)) BlindOutcomeView(
media: .video(url, nil),
time: "1:45",
description: "Video content with time and description"
)
} }
} }
} }

View File

@ -58,7 +58,6 @@ struct FeedbackView: View {
VStack(spacing: 24) { VStack(spacing: 24) {
Text("How are you feeling?") Text("How are you feeling?")
.font(Typography.font(for: .title2, family: .quicksandBold)) .font(Typography.font(for: .title2, family: .quicksandBold))
.fontWeight(.semibold)
.multilineTextAlignment(.center) .multilineTextAlignment(.center)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.padding(.bottom, 50) .padding(.bottom, 50)
@ -100,7 +99,6 @@ struct FeedbackView: View {
.padding(.vertical, 24) .padding(.vertical, 24)
.background(Color.white) .background(Color.white)
.cornerRadius(16) .cornerRadius(16)
.shadow(color: Color.black.opacity(0.2), radius: 12, x: 0, y: 4)
.padding(.horizontal, 16) .padding(.horizontal, 16)
.frame(minHeight: geometry.size.height - 120) // Subtract navigation bar and bottom button height .frame(minHeight: geometry.size.height - 120) // Subtract navigation bar and bottom button height
@ -109,8 +107,8 @@ struct FeedbackView: View {
} }
.frame(maxWidth: .infinity, minHeight: geometry.size.height - 44) // Subtract navigation bar height .frame(maxWidth: .infinity, minHeight: geometry.size.height - 44) // Subtract navigation bar height
} }
.background(Color.themeTextWhiteSecondary)
} }
.background(Color.themeTextWhiteSecondary) // Add background color to the GeometryReader
// Continue Button // Continue Button
@ -119,18 +117,20 @@ struct FeedbackView: View {
}) { }) {
Text("Continue") Text("Continue")
.font(.headline) .font(.headline)
.foregroundColor(selectedFeedback != nil ? .white : .gray) .foregroundColor(selectedFeedback != nil ? .themeTextMessageMain : .gray)
.frame(maxWidth: .infinity) .frame(maxWidth: .infinity)
.frame(height: 56) .frame(height: 56)
.background( .background(
RoundedRectangle(cornerRadius: 25) RoundedRectangle(cornerRadius: 32)
.fill(selectedFeedback != nil ? .fill(selectedFeedback != nil ?
Color.themePrimary : Color(.systemGray5)) Color.themePrimary : Color.themeTextWhiteSecondary)
) )
} }
.disabled(selectedFeedback == nil) .disabled(selectedFeedback == nil)
.padding() .padding()
.background(Color.themeTextWhiteSecondary) // Add background color to the button area
} }
.background(Color.themeTextWhiteSecondary) // Set the background for the entire view
.navigationBarHidden(true) .navigationBarHidden(true)
} }
} }