// // FloatingTextField.swift // MattermostShare // // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. // import SwiftUI struct ViewHeightKey: PreferenceKey { static var defaultValue: CGFloat { 0 } static func reduce(value: inout Value, nextValue: () -> Value) { value = value + nextValue() } } struct FloatingTextField: View { @EnvironmentObject var shareViewModel: ShareViewModel private let placeholderText: String @Binding var text: String @FocusState private var focusState: Bool @State private var isFocused: Bool = false @State private var textEditorHeight : CGFloat = 104 public init(placeholderText: String, text: Binding) { self._text = text self.placeholderText = placeholderText } var shouldPlaceholderMove: Bool { isFocused || text.count != 0 } var error: Bool { text.count > shareViewModel.server!.maxMessageLength } var focusedColor: Color { if error { return Color.theme.errorTextColor } return isFocused ? Color.theme.linkColor : Color.theme.centerChannelColor.opacity(0.64) } var focusedBorderColor: Color { if error { return Color.theme.errorTextColor } return isFocused ? Color.theme.linkColor : Color.theme.centerChannelColor.opacity(0.16) } func formatLength(_ value: Int64) -> String { let formatter = NumberFormatter() formatter.numberStyle = .decimal formatter.maximumFractionDigits = 0 let number = NSNumber(value: value) return formatter.string(from: number)! } var body: some View { VStack (alignment: .leading) { if (error) { ErrorLabelView( error: "Message must be less than \(formatLength(shareViewModel.server!.maxMessageLength)) characters" ) } ZStack(alignment: .topLeading) { Text(text) .font(Font.custom("OpenSans", size: 16)) .foregroundColor(.clear) .background(GeometryReader { Color.clear.preference(key: ViewHeightKey.self, value: $0.frame(in: .local).size.height + 32) }) TextEditor(text: $text) .focused($focusState) .onChange(of: focusState, perform: {value in withAnimation{ isFocused = value } }) .accentColor(.accentColor) .padding(.horizontal, 10) .font(Font.custom("OpenSans", size: 16)) .foregroundColor(Color.theme.centerChannelColor) .multilineTextAlignment(.leading) .frame(minHeight: 104) .frame(maxHeight: isFocused ? 104 : max(104, textEditorHeight), alignment: .leading) .overlay( RoundedRectangle(cornerRadius: 4) .stroke(focusedBorderColor, lineWidth: isFocused ? 2 : 1) ) Text(placeholderText) .foregroundColor(focusedColor) .font( Font.custom("OpenSans", size: shouldPlaceholderMove ? 10 : 16)) .padding( shouldPlaceholderMove ? EdgeInsets(top: 0, leading: 5, bottom: 0, trailing: 5) : EdgeInsets(top: 8, leading: 15, bottom: 0, trailing: 0) ) .background(Color(UIColor.systemBackground).opacity(shouldPlaceholderMove ? 1.0 : 0)) .offset(x: shouldPlaceholderMove ? 10 : 0, y: shouldPlaceholderMove ? -8 : 0) .animation(.easeInOut(duration: 0.2), value: shouldPlaceholderMove) } .onPreferenceChange(ViewHeightKey.self) { textEditorHeight = $0 } } } }