Редактор текста SwiftUI #правильная поддержка хэштегов и текстовых заполнителей

#swiftui

Вопрос:

Что я пытаюсь добавить:

  1. Поддержка текста-заполнителя в редакторе текста почти идеальна, за исключением того, что, когда я начинаю нажимать на поле, заполнитель и курсор ввода смещены, поэтому я хочу добиться примерно такого же поведения, как стандартное текстовое поле с заполнителем.
  2. Обнаруживайте и выделяйте хэштеги #внутри текстового редактора с помощью цвета фона и радиуса угла. У меня есть функция для обнаружения #хэштегов и размещения в отдельном представлении под названием textWithHashtags, но мне интересно, можно ли как-то преобразовать и сделать ее полезной для редактора текста?

Пожалуйста, дайте мне знать, если у вас есть решение для этого, я вам очень признателен. Вот код:

 struct ContentView: View {
    @Environment(.presentationMode) var presentationMode
    @State private var messageToSend = ""
    
    var body: some View {
        NavigationView {
            GeometryReader { geometry in
                ZStack {
                    ScrollView(.vertical, showsIndicators: false) {
                        VStack(spacing: geometry.size.height * 0.1) {
                            
                            ZStack(alignment: .leading) {
                                if messageToSend.isEmpty {
                                    Text("Type message here")
                                        .foregroundColor(.gray.opacity(0.7))
                                        .padding([.leading], 8)
                                        .zIndex(1)
                                }
                                
                                TextEditor(text: $messageToSend)
                                    .frame(height: geometry.size.height * 0.20)
                                    .keyboardType(.alphabet)
                                    .font(.system(size: 18))
                                    .foregroundColor(Color.primary.opacity(0.8))
                                    .padding(8)
                            }
                            .background(
                                RoundedRectangle(cornerRadius: 8, style: .continuous)
                                    .stroke(Color.black, lineWidth: 1)
                            )
                            
                            Button {
                                // action
                            } label: {
                                Image(systemName: "paperplane")
                                    .font(.system(size: 20))
                                    .foregroundColor(.white)
                                    .padding()
                                    .frame(width: geometry.size.width * 0.2, height: 45)
                                    .background(
                                        RoundedRectangle(cornerRadius: 8, style: .continuous)
                                            .fill(Color.blue.opacity(1))
                                    )
                            }
                        }
                        .frame(width: geometry.size.width * 0.7, height: geometry.size.height, alignment: .center)
                    }
                    .frame(
                        minWidth: 0,
                        idealWidth: geometry.size.width * 0.8,
                        maxWidth: .infinity,
                        minHeight: 0,
                        idealHeight: geometry.size.height,
                        maxHeight: .infinity,
                        alignment: .center
                    )
                }
                .navigationBarItems(leading: Button("Cancel", action: { presentationMode.wrappedValue.dismiss() }))
                .navigationBarTitle(Text(""))
            }
        }
    }
    
    func textWithHashtags(_ text: String, color: Color) -> Text {
        let words = text.split(separator: " ")
        var output: Text = Text("")

        for word in words {
            if word.hasPrefix("#") { // Pick out hash in words
                output = output   Text(" ")   Text(String(word))
                    .foregroundColor(.blue)

            } else {
                output = output   Text(" ")   Text(String(word))
            }
        }

        return output
    }
}