mattermost-mobile/ios/MattermostShare/Views/ContentViews/FloatingTextField.swift
Elias Nahum 3a3123674a
[Gekidou] iOS Share extension (#6432)
* iOS Share extension

* Add Fastlane steps for iOS Share Extension

* new multi file layout

* Add recent label

* Refactor code & identation

* ux feedback

* downsample images

* remove options horizontal padding
2022-07-27 10:31:45 -04:00

111 lines
3.5 KiB
Swift

//
// 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<String>) {
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 }
}
}
}