Compare commits

...

2 Commits

Author SHA1 Message Date
5e7bdb64c5 feat: 订阅状态栏完成 2025-09-11 10:38:26 +08:00
35e7454695 feat: 订阅状态栏初步修改 2025-09-11 10:08:11 +08:00
4 changed files with 112 additions and 143 deletions

BIN
wake/Assets/.DS_Store vendored

Binary file not shown.

View File

@ -159,7 +159,7 @@ struct UserProfileModal: View {
HStack(spacing: 16) { HStack(spacing: 16) {
Image(systemName: "tray.and.arrow.up") Image(systemName: "tray.and.arrow.up")
.font(.system(size: 20, weight: .regular)) .font(.system(size: 20, weight: .regular))
.foregroundColor(.orange) // .foregroundColor(.orange)
Text("Upload Resources") Text("Upload Resources")
.font(Typography.font(for: .body)) .font(Typography.font(for: .body))
@ -181,7 +181,7 @@ struct UserProfileModal: View {
HStack(spacing: 16) { HStack(spacing: 16) {
Image(systemName: "photo.on.rectangle") Image(systemName: "photo.on.rectangle")
.font(.system(size: 20, weight: .regular)) .font(.system(size: 20, weight: .regular))
.foregroundColor(.orange) // .foregroundColor(.orange)
Text("My Memories") Text("My Memories")
.font(Typography.font(for: .body)) .font(Typography.font(for: .body))
@ -226,10 +226,10 @@ struct UserProfileModal: View {
}) { }) {
HStack(spacing: 16) { HStack(spacing: 16) {
Image(systemName: "gearshape") Image(systemName: "gearshape")
.font(.system(size: 20, weight: .regular)) .font(.system(size: 22, weight: .regular))
.foregroundColor(.orange) // .foregroundColor(.orange)
Text("Setting") Text("Settings")
.font(Typography.font(for: .body)) .font(Typography.font(for: .body))
.fontWeight(.bold) .fontWeight(.bold)
.foregroundColor(.themeTextMessageMain) .foregroundColor(.themeTextMessageMain)
@ -284,7 +284,8 @@ struct UserProfileModal: View {
onSubscribeTap: { onSubscribeTap: {
// //
Router.shared.navigate(to: .subscribe) Router.shared.navigate(to: .subscribe)
} },
size: "sm"
) )
.padding(.horizontal, Theme.Spacing.xl) .padding(.horizontal, Theme.Spacing.xl)
} }
@ -313,6 +314,17 @@ struct UserProfileModal: View {
} }
} }
#Preview { #if DEBUG
struct UserProfileModal_Previews: PreviewProvider {
static var previews: some View {
Group {
UserProfileModal(showModal: .constant(true), showSettings: .constant(false), isMember: .constant(true), memberDate: .constant("")) UserProfileModal(showModal: .constant(true), showSettings: .constant(false), isMember: .constant(true), memberDate: .constant(""))
.previewDisplayName("Pioneer")
UserProfileModal(showModal: .constant(true), showSettings: .constant(false), isMember: .constant(false), memberDate: .constant(""))
.previewDisplayName("Free")
}
.previewLayout(.sizeThatFits)
}
} }
#endif

View File

@ -1,111 +0,0 @@
import SwiftUI
struct ModalContentView: View {
let goBack: () -> Void
@Environment(\.dismiss) private var dismissModal
var body: some View {
VStack(spacing: 20) {
//
HStack(alignment: .center, spacing: 16) {
Image(systemName: "person.circle.fill")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(width: 60, height: 60)
.foregroundColor(.blue)
.clipShape(Circle())
VStack(alignment: .leading, spacing: 4) {
Text("用户名")
.font(.headline)
Text("ID: 12345678")
.font(.subheadline)
.foregroundColor(.secondary)
}
Spacer()
}
.padding(.horizontal, 16)
.padding(.top, 16)
//
VStack(alignment: .leading, spacing: 8) {
Text("会员等级").font(.headline)
Text("会员时间").font(.subheadline).foregroundColor(.secondary)
Text("会员中心").font(.subheadline).foregroundColor(.secondary)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(16)
.background(Color(red: 0.92, green: 0.92, blue: 0.92))
.cornerRadius(10)
.padding(.horizontal, 16)
//
VStack(spacing: 12) {
ModalButton(icon: "crown.fill", color: .orange, text: "My Memories")
ModalButton(icon: "clock.fill", color: .blue, text: "My Bind Box")
//
Button(action: {
goBack()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
//
}
}) {
HStack(spacing: 16) {
Image(systemName: "person.circle.fill")
.foregroundColor(.purple)
.frame(width: 24, height: 24)
Text("Setting")
.font(.headline)
.foregroundColor(.primary)
Spacer()
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(10)
}
.buttonStyle(PlainButtonStyle())
}
.padding(.horizontal, 16)
Spacer()
}
.padding(.vertical, 8)
}
}
// MARK: -
struct ModalButton: View {
let icon: String
let color: Color
let text: String
let action: () -> Void
init(icon: String, color: Color, text: String, action: @escaping () -> Void = {}) {
self.icon = icon
self.color = color
self.text = text
self.action = action
}
var body: some View {
Button(action: action) {
HStack(spacing: 16) {
Image(systemName: icon)
.foregroundColor(color)
.frame(width: 24, height: 24)
Text(text)
.font(.headline)
.foregroundColor(.primary)
Spacer()
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(10)
}
.buttonStyle(PlainButtonStyle())
}
}

View File

@ -15,7 +15,7 @@ enum SubscriptionStatus {
var title: String { var title: String {
switch self { switch self {
case .free: case .free:
return "" return "Free"
case .pioneer: case .pioneer:
return "Pioneer" return "Pioneer"
} }
@ -53,18 +53,22 @@ enum SubscriptionStatus {
struct SubscriptionStatusBar: View { struct SubscriptionStatusBar: View {
let status: SubscriptionStatus let status: SubscriptionStatus
let onSubscribeTap: (() -> Void)? let onSubscribeTap: (() -> Void)?
let size: String
private let height: CGFloat private let height: CGFloat
private let backgroundColor: Color?
init(status: SubscriptionStatus, height: CGFloat? = nil, onSubscribeTap: (() -> Void)? = nil) { init(status: SubscriptionStatus, height: CGFloat? = nil, backgroundColor: Color? = nil, onSubscribeTap: (() -> Void)? = nil, size: String? = "md") {
self.status = status self.status = status
self.height = height ?? 155 // 155 self.height = height ?? 155 // 155
self.backgroundColor = backgroundColor
self.onSubscribeTap = onSubscribeTap self.onSubscribeTap = onSubscribeTap
self.size = size ?? "md"
} }
var body: some View { var body: some View {
ZStack(alignment: .leading) { ZStack(alignment: .leading) {
// SwiftUI // SwiftUI
SubscriptionBackground(status: status) SubscriptionBackground(status: status, customBackground: backgroundColor, size: size)
.frame(maxWidth: .infinity, minHeight: 120) .frame(maxWidth: .infinity, minHeight: 120)
.clipped() .clipped()
@ -72,7 +76,7 @@ struct SubscriptionStatusBar: View {
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
// Title - Centered vertically // Title - Centered vertically
Text(status.title) Text(status.title)
.font(.system(size: 28, weight: .bold, design: .rounded)) .font(.system(size: size == "sm" ? 24 : 28, weight: .bold, design: .rounded))
.foregroundColor(status.textColor) .foregroundColor(status.textColor)
.frame(maxHeight: .infinity, alignment: .center) // Center vertically .frame(maxHeight: .infinity, alignment: .center) // Center vertically
.padding(.leading, 12) .padding(.leading, 12)
@ -110,33 +114,95 @@ struct SubscriptionStatusBar: View {
// MARK: - // MARK: -
private struct SubscriptionBackground: View { private struct SubscriptionBackground: View {
let status: SubscriptionStatus let status: SubscriptionStatus
let customBackground: Color?
let size: String
private let parallelogramHeight: CGFloat
private let parallelogramWidth: CGFloat
init(status: SubscriptionStatus, customBackground: Color? = nil, size: String? = "md") {
self.status = status
self.customBackground = customBackground
self.size = size ?? "md"
self.parallelogramHeight = size == "sm" ? 14 : 18
self.parallelogramWidth = size == "sm" ? 12 : 16
}
var body: some View { var body: some View {
ZStack(alignment: .topTrailing) { ZStack {
RoundedRectangle(cornerRadius: 20) //
.fill(background) if let color = customBackground {
RoundedRectangle(cornerRadius: 10)
.fill(color)
.shadow(color: Color.black.opacity(0.06), radius: 10, x: 0, y: 6) .shadow(color: Color.black.opacity(0.06), radius: 10, x: 0, y: 6)
//
if case .pioneer = status {
Circle()
.fill(Color.black.opacity(0.08))
.frame(width: 90, height: 90)
.offset(x: 12, y: -12)
} else { } else {
Circle() RoundedRectangle(cornerRadius: 10)
.fill(Color.black.opacity(0.04)) .fill(defaultBackground)
.frame(width: 70, height: 70) .shadow(color: Color.black.opacity(0.06), radius: 10, x: 0, y: 6)
.offset(x: 12, y: -12)
}
}
.clipShape(RoundedRectangle(cornerRadius: 20))
} }
private var background: some ShapeStyle { //
VStack {
HStack {
ParallelogramRow(
count: 6,
itemSize: CGSize(width: parallelogramWidth, height: parallelogramHeight),
shear: -0.35,
cornerRadius: 2,
color: .black.opacity(0.85),
spacing: 1
)
Spacer()
}
Spacer()
}
.padding(.top, 12)
.padding(.leading, 16)
//
VStack {
Spacer()
HStack {
Spacer()
ParallelogramRow(
count: 3,
itemSize: CGSize(width: parallelogramWidth, height: parallelogramHeight),
shear: -0.35,
cornerRadius: 2,
color: .black.opacity(0.85),
spacing: 1
)
}
}
.padding(.bottom, 14)
.padding(.trailing, 16)
// +
VStack {
HStack {
Spacer()
ZStack {
CircleView(diameter: size == "sm" ? 70 : 100, color: .black)
TriangleView(
width: size == "sm" ? 20 : 24,
height: size == "sm" ? 20 : 24,
direction: .right,
color: Color(white: 0.9),
rotation: .degrees(157)
)
}
.offset(x: size == "sm" ? 8 : 12, y: size == "sm" ? -8 : -12)
}
Spacer()
}
}
.clipShape(RoundedRectangle(cornerRadius: 16))
}
private var defaultBackground: LinearGradient {
switch status { switch status {
case .free: case .free:
return LinearGradient(colors: [Color.white, Color.white.opacity(0.96)], startPoint: .topLeading, endPoint: .bottomTrailing) return LinearGradient(colors: [Color(hex: "FFF8DE")], startPoint: .topLeading, endPoint: .bottomTrailing)
case .pioneer: case .pioneer:
return LinearGradient(colors: [Color.themePrimary.opacity(0.85), Color.orange.opacity(0.6)], startPoint: .topLeading, endPoint: .bottomTrailing) return LinearGradient(colors: [Color.themePrimary.opacity(0.85), Color.orange.opacity(0.6)], startPoint: .topLeading, endPoint: .bottomTrailing)
} }
@ -149,6 +215,7 @@ private struct SubscriptionBackground: View {
// Free status preview // Free status preview
SubscriptionStatusBar( SubscriptionStatusBar(
status: .free, status: .free,
backgroundColor: Color(white: 0.98),
onSubscribeTap: { onSubscribeTap: {
print("Subscribe tapped") print("Subscribe tapped")
} }
@ -159,7 +226,8 @@ private struct SubscriptionBackground: View {
SubscriptionStatusBar( SubscriptionStatusBar(
status: .pioneer( status: .pioneer(
expiryDate: Calendar.current.date(byAdding: .month, value: 6, to: Date()) ?? Date() expiryDate: Calendar.current.date(byAdding: .month, value: 6, to: Date()) ?? Date()
) ),
backgroundColor: Color.orange.opacity(0.9)
) )
.padding(.horizontal) .padding(.horizontal)
} }