* 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
111 lines
3.5 KiB
Swift
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 }
|
|
}
|
|
}
|
|
}
|