mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-11 13:59:13 +00:00
#43: Add the DesignKit package to the project.
* Add ElementTextFieldStyle and static style properties. * Rename button styles, support sizes and simplify colour.
This commit is contained in:
parent
7a458377d6
commit
596cf2df0b
@ -17,32 +17,44 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
import DesignTokens
|
import DesignTokens
|
||||||
|
|
||||||
public struct PrimaryActionButtonStyle: ButtonStyle {
|
public extension ButtonStyle where Self == ElementActionButtonStyle {
|
||||||
|
/// The CTA button style as defined in Compound.
|
||||||
|
/// - Parameter size: The control size to use. Defaults to regular.
|
||||||
|
/// - Parameter color: The color of the button's background. Defaults to the accent color.
|
||||||
|
static func elementAction(_ size: ElementControlSize = .regular,
|
||||||
|
color: Color = .element.accent) -> ElementActionButtonStyle {
|
||||||
|
ElementActionButtonStyle(size: size, color: color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ElementActionButtonStyle: ButtonStyle {
|
||||||
@Environment(\.isEnabled) private var isEnabled
|
@Environment(\.isEnabled) private var isEnabled
|
||||||
@Environment(\.colorScheme) private var colorScheme
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
|
||||||
public var customColor: Color?
|
public var size: ElementControlSize
|
||||||
|
public var color: Color
|
||||||
|
|
||||||
|
private var verticalPadding: CGFloat { size == .xLarge ? 12 : 4 }
|
||||||
|
private var maxWidth: CGFloat? { size == .xLarge ? .infinity : nil }
|
||||||
|
|
||||||
private var fontColor: Color {
|
private var fontColor: Color {
|
||||||
// Always white unless disabled with a dark theme.
|
// Always white unless disabled with a dark theme.
|
||||||
.white.opacity(colorScheme == .dark && !isEnabled ? 0.3 : 1.0)
|
.white.opacity(colorScheme == .dark && !isEnabled ? 0.3 : 1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var backgroundColor: Color {
|
public init(size: ElementControlSize = .regular, color: Color = .element.accent) {
|
||||||
customColor ?? .element.accent
|
self.size = size
|
||||||
}
|
self.color = color
|
||||||
|
|
||||||
public init(customColor: Color? = nil) {
|
|
||||||
self.customColor = customColor
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public func makeBody(configuration: Self.Configuration) -> some View {
|
public func makeBody(configuration: Self.Configuration) -> some View {
|
||||||
configuration.label
|
configuration.label
|
||||||
.padding(12.0)
|
.padding(.horizontal, 12)
|
||||||
.frame(maxWidth: .infinity)
|
.padding(.vertical, verticalPadding)
|
||||||
|
.frame(maxWidth: maxWidth)
|
||||||
.foregroundColor(fontColor)
|
.foregroundColor(fontColor)
|
||||||
.font(.element.body)
|
.font(.element.body)
|
||||||
.background(backgroundColor.opacity(backgroundOpacity(when: configuration.isPressed)))
|
.background(color.opacity(backgroundOpacity(when: configuration.isPressed)))
|
||||||
.cornerRadius(8.0)
|
.cornerRadius(8.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,24 +64,24 @@ public struct PrimaryActionButtonStyle: ButtonStyle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct PrimaryActionButtonStyle_Previews: PreviewProvider {
|
public struct ElementActionButtonStyle_Previews: PreviewProvider {
|
||||||
public static var states: some View {
|
public static var states: some View {
|
||||||
VStack {
|
VStack {
|
||||||
Button("Enabled") { /* preview */ }
|
Button("Enabled") { /* preview */ }
|
||||||
.buttonStyle(PrimaryActionButtonStyle())
|
.buttonStyle(ElementActionButtonStyle())
|
||||||
|
|
||||||
Button("Disabled") { /* preview */ }
|
Button("Disabled") { /* preview */ }
|
||||||
.buttonStyle(PrimaryActionButtonStyle())
|
.buttonStyle(ElementActionButtonStyle())
|
||||||
.disabled(true)
|
.disabled(true)
|
||||||
|
|
||||||
Button { /* preview */ } label: {
|
Button { /* preview */ } label: {
|
||||||
Text("Clear BG")
|
Text("Clear BG")
|
||||||
.foregroundColor(.element.alert)
|
.foregroundColor(.element.alert)
|
||||||
}
|
}
|
||||||
.buttonStyle(PrimaryActionButtonStyle(customColor: .clear))
|
.buttonStyle(ElementActionButtonStyle(color: .clear))
|
||||||
|
|
||||||
Button("Red BG") { /* preview */ }
|
Button("Red BG") { /* preview */ }
|
||||||
.buttonStyle(PrimaryActionButtonStyle(customColor: .element.alert))
|
.buttonStyle(ElementActionButtonStyle(color: .element.alert))
|
||||||
}
|
}
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
99
DesignKit/Sources/Buttons/ElementGhostButtonStyle.swift
Normal file
99
DesignKit/Sources/Buttons/ElementGhostButtonStyle.swift
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2021 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import DesignTokens
|
||||||
|
|
||||||
|
public extension ButtonStyle where Self == ElementGhostButtonStyle {
|
||||||
|
/// The Ghost button style as defined in Compound.
|
||||||
|
/// - Parameter size: The control size to use. Defaults to `regular`.
|
||||||
|
/// - Parameter color: The color of the label and border. Defaults to the accent color.
|
||||||
|
static func elementGhost(_ size: ElementControlSize = .regular,
|
||||||
|
color: Color = .element.accent) -> ElementGhostButtonStyle {
|
||||||
|
ElementGhostButtonStyle(size: size, color: color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ElementGhostButtonStyle: ButtonStyle {
|
||||||
|
@Environment(\.isEnabled) private var isEnabled
|
||||||
|
|
||||||
|
public var size: ElementControlSize
|
||||||
|
public var color: Color
|
||||||
|
|
||||||
|
private var verticalPadding: CGFloat { size == .xLarge ? 12 : 4 }
|
||||||
|
private var maxWidth: CGFloat? { size == .xLarge ? .infinity : nil }
|
||||||
|
|
||||||
|
public init(size: ElementControlSize = .regular, color: Color = .element.accent) {
|
||||||
|
self.size = size
|
||||||
|
self.color = color
|
||||||
|
}
|
||||||
|
|
||||||
|
public func makeBody(configuration: Self.Configuration) -> some View {
|
||||||
|
configuration.label
|
||||||
|
.padding(.horizontal, 12)
|
||||||
|
.padding(.vertical, verticalPadding)
|
||||||
|
.frame(maxWidth: maxWidth)
|
||||||
|
.foregroundColor(color)
|
||||||
|
.font(.element.body)
|
||||||
|
.background(border)
|
||||||
|
.opacity(opacity(when: configuration.isPressed))
|
||||||
|
}
|
||||||
|
|
||||||
|
private var border: some View {
|
||||||
|
RoundedRectangle(cornerRadius: 8)
|
||||||
|
.strokeBorder()
|
||||||
|
.foregroundColor(color)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func opacity(when isPressed: Bool) -> CGFloat {
|
||||||
|
guard isEnabled else { return 0.6 }
|
||||||
|
return isPressed ? 0.6 : 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ElementGhostButtonStyle_Previews: PreviewProvider {
|
||||||
|
public static var previews: some View {
|
||||||
|
Group {
|
||||||
|
states
|
||||||
|
}
|
||||||
|
.preferredColorScheme(.light)
|
||||||
|
Group {
|
||||||
|
states
|
||||||
|
}
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var states: some View {
|
||||||
|
VStack {
|
||||||
|
Button("Enabled") { /* preview */ }
|
||||||
|
.buttonStyle(ElementGhostButtonStyle())
|
||||||
|
|
||||||
|
Button("Disabled") { /* preview */ }
|
||||||
|
.buttonStyle(ElementGhostButtonStyle())
|
||||||
|
.disabled(true)
|
||||||
|
|
||||||
|
Button("Red BG") { /* preview */ }
|
||||||
|
.buttonStyle(ElementGhostButtonStyle(color: .element.alert))
|
||||||
|
|
||||||
|
Button { /* preview */ } label: {
|
||||||
|
Text("Custom")
|
||||||
|
.foregroundColor(.element.primaryContent)
|
||||||
|
}
|
||||||
|
.buttonStyle(ElementGhostButtonStyle(color: .element.quaternaryContent))
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
@ -1,82 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright 2021 New Vector Ltd
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
|
|
||||||
import SwiftUI
|
|
||||||
import DesignTokens
|
|
||||||
|
|
||||||
public struct SecondaryActionButtonStyle: ButtonStyle {
|
|
||||||
@Environment(\.isEnabled) private var isEnabled
|
|
||||||
|
|
||||||
public var customColor: Color?
|
|
||||||
|
|
||||||
public init(customColor: Color? = nil) {
|
|
||||||
self.customColor = customColor
|
|
||||||
}
|
|
||||||
|
|
||||||
public func makeBody(configuration: Self.Configuration) -> some View {
|
|
||||||
configuration.label
|
|
||||||
.padding(12.0)
|
|
||||||
.frame(maxWidth: .infinity)
|
|
||||||
.foregroundColor(strokeColor(configuration.isPressed))
|
|
||||||
.font(.element.body)
|
|
||||||
.background(RoundedRectangle(cornerRadius: 8)
|
|
||||||
.strokeBorder()
|
|
||||||
.foregroundColor(strokeColor(configuration.isPressed)))
|
|
||||||
.opacity(isEnabled ? 1.0 : 0.6)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func strokeColor(_ isPressed: Bool) -> Color {
|
|
||||||
if let customColor = customColor {
|
|
||||||
return customColor
|
|
||||||
}
|
|
||||||
|
|
||||||
return isPressed ? .element.accent.opacity(0.6) : .element.accent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct SecondaryActionButtonStyle_Previews: PreviewProvider {
|
|
||||||
public static var previews: some View {
|
|
||||||
Group {
|
|
||||||
states
|
|
||||||
}
|
|
||||||
.preferredColorScheme(.light)
|
|
||||||
Group {
|
|
||||||
states
|
|
||||||
}
|
|
||||||
.preferredColorScheme(.dark)
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var states: some View {
|
|
||||||
VStack {
|
|
||||||
Button("Enabled") { /* preview */ }
|
|
||||||
.buttonStyle(SecondaryActionButtonStyle())
|
|
||||||
|
|
||||||
Button("Disabled") { /* preview */ }
|
|
||||||
.buttonStyle(SecondaryActionButtonStyle())
|
|
||||||
.disabled(true)
|
|
||||||
|
|
||||||
Button { /* preview */ } label: {
|
|
||||||
Text("Clear BG")
|
|
||||||
.foregroundColor(.element.alert)
|
|
||||||
}
|
|
||||||
.buttonStyle(SecondaryActionButtonStyle(customColor: .clear))
|
|
||||||
|
|
||||||
Button("Red BG") { /* preview */ }
|
|
||||||
.buttonStyle(SecondaryActionButtonStyle(customColor: .element.alert))
|
|
||||||
}
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
}
|
|
22
DesignKit/Sources/Common/ElementControlSize.swift
Normal file
22
DesignKit/Sources/Common/ElementControlSize.swift
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2021 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
public enum ElementControlSize {
|
||||||
|
case regular
|
||||||
|
case xLarge
|
||||||
|
}
|
@ -16,12 +16,16 @@
|
|||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct RoundedCornerShape: Shape {
|
public struct RoundedCornerShape: Shape {
|
||||||
|
|
||||||
let radius: CGFloat
|
let radius: CGFloat
|
||||||
let corners: UIRectCorner
|
let corners: UIRectCorner
|
||||||
|
|
||||||
func path(in rect: CGRect) -> Path {
|
public init(radius: CGFloat, corners: UIRectCorner) {
|
||||||
|
self.radius = radius
|
||||||
|
self.corners = corners
|
||||||
|
}
|
||||||
|
|
||||||
|
public func path(in rect: CGRect) -> Path {
|
||||||
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
|
let path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
|
||||||
return Path(path.cgPath)
|
return Path(path.cgPath)
|
||||||
}
|
}
|
@ -28,22 +28,15 @@ public struct BorderedInputFieldStyle: TextFieldStyle {
|
|||||||
|
|
||||||
public var isEditing: Bool
|
public var isEditing: Bool
|
||||||
public var isError: Bool
|
public var isError: Bool
|
||||||
|
public var returnKey: UIReturnKeyType?
|
||||||
|
|
||||||
private var borderColor: Color {
|
private var borderColor: Color {
|
||||||
if isError {
|
guard !isError else { return .element.alert }
|
||||||
return .element.alert
|
return isEditing ? .element.accent : .element.quinaryContent
|
||||||
} else if isEditing {
|
|
||||||
return .element.accent
|
|
||||||
} else {
|
|
||||||
return .element.quinaryContent
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var accentColor: Color {
|
private var accentColor: Color {
|
||||||
if isError {
|
isError ? .element.alert : .element.accent
|
||||||
return .element.alert
|
|
||||||
}
|
|
||||||
return .element.accent
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var textColor: Color {
|
private var textColor: Color {
|
||||||
@ -62,16 +55,22 @@ public struct BorderedInputFieldStyle: TextFieldStyle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var placeholderColor: Color {
|
private var placeholderColor: Color {
|
||||||
return .element.tertiaryContent
|
.element.tertiaryContent
|
||||||
}
|
}
|
||||||
|
|
||||||
private var borderWidth: CGFloat {
|
private var borderWidth: CGFloat {
|
||||||
return isEditing || isError ? 2.0 : 1.5
|
isEditing || isError ? 2.0 : 1.5
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(isEditing: Bool = false, isError: Bool = false) {
|
/// Creates the text field style configured as required.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - isEditing: Whether or not the text field is currently being edited.
|
||||||
|
/// - isError: Whether or not the text field is currently in the error state.
|
||||||
|
/// - returnKey: The return key to be used. Pass `nil` for iOS 15+ and use `.submitLabel` instead.
|
||||||
|
public init(isEditing: Bool = false, isError: Bool = false, returnKey: UIReturnKeyType? = .done) {
|
||||||
self.isEditing = isEditing
|
self.isEditing = isEditing
|
||||||
self.isError = isError
|
self.isError = isError
|
||||||
|
self.returnKey = returnKey
|
||||||
}
|
}
|
||||||
|
|
||||||
public func _body(configuration: TextField<_Label>) -> some View {
|
public func _body(configuration: TextField<_Label>) -> some View {
|
||||||
@ -80,13 +79,16 @@ public struct BorderedInputFieldStyle: TextFieldStyle {
|
|||||||
.font(.element.callout)
|
.font(.element.callout)
|
||||||
.foregroundColor(textColor)
|
.foregroundColor(textColor)
|
||||||
.accentColor(accentColor)
|
.accentColor(accentColor)
|
||||||
.frame(height: 48.0)
|
.padding(.vertical, 12.0)
|
||||||
.padding(.horizontal, 8.0)
|
.padding(.horizontal, 8.0)
|
||||||
.background(backgroundColor)
|
.background(backgroundColor)
|
||||||
.clipShape(rect)
|
.clipShape(rect)
|
||||||
.overlay(rect.stroke(borderColor, lineWidth: borderWidth))
|
.overlay(rect.stroke(borderColor, lineWidth: borderWidth))
|
||||||
.introspectTextField { textField in
|
.introspectTextField { textField in
|
||||||
textField.returnKeyType = .done
|
if let returnKey = returnKey {
|
||||||
|
textField.returnKeyType = returnKey
|
||||||
|
}
|
||||||
|
|
||||||
textField.clearButtonMode = .whileEditing
|
textField.clearButtonMode = .whileEditing
|
||||||
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "",
|
textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "",
|
||||||
attributes: [NSAttributedString.Key.foregroundColor: UIColor(placeholderColor)])
|
attributes: [NSAttributedString.Key.foregroundColor: UIColor(placeholderColor)])
|
||||||
|
100
DesignKit/Sources/TextFields/ElementTextFieldStyle.swift
Normal file
100
DesignKit/Sources/TextFields/ElementTextFieldStyle.swift
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// Copyright 2021 New Vector Ltd
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import DesignTokens
|
||||||
|
|
||||||
|
@available(iOS 15.0, *)
|
||||||
|
public extension TextFieldStyle where Self == ElementTextFieldStyle {
|
||||||
|
static func elementInput(labelText: String? = nil,
|
||||||
|
footerText: String? = nil,
|
||||||
|
isError: Bool = false) -> ElementTextFieldStyle {
|
||||||
|
ElementTextFieldStyle(labelText: labelText, footerText: footerText, isError: isError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 15.0, *)
|
||||||
|
public struct ElementTextFieldStyle: TextFieldStyle {
|
||||||
|
@Environment(\.isEnabled) private var isEnabled
|
||||||
|
@Environment(\.colorScheme) private var colorScheme
|
||||||
|
|
||||||
|
@FocusState private var isFocused: Bool
|
||||||
|
public let labelText: String?
|
||||||
|
public let footerText: String?
|
||||||
|
public let isError: Bool
|
||||||
|
|
||||||
|
private var labelColor: Color {
|
||||||
|
guard colorScheme == .light else { return .element.tertiaryContent }
|
||||||
|
return isEnabled ? .element.primaryContent : .element.quaternaryContent
|
||||||
|
}
|
||||||
|
|
||||||
|
private var footerColor: Color {
|
||||||
|
isError ? .element.alert : .element.tertiaryContent
|
||||||
|
}
|
||||||
|
|
||||||
|
public init(labelText: String? = nil, footerText: String? = nil, isError: Bool = false) {
|
||||||
|
self.labelText = labelText
|
||||||
|
self.footerText = footerText
|
||||||
|
self.isError = isError
|
||||||
|
}
|
||||||
|
|
||||||
|
public func _body(configuration: TextField<_Label>) -> some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
if let labelText = labelText {
|
||||||
|
Text(labelText)
|
||||||
|
.font(.element.subheadline)
|
||||||
|
.foregroundColor(labelColor)
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration
|
||||||
|
.textFieldStyle(BorderedInputFieldStyle(isEditing: isFocused, isError: isError, returnKey: nil))
|
||||||
|
.focused($isFocused)
|
||||||
|
|
||||||
|
if let footerText = footerText {
|
||||||
|
Text(footerText)
|
||||||
|
.font(.element.footnote)
|
||||||
|
.foregroundColor(footerColor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS 15.0, *)
|
||||||
|
struct ElementTextFieldStyle_Previews: PreviewProvider {
|
||||||
|
public static var states: some View {
|
||||||
|
VStack(spacing: 12) {
|
||||||
|
TextField("Placeholder", text: .constant(""))
|
||||||
|
.textFieldStyle(.elementInput(labelText: "Label", footerText: "Footer"))
|
||||||
|
TextField("Placeholder", text: .constant("Input text"))
|
||||||
|
.textFieldStyle(.elementInput(labelText: "Title", footerText: "Footer"))
|
||||||
|
TextField("Placeholder", text: .constant("Bad text"))
|
||||||
|
.textFieldStyle(.elementInput(labelText: "Title", footerText: "Footer", isError: true))
|
||||||
|
TextField("Placeholder", text: .constant(""))
|
||||||
|
.textFieldStyle(.elementInput(labelText: "Title", footerText: "Footer"))
|
||||||
|
.disabled(true)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var previews: some View {
|
||||||
|
Group {
|
||||||
|
states
|
||||||
|
.preferredColorScheme(.light)
|
||||||
|
states
|
||||||
|
.preferredColorScheme(.dark)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 51;
|
objectVersion = 52;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@ -38,7 +38,7 @@
|
|||||||
1999ECC6777752A2616775CF /* MemberDetailsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A152791A2F56BD193BFE986 /* MemberDetailsProvider.swift */; };
|
1999ECC6777752A2616775CF /* MemberDetailsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A152791A2F56BD193BFE986 /* MemberDetailsProvider.swift */; };
|
||||||
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; };
|
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */ = {isa = PBXBuildFile; productRef = A678E40E917620059695F067 /* MatrixRustSDK */; };
|
||||||
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; };
|
1AE4AEA0FA8DEF52671832E0 /* RoomTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED1D792EB82506A19A72C8DE /* RoomTimelineItemProtocol.swift */; };
|
||||||
1F3232BD368DF430AB433907 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */; };
|
1F3232BD368DF430AB433907 /* DesignKit in Frameworks */ = {isa = PBXBuildFile; productRef = A5A56C4F47C368EBE5C5E870 /* DesignKit */; };
|
||||||
206F0DBAB6AF042CA1FF2C0D /* SettingsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D487C1185D658F8B15B8F55 /* SettingsViewModelTests.swift */; };
|
206F0DBAB6AF042CA1FF2C0D /* SettingsViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D487C1185D658F8B15B8F55 /* SettingsViewModelTests.swift */; };
|
||||||
224A55EEAEECF5336B14A4A5 /* EmoteRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE2DF459F1737A594667CC46 /* EmoteRoomMessage.swift */; };
|
224A55EEAEECF5336B14A4A5 /* EmoteRoomMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE2DF459F1737A594667CC46 /* EmoteRoomMessage.swift */; };
|
||||||
22DADD537401E79D66132134 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4173A48FD8542CD4AD3645C /* NavigationRouter.swift */; };
|
22DADD537401E79D66132134 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B4173A48FD8542CD4AD3645C /* NavigationRouter.swift */; };
|
||||||
@ -71,11 +71,12 @@
|
|||||||
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
|
38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */; };
|
||||||
39AE84C8E5F2FE9D2DC7775C /* EventBasedTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56008790A9C4479A6B31FDF4 /* EventBasedTimelineView.swift */; };
|
39AE84C8E5F2FE9D2DC7775C /* EventBasedTimelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56008790A9C4479A6B31FDF4 /* EventBasedTimelineView.swift */; };
|
||||||
3B770CB4DED51CC362C66D47 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4990FDBDA96B88E214F92F48 /* SettingsModels.swift */; };
|
3B770CB4DED51CC362C66D47 /* SettingsModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4990FDBDA96B88E214F92F48 /* SettingsModels.swift */; };
|
||||||
3C549A0BF39F8A854D45D9FD /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 7731767AE437BA3BD2CC14A8 /* Sentry */; };
|
3C549A0BF39F8A854D45D9FD /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; };
|
||||||
3D325A1147F6281C57BFCDF6 /* EventBrief.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4411C0DA0087A1CB143E96FA /* EventBrief.swift */; };
|
3D325A1147F6281C57BFCDF6 /* EventBrief.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4411C0DA0087A1CB143E96FA /* EventBrief.swift */; };
|
||||||
3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC38E64A5ED3FDB201029A /* BugReportService.swift */; };
|
3DA57CA0D609A6B37CA1DC2F /* BugReportService.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6DC38E64A5ED3FDB201029A /* BugReportService.swift */; };
|
||||||
3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; };
|
3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2A5C6FBF97B6EED3D4FA5EFF /* AttributedStringBuilder.swift */; };
|
||||||
418B4AEFD03DC7A6D2C9D5C8 /* EventBriefFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36322DD0D4E29D31B0945ADC /* EventBriefFactory.swift */; };
|
418B4AEFD03DC7A6D2C9D5C8 /* EventBriefFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36322DD0D4E29D31B0945ADC /* EventBriefFactory.swift */; };
|
||||||
|
41DFDD212D1BE57CA50D783B /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = 7731767AE437BA3BD2CC14A8 /* Sentry */; };
|
||||||
438FB9BC535BC95948AA5F34 /* SettingsViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2F9D5C39A4494D19F33E38 /* SettingsViewModelProtocol.swift */; };
|
438FB9BC535BC95948AA5F34 /* SettingsViewModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2F9D5C39A4494D19F33E38 /* SettingsViewModelProtocol.swift */; };
|
||||||
462813B93C39DF93B1249403 /* RoundedToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFABDF2E19D349DAAAC18C65 /* RoundedToastView.swift */; };
|
462813B93C39DF93B1249403 /* RoundedToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFABDF2E19D349DAAAC18C65 /* RoundedToastView.swift */; };
|
||||||
46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; };
|
46562110EE202E580A5FFD9C /* RoomScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */; };
|
||||||
@ -111,7 +112,7 @@
|
|||||||
6A367F3D7A437A79B7D9A31C /* FullscreenLoadingViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4112D04077F6709C5CA0A13E /* FullscreenLoadingViewPresenter.swift */; };
|
6A367F3D7A437A79B7D9A31C /* FullscreenLoadingViewPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4112D04077F6709C5CA0A13E /* FullscreenLoadingViewPresenter.swift */; };
|
||||||
6C72F66DA26A0956E9A9077A /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BEB3259B2208E5AE5BB3F65 /* Settings.swift */; };
|
6C72F66DA26A0956E9A9077A /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2BEB3259B2208E5AE5BB3F65 /* Settings.swift */; };
|
||||||
6EA61FCA55D950BDE326A1A7 /* ImageAnonymizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */; };
|
6EA61FCA55D950BDE326A1A7 /* ImageAnonymizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 12A626D74BBE9F4A60763B45 /* ImageAnonymizer.swift */; };
|
||||||
6F2AB43A1EFAD8A97AF41A15 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 5986E300FC849DEAB2EE7AEB /* Introspect */; };
|
6F2AB43A1EFAD8A97AF41A15 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
|
||||||
7002C55A4C917F3715765127 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */; };
|
7002C55A4C917F3715765127 /* MediaProviderProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = C888BCD78E2A55DCE364F160 /* MediaProviderProtocol.swift */; };
|
||||||
7405B4824D45BA7C3D943E76 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0CBC76C80E04345E11F2DB /* Application.swift */; };
|
7405B4824D45BA7C3D943E76 /* Application.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7D0CBC76C80E04345E11F2DB /* Application.swift */; };
|
||||||
7434A7F02D587A920B376A9A /* LoginScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */; };
|
7434A7F02D587A920B376A9A /* LoginScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5A43964330459965AF048A8C /* LoginScreenViewModelTests.swift */; };
|
||||||
@ -141,18 +142,18 @@
|
|||||||
8D9F646387DF656EF91EE4CB /* RoomMessageFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96F37AB24AF5A006521D38D1 /* RoomMessageFactoryProtocol.swift */; };
|
8D9F646387DF656EF91EE4CB /* RoomMessageFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96F37AB24AF5A006521D38D1 /* RoomMessageFactoryProtocol.swift */; };
|
||||||
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
|
90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; };
|
||||||
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
|
90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; };
|
||||||
93BA4A81B6D893271101F9F0 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = FD43A50D9B75C9D6D30F006B /* SwiftyBeaver */; };
|
93BA4A81B6D893271101F9F0 /* Introspect in Frameworks */ = {isa = PBXBuildFile; productRef = 5986E300FC849DEAB2EE7AEB /* Introspect */; };
|
||||||
964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; };
|
964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; };
|
||||||
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
|
978BB24F2A5D31EE59EEC249 /* UserSessionProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F4134FEFE4EB55759017408 /* UserSessionProtocol.swift */; };
|
||||||
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
|
992F5E750F5030C4BA2D0D03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 01C4C7DB37597D7D8379511A /* Assets.xcassets */; };
|
||||||
99ED42B8F8D6BFB1DBCF4C45 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
|
99ED42B8F8D6BFB1DBCF4C45 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 36B7FC232711031AA2B0D188 /* DTCoreText */; };
|
||||||
9AC5F8142413862A9E3A2D98 /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
|
9AC5F8142413862A9E3A2D98 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = FD43A50D9B75C9D6D30F006B /* SwiftyBeaver */; };
|
||||||
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; };
|
9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; };
|
||||||
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
|
9BD3A773186291560DF92B62 /* RoomTimelineProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66F2402D738694F98729A441 /* RoomTimelineProvider.swift */; };
|
||||||
9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */; };
|
9C45CE85325CD591DADBC4CA /* ElementXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBFEAC3AC691CBB84983E275 /* ElementXTests.swift */; };
|
||||||
9C9E48A627C7C166084E3F5B /* LabelledActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56F01DD1BBD4450E18115916 /* LabelledActivityIndicatorView.swift */; };
|
9C9E48A627C7C166084E3F5B /* LabelledActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56F01DD1BBD4450E18115916 /* LabelledActivityIndicatorView.swift */; };
|
||||||
9CB5129C83F75921E5E28028 /* ToastViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C82DAE0B8EB28234E84E6CF /* ToastViewState.swift */; };
|
9CB5129C83F75921E5E28028 /* ToastViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C82DAE0B8EB28234E84E6CF /* ToastViewState.swift */; };
|
||||||
9D2E03DB175A6AB14589076D /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 0DD568A494247444A4B56031 /* Kingfisher */; };
|
9D2E03DB175A6AB14589076D /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; };
|
||||||
9DC5FB22B8F86C3B51E907C1 /* HomeScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6E4C37E9F0E53D3DF951AC /* HomeScreenUITests.swift */; };
|
9DC5FB22B8F86C3B51E907C1 /* HomeScreenUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D6E4C37E9F0E53D3DF951AC /* HomeScreenUITests.swift */; };
|
||||||
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; };
|
A0A0D2A9564BDA3FDE2E360F /* FormattedBodyText.swift in Sources */ = {isa = PBXBuildFile; fileRef = F73FF1A33198F5FAE9D34B1F /* FormattedBodyText.swift */; };
|
||||||
A32517FB1CA0BBCE2BC75249 /* BugReportCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6C07DA7D3FF193F7419F55 /* BugReportCoordinator.swift */; };
|
A32517FB1CA0BBCE2BC75249 /* BugReportCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD6C07DA7D3FF193F7419F55 /* BugReportCoordinator.swift */; };
|
||||||
@ -183,7 +184,7 @@
|
|||||||
C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */; };
|
C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1E508AB0EDEE017FF4F6F8D1 /* DTHTMLElement+AttributedStringBuilder.swift */; };
|
||||||
C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */; };
|
C55A44C99F64A479ABA85B46 /* RoomScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5221DFDF809142A2D6AC82B9 /* RoomScreen.swift */; };
|
||||||
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; };
|
C7CFDB4929DDD9A3B5BA085D /* BugReportViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB7ED3A898B07976F3AA90F /* BugReportViewModelTests.swift */; };
|
||||||
CB137BFB3E083C33E398A6CB /* GZIP in Frameworks */ = {isa = PBXBuildFile; productRef = 997C7385E1A07E061D7E2100 /* GZIP */; };
|
CB137BFB3E083C33E398A6CB /* SwiftState in Frameworks */ = {isa = PBXBuildFile; productRef = 9573B94B1C86C6DF751AF3FD /* SwiftState */; };
|
||||||
CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EAD710A2C16EFF7C3EA16F /* Benchmark.swift */; };
|
CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49EAD710A2C16EFF7C3EA16F /* Benchmark.swift */; };
|
||||||
CB498F4E27AA0545DCEF0F6F /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
|
CB498F4E27AA0545DCEF0F6F /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 50009897F60FAE7D63EF5E5B /* Kingfisher */; };
|
||||||
CC736DA1AA8F8B9FD8785009 /* ScreenshotDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */; };
|
CC736DA1AA8F8B9FD8785009 /* ScreenshotDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = F5C4AF6E3885730CD560311C /* ScreenshotDetector.swift */; };
|
||||||
@ -207,7 +208,7 @@
|
|||||||
EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */; };
|
EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 184CF8C196BE143AE226628D /* DecorationTimelineItemProtocol.swift */; };
|
||||||
F03E16ED043C62FED5A07AE0 /* MatrixEntitityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B81C8227BBEA95CCE86037 /* MatrixEntitityRegex.swift */; };
|
F03E16ED043C62FED5A07AE0 /* MatrixEntitityRegex.swift in Sources */ = {isa = PBXBuildFile; fileRef = F7B81C8227BBEA95CCE86037 /* MatrixEntitityRegex.swift */; };
|
||||||
F56261126E368C831B3DE976 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEC02D93AFF46BC13313A /* NavigationRouterType.swift */; };
|
F56261126E368C831B3DE976 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 752DEC02D93AFF46BC13313A /* NavigationRouterType.swift */; };
|
||||||
F656F92A63D3DC1978D79427 /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = 020597E28A4BC8E1BE8EDF6E /* KeychainAccess */; };
|
F656F92A63D3DC1978D79427 /* DTCoreText in Frameworks */ = {isa = PBXBuildFile; productRef = 531CE4334AC5CA8DFF6AEB84 /* DTCoreText */; };
|
||||||
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; };
|
F6F49E37272AD7397CD29A01 /* HomeScreenViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 505208F28007C0FEC14E1FF0 /* HomeScreenViewModelTests.swift */; };
|
||||||
F78C57B197DA74735FEBB42C /* EventBriefFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B61C243325DC76D3086494 /* EventBriefFactoryProtocol.swift */; };
|
F78C57B197DA74735FEBB42C /* EventBriefFactoryProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B61C243325DC76D3086494 /* EventBriefFactoryProtocol.swift */; };
|
||||||
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
|
FA9C427FFB11B1AA2DCC5602 /* RoomProxyProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47111410B6E659A697D472B5 /* RoomProxyProtocol.swift */; };
|
||||||
@ -509,6 +510,7 @@
|
|||||||
CF47564C584F614B7287F3EB /* RootRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouter.swift; sourceTree = "<group>"; };
|
CF47564C584F614B7287F3EB /* RootRouter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouter.swift; sourceTree = "<group>"; };
|
||||||
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
|
D0A45283CF1DB96E583BECA6 /* ImageRoomTimelineView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageRoomTimelineView.swift; sourceTree = "<group>"; };
|
||||||
D29EBCBFEC6FD0941749404D /* NavigationRouterStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouterStore.swift; sourceTree = "<group>"; };
|
D29EBCBFEC6FD0941749404D /* NavigationRouterStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouterStore.swift; sourceTree = "<group>"; };
|
||||||
|
D31DC8105C6233E5FFD9B84C /* element-x-ios */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "element-x-ios"; path = .; sourceTree = SOURCE_ROOT; };
|
||||||
D4DA544B2520BFA65D6DB4BB /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
D4DA544B2520BFA65D6DB4BB /* target.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = target.yml; sourceTree = "<group>"; };
|
||||||
D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenCoordinator.swift; sourceTree = "<group>"; };
|
D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenCoordinator.swift; sourceTree = "<group>"; };
|
||||||
D67CBAFA48ED0B6FCE74F88F /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lt; path = lt.lproj/Localizable.strings; sourceTree = "<group>"; };
|
D67CBAFA48ED0B6FCE74F88F /* lt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = lt; path = lt.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
@ -578,14 +580,15 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */,
|
1A70A2199394B5EC660934A5 /* MatrixRustSDK in Frameworks */,
|
||||||
1F3232BD368DF430AB433907 /* DTCoreText in Frameworks */,
|
1F3232BD368DF430AB433907 /* DesignKit in Frameworks */,
|
||||||
F656F92A63D3DC1978D79427 /* KeychainAccess in Frameworks */,
|
F656F92A63D3DC1978D79427 /* DTCoreText in Frameworks */,
|
||||||
9D2E03DB175A6AB14589076D /* Kingfisher in Frameworks */,
|
9D2E03DB175A6AB14589076D /* KeychainAccess in Frameworks */,
|
||||||
6F2AB43A1EFAD8A97AF41A15 /* Introspect in Frameworks */,
|
6F2AB43A1EFAD8A97AF41A15 /* Kingfisher in Frameworks */,
|
||||||
93BA4A81B6D893271101F9F0 /* SwiftyBeaver in Frameworks */,
|
93BA4A81B6D893271101F9F0 /* Introspect in Frameworks */,
|
||||||
9AC5F8142413862A9E3A2D98 /* SwiftState in Frameworks */,
|
9AC5F8142413862A9E3A2D98 /* SwiftyBeaver in Frameworks */,
|
||||||
CB137BFB3E083C33E398A6CB /* GZIP in Frameworks */,
|
CB137BFB3E083C33E398A6CB /* SwiftState in Frameworks */,
|
||||||
3C549A0BF39F8A854D45D9FD /* Sentry in Frameworks */,
|
3C549A0BF39F8A854D45D9FD /* GZIP in Frameworks */,
|
||||||
|
41DFDD212D1BE57CA50D783B /* Sentry in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -742,6 +745,7 @@
|
|||||||
A4852B57D55D71EEBFCD931D /* UnitTests */,
|
A4852B57D55D71EEBFCD931D /* UnitTests */,
|
||||||
C0FAC17D4DD7D3A502822550 /* UITests */,
|
C0FAC17D4DD7D3A502822550 /* UITests */,
|
||||||
823ED0EC3F1B6CF47D284011 /* Tools */,
|
823ED0EC3F1B6CF47D284011 /* Tools */,
|
||||||
|
9413F680ECDFB2B0DDB0DEF2 /* Packages */,
|
||||||
681566846AF307E9BA4C72C6 /* Products */,
|
681566846AF307E9BA4C72C6 /* Products */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1016,6 +1020,14 @@
|
|||||||
path = HTMLParsing;
|
path = HTMLParsing;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
9413F680ECDFB2B0DDB0DEF2 /* Packages */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
D31DC8105C6233E5FFD9B84C /* element-x-ios */,
|
||||||
|
);
|
||||||
|
name = Packages;
|
||||||
|
sourceTree = SOURCE_ROOT;
|
||||||
|
};
|
||||||
951A66D15CD44C0EACE4A951 /* Sources */ = {
|
951A66D15CD44C0EACE4A951 /* Sources */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -1336,6 +1348,7 @@
|
|||||||
name = ElementX;
|
name = ElementX;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
A678E40E917620059695F067 /* MatrixRustSDK */,
|
A678E40E917620059695F067 /* MatrixRustSDK */,
|
||||||
|
A5A56C4F47C368EBE5C5E870 /* DesignKit */,
|
||||||
531CE4334AC5CA8DFF6AEB84 /* DTCoreText */,
|
531CE4334AC5CA8DFF6AEB84 /* DTCoreText */,
|
||||||
020597E28A4BC8E1BE8EDF6E /* KeychainAccess */,
|
020597E28A4BC8E1BE8EDF6E /* KeychainAccess */,
|
||||||
0DD568A494247444A4B56031 /* Kingfisher */,
|
0DD568A494247444A4B56031 /* Kingfisher */,
|
||||||
@ -1367,7 +1380,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 7AE41FCCF9D1352E2770D1F9 /* Build configuration list for PBXProject "ElementX" */;
|
buildConfigurationList = 7AE41FCCF9D1352E2770D1F9 /* Build configuration list for PBXProject "ElementX" */;
|
||||||
compatibilityVersion = "Xcode 10.0";
|
compatibilityVersion = "Xcode 11.0";
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
@ -2360,6 +2373,10 @@
|
|||||||
package = 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */;
|
package = 701C7BEF8F70F7A83E852DCC /* XCRemoteSwiftPackageReference "GZIP" */;
|
||||||
productName = GZIP;
|
productName = GZIP;
|
||||||
};
|
};
|
||||||
|
A5A56C4F47C368EBE5C5E870 /* DesignKit */ = {
|
||||||
|
isa = XCSwiftPackageProductDependency;
|
||||||
|
productName = DesignKit;
|
||||||
|
};
|
||||||
A678E40E917620059695F067 /* MatrixRustSDK */ = {
|
A678E40E917620059695F067 /* MatrixRustSDK */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 4FCDA8D25C7415C8FB33490D /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */;
|
package = 4FCDA8D25C7415C8FB33490D /* XCRemoteSwiftPackageReference "matrix-rust-components-swift" */;
|
||||||
|
@ -18,6 +18,15 @@
|
|||||||
"version" : "1.7.18"
|
"version" : "1.7.18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"identity" : "element-design-tokens",
|
||||||
|
"kind" : "remoteSourceControl",
|
||||||
|
"location" : "https://github.com/vector-im/element-design-tokens.git",
|
||||||
|
"state" : {
|
||||||
|
"branch" : "main",
|
||||||
|
"revision" : "4aafdc25ca0e322c0de930d4ec86121f5503023e"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"identity" : "gzip",
|
"identity" : "gzip",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
@ -59,8 +68,8 @@
|
|||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/getsentry/sentry-cocoa.git",
|
"location" : "https://github.com/getsentry/sentry-cocoa.git",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "afa4cd596e5cf97a797fb9b5c3afeea4add2c7a3",
|
"revision" : "b34ce9048e6b8b082ea6b15e6b50583d46c936ea",
|
||||||
"version" : "7.15.0"
|
"version" : "7.16.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "1200"
|
LastUpgradeVersion = "1200"
|
||||||
version = "1.3">
|
version = "1.7">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
buildImplicitDependencies = "YES"
|
buildImplicitDependencies = "YES"
|
||||||
|
@ -26,6 +26,7 @@ enum LoginScreenViewAction {
|
|||||||
|
|
||||||
struct LoginScreenViewState: BindableState {
|
struct LoginScreenViewState: BindableState {
|
||||||
var bindings: LoginScreenViewStateBindings
|
var bindings: LoginScreenViewStateBindings
|
||||||
|
var hasCredentials: Bool { !bindings.username.isEmpty && !bindings.password.isEmpty }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LoginScreenViewStateBindings {
|
struct LoginScreenViewStateBindings {
|
||||||
|
@ -15,35 +15,48 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import DesignKit
|
||||||
|
|
||||||
struct LoginScreen: View {
|
struct LoginScreen: View {
|
||||||
|
|
||||||
@ObservedObject var context: LoginScreenViewModel.Context
|
@ObservedObject var context: LoginScreenViewModel.Context
|
||||||
|
|
||||||
|
enum Field { case username, password }
|
||||||
|
@FocusState private var focussedField: Field?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
|
||||||
VStack {
|
VStack {
|
||||||
TextField("Username", text: $context.username)
|
TextField("Username", text: $context.username)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.elementInput())
|
||||||
.disableAutocorrection(true)
|
.disableAutocorrection(true)
|
||||||
|
.textContentType(.username)
|
||||||
.autocapitalization(.none)
|
.autocapitalization(.none)
|
||||||
SecureField("Password", text: $context.password)
|
.focused($focussedField, equals: .username)
|
||||||
.textFieldStyle(.roundedBorder)
|
.submitLabel(.next)
|
||||||
|
.onSubmit { focussedField = .password }
|
||||||
|
|
||||||
Button("Login") {
|
SecureField("Password", text: $context.password)
|
||||||
context.send(viewAction: .login)
|
.textFieldStyle(.elementInput())
|
||||||
}
|
.textContentType(.password)
|
||||||
.buttonStyle(.borderedProminent)
|
.focused($focussedField, equals: .password)
|
||||||
.padding(.horizontal, 50)
|
.submitLabel(.go)
|
||||||
|
.onSubmit(submit)
|
||||||
|
|
||||||
|
Button("Login", action: submit)
|
||||||
|
.buttonStyle(.elementAction(.xLarge))
|
||||||
|
.disabled(!context.viewState.hasCredentials)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 8.0)
|
.padding(.horizontal, 8.0)
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.background(Color.element.background.ignoresSafeArea())
|
||||||
.navigationTitle("Login")
|
.navigationTitle("Login")
|
||||||
.navigationBarTitleDisplayMode(.inline)
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
.onSubmit {
|
}
|
||||||
|
|
||||||
|
func submit() {
|
||||||
|
guard context.viewState.hasCredentials else { return }
|
||||||
context.send(viewAction: .login)
|
context.send(viewAction: .login)
|
||||||
}
|
focussedField = nil
|
||||||
}
|
|
||||||
.navigationViewStyle(StackNavigationViewStyle())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +65,9 @@ struct LoginScreen: View {
|
|||||||
struct LoginScreen_Previews: PreviewProvider {
|
struct LoginScreen_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
let viewModel = LoginScreenViewModel()
|
let viewModel = LoginScreenViewModel()
|
||||||
|
NavigationView {
|
||||||
LoginScreen(context: viewModel.context)
|
LoginScreen(context: viewModel.context)
|
||||||
}
|
}
|
||||||
|
.navigationViewStyle(.stack)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ targets:
|
|||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- package: MatrixRustSDK
|
- package: MatrixRustSDK
|
||||||
|
- package: DesignKit
|
||||||
- package: DTCoreText
|
- package: DTCoreText
|
||||||
- package: KeychainAccess
|
- package: KeychainAccess
|
||||||
- package: Kingfisher
|
- package: Kingfisher
|
||||||
|
@ -21,7 +21,6 @@ class LoginScreenUITests: XCTestCase {
|
|||||||
let app = Application.launch()
|
let app = Application.launch()
|
||||||
app.goToScreenWithIdentifier("Login screen")
|
app.goToScreenWithIdentifier("Login screen")
|
||||||
|
|
||||||
XCTAssert(app.staticTexts["Login"].exists)
|
|
||||||
XCTAssert(app.buttons["Login"].exists)
|
XCTAssert(app.buttons["Login"].exists)
|
||||||
XCTAssert(app.textFields["Username"].exists)
|
XCTAssert(app.textFields["Username"].exists)
|
||||||
XCTAssert(app.secureTextFields["Password"].exists)
|
XCTAssert(app.secureTextFields["Password"].exists)
|
||||||
|
1
changelog.d/43.change
Normal file
1
changelog.d/43.change
Normal file
@ -0,0 +1 @@
|
|||||||
|
DesignKit: Add DesignKit to the ElementX project and style the login screen with it.
|
@ -33,6 +33,8 @@ packages:
|
|||||||
MatrixRustSDK:
|
MatrixRustSDK:
|
||||||
url: https://github.com/matrix-org/matrix-rust-components-swift.git
|
url: https://github.com/matrix-org/matrix-rust-components-swift.git
|
||||||
branch: main
|
branch: main
|
||||||
|
DesignKit:
|
||||||
|
path: ./
|
||||||
DTCoreText:
|
DTCoreText:
|
||||||
url: https://github.com/Cocoanetics/DTCoreText
|
url: https://github.com/Cocoanetics/DTCoreText
|
||||||
majorVersion: 1.6.26
|
majorVersion: 1.6.26
|
||||||
|
Loading…
x
Reference in New Issue
Block a user