From 5ca76c4e5ba19cccf0b4cb0d59fcac0cc18a84ce Mon Sep 17 00:00:00 2001 From: Junhui Chen Date: Wed, 10 Sep 2025 19:25:33 +0800 Subject: [PATCH] chore --- wake/Features/BlindBox/Components/Card.swift | 90 ++++++++++-------- .../Features/BlindBox/View/BlindBoxView.swift | 52 +++++++++- wake/Media.xcassets/IP.imageset/Contents.json | 21 ++++ wake/Media.xcassets/IP.imageset/IP.png | Bin 0 -> 15932 bytes .../Media.xcassets/IP1.imageset/Contents.json | 21 ++++ wake/Media.xcassets/IP1.imageset/IP1.png | Bin 0 -> 15932 bytes wake/View/Owner/AboutUsView.swift | 28 +++++- wake/View/Owner/UserInfo/AvatarPicker.swift | 49 ++++++---- wake/View/Subscribe/JoinModal.swift | 70 +++++++++----- 9 files changed, 238 insertions(+), 93 deletions(-) create mode 100644 wake/Media.xcassets/IP.imageset/Contents.json create mode 100644 wake/Media.xcassets/IP.imageset/IP.png create mode 100644 wake/Media.xcassets/IP1.imageset/Contents.json create mode 100644 wake/Media.xcassets/IP1.imageset/IP1.png diff --git a/wake/Features/BlindBox/Components/Card.swift b/wake/Features/BlindBox/Components/Card.swift index f5f8e41..f057b6f 100644 --- a/wake/Features/BlindBox/Components/Card.swift +++ b/wake/Features/BlindBox/Components/Card.swift @@ -19,6 +19,52 @@ struct CustomLightSequenceAnimation: View { self.squareSize = screenWidth * 1.8 // 正方形背景尺寸 self.imageSize = squareSize / 3 // 光束卡片尺寸(1/3背景大小) } + +// MARK: - SwiftUI 背景重绘(方形版本) +private struct CardBlindBackground: View { + var body: some View { + GeometryReader { geo in + let w = geo.size.width + let h = geo.size.height + ZStack { + // 主背景卡片(方形) + RoundedRectangle(cornerRadius: 28) + .fill( + LinearGradient( + colors: [Color.white, Color.white.opacity(0.96)], + startPoint: .topLeading, + endPoint: .bottomTrailing + ) + ) + .shadow(color: Color.black.opacity(0.06), radius: 16, x: 0, y: 8) + .frame(width: w * 0.88, height: h * 0.88) + .position(x: w / 2, y: h / 2) + + // 左上光斑 + Circle() + .fill(Color.themePrimary.opacity(0.18)) + .blur(radius: 40) + .frame(width: min(w, h) * 0.35, height: min(w, h) * 0.35) + .position(x: w * 0.25, y: h * 0.25) + + // 右下光斑 + Circle() + .fill(Color.orange.opacity(0.14)) + .blur(radius: 50) + .frame(width: min(w, h) * 0.40, height: min(w, h) * 0.40) + .position(x: w * 0.75, y: h * 0.75) + + // 中央高光描边 + RoundedRectangle(cornerRadius: 28) + .stroke(Color.white.opacity(0.35), lineWidth: 1) + .frame(width: w * 0.88, height: h * 0.88) + .position(x: w / 2, y: h / 2) + .blendMode(.overlay) + .opacity(0.7) + } + } + } +} // 卡片中心位置(固定,确保摆正居中) private var centerPosition: CGPoint { @@ -27,53 +73,13 @@ struct CustomLightSequenceAnimation: View { var body: some View { ZStack { - // 底部背景(正方形) - SVGImage(svgName: "BlindBg") + // 底部背景(正方形,SwiftUI 重绘) + CardBlindBackground() .frame(width: squareSize, height: squareSize) .position(centerPosition) - - // 当前显示的光束卡片(摆正状态) - SVGImage(svgName: "Light\(currentLight)") - .frame(width: imageSize, height: imageSize) - .position(centerPosition) - .opacity(currentOpacity) - - // 下一张待显示的光束卡片(提前加载,摆正状态) - SVGImage(svgName: "Light\(nextLight)") - .frame(width: imageSize, height: imageSize) - .position(centerPosition) - .opacity(nextOpacity) - } - .onAppear { - startLoopAnimation() } } - // 计算下一张卡片序号(基于当前索引循环) - private var nextLight: Int { - let nextIdx = (sequenceIndex + 1) % baseSequence.count - return baseSequence[nextIdx] - } - - // 启动循环切换动画 - private func startLoopAnimation() { - // 每1.2秒切换一次(可调整速度) - Timer.scheduledTimer(withTimeInterval: 1.2, repeats: true) { _ in - // 0.5秒淡入淡出过渡(丝滑无卡顿) - withAnimation(Animation.easeInOut(duration: 0.5)) { - currentOpacity = 0.0 - nextOpacity = 1.0 - } - - // 动画完成后更新状态(确保顺序无偏差) - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - currentLight = nextLight - sequenceIndex = (sequenceIndex + 1) % baseSequence.count - currentOpacity = 1.0 - nextOpacity = 0.0 - } - } - } } // 预览 diff --git a/wake/Features/BlindBox/View/BlindBoxView.swift b/wake/Features/BlindBox/View/BlindBoxView.swift index b79b3b3..019a545 100644 --- a/wake/Features/BlindBox/View/BlindBoxView.swift +++ b/wake/Features/BlindBox/View/BlindBoxView.swift @@ -384,11 +384,9 @@ struct BlindBoxView: View { // 盲盒 ZStack { - // 1. 背景SVG + // 1. 背景(SwiftUI 重绘) if !showScalingOverlay { - SVGImage(svgName: "BlindBg", contentMode: .fit) - // .position(x: UIScreen.main.bounds.width / 2, - // y: UIScreen.main.bounds.height * 0.325) + BlindBackground() .opacity(showScalingOverlay ? 0 : 1) .animation(.easeOut(duration: 1.5), value: showScalingOverlay) } @@ -665,6 +663,52 @@ struct BlindBoxView: View { ) } } + + // MARK: - 盲盒背景(SwiftUI 重绘) + private struct BlindBackground: View { + var body: some View { + GeometryReader { geo in + let w = geo.size.width + let h = geo.size.height + ZStack { + // 主背景卡片 + RoundedRectangle(cornerRadius: 28) + .fill( + LinearGradient( + colors: [Color.white, Color.white.opacity(0.96)], + startPoint: .topLeading, + endPoint: .bottomTrailing + ) + ) + .shadow(color: Color.black.opacity(0.06), radius: 16, x: 0, y: 8) + .frame(width: min(w * 0.9, 360), height: min(h * 0.6, 260)) + .position(x: w / 2, y: h * 0.35) + + // 左上光斑 + Circle() + .fill(Color.themePrimary.opacity(0.18)) + .blur(radius: 40) + .frame(width: 160, height: 160) + .position(x: w * 0.22, y: h * 0.18) + + // 右下光斑 + Circle() + .fill(Color.orange.opacity(0.14)) + .blur(radius: 50) + .frame(width: 180, height: 180) + .position(x: w * 0.78, y: h * 0.55) + + // 中央高光 + RoundedRectangle(cornerRadius: 28) + .stroke(Color.white.opacity(0.35), lineWidth: 1) + .frame(width: min(w * 0.9, 360), height: min(h * 0.6, 260)) + .position(x: w / 2, y: h * 0.35) + .blendMode(.overlay) + .opacity(0.7) + } + } + } + } /// 隐藏设置页面 private func hideSettings() { diff --git a/wake/Media.xcassets/IP.imageset/Contents.json b/wake/Media.xcassets/IP.imageset/Contents.json new file mode 100644 index 0000000..5f2f361 --- /dev/null +++ b/wake/Media.xcassets/IP.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "filename" : "IP.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/wake/Media.xcassets/IP.imageset/IP.png b/wake/Media.xcassets/IP.imageset/IP.png new file mode 100644 index 0000000000000000000000000000000000000000..0c6ffe6ad1287bf3a8c2a993c729d5dbe90b54bd GIT binary patch literal 15932 zcmV-CKEuI@P)@~0drDELIAGL9O(c600d`2O+f$vv5yPDzsO49=%Y zB1p{dxqbTd_xuvTFbq=y^1=7#V1IuBrs8uDM;D;gZUTro5TO3V|3ovpb!3+=T6 zdaWKc*1^xTuL4}#%D6rf-~H=aWD>A}Wf;a8dH-#c1Fk{{WV#I^dIqwsjOv*ks!^2> zUSEK;c>xa716bJqmon13*uXLj<3teSibfS+6QahJxcSq4ATly*L8fa(r+2Xi%P^&_BRO_Ohfj24GxEhO;V*R^3CcOGx2&!Aw~z%mR&BRyPF+UOkQ0=-sP7q`|nz>#iB zn6M14&Cfi6f?)&8FboY5b^ICjC!5()4za{U<1oA3<(|apKY#Yfhr4>k;|*OipU{r0gda--7>4b z*uXLjLq;1*k-QHh^GZ#o0N&2kxN6dK7wNJ<`NkFDN-l`-oUumFV@;Cm+2GO`pv_tZx#&0oTRd)vN~Hp&b{M2sj^d5 zQb9E-LdFih>JZZ874bk(6P*%2+s*>OD#S{9(rGEzoXet7L7Fbq>GDrsPK z-$#HIm@tgw(QxxdMI+2;WQJjaQ8@!^T9b*%G$uy!aPzE%T$De4B}XTDhGB}PdLv^F z&s>E>RPuPA2c^4WKg)dY>p#6V1;D{BX0qr@Q^c4{EY9f)P0R**arjL9=;w|T6w0Sk z23AW0BBHb<8;+0%P!X~Uw26~E7{&!1z)oLYQa>&!qq+#P-Bj!T=mu?>{U89Qr*Qr3 z>P}hbU#yGo{zIw#U8z*Yz#4thqcjkU7f=DR_vK}VeA&%|872>UEga6TfRtCPM{R4= ziB`m~!RKdQQzyY%RccnpgPlNWAj{)@2Yi4n*_g3p#T(z!o{?#37tH%HjfcK52YYc7 zX0~_4O_py4p+Bd?OK*Tot{97xEB*ee@@TKX{PVkY@MbGvVC92r%lgBgG;nsi@U&?} zaYa0GG%BxV-p8-@t7KHP&MlP`)3<&*-p}l!{Ny`c7Nz|7%?t2VqMj?Oz?;T@Tv8I( z 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 z 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 UIImage? { + // 获取主 AppIcon 名称列表中最后一个(通常是最大尺寸) + if let iconsDictionary = Bundle.main.infoDictionary?["CFBundleIcons"] as? [String: Any], + let primaryIconsDictionary = iconsDictionary["CFBundlePrimaryIcon"] as? [String: Any], + let iconFiles = primaryIconsDictionary["CFBundleIconFiles"] as? [String], + let lastIcon = iconFiles.last, + let image = UIImage(named: lastIcon) { + return image + } + return nil + } + private func getIPAddress() -> String? { var address: String? var ifaddr: UnsafeMutablePointer? diff --git a/wake/View/Owner/UserInfo/AvatarPicker.swift b/wake/View/Owner/UserInfo/AvatarPicker.swift index 08d94de..ccfa25a 100644 --- a/wake/View/Owner/UserInfo/AvatarPicker.swift +++ b/wake/View/Owner/UserInfo/AvatarPicker.swift @@ -59,28 +59,35 @@ public struct AvatarPicker: View { ) .scaleEffect(scaleFactor) } else { - // Default SVG avatar with animated dashed border - SVGImageHtml(svgName: "IP") - .frame(width: 225, height: 225) - .scaleEffect(scaleFactor) - .contentShape(Rectangle()) - .clipShape(RoundedRectangle(cornerRadius: 20 * scaleFactor)) - .overlay( - RoundedRectangle(cornerRadius: 20) - .stroke(style: StrokeStyle( - lineWidth: borderWidth, - lineCap: .round, - dash: [12, 8], - dashPhase: isAnimating ? 40 : 0 - )) - .foregroundColor(Color.themePrimary) - .scaleEffect(scaleFactor) - ) - .onAppear { - withAnimation(Animation.linear(duration: 1.5).repeatForever(autoreverses: false)) { - isAnimating = true - } + // SwiftUI 占位:白底 + 虚线边框 + 居中加号(带虚线动画) + ZStack { + RoundedRectangle(cornerRadius: 20) + .fill(Color.white) + .frame(width: 225, height: 225) + + Image(systemName: "plus") + .font(.system(size: 32, weight: .bold)) + .foregroundColor(.black) + } + .scaleEffect(scaleFactor) + .contentShape(Rectangle()) + .clipShape(RoundedRectangle(cornerRadius: 20 * scaleFactor)) + .overlay( + RoundedRectangle(cornerRadius: 20) + .stroke(style: StrokeStyle( + lineWidth: borderWidth, + lineCap: .round, + dash: [12, 8], + dashPhase: isAnimating ? 40 : 0 + )) + .foregroundColor(Color.themePrimary) + .scaleEffect(scaleFactor) + ) + .onAppear { + withAnimation(Animation.linear(duration: 1.5).repeatForever(autoreverses: false)) { + isAnimating = true } + } } // Upload indicator diff --git a/wake/View/Subscribe/JoinModal.swift b/wake/View/Subscribe/JoinModal.swift index 2a21e5c..9201191 100644 --- a/wake/View/Subscribe/JoinModal.swift +++ b/wake/View/Subscribe/JoinModal.swift @@ -19,16 +19,7 @@ struct JoinModal: View { // Modal content if isPresented { VStack(spacing: 0) { - // IP Image peeking from top - HStack { - // Make sure you have an image named "IP" in your assets - SVGImageHtml(svgName: "IP1") - .frame(width: 116, height: 65) - .offset(x: 30) - Spacer() - } - .frame(height: 65) - + // 顶部装饰图已移除(按需求) VStack(spacing: 0) { // Close button on the right HStack { @@ -57,9 +48,9 @@ struct JoinModal: View { } .padding(.vertical, 12) // List content - VStack (alignment: .leading) { + VStack (alignment: .leading) { HStack { - SVGImage(svgName: "JoinList") + JoinListMark() .frame(width: 32, height: 32) HStack (alignment: .top){ Text("Unlimited") @@ -73,7 +64,7 @@ struct JoinModal: View { .padding(.vertical, 12) .padding(.leading,12) HStack (alignment: .center) { - SVGImage(svgName: "JoinList") + JoinListMark() .frame(width: 32, height: 32) VStack (alignment: .leading,spacing: 4) { HStack { @@ -91,9 +82,9 @@ struct JoinModal: View { } .padding(.vertical, 12) .padding(.leading,12) - + HStack(alignment: .top) { - SVGImage(svgName: "JoinList") + JoinListMark() .frame(width: 32, height: 32) VStack (alignment: .leading,spacing: 4) { HStack { @@ -123,7 +114,7 @@ struct JoinModal: View { } .padding(.top, 12) .padding(.leading,12) - HStack { + HStack { Spacer() // This will push the button to the right Button(action: { // 点击跳转到会员页面 @@ -164,7 +155,7 @@ struct JoinModal: View { HStack(alignment: .center) { Button(action: { // Action for Terms of Service - if let url = URL(string: "https://memorywake.com/privacy-policy") { + if let url = URL(string: "https://memorywake.com/privacy-policy") { UIApplication.shared.open(url) } }) { @@ -173,11 +164,11 @@ struct JoinModal: View { .foregroundColor(.themeTextMessage) .underline() // Add underline } - Rectangle() + Rectangle() .fill(Color.gray.opacity(0.5)) .frame(width: 1, height: 16) .padding(.vertical, 4) - Button(action: { + Button(action: { // 打开网页 if let url = URL(string: "https://memorywake.com/privacy-policy") { UIApplication.shared.open(url) @@ -188,13 +179,13 @@ struct JoinModal: View { .foregroundColor(.themeTextMessage) .underline() // Add underline } - Rectangle() + Rectangle() .fill(Color.gray.opacity(0.5)) .frame(width: 1, height: 16) .padding(.vertical, 4) - Button(action: { + Button(action: { // Action for Restore Purchase - if let url = URL(string: "https://memorywake.com/privacy-policy") { + if let url = URL(string: "https://memorywake.com/privacy-policy") { UIApplication.shared.open(url) } }) { @@ -206,8 +197,8 @@ struct JoinModal: View { } .padding(.bottom, 24) .frame(maxWidth: .infinity, alignment: .center) - } - .padding(.horizontal, 16) + } + .padding(.horizontal, 16) } .background(Color.white) .cornerRadius(20, corners: [.topLeft, .topRight]) @@ -222,6 +213,37 @@ struct JoinModal: View { } } +// MARK: - SwiftUI JoinList 图标重绘 +private struct JoinListMark: View { + var body: some View { + ZStack { + // 背景圆 + Circle() + .fill( + LinearGradient(colors: [Color.themePrimary.opacity(0.9), Color.orange.opacity(0.8)], + startPoint: .topLeading, + endPoint: .bottomTrailing) + ) + .shadow(color: Color.black.opacity(0.12), radius: 4, x: 0, y: 2) + + // 右指三角(白色) + GeometryReader { geo in + Path { path in + let w = geo.size.width + let h = geo.size.height + path.move(to: CGPoint(x: w*0.42, y: h*0.30)) + path.addLine(to: CGPoint(x: w*0.70, y: h*0.50)) + path.addLine(to: CGPoint(x: w*0.42, y: h*0.70)) + path.closeSubpath() + } + .fill(Color.white) + .opacity(0.95) + } + .padding(8) + } + } +} + struct JoinModal_Previews: PreviewProvider { static var previews: some View { JoinModal(isPresented: .constant(true))