#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:
Doug 2022-06-09 14:44:46 +01:00 committed by GitHub
parent 7a458377d6
commit 596cf2df0b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 366 additions and 163 deletions

View File

@ -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()
} }

View 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()
}
}

View File

@ -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()
}
}

View 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
}

View File

@ -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)
} }

View File

@ -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)])

View 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)
}
}
}

View File

@ -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" */;

View File

@ -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"
} }
}, },
{ {

View File

@ -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"

View File

@ -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 {

View File

@ -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)
}
} }

View File

@ -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

View File

@ -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
View File

@ -0,0 +1 @@
DesignKit: Add DesignKit to the ElementX project and style the login screen with it.

View File

@ -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