|
|
@@ -1,5 +1,6 @@
|
|
|
import SwiftUI
|
|
|
import SwiftData
|
|
|
+import UIKit
|
|
|
|
|
|
// MARK: - ActiveRecordingView
|
|
|
/// The live recording screen showing real-time waveform, elapsed time,
|
|
|
@@ -717,8 +718,6 @@ struct RecordNameEditorSheet: View {
|
|
|
let onSave: () -> Void
|
|
|
let onCancel: () -> Void
|
|
|
|
|
|
- @FocusState private var isRecordNameFocused: Bool
|
|
|
-
|
|
|
var body: some View {
|
|
|
NavigationStack {
|
|
|
ZStack {
|
|
|
@@ -730,20 +729,16 @@ struct RecordNameEditorSheet: View {
|
|
|
.foregroundStyle(Color.secondary)
|
|
|
.tracking(1.4)
|
|
|
|
|
|
- TextField("输入记录名称", text: $recordName)
|
|
|
- .focused($isRecordNameFocused)
|
|
|
- .font(.system(size: 18, weight: .semibold))
|
|
|
- .foregroundStyle(Color.primary)
|
|
|
- .textInputAutocapitalization(.never)
|
|
|
- .autocorrectionDisabled()
|
|
|
- .submitLabel(.done)
|
|
|
+ SuffixSelectingTextField(
|
|
|
+ placeholder: "输入记录名称",
|
|
|
+ text: $recordName,
|
|
|
+ selectedSuffix: "现场记录",
|
|
|
+ onSubmit: onSave
|
|
|
+ )
|
|
|
.padding(.horizontal, 14)
|
|
|
.padding(.vertical, 12)
|
|
|
.background(Color.cardBackground.opacity(0.5))
|
|
|
.businessBorder(cornerRadius: 8)
|
|
|
- .onSubmit {
|
|
|
- onSave()
|
|
|
- }
|
|
|
|
|
|
Spacer()
|
|
|
}
|
|
|
@@ -766,10 +761,84 @@ struct RecordNameEditorSheet: View {
|
|
|
.presentationDetents([.height(190)])
|
|
|
.presentationDragIndicator(.visible)
|
|
|
.presentationBackground(Color.spaceBlack)
|
|
|
- .onAppear {
|
|
|
- DispatchQueue.main.async {
|
|
|
- isRecordNameFocused = true
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+private struct SuffixSelectingTextField: UIViewRepresentable {
|
|
|
+ let placeholder: String
|
|
|
+ @Binding var text: String
|
|
|
+ let selectedSuffix: String
|
|
|
+ let onSubmit: () -> Void
|
|
|
+
|
|
|
+ func makeCoordinator() -> Coordinator {
|
|
|
+ Coordinator(text: $text, selectedSuffix: selectedSuffix, onSubmit: onSubmit)
|
|
|
+ }
|
|
|
+
|
|
|
+ func makeUIView(context: Context) -> UITextField {
|
|
|
+ let textField = UITextField()
|
|
|
+ textField.placeholder = placeholder
|
|
|
+ textField.text = text
|
|
|
+ textField.font = .systemFont(ofSize: 18, weight: .semibold)
|
|
|
+ textField.textColor = .label
|
|
|
+ textField.tintColor = UIColor(Color.accentColor)
|
|
|
+ textField.autocapitalizationType = .none
|
|
|
+ textField.autocorrectionType = .no
|
|
|
+ textField.returnKeyType = .done
|
|
|
+ textField.delegate = context.coordinator
|
|
|
+ textField.addTarget(
|
|
|
+ context.coordinator,
|
|
|
+ action: #selector(Coordinator.textDidChange(_:)),
|
|
|
+ for: .editingChanged
|
|
|
+ )
|
|
|
+
|
|
|
+ DispatchQueue.main.async {
|
|
|
+ textField.becomeFirstResponder()
|
|
|
+ context.coordinator.selectSuffixIfNeeded(in: textField)
|
|
|
+ }
|
|
|
+ return textField
|
|
|
+ }
|
|
|
+
|
|
|
+ func updateUIView(_ textField: UITextField, context: Context) {
|
|
|
+ if textField.text != text {
|
|
|
+ textField.text = text
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ final class Coordinator: NSObject, UITextFieldDelegate {
|
|
|
+ @Binding private var text: String
|
|
|
+ private let selectedSuffix: String
|
|
|
+ private let onSubmit: () -> Void
|
|
|
+ private var hasAppliedInitialSelection = false
|
|
|
+
|
|
|
+ init(text: Binding<String>, selectedSuffix: String, onSubmit: @escaping () -> Void) {
|
|
|
+ _text = text
|
|
|
+ self.selectedSuffix = selectedSuffix
|
|
|
+ self.onSubmit = onSubmit
|
|
|
+ }
|
|
|
+
|
|
|
+ @objc func textDidChange(_ textField: UITextField) {
|
|
|
+ text = textField.text ?? ""
|
|
|
+ }
|
|
|
+
|
|
|
+ func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
|
|
+ onSubmit()
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ func selectSuffixIfNeeded(in textField: UITextField) {
|
|
|
+ guard !hasAppliedInitialSelection else { return }
|
|
|
+ hasAppliedInitialSelection = true
|
|
|
+
|
|
|
+ let fullText = textField.text ?? ""
|
|
|
+ guard fullText.hasSuffix(selectedSuffix),
|
|
|
+ let start = textField.position(
|
|
|
+ from: textField.endOfDocument,
|
|
|
+ offset: -selectedSuffix.utf16.count
|
|
|
+ ),
|
|
|
+ let range = textField.textRange(from: start, to: textField.endOfDocument) else {
|
|
|
+ return
|
|
|
}
|
|
|
+ textField.selectedTextRange = range
|
|
|
}
|
|
|
}
|
|
|
}
|