feat: 首次登录

This commit is contained in:
jinyaqiu 2025-08-29 13:29:17 +08:00
parent 5080b104a4
commit 8044927b51
12 changed files with 86 additions and 57 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

11
wake/Assets/Svg/Tips.svg Normal file
View File

@ -0,0 +1,11 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_7357_2809)">
<path d="M3.33325 12.6668V6.00016C3.33325 3.42283 5.42259 1.3335 7.99992 1.3335C10.5773 1.3335 12.6666 3.42283 12.6666 6.00016V12.6668M1.33325 12.6668H14.6666" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.99992 14.6665C8.92039 14.6665 9.66659 13.9203 9.66659 12.9998V12.6665H6.33325V12.9998C6.33325 13.9203 7.07945 14.6665 7.99992 14.6665Z" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_7357_2809">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 731 B

View File

@ -169,7 +169,7 @@ struct ContentView: View {
LoginView() LoginView()
} }
} }
.padding() .padding(.horizontal)
.padding(.top, 20) .padding(.top, 20)
// //
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {

View File

@ -11,6 +11,7 @@ enum AppRoute: Hashable {
case blindOutcome(media: MediaType) case blindOutcome(media: MediaType)
case memories case memories
case subscribe case subscribe
case userInfo
@ViewBuilder @ViewBuilder
var view: some View { var view: some View {
@ -33,6 +34,8 @@ enum AppRoute: Hashable {
MemoriesView() MemoriesView()
case .subscribe: case .subscribe:
SubscribeView() SubscribeView()
case .userInfo:
UserInfo()
} }
} }
} }

View File

@ -9,6 +9,12 @@ private enum MediaURLs {
static let VideoBlindURL = "https://cdn.memorywake.com/users/7363409620351717377/files/7366658779259211776/AD970D28-9D1E-4817-A245-F11967441B8F.mp4" static let VideoBlindURL = "https://cdn.memorywake.com/users/7363409620351717377/files/7366658779259211776/AD970D28-9D1E-4817-A245-F11967441B8F.mp4"
} }
private enum BlindBoxAnimationPhase {
case loading
case ready
case opening
}
extension Notification.Name { extension Notification.Name {
static let navigateToMediaViewer = Notification.Name("navigateToMediaViewer") static let navigateToMediaViewer = Notification.Name("navigateToMediaViewer")
} }
@ -71,6 +77,7 @@ struct BlindBoxView: View {
let mediaType: BlindBoxMediaType let mediaType: BlindBoxMediaType
@State private var showLottieAnimation = true @State private var showLottieAnimation = true
@State private var showScalingOverlay = false @State private var showScalingOverlay = false
@State private var animationPhase: BlindBoxAnimationPhase = .loading
@State private var scale: CGFloat = 0.1 @State private var scale: CGFloat = 0.1
@State private var videoPlayer: AVPlayer? @State private var videoPlayer: AVPlayer?
@State private var showControls = false @State private var showControls = false
@ -263,20 +270,49 @@ struct BlindBoxView: View {
.opacity(showScalingOverlay ? 0 : 1) .opacity(showScalingOverlay ? 0 : 1)
.animation(.easeOut(duration: 1.5), value: showScalingOverlay) .animation(.easeOut(duration: 1.5), value: showScalingOverlay)
} }
if !showScalingOverlay { if !showScalingOverlay {
VStack(spacing: 20) { VStack(spacing: 20) {
let player = AVPlayer(url: URL(string: MediaURLs.VideoBlindURL)!) switch animationPhase {
VideoPlayer(player: player) case .loading:
.background(TransparentVideoPlayer()) GIFView(name: "BlindLoading")
.frame(width: 300, height: 300)
.onAppear {
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
withAnimation {
animationPhase = .ready
}
}
}
case .ready:
ZStack {
GIFView(name: "BlindReady")
.frame(width: 300, height: 300)
// Add a transparent overlay to capture taps
Color.clear
.contentShape(Rectangle()) // Make the entire area tappable
.frame(width: 300, height: 300)
.onTapGesture {
print("点击了盲盒")
withAnimation {
animationPhase = .opening
}
}
}
.frame(width: 300, height: 300) .frame(width: 300, height: 300)
.onAppear {
player.play() case .opening:
player.isMuted = true GIFView(name: "BlindOpen")
} .frame(width: 300, height: 300)
.onDisappear { .onAppear {
player.pause() self.loadMedia()
} // Start animation after media is loaded
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.startScalingAnimation()
}
}
}
} }
.compositingGroup() .compositingGroup()
.padding() .padding()
@ -298,13 +334,6 @@ struct BlindBoxView: View {
} }
} }
.navigationBarBackButtonHidden(true) .navigationBarBackButtonHidden(true)
.onAppear {
self.loadMedia()
// Start animation after media is loaded
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
self.startScalingAnimation()
}
}
} }
} }

View File

@ -61,11 +61,6 @@ struct LoginView: View {
} }
.navigationBarBackButtonHidden(true) .navigationBarBackButtonHidden(true)
.navigationBarHidden(true) .navigationBarHidden(true)
.fullScreenCover(isPresented: $isLoggedIn) {
NavigationStack {
UserInfo()
}
}
} }
// MARK: - Views // MARK: - Views
@ -264,6 +259,8 @@ struct LoginView: View {
self.errorMessage = "登录信息不完整,请重试" self.errorMessage = "登录信息不完整,请重试"
self.showError = true self.showError = true
} }
// userinfo
Router.shared.navigate(to: .userInfo)
case .failure(let error): case .failure(let error):
print("❌ [15] 后端认证失败") print("❌ [15] 后端认证失败")

View File

@ -61,28 +61,23 @@ struct UserInfo: View {
.background(Color.themeTextWhiteSecondary) .background(Color.themeTextWhiteSecondary)
.zIndex(1) // .zIndex(1) //
// Dynamic text that changes based on keyboard state // Dynamic text that changes based on keyboard state
HStack(spacing: 20) { HStack(spacing: 6) {
SVGImage(svgName: "Tips")
.frame(width: 16, height: 16)
.padding(.leading,6)
Text("Choose a photo as your avatar, and we'll generate a video mystery box for you.") Text("Choose a photo as your avatar, and we'll generate a video mystery box for you.")
.font(Typography.font(for: .caption)) .font(Typography.font(for: .caption))
.foregroundColor(.black) .foregroundColor(.black)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.lineLimit(isKeyboardVisible ? 1 : 2) .padding(3)
.padding(6)
.background(
LinearGradient(
gradient: Gradient(colors: [
Color(red: 1.0, green: 0.97, blue: 0.87),
.white,
Color(red: 1.0, green: 0.97, blue: 0.84)
]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
)
} }
.padding(10)
.animation(.easeInOut(duration: 0.3), value: isKeyboardVisible) .animation(.easeInOut(duration: 0.3), value: isKeyboardVisible)
.transition(.opacity) .transition(.opacity)
.background(
Color.themeTextWhite
.cornerRadius(12)
)
.padding(10)
// //
GeometryReader { geometry in GeometryReader { geometry in
@ -141,7 +136,6 @@ struct UserInfo: View {
// Continue Button // Continue Button
Button(action: { Button(action: {
Router.shared.navigate(to: .blindBox(mediaType: .image))
if showUsername { if showUsername {
let parameters: [String: Any] = [ let parameters: [String: Any] = [
"username": userName, "username": userName,

View File

@ -82,33 +82,28 @@ struct MediaUploadView: View {
.padding(.trailing, 16) .padding(.trailing, 16)
} }
.background(Color.themeTextWhiteSecondary) .background(Color.themeTextWhiteSecondary)
.padding(.horizontal) // .padding(.horizontal)
.zIndex(1) // .zIndex(1) //
} }
/// ///
private var uploadHintView: some View { private var uploadHintView: some View {
HStack { HStack (spacing: 6) {
SVGImage(svgName: "Tips")
.frame(width: 16, height: 16)
.padding(.leading,6)
Text("The upload process will take approximately 2 minutes. Thank you for your patience.") Text("The upload process will take approximately 2 minutes. Thank you for your patience.")
.font(.caption) .font(.caption)
.foregroundColor(.black) .foregroundColor(.black)
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.padding(3) .padding(3)
.background(
LinearGradient(
gradient: Gradient(colors: [
Color(red: 1.0, green: 0.97, blue: 0.87),
.white,
Color(red: 1.0, green: 0.97, blue: 0.84)
]),
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.cornerRadius(8)
)
.padding(.horizontal)
} }
.background(
Color.themeTextWhite
.cornerRadius(6)
)
.padding(.vertical, 8) .padding(.vertical, 8)
.padding(.horizontal)
} }
/// ///

View File

@ -46,10 +46,10 @@ struct WakeApp: App {
// //
if authState.isAuthenticated { if authState.isAuthenticated {
// userInfo // userInfo
LoginView()
.environmentObject(authState)
// ContentView() // ContentView()
// .environmentObject(authState) // .environmentObject(authState)
ContentView()
.environmentObject(authState)
} else { } else {
// //
LoginView() LoginView()