Created
October 29, 2025 05:51
-
-
Save wangcheng/ac4f53ded30bae1a4941cd3fe8045566 to your computer and use it in GitHub Desktop.
RecordingView.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // RecordingView.swift | |
| // voicekeyboard | |
| // | |
| // Informational view shown when app is launched via voicekeyboard://record | |
| // Pure UI component - business logic handled in voicekeyboardApp.handleRecognitionRequest | |
| // | |
| import SwiftUI | |
| struct RecordingView: View { | |
| @State private var animationOffset: CGFloat = -50 | |
| @State private var animationOpacity: Double = 0 | |
| private var bottomInset: CGFloat { | |
| if let keyWindow = UIApplication.shared.keyWindow { | |
| return keyWindow.safeAreaInsets.bottom | |
| } else { | |
| return 0 | |
| } | |
| } | |
| // Detect if device has home button (iPhone SE, older models) | |
| private var hasHomeButton: Bool { | |
| return bottomInset == 0 | |
| } | |
| var body: some View { | |
| ZStack { | |
| VStack(spacing: 24) { | |
| Image("AppIcon") | |
| .resizable() | |
| .scaledToFit() | |
| .frame(width: 140, height: 140) | |
| .clipShape(RoundedRectangle(cornerRadius: 44, style: .continuous)) | |
| .overlay( | |
| RoundedRectangle(cornerRadius: 44, style: .continuous) | |
| .stroke(Color.black.opacity(0.1), lineWidth: 0.5) | |
| ) | |
| // Informational Text | |
| Text("Due to system limitations, starting voice input requires opening the app") | |
| .font(.headline) | |
| .multilineTextAlignment(.center) | |
| } | |
| .padding(.horizontal, 30) | |
| if hasHomeButton { | |
| VStack { | |
| // Animated tap indicator for top-left corner | |
| HStack(spacing: 12) { | |
| Image(systemName: "hand.tap.fill") | |
| .font(.system(size: 32)) | |
| .foregroundColor(.accentColor) | |
| .opacity(animationOpacity) | |
| // Instructions for devices with home button (iPhone SE, etc.) | |
| Text("Tap to return to the previous app.") | |
| .font(.subheadline) | |
| .foregroundColor(.secondary) | |
| Spacer() | |
| } | |
| .padding(.horizontal, 12) | |
| .onAppear { // Tap/pulse animation for home button devices | |
| withAnimation( | |
| .easeInOut(duration: 0.8) | |
| .repeatForever(autoreverses: true) | |
| ) { | |
| animationOpacity = 1 | |
| } | |
| } | |
| Spacer() | |
| } | |
| } else { | |
| VStack { | |
| Spacer() | |
| // Instructions for devices with swipe gestures (iPhone X and newer) | |
| Text("Swipe right to return to the previous app.") | |
| .font(.subheadline) | |
| .foregroundColor(.secondary) | |
| .multilineTextAlignment(.center) | |
| // Animated swipe gesture indicator | |
| HStack(spacing: 12) { | |
| Image(systemName: "hand.tap.fill") | |
| .font(.system(size: 32)) | |
| .foregroundColor(.accentColor) | |
| .offset(x: animationOffset) | |
| .opacity(animationOpacity) | |
| Image(systemName: "arrow.right") | |
| .font(.system(size: 16)) | |
| .foregroundColor(.accentColor) | |
| .offset(x: animationOffset) | |
| .opacity(animationOpacity) | |
| } | |
| .onAppear { | |
| // Swipe animation for gesture-based devices | |
| withAnimation( | |
| .easeInOut(duration: 1.5) | |
| .repeatForever(autoreverses: false) | |
| ) { | |
| animationOffset = 50 | |
| animationOpacity = 1 | |
| } | |
| withAnimation( | |
| .easeInOut(duration: 0.75) | |
| .repeatForever(autoreverses: true) | |
| ) { | |
| animationOpacity = 0.3 | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| #Preview { | |
| NavigationView { | |
| RecordingView() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment