Skip to content

Instantly share code, notes, and snippets.

@wangcheng
Created October 29, 2025 05:51
Show Gist options
  • Save wangcheng/ac4f53ded30bae1a4941cd3fe8045566 to your computer and use it in GitHub Desktop.
Save wangcheng/ac4f53ded30bae1a4941cd3fe8045566 to your computer and use it in GitHub Desktop.

Revisions

  1. wangcheng created this gist Oct 29, 2025.
    120 changes: 120 additions & 0 deletions RecordingView.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,120 @@
    //
    // 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()
    }
    }