Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TextView_1048] Fix focus mode #1058

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,9 @@ final class TextEditorBorderUseCaseTests: XCTestCase {

let texteditorBorders = TextEditorBordersUseCase().execute(theme: theme, intent: intent, isFocused: false)

let borderWidth: CGFloat

if intent == .neutral {
borderWidth = theme.border.width.small
} else {
borderWidth = theme.border.width.medium
}


let expectedBorders = TextEditorBorders (
radius: theme.border.radius.large,
width: borderWidth
width: theme.border.width.small
)
XCTAssertEqual(texteditorBorders, expectedBorders, "Wrong border width")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,7 @@ final class TextEditorBordersUseCase: TextEditorBordersUseCasable {
isFocused: Bool) -> TextEditorBorders {

let radious = theme.border.radius.large
let width: CGFloat

if intent == .neutral, !isFocused {
width = theme.border.width.small
} else {
width = theme.border.width.medium
}
let width = isFocused ? theme.border.width.medium : theme.border.width.small

return .init(
radius: radious,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct TextEditorColorsUseCase: TextEditorColorsUseCasable {
let background: any ColorToken

if !isEnabled || isReadonly {
let dim = isReadonly ? theme.dims.none : theme.dims.dim3
let dim = !isEnabled ? theme.dims.dim3 : theme.dims.none
text = theme.colors.base.onSurface.opacity(dim)
border = theme.colors.base.onSurface.opacity(theme.dims.dim3)
background = theme.colors.base.onSurface.opacity(theme.dims.dim5)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

import SwiftUI

enum Field: Hashable {
case text
}

public struct TextEditorView: View {

@ScaledMetric private var minHeight: CGFloat = 44
Expand All @@ -19,10 +23,16 @@ public struct TextEditorView: View {

@Binding private var text: String
private var titleKey: String
@FocusState private var isFocused: Bool
@FocusState private var focusedField: Field?
@Environment(\.isEnabled) private var isEnabled
@State private var textEditorEnabled: Bool = true

private var isPlaceholderTextHidden: Bool {
return !self.titleKey.isEmpty && self.text.isEmpty
}

private var isPlaceholderHidden: Bool {
return !self.titleKey.isEmpty && self.text.isEmpty && !self.viewModel.isFocused
return self.isPlaceholderTextHidden || self.viewModel.isReadOnly
}

public init(
Expand Down Expand Up @@ -66,16 +76,27 @@ public struct TextEditorView: View {
.border(width: self.viewModel.borderWidth * self.scaleFactor, radius: self.viewModel.borderRadius, colorToken: self.viewModel.borderColor)
.tint(self.viewModel.textColor.color)
.allowsHitTesting(self.viewModel.isEnabled)
.focused(self.$isFocused)
.onChange(of: self.isFocused) { value in
self.viewModel.isFocused = value
.focused(self.$focusedField, equals: .text)
.onChange(of: self.focusedField) { focusedField in
self.viewModel.isFocused = focusedField == .text
}
.isEnabledChanged { isEnabled in
.isEnabled(self.isEnabled) { isEnabled in
self.viewModel.isEnabled = isEnabled
}
.onChange(of: self.viewModel.isEnabled) { isEnabled in
if !isEnabled {
self.focusedField = nil
}
self.textEditorEnabled = isEnabled
}
.onChange(of: self.viewModel.isReadOnly) { isReadOnly in
if isReadOnly {
self.focusedField = nil
}
}
.onTapGesture {
if !self.viewModel.isReadOnly {
self.isFocused = true
self.focusedField = .text
}
}
.accessibilityElement()
Expand All @@ -97,21 +118,21 @@ public struct TextEditorView: View {
trailing: self.viewModel.horizontalSpacing - self.defaultTexEditorHorizontalPadding
)
)
.opacity(self.isPlaceholderHidden || self.viewModel.isReadOnly ? 0 : 1)
.opacity(!self.isPlaceholderHidden || self.viewModel.isFocused ? 1 : 0)
.accessibilityHidden(true)

.environment(\.isEnabled, self.textEditorEnabled)
}

@ViewBuilder
private func placeHolderView() -> some View {
ScrollView {
HStack(spacing: 0) {
VStack(spacing: 0) {
Text(self.isPlaceholderHidden && !self.viewModel.isReadOnly ? self.titleKey : self.$text.wrappedValue)
Text(self.isPlaceholderTextHidden ? self.titleKey : self.$text.wrappedValue)
.font(self.viewModel.font.font)
.foregroundStyle(self.viewModel.isReadOnly ? self.viewModel.textColor.color : self.viewModel.placeholderColor.color)
.foregroundStyle(self.isPlaceholderTextHidden ? self.viewModel.placeholderColor.color : self.viewModel.textColor.color)
.frame(maxWidth: .infinity, alignment: .leading)
.opacity(self.isPlaceholderHidden || self.viewModel.isReadOnly ? 1 : 0)
.opacity(self.isPlaceholderHidden ? 1 : 0)
.accessibilityHidden(true)
Spacer(minLength: 0)
}
Expand All @@ -133,3 +154,12 @@ public struct TextEditorView: View {
return self
}
}

private extension View {
func isEnabled(_ value: Bool, complition: @escaping (Bool) -> Void) -> some View {
DispatchQueue.main.async {
complition(value)
}
return self.disabled(!value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public final class TextEditorUIView: UITextView {
@ScaledUIMetric private var defaultSystemVerticalPadding: CGFloat = 8
@ScaledUIMetric private var scaleFactor: CGFloat = 1.0

private let viewModel: TextEditorViewModel
private var viewModel: TextEditorViewModel!
private var cancellables = Set<AnyCancellable>()
private var placeHolderConstarints: [NSLayoutConstraint]?
private var placeHolderLabelYAnchor: NSLayoutConstraint?
Expand Down Expand Up @@ -45,7 +45,7 @@ public final class TextEditorUIView: UITextView {
self._delegate = newValue
}
get {
return self._delegate
return super.delegate
}
}

Expand Down Expand Up @@ -104,6 +104,9 @@ public final class TextEditorUIView: UITextView {
set {
self.viewModel.isEnabled = newValue
self.isUserInteractionEnabled = newValue
if !isEnabled {
_ = self.resignFirstResponder()
}
}
}

Expand Down Expand Up @@ -293,7 +296,7 @@ extension TextEditorUIView: UITextViewDelegate {
}

public func textViewDidBeginEditing(_ textView: UITextView) {
self.hidePlaceHolder(true)
self.hidePlaceHolder(!textView.text.isEmpty)
self._delegate?.textViewDidBeginEditing?(textView)
}

Expand Down
Loading