MESSENGER-3671 Merge FOSS 1.9.8

Conflicts:
 - CommonConfiguration.swift
 - BuildSettings.swift
 - Generated/images.Swift
 - RoomMemberDetailsViewController.m
 - LiveLocationSharingViewModell
-  PinCodeEnterViewController.m
This commit is contained in:
Frank Rotermund
2022-10-05 15:47:27 +02:00
744 changed files with 6999 additions and 3819 deletions
@@ -1,4 +1,4 @@
//
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,6 @@
import SwiftUI
struct BorderModifier<Shape: InsettableShape>: ViewModifier {
var color: Color
var borderWidth: CGFloat
var shape: Shape
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,20 +15,19 @@
//
import Foundation
import SwiftUI
import Introspect
import SwiftUI
/// A bordered style of text input
///
/// As defined in:
/// https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=2039%3A26415
struct BorderedInputFieldStyle: TextFieldStyle {
@Environment(\.theme) private var theme: ThemeSwiftUI
@Environment(\.isEnabled) private var isEnabled: Bool
var isEditing: Bool = false
var isError: Bool = false
var isEditing = false
var isError = false
private var borderColor: Color {
if isError {
@@ -47,7 +46,7 @@ struct BorderedInputFieldStyle: TextFieldStyle {
}
private var textColor: Color {
if (theme.identifier == ThemeIdentifier.dark) {
if theme.identifier == ThemeIdentifier.dark {
return (isEnabled ? theme.colors.primaryContent : theme.colors.tertiaryContent)
} else {
return (isEnabled ? theme.colors.primaryContent : theme.colors.quarterlyContent)
@@ -55,18 +54,18 @@ struct BorderedInputFieldStyle: TextFieldStyle {
}
private var backgroundColor: Color {
if !isEnabled && (theme.identifier == ThemeIdentifier.dark) {
if !isEnabled, theme.identifier == ThemeIdentifier.dark {
return theme.colors.quinaryContent
}
return theme.colors.background
}
private var placeholderColor: Color {
return theme.colors.tertiaryContent
theme.colors.tertiaryContent
}
private var borderWidth: CGFloat {
return isEditing || isError ? 2.0 : 1.5
isEditing || isError ? 2.0 : 1.5
}
func _body(configuration: TextField<_Label>) -> some View {
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@ import SwiftUI
extension ThemableTextEditor {
func showClearButton(text: Binding<String>, alignment: VerticalAlignment = .top) -> some View {
return modifier(ClearViewModifier(alignment: alignment, text: text))
modifier(ClearViewModifier(alignment: alignment, text: text))
}
}
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -19,7 +19,6 @@ import SwiftUI
@available(iOS, introduced: 14.0, deprecated: 15.0, message: "Use Text with an AttributedString instead that includes a link and handle the tap by adding an OpenURLAction to the environment.")
/// A `Button`, that fakes having a tappable string inside of a regular string.
struct InlineTextButton: View {
private struct StringComponent {
let string: Substring
let isTinted: Bool
@@ -33,7 +32,6 @@ struct InlineTextButton: View {
private let components: [StringComponent]
private let action: () -> Void
// MARK: - Setup
/// Creates a new `InlineTextButton`.
@@ -43,7 +41,7 @@ struct InlineTextButton: View {
/// - action: The action to perform when tapping the button.
internal init(_ mainText: String, tappableText: String, action: @escaping () -> Void) {
guard let range = mainText.range(of: "%@") else {
self.components = [StringComponent(string: Substring(mainText), isTinted: false)]
components = [StringComponent(string: Substring(mainText), isTinted: false)]
self.action = action
return
}
@@ -52,7 +50,7 @@ struct InlineTextButton: View {
let middleComponent = StringComponent(string: Substring(tappableText), isTinted: true)
let lastComponent = StringComponent(string: mainText[range.upperBound...], isTinted: false)
self.components = [firstComponent, middleComponent, lastComponent]
components = [firstComponent, middleComponent, lastComponent]
self.action = action
}
@@ -63,7 +61,7 @@ struct InlineTextButton: View {
EmptyView()
}
.buttonStyle(Style(components: components))
.accessibilityLabel(components.map { $0.string }.joined())
.accessibilityLabel(components.map(\.string).joined())
}
private struct Style: ButtonStyle {
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,14 +17,13 @@
import SwiftUI
struct MultilineTextField: View {
@Environment(\.theme) private var theme: ThemeSwiftUI
@Binding private var text: String
@State private var dynamicHeight: CGFloat = 100
@State private var isEditing = false
private var placeholder: String = ""
private var placeholder = ""
private var showingPlaceholder: Bool {
text.isEmpty
@@ -32,11 +31,11 @@ struct MultilineTextField: View {
init(_ placeholder: String, text: Binding<String>) {
self.placeholder = placeholder
self._text = text
_text = text
}
private var textColor: Color {
if (theme.identifier == ThemeIdentifier.dark) {
if theme.identifier == ThemeIdentifier.dark {
return theme.colors.primaryContent
} else {
return theme.colors.primaryContent
@@ -44,11 +43,11 @@ struct MultilineTextField: View {
}
private var backgroundColor: Color {
return theme.colors.background
theme.colors.background
}
private var placeholderColor: Color {
return theme.colors.tertiaryContent
theme.colors.tertiaryContent
}
private var borderColor: Color {
@@ -60,7 +59,7 @@ struct MultilineTextField: View {
}
private var borderWidth: CGFloat {
return isEditing ? 2.0 : 1.5
isEditing ? 2.0 : 1.5
}
var body: some View {
@@ -91,7 +90,7 @@ struct MultilineTextField: View {
}
}
fileprivate struct UITextViewWrapper: UIViewRepresentable {
private struct UITextViewWrapper: UIViewRepresentable {
typealias UIViewType = UITextView
@Binding var text: String
@@ -115,8 +114,8 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable {
}
func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext<UITextViewWrapper>) {
if uiView.text != self.text {
uiView.text = self.text
if uiView.text != text {
uiView.text = text
}
UITextViewWrapper.recalculateHeight(view: uiView, result: $calculatedHeight)
@@ -132,7 +131,7 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable {
}
func makeCoordinator() -> Coordinator {
return Coordinator(text: $text, height: $calculatedHeight, isEditing: $isEditing)
Coordinator(text: $text, height: $calculatedHeight, isEditing: $isEditing)
}
final class Coordinator: NSObject, UITextViewDelegate {
@@ -142,7 +141,7 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable {
init(text: Binding<String>, height: Binding<CGFloat>, isEditing: Binding<Bool>) {
self.text = text
self.calculatedHeight = height
calculatedHeight = height
self.isEditing = isEditing
}
@@ -171,9 +170,8 @@ fileprivate struct UITextViewWrapper: UIViewRepresentable {
}
struct MultilineTextField_Previews: PreviewProvider {
static var previews: some View {
return Group {
Group {
VStack {
PreviewWrapper()
PlaceholderPreviewWrapper()
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,11 +17,9 @@
import SwiftUI
struct OptionButton: View {
// MARK: - Style
private struct Style: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.scaleEffect(configuration.isPressed ? 0.97 : 1)
@@ -61,8 +59,7 @@ struct OptionButton: View {
.background(theme.colors.quinaryContent)
.foregroundColor(theme.colors.secondaryContent)
.clipShape(RoundedRectangle(cornerRadius: 8))
}
)
})
.buttonStyle(Style())
}
}
@@ -73,14 +70,14 @@ struct OptionButton_Previews: PreviewProvider {
static var previews: some View {
Group {
VStack {
OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.light)
OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.light)
OptionButton(icon: nil, title: "A title", detailMessage: nil, action: {}).theme(.light)
OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.light)
OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.light)
OptionButton(icon: nil, title: "A title", detailMessage: nil, action: { }).theme(.light)
}
VStack {
OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.dark)
OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: {}).theme(.dark)
OptionButton(icon: nil, title: "A title", detailMessage: nil, action: {}).theme(.dark)
OptionButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.dark)
OptionButton(icon: nil, title: "A title", detailMessage: "Some details for this option", action: { }).theme(.dark)
OptionButton(icon: nil, title: "A title", detailMessage: nil, action: { }).theme(.dark)
}.preferredColorScheme(.dark)
}
.padding()
@@ -19,7 +19,6 @@ import SwiftUI
/// Adds a reveal password button (e.g. an eye button) on the
/// right side of the view. For use with `ThemableTextField`.
struct PasswordButtonModifier: ViewModifier {
// MARK: - Properties
let text: String
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +20,7 @@ struct PrimaryActionButtonStyle: ButtonStyle {
@Environment(\.theme) private var theme
@Environment(\.isEnabled) private var isEnabled
var customColor: Color? = nil
var customColor: Color?
private var fontColor: Color {
// Always white unless disabled with a dark theme.
@@ -69,7 +69,7 @@ struct PrimaryActionButtonStyle_Previews: PreviewProvider {
.buttonStyle(PrimaryActionButtonStyle(customColor: .clear))
Button("Red BG") { }
.buttonStyle(PrimaryActionButtonStyle(customColor: .red))
.buttonStyle(PrimaryActionButtonStyle(customColor: .red))
}
.padding()
}
@@ -1,4 +1,4 @@
//
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,6 @@
import SwiftUI
struct RadioButton: View {
// MARK: - Properties
var title: String
@@ -61,8 +60,8 @@ struct RadioButton_Previews: PreviewProvider {
static var buttonGroup: some View {
VStack {
RadioButton(title: "A title", selected: false, action: {})
RadioButton(title: "A title", selected: true, action: {})
RadioButton(title: "A title", selected: false, action: { })
RadioButton(title: "A title", selected: true, action: { })
}
}
}
@@ -1,4 +1,4 @@
//
//
// Copyright 2022 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,7 @@ import SwiftUI
/// Positions this view within an invisible frame that fills the width of its parent view,
/// whilst limiting the width of the content to a readable size (which is customizable).
fileprivate struct ReadableFrameModifier: ViewModifier {
private struct ReadableFrameModifier: ViewModifier {
var maxWidth: CGFloat
func body(content: Content) -> some View {
@@ -18,8 +18,7 @@ import UIKit
/// `ResponderManager` is used to chain `SwiftUI` text editing views that embed `UIKit` text editing views using `UIViewRepresentable`
class ResponderManager {
private static var tagIndex: Int = 1000
private static var tagIndex = 1000
private static var registeredResponders = NSMapTable<NSNumber, UIView>(keyOptions: .strongMemory, valueOptions: .weakMemory)
private static var nextIndex: Int {
@@ -63,7 +62,7 @@ class ResponderManager {
/// Tries to get the focused registered responder and give the focus to it's next responder
/// - Returns: `True` if the next responder has been found and is successfully focused. `False` otherwise.
static func makeActiveNextResponder() -> Bool {
guard let firstResponder = self.firstResponder else {
guard let firstResponder = firstResponder else {
return false
}
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,17 +17,16 @@
import SwiftUI
struct RoundedBorderTextEditor: View {
// MARK: - Properties
var title: String? = nil
var title: String?
let placeHolder: String
@Binding var text: String
var textMaxHeight: CGFloat? = nil
var error: String? = nil
var textMaxHeight: CGFloat?
var error: String?
var onTextChanged: ((String) -> Void)? = nil
var onEditingChanged: ((Bool) -> Void)? = nil
var onTextChanged: ((String) -> Void)?
var onEditingChanged: ((Bool) -> Void)?
@State private var editing = false
@@ -62,7 +61,7 @@ struct RoundedBorderTextEditor: View {
})
.showClearButton(text: $text)
// Found no good solution here. Hidding next button for the moment
// .modifier(NextViewModifier(alignment: .bottomTrailing, isEditing: $editing))
// .modifier(NextViewModifier(alignment: .bottomTrailing, isEditing: $editing))
.padding(EdgeInsets(top: 2, leading: 6, bottom: 0, trailing: 0))
.onChange(of: text, perform: { newText in
onTextChanged?(newText)
@@ -82,7 +81,7 @@ struct RoundedBorderTextEditor: View {
}
.background(RoundedRectangle(cornerRadius: 8).fill(theme.colors.background))
.overlay(RoundedRectangle(cornerRadius: 8)
.stroke(editing ? theme.colors.accent : (error == nil ? theme.colors.quinaryContent : theme.colors.alert), lineWidth: editing || error != nil ? 2 : 1))
.stroke(editing ? theme.colors.accent : (error == nil ? theme.colors.quinaryContent : theme.colors.alert), lineWidth: editing || error != nil ? 2 : 1))
.frame(height: textMaxHeight)
if let error = self.error {
Text(error)
@@ -101,7 +100,6 @@ struct RoundedBorderTextEditor: View {
struct ThemableTextEditor_Previews: PreviewProvider {
static var previews: some View {
Group {
sampleView.theme(.light).preferredColorScheme(.light)
sampleView.theme(.dark).preferredColorScheme(.dark)
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,22 +17,21 @@
import SwiftUI
struct RoundedBorderTextField: View {
// MARK: - Properties
var title: String? = nil
var title: String?
let placeHolder: String
@Binding var text: String
var footerText: String? = nil
var isError: Bool = false
var footerText: String?
var isError = false
var isFirstResponder = false
var configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration()
var configuration = UIKitTextInputConfiguration()
@State var isSecureTextVisible = false
var onTextChanged: ((String) -> Void)? = nil
var onEditingChanged: ((Bool) -> Void)? = nil
var onCommit: (() -> Void)? = nil
var onTextChanged: ((String) -> Void)?
var onEditingChanged: ((Bool) -> Void)?
var onCommit: (() -> Void)?
// MARK: Private
@@ -101,7 +100,7 @@ struct RoundedBorderTextField: View {
private var borderColor: Color {
if isEditing {
return theme.colors.accent
} else if footerText != nil && isError {
} else if footerText != nil, isError {
return theme.colors.alert
} else {
return theme.colors.quinaryContent
@@ -118,7 +117,6 @@ struct RoundedBorderTextField: View {
struct TextFieldWithError_Previews: PreviewProvider {
static var previews: some View {
Group {
sampleView.theme(.light).preferredColorScheme(.light)
sampleView.theme(.dark).preferredColorScheme(.dark)
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,6 @@ import Foundation
import SwiftUI
struct RoundedCornerShape: Shape {
let radius: CGFloat
let corners: UIRectCorner
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,7 +22,6 @@ import SwiftUI
Replace with Swift 5.5 bindings enumerator later.
*/
struct SafeBindingCollectionEnumerator<T: RandomAccessCollection & MutableCollection, C: View>: View {
typealias BoundElement = Binding<T.Element>
private let binding: BoundElement
private let content: (BoundElement) -> C
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -33,6 +33,6 @@ struct ScreenTrackerViewModifier: ViewModifier {
extension View {
func track(screen: AnalyticsScreen) -> some View {
return self.modifier(ScreenTrackerViewModifier(screen: screen))
modifier(ScreenTrackerViewModifier(screen: screen))
}
}
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,6 @@
import SwiftUI
struct SearchBar: View {
// MARK: - Properties
var placeholder: String
@@ -49,7 +48,7 @@ struct SearchBar: View {
.foregroundColor(theme.colors.quarterlyContent)
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
if isEditing && !text.isEmpty {
if isEditing, !text.isEmpty {
Button(action: {
self.text = ""
}) {
@@ -20,7 +20,7 @@ struct SecondaryActionButtonStyle: ButtonStyle {
@Environment(\.theme) private var theme
@Environment(\.isEnabled) private var isEnabled
var customColor: Color? = nil
var customColor: Color?
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
@@ -29,8 +29,8 @@ struct SecondaryActionButtonStyle: ButtonStyle {
.foregroundColor(customColor ?? theme.colors.accent)
.font(theme.fonts.body)
.background(RoundedRectangle(cornerRadius: 8)
.strokeBorder()
.foregroundColor(customColor ?? theme.colors.accent))
.strokeBorder()
.foregroundColor(customColor ?? theme.colors.accent))
.opacity(opacity(when: configuration.isPressed))
}
@@ -62,7 +62,7 @@ struct SecondaryActionButtonStyle_Previews: PreviewProvider {
.disabled(true)
Button("Red BG") { }
.buttonStyle(SecondaryActionButtonStyle(customColor: .red))
.buttonStyle(SecondaryActionButtonStyle(customColor: .red))
Button { } label: {
Text("Custom")
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,14 +14,13 @@
// limitations under the License.
//
import SwiftUI
import DesignKit
import SwiftUI
@available(iOS, introduced: 14.0, deprecated: 15.0, message: "Use Text with an AttributedString instead.")
/// A `Text` view that renders attributed strings with their `.font` and `.foregroundColor` attributes.
/// This view is a workaround for iOS 13/14 not supporting `AttributedString`.
struct StyledText: View {
// MARK: - Properties
// MARK: Private
@@ -31,8 +30,8 @@ struct StyledText: View {
/// A string with a bold property.
private struct StringComponent {
let string: String
var font: Font? = nil
var color: Color? = nil
var font: Font?
var color: Color?
}
/// Internal representation of the string as composable parts.
@@ -47,7 +46,7 @@ struct StyledText: View {
let range = NSRange(location: 0, length: attributedString.length)
let string = attributedString.string as NSString
attributedString.enumerateAttributes(in: range, options: []) { attributes, range, stop in
attributedString.enumerateAttributes(in: range, options: []) { attributes, range, _ in
let font = attributes[.font] as? UIFont
let color = attributes[.foregroundColor] as? UIColor
@@ -66,7 +65,7 @@ struct StyledText: View {
/// Creates a `StyledText` using a plain string.
/// - Parameter string: The plain string to display
init(_ string: String) {
self.components = [StringComponent(string: string, font: nil)]
components = [StringComponent(string: string, font: nil)]
}
// MARK: - Views
@@ -80,7 +79,6 @@ struct StyledText: View {
}
}
struct StyledText_Previews: PreviewProvider {
static func prettyText() -> NSAttributedString {
let string = NSMutableAttributedString(string: "T", attributes: [
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,11 +17,9 @@
import SwiftUI
struct ThemableButton: View {
// MARK: - Style
private struct Style: ButtonStyle {
func makeBody(configuration: Configuration) -> some View {
configuration.label
.scaleEffect(configuration.isPressed ? 0.97 : 1)
@@ -67,12 +65,12 @@ struct ThemableButton_Previews: PreviewProvider {
static var previews: some View {
Group {
VStack(alignment: .center, spacing: 20) {
ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: {}).theme(.light).preferredColorScheme(.light)
ThemableButton(icon: nil, title: "A title", action: {}).theme(.light).preferredColorScheme(.light)
ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: { }).theme(.light).preferredColorScheme(.light)
ThemableButton(icon: nil, title: "A title", action: { }).theme(.light).preferredColorScheme(.light)
}
VStack(alignment: .center, spacing: 20) {
ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: {}).theme(.dark).preferredColorScheme(.dark)
ThemableButton(icon: nil, title: "A title", action: {}).theme(.dark).preferredColorScheme(.dark)
ThemableButton(icon: Asset.Images.spaceTypeIcon.image, title: "A title", action: { }).theme(.dark).preferredColorScheme(.dark)
ThemableButton(icon: nil, title: "A title", action: { }).theme(.dark).preferredColorScheme(.dark)
}
}
.padding()
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -17,7 +17,6 @@
import SwiftUI
struct ThemableNavigationBar: View {
// MARK: - Style
// MARK: - Properties
@@ -36,8 +35,7 @@ struct ThemableNavigationBar: View {
@ViewBuilder
var body: some View {
HStack {
Button(action: {backAction()})
{
Button(action: { backAction() }) {
Image(uiImage: Asset.Images.spacesModalBack.image)
.renderingMode(.template)
.foregroundColor(theme.colors.secondaryContent)
@@ -49,8 +47,7 @@ struct ThemableNavigationBar: View {
.foregroundColor(theme.colors.primaryContent)
}
Spacer()
Button(action: {closeAction()})
{
Button(action: { closeAction() }) {
Image(uiImage: Asset.Images.spacesModalClose.image)
.renderingMode(.template)
.foregroundColor(theme.colors.secondaryContent)
@@ -68,16 +65,16 @@ struct NavigationBar_Previews: PreviewProvider {
static var previews: some View {
Group {
VStack {
ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {})
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {})
ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {})
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {})
ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { })
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { })
ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { })
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { })
}
VStack {
ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { }).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { }).theme(.dark)
ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { }).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { }).theme(.dark)
}.preferredColorScheme(.dark)
}
.padding()
@@ -16,20 +16,18 @@
import SwiftUI
struct ThemableTextEditor: UIViewRepresentable {
// MARK: Properties
@Binding var text: String
@State var configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration()
@State var configuration = UIKitTextInputConfiguration()
var onEditingChanged: ((_ edit: Bool) -> Void)?
// MARK: Private
@Environment(\.theme) private var theme: ThemeSwiftUI
private let textView: UITextView = UITextView()
private let textView = UITextView()
private let internalParams = InternalParams()
// MARK: Setup
@@ -37,8 +35,8 @@ struct ThemableTextEditor: UIViewRepresentable {
init(text: Binding<String>,
configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration(),
onEditingChanged: ((_ edit: Bool) -> Void)? = nil) {
self._text = text
self._configuration = State(initialValue: configuration)
_text = text
_configuration = State(initialValue: configuration)
self.onEditingChanged = onEditingChanged
ResponderManager.register(view: textView)
@@ -63,8 +61,8 @@ struct ThemableTextEditor: UIViewRepresentable {
uiView.textColor = UIColor(theme.colors.primaryContent)
uiView.tintColor = UIColor(theme.colors.accent)
if uiView.text != self.text {
uiView.text = self.text
if uiView.text != text {
uiView.text = text
}
uiView.keyboardType = configuration.keyboardType
@@ -81,7 +79,7 @@ struct ThemableTextEditor: UIViewRepresentable {
// MARK: - Private
private func replaceText(with newText: String) {
self.text = newText
text = newText
}
private class InternalParams {
@@ -91,7 +89,7 @@ struct ThemableTextEditor: UIViewRepresentable {
// MARK: - Coordinator
func makeCoordinator() -> Coordinator {
return Coordinator(self)
Coordinator(self)
}
class Coordinator: NSObject, UITextViewDelegate {
@@ -19,18 +19,17 @@ import SwiftUI
struct UIKitTextInputConfiguration {
var keyboardType: UIKeyboardType = .default
var returnKeyType: UIReturnKeyType = .default
var isSecureTextEntry: Bool = false
var isSecureTextEntry = false
var autocapitalizationType: UITextAutocapitalizationType = .sentences
var autocorrectionType: UITextAutocorrectionType = .default
}
struct ThemableTextField: UIViewRepresentable {
// MARK: Properties
@State var placeholder: String?
@Binding var text: String
@State var configuration: UIKitTextInputConfiguration = UIKitTextInputConfiguration()
@State var configuration = UIKitTextInputConfiguration()
@Binding var isSecureTextVisible: Bool
var onEditingChanged: ((_ edit: Bool) -> Void)?
var onCommit: (() -> Void)?
@@ -39,7 +38,7 @@ struct ThemableTextField: UIViewRepresentable {
@Environment(\.theme) private var theme: ThemeSwiftUI
private let textField: UITextField = UITextField()
private let textField = UITextField()
private let internalParams = InternalParams()
// MARK: Setup
@@ -50,10 +49,10 @@ struct ThemableTextField: UIViewRepresentable {
isSecureTextVisible: Binding<Bool> = .constant(false),
onEditingChanged: ((_ edit: Bool) -> Void)? = nil,
onCommit: (() -> Void)? = nil) {
self._text = text
self._placeholder = State(initialValue: placeholder)
self._configuration = State(initialValue: configuration)
self._isSecureTextVisible = isSecureTextVisible
_text = text
_placeholder = State(initialValue: placeholder)
_configuration = State(initialValue: configuration)
_isSecureTextVisible = isSecureTextVisible
self.onEditingChanged = onEditingChanged
self.onCommit = onCommit
@@ -84,8 +83,8 @@ struct ThemableTextField: UIViewRepresentable {
uiView.textColor = UIColor(theme.colors.primaryContent)
uiView.tintColor = UIColor(theme.colors.accent)
if uiView.text != self.text {
uiView.text = self.text
if uiView.text != text {
uiView.text = text
}
uiView.placeholder = placeholder
@@ -103,17 +102,16 @@ struct ThemableTextField: UIViewRepresentable {
// MARK: - Private
private func replaceText(with newText: String) {
self.text = newText
text = newText
}
// MARK: - Coordinator
func makeCoordinator() -> Coordinator {
return Coordinator(self)
Coordinator(self)
}
class Coordinator: NSObject, UITextFieldDelegate {
var parent: ThemableTextField
init(_ parent: ThemableTextField) {
@@ -146,14 +144,13 @@ struct ThemableTextField: UIViewRepresentable {
private class InternalParams {
var isFirstResponder = false
}
}
// MARK: - modifiers
extension ThemableTextField {
func makeFirstResponder() -> ThemableTextField {
return makeFirstResponder(true)
makeFirstResponder(true)
}
func makeFirstResponder(_ isFirstResponder: Bool) -> ThemableTextField {
@@ -167,7 +164,7 @@ extension ThemableTextField {
/// - alignment: The vertical alignment of the button in the text field. Default to `center`
@ViewBuilder
func addButton(_ show: Bool, alignment: VerticalAlignment = .center) -> some View {
if show && configuration.isSecureTextEntry {
if show, configuration.isSecureTextEntry {
modifier(PasswordButtonModifier(text: text,
isSecureTextVisible: $isSecureTextVisible,
alignment: alignment))
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +20,7 @@ import SwiftUI
extension View {
@ViewBuilder func isHidden(_ isHidden: Bool) -> some View {
if isHidden {
self.hidden()
hidden()
} else {
self
}
@@ -1,4 +1,4 @@
//
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
@@ -18,7 +18,6 @@ import SwiftUI
/// A modifier for showing the wait overlay view over a view.
struct WaitOverlayModifier: ViewModifier {
var allowUserInteraction: Bool
var show: Bool
var message: String?
@@ -27,15 +26,16 @@ struct WaitOverlayModifier: ViewModifier {
func body(content: Content) -> some View {
content
.modifier(WaitOverlay(
allowUserInteraction: allowUserInteraction,
message: message,
isLoading: show))
allowUserInteraction: allowUserInteraction,
message: message,
isLoading: show
))
}
}
extension View {
func waitOverlay(show: Bool, message: String? = nil, allowUserInteraction: Bool = true) -> some View {
self.modifier(WaitOverlayModifier(allowUserInteraction: allowUserInteraction, show: show, message: message))
modifier(WaitOverlayModifier(allowUserInteraction: allowUserInteraction, show: show, message: message))
}
}
@@ -44,7 +44,7 @@ struct WaitOverlay: ViewModifier {
// MARK: - Properties
var alignment: Alignment = .center
var allowUserInteraction: Bool = true
var allowUserInteraction = true
var message: String?
var isLoading: Bool
@@ -66,8 +66,7 @@ struct WaitOverlay: ViewModifier {
// MARK: - Public
public func body(content: Content) -> some View
{
public func body(content: Content) -> some View {
ZStack {
content
if isLoading {
@@ -89,7 +88,7 @@ struct WaitOverlay: ViewModifier {
}
.padding(12)
.background(RoundedRectangle(cornerRadius: 8, style: .continuous)
.fill(theme.colors.navigation.opacity(0.9)))
.fill(theme.colors.navigation.opacity(0.9)))
}
.edgesIgnoringSafeArea(.all)
.transition(.opacity)
@@ -103,24 +102,24 @@ struct WaitOverlay_Previews: PreviewProvider {
static var previews: some View {
Group {
VStack {
ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {})
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {})
ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {})
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {})
ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { })
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { })
ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { })
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { })
}
.modifier(WaitOverlay(isLoading: true))
VStack {
ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {})
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {})
ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {})
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {})
ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { })
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { })
ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { })
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { })
}
.modifier(WaitOverlay(alignment:.topLeading, isLoading: true))
.modifier(WaitOverlay(alignment: .topLeading, isLoading: true))
VStack {
ThemableNavigationBar(title: nil, showBackButton: true, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: nil, showBackButton: false, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: {}, closeAction: {}).theme(.dark)
ThemableNavigationBar(title: nil, showBackButton: true, backAction: { }, closeAction: { }).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: true, backAction: { }, closeAction: { }).theme(.dark)
ThemableNavigationBar(title: nil, showBackButton: false, backAction: { }, closeAction: { }).theme(.dark)
ThemableNavigationBar(title: "Some Title", showBackButton: false, backAction: { }, closeAction: { }).theme(.dark)
}
.modifier(WaitOverlay(isLoading: true)).theme(.dark)