feat: initial release v0.1.0
- Custom Keyboard Extension with push-to-talk UI - iOS 26 SpeechAnalyzer + DictationTranscriber (iOS 18 SF fallback) - OpenAI-compatible LLM client (4 built-in providers + custom) - 3-page onboarding flow + provider config UI - App Group shared storage for cross-process config - 8s LLM timeout with raw-transcript fallback - App Store privacy manifests for both targets - SwiftLint + XcodeGen + GitHub Actions CI - Unit tests (4/4 passing)
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
// WaveformView.swift
|
||||
// OSGKeyboard · Keyboard Extension
|
||||
//
|
||||
// Simple animated waveform that responds to a 0-1 audio level.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
public struct WaveformView: View {
|
||||
public let level: Double // 0...1
|
||||
public let barCount: Int
|
||||
public let color: Color
|
||||
|
||||
public init(level: Double, barCount: Int = 5, color: Color = .red) {
|
||||
self.level = max(0, min(1, level))
|
||||
self.barCount = barCount
|
||||
self.color = color
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
HStack(spacing: 4) {
|
||||
ForEach(0..<barCount, id: \.self) { i in
|
||||
Capsule()
|
||||
.fill(color)
|
||||
.frame(width: 3, height: heightFor(index: i))
|
||||
.animation(.easeInOut(duration: 0.18), value: level)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func heightFor(index: Int) -> CGFloat {
|
||||
// Center bars taller; outer shorter — symmetric pattern
|
||||
let center = Double(barCount - 1) / 2.0
|
||||
let distance = abs(Double(index) - center) / max(center, 1)
|
||||
let base = max(6, 28 * level)
|
||||
return CGFloat(base * (1.0 - distance * 0.4))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user