diff --git a/Components/Sources/Components/Assets.xcassets/editor/Contents.json b/Components/Sources/Components/Assets.xcassets/editor/Contents.json
deleted file mode 100644
index 6e965652df6..00000000000
--- a/Components/Sources/Components/Assets.xcassets/editor/Contents.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "info" : {
- "author" : "xcode",
- "version" : 1
- },
- "properties" : {
- "provides-namespace" : true
- }
-}
diff --git a/Components/Sources/Components/Assets.xcassets/editor/format-heading.imageset/Contents.json b/Components/Sources/Components/Assets.xcassets/editor/format-heading.imageset/Contents.json
deleted file mode 100644
index df5dab3d469..00000000000
--- a/Components/Sources/Components/Assets.xcassets/editor/format-heading.imageset/Contents.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "images" : [
- {
- "filename" : "format-heading.pdf",
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- },
- "properties" : {
- "template-rendering-intent" : "template"
- }
-}
diff --git a/Components/Sources/Components/Assets.xcassets/editor/format-heading.imageset/format-heading.pdf b/Components/Sources/Components/Assets.xcassets/editor/format-heading.imageset/format-heading.pdf
deleted file mode 100644
index e07d8a33641..00000000000
Binary files a/Components/Sources/Components/Assets.xcassets/editor/format-heading.imageset/format-heading.pdf and /dev/null differ
diff --git a/Components/Sources/Components/Assets.xcassets/editor/format-text.imageset/Contents.json b/Components/Sources/Components/Assets.xcassets/separator.imageset/Contents.json
similarity index 83%
rename from Components/Sources/Components/Assets.xcassets/editor/format-text.imageset/Contents.json
rename to Components/Sources/Components/Assets.xcassets/separator.imageset/Contents.json
index 7efb62f1c78..68b1578a788 100644
--- a/Components/Sources/Components/Assets.xcassets/editor/format-text.imageset/Contents.json
+++ b/Components/Sources/Components/Assets.xcassets/separator.imageset/Contents.json
@@ -1,7 +1,7 @@
{
"images" : [
{
- "filename" : "format-text.pdf",
+ "filename" : "separator.pdf",
"idiom" : "universal"
}
],
diff --git a/Components/Sources/Components/Assets.xcassets/editor/format-text.imageset/format-text.pdf b/Components/Sources/Components/Assets.xcassets/separator.imageset/separator.pdf
similarity index 54%
rename from Components/Sources/Components/Assets.xcassets/editor/format-text.imageset/format-text.pdf
rename to Components/Sources/Components/Assets.xcassets/separator.imageset/separator.pdf
index 2a69d1a6c52..04d07b798e4 100644
Binary files a/Components/Sources/Components/Assets.xcassets/editor/format-text.imageset/format-text.pdf and b/Components/Sources/Components/Assets.xcassets/separator.imageset/separator.pdf differ
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarButton.swift b/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarButton.swift
index cf60cdc87e2..b10a7623b57 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarButton.swift
+++ b/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarButton.swift
@@ -5,10 +5,8 @@ class WKEditorToolbarButton: WKComponentView {
// MARK: - Properties
- private lazy var button: UIButton = {
- let button = UIButton(type: .custom)
- return button
- }()
+ private var button: UIButton?
+ private var image: UIImage?
// MARK: - Lifecycle
@@ -23,6 +21,13 @@ class WKEditorToolbarButton: WKComponentView {
}
private func setup() {
+
+ button = createButton()
+
+ guard let button else {
+ return
+ }
+
layer.cornerRadius = 4
clipsToBounds = true
@@ -39,8 +44,6 @@ class WKEditorToolbarButton: WKComponentView {
button.topAnchor.constraint(equalTo: topAnchor),
button.bottomAnchor.constraint(equalTo: bottomAnchor)
])
-
- updateColors()
}
// MARK: - Overrides
@@ -52,49 +55,87 @@ class WKEditorToolbarButton: WKComponentView {
}
override func appEnvironmentDidChange() {
- updateColors()
+
+ guard let button else {
+ return
+ }
+
+ let buttonConfig = createButtonConfig(image: image)
+ button.configuration = buttonConfig
+ button.configurationUpdateHandler = buttonConfigurationUpdateHandler(button:)
}
// MARK: - Button passthrough methods
var isSelected: Bool {
get {
- return button.isSelected
+ return button?.isSelected ?? false
}
set {
- button.isSelected = newValue
- updateColors()
- accessibilityTraits = button.accessibilityTraits
+ button?.isSelected = newValue
+ accessibilityTraits = button?.accessibilityTraits ?? []
}
}
var isEnabled: Bool {
get {
- return button.isEnabled
+ return button?.isEnabled ?? true
}
set {
- button.isEnabled = newValue
- updateColors()
- accessibilityTraits = button.accessibilityTraits
+ button?.isEnabled = newValue
+ accessibilityTraits = button?.accessibilityTraits ?? []
}
}
- func setImage(_ image: UIImage?, for state: UIControl.State) {
- button.setImage(image, for: state)
+ func setImage(_ image: UIImage?) {
+
+ guard let button else {
+ return
+ }
+
+ self.image = image
+
+ var buttonConfig = button.configuration
+ buttonConfig?.image = image
+ button.configuration = buttonConfig
}
func addTarget(_ target: Any?, action: Selector, for controlEvent: UIControl.Event) {
- button.addTarget(target, action: action, for: controlEvent)
+ button?.addTarget(target, action: action, for: controlEvent)
}
func removeTarget(_ target: Any?, action: Selector?, for controlEvent: UIControl.Event) {
- button.removeTarget(target, action: action, for: controlEvent)
+ button?.removeTarget(target, action: action, for: controlEvent)
}
// MARK: - Private Helpers
- func updateColors() {
- button.tintColor = isSelected ? WKAppEnvironment.current.theme.inputAccessoryButtonSelectedTint : WKAppEnvironment.current.theme.inputAccessoryButtonTint
- backgroundColor = self.isSelected ? WKAppEnvironment.current.theme.inputAccessoryButtonSelectedBackgroundColor : .clear
+ private func createButtonConfig(image: UIImage? = nil) -> UIButton.Configuration {
+ var buttonConfig = UIButton.Configuration.plain()
+
+ buttonConfig.baseForegroundColor = (button?.isSelected ?? false) ? theme.inputAccessoryButtonSelectedTint : theme.inputAccessoryButtonTint
+ buttonConfig.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
+ buttonConfig.background.cornerRadius = 0
+ if let image {
+ buttonConfig.image = image
+ }
+
+ return buttonConfig
+ }
+
+ private func buttonConfigurationUpdateHandler(button: UIButton) {
+ var buttonConfig = button.configuration
+ buttonConfig?.baseForegroundColor = button.isSelected ? theme.inputAccessoryButtonSelectedTint : theme.inputAccessoryButtonTint
+ buttonConfig?.background.backgroundColor = button.isSelected ? theme.inputAccessoryButtonSelectedBackgroundColor : theme.accessoryBackground
+ button.configuration = buttonConfig
+ }
+
+ private func createButton() -> UIButton {
+
+ let buttonConfig = createButtonConfig()
+ let button = UIButton(configuration: buttonConfig)
+ button.configurationUpdateHandler = buttonConfigurationUpdateHandler(button:)
+
+ return button
}
}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarView.swift b/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarView.swift
index 6bad2c45cbd..9fe2eb37f79 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarView.swift
+++ b/Components/Sources/Components/Components/Editors/Common Views/Base/WKEditorToolbarView.swift
@@ -14,6 +14,7 @@ class WKEditorToolbarView: WKComponentView {
super.awakeFromNib()
accessibilityElements = buttons
updateColors()
+ maximumContentSizeCategory = .accessibilityMedium
}
// MARK: - Overrides
@@ -32,5 +33,10 @@ class WKEditorToolbarView: WKComponentView {
private func updateColors() {
tintColor = WKAppEnvironment.current.theme.link
backgroundColor = WKAppEnvironment.current.theme.accessoryBackground
+
+ layer.shadowOffset = CGSize(width: 0, height: -2)
+ layer.shadowRadius = 10
+ layer.shadowOpacity = 1.0
+ layer.shadowColor = theme.editorKeyboardShadow.cgColor
}
}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Expanding/WKEditorToolbarExpandingView.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Expanding/WKEditorToolbarExpandingView.swift
index 09b15ebca68..79d64bd89b3 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Expanding/WKEditorToolbarExpandingView.swift
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Expanding/WKEditorToolbarExpandingView.swift
@@ -85,70 +85,77 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
expandButton.setImage(WKSFSymbolIcon.for(symbol: .chevronRightCircle), for: .normal)
expandButton.addTarget(self, action: #selector(tappedExpand), for: .touchUpInside)
expandButton.isAccessibilityElement = false
+ updateExpandButtonVisibility()
- formatTextButton.setImage(WKIcon.formatText, for: .normal)
+ formatTextButton.setImage(WKSFSymbolIcon.for(symbol: .textFormat))
formatTextButton.addTarget(self, action: #selector(tappedFormatText), for: .touchUpInside)
formatTextButton.accessibilityIdentifier = WKSourceEditorAccessibilityIdentifiers.current?.formatTextButton
formatTextButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonFormatText
- referenceButton.setImage(WKSFSymbolIcon.for(symbol: .quoteOpening), for: .normal)
+ referenceButton.setImage(WKSFSymbolIcon.for(symbol: .quoteOpening))
referenceButton.addTarget(self, action: #selector(tappedReference), for: .touchUpInside)
referenceButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCitation
- linkButton.setImage(WKSFSymbolIcon.for(symbol: .link), for: .normal)
+ linkButton.setImage(WKSFSymbolIcon.for(symbol: .link))
linkButton.addTarget(self, action: #selector(tappedLink), for: .touchUpInside)
linkButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonLink
- templateButton.setImage(WKSFSymbolIcon.for(symbol: .curlybraces), for: .normal)
+ templateButton.setImage(WKSFSymbolIcon.for(symbol: .curlybraces))
templateButton.addTarget(self, action: #selector(tappedTemplate), for: .touchUpInside)
templateButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonTemplate
- imageButton.setImage(WKSFSymbolIcon.for(symbol: .photo), for: .normal)
+ imageButton.setImage(WKSFSymbolIcon.for(symbol: .photo))
imageButton.addTarget(self, action: #selector(tappedMedia), for: .touchUpInside)
imageButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonMedia
- findInPageButton.setImage(WKSFSymbolIcon.for(symbol: .docTextMagnifyingGlass), for: .normal)
+ findInPageButton.setImage(WKSFSymbolIcon.for(symbol: .docTextMagnifyingGlass))
findInPageButton.addTarget(self, action: #selector(tappedFindInPage), for: .touchUpInside)
findInPageButton.accessibilityIdentifier = WKSourceEditorAccessibilityIdentifiers.current?.findButton
findInPageButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonFind
- unorderedListButton.setImage(WKSFSymbolIcon.for(symbol: .listBullet), for: .normal)
+ unorderedListButton.setImage(WKSFSymbolIcon.for(symbol: .listBullet))
unorderedListButton.addTarget(self, action: #selector(tappedUnorderedList), for: .touchUpInside)
unorderedListButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonListUnordered
- orderedListButton.setImage(WKSFSymbolIcon.for(symbol: .listNumber), for: .normal)
+ orderedListButton.setImage(WKSFSymbolIcon.for(symbol: .listNumber))
orderedListButton.addTarget(self, action: #selector(tappedOrderedList), for: .touchUpInside)
orderedListButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonListOrdered
- decreaseIndentionButton.setImage(WKSFSymbolIcon.for(symbol: .decreaseIndent), for: .normal)
+ decreaseIndentionButton.setImage(WKSFSymbolIcon.for(symbol: .decreaseIndent))
decreaseIndentionButton.addTarget(self, action: #selector(tappedDecreaseIndentation), for: .touchUpInside)
decreaseIndentionButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonDecreaseIndent
decreaseIndentionButton.isEnabled = false
- increaseIndentionButton.setImage(WKSFSymbolIcon.for(symbol: .increaseIndent), for: .normal)
+ increaseIndentionButton.setImage(WKSFSymbolIcon.for(symbol: .increaseIndent))
increaseIndentionButton.addTarget(self, action: #selector(tappedIncreaseIndentation), for: .touchUpInside)
increaseIndentionButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonInceaseIndent
increaseIndentionButton.isEnabled = false
- cursorUpButton.setImage(WKSFSymbolIcon.for(symbol: .chevronUp), for: .normal)
+ cursorUpButton.setImage(WKSFSymbolIcon.for(symbol: .chevronUp))
cursorUpButton.addTarget(self, action: #selector(tappedCursorUp), for: .touchUpInside)
cursorUpButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCursorUp
- cursorDownButton.setImage(WKSFSymbolIcon.for(symbol: .chevronDown), for: .normal)
+ cursorDownButton.setImage(WKSFSymbolIcon.for(symbol: .chevronDown))
cursorDownButton.addTarget(self, action: #selector(tappedCursorDown), for: .touchUpInside)
cursorDownButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCursorDown
- cursorLeftButton.setImage(WKSFSymbolIcon.for(symbol: .chevronBackward), for: .normal)
+ cursorLeftButton.setImage(WKSFSymbolIcon.for(symbol: .chevronBackward))
cursorLeftButton.addTarget(self, action: #selector(tappedCursorLeft), for: .touchUpInside)
cursorLeftButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCursorLeft
- cursorRightButton.setImage(WKSFSymbolIcon.for(symbol: .chevronForward), for: .normal)
+ cursorRightButton.setImage(WKSFSymbolIcon.for(symbol: .chevronForward))
cursorRightButton.addTarget(self, action: #selector(tappedCursorRight), for: .touchUpInside)
cursorRightButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCursorRight
NotificationCenter.default.addObserver(self, selector: #selector(updateButtonSelectionState(_:)), name: Notification.WKSourceEditorSelectionState, object: nil)
}
+ // MARK: - Overrides
+
+ override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
+ updateExpandButtonVisibility()
+ }
+
// MARK: - Notifications
@objc private func updateButtonSelectionState(_ notification: NSNotification) {
@@ -281,5 +288,11 @@ class WKEditorToolbarExpandingView: WKEditorToolbarView {
@objc private func tappedMedia() {
delegate?.toolbarExpandingViewDidTapImage(toolbarView: self)
}
+
+ // MARK: - Private Helpers
+
+ private func updateExpandButtonVisibility() {
+ expandButton.isHidden = traitCollection.horizontalSizeClass == .regular
+ }
}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.swift
index 3a478fda465..fd4d876635b 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.swift
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.swift
@@ -54,29 +54,39 @@ class WKFindAndReplaceView: WKComponentView {
override func awakeFromNib() {
super.awakeFromNib()
+
+ maximumContentSizeCategory = .accessibilityLarge
closeButton.setImage(WKSFSymbolIcon.for(symbol: .close), for: .normal)
closeButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelFindButtonClose
previousButton.setImage(WKSFSymbolIcon.for(symbol: .chevronUp), for: .normal)
previousButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelFindButtonPrevious
+ previousButton.imageView?.contentMode = .center
nextButton.setImage(WKSFSymbolIcon.for(symbol: .chevronDown), for: .normal)
nextButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelFindButtonNext
+ nextButton.imageView?.contentMode = .center
replaceButton.setImage(WKIcon.replace, for: .normal)
replaceButton.accessibilityLabel = String.localizedStringWithFormat(WKSourceEditorLocalizedStrings.current.accessibilityLabelReplaceButtonPerformFormat, WKSourceEditorLocalizedStrings.current.accessibilityLabelReplaceTypeSingle)
+ replaceButton.imageView?.contentMode = .center
replaceSwitchButton.setImage(WKSFSymbolIcon.for(symbol: .ellipsis), for: .normal)
replaceSwitchButton.accessibilityLabel = String.localizedStringWithFormat(WKSourceEditorLocalizedStrings.current.accessibilityLabelReplaceButtonSwitchFormat, WKSourceEditorLocalizedStrings.current.accessibilityLabelReplaceTypeSingle)
+ replaceSwitchButton.imageView?.contentMode = .center
replaceSwitchButton.showsMenuAsPrimaryAction = true
replaceSwitchButton.menu = replaceSwitchButtonMenu()
magnifyImageView.image = WKSFSymbolIcon.for(symbol: .magnifyingGlass)
- pencilImageView.image = WKSFSymbolIcon.for(symbol: .pencil)
+ magnifyImageView.contentMode = .center
+ pencilImageView.image = WKIcon.pencil
+ pencilImageView.contentMode = .center
findClearButton.setImage(WKSFSymbolIcon.for(symbol: .multiplyCircleFill), for: .normal)
findClearButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelFindButtonClear
+ findClearButton.imageView?.contentMode = .center
replaceClearButton.setImage(WKSFSymbolIcon.for(symbol: .multiplyCircleFill), for: .normal)
replaceClearButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelReplaceButtonClear
+ replaceClearButton.imageView?.contentMode = .center
findTextField.adjustsFontForContentSizeCategory = true
findTextField.font = WKFont.for(.caption1, compatibleWith: appEnvironment.traitCollection)
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.xib b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.xib
index 5feca0d9b7f..e8c6d2c46b7 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.xib
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Find and Replace/WKFindAndReplaceView.xib
@@ -51,7 +51,7 @@
-
+
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Highlight/WKEditorToolbarHighlightView.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Highlight/WKEditorToolbarHighlightView.swift
index 33238ec9cd9..69d26511737 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Highlight/WKEditorToolbarHighlightView.swift
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Accessory Views/Highlight/WKEditorToolbarHighlightView.swift
@@ -32,23 +32,23 @@ class WKEditorToolbarHighlightView: WKEditorToolbarView {
stackView.isLayoutMarginsRelativeArrangement = true
stackView.layoutMargins = UIEdgeInsets(top: 5, left: 0, bottom: 5, right: 0)
- boldButton.setImage(WKSFSymbolIcon.for(symbol: .bold), for: .normal)
+ boldButton.setImage(WKSFSymbolIcon.for(symbol: .bold))
boldButton.addTarget(self, action: #selector(tappedBold), for: .touchUpInside)
boldButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonBold
- italicsButton.setImage(WKSFSymbolIcon.for(symbol: .italic), for: .normal)
+ italicsButton.setImage(WKSFSymbolIcon.for(symbol: .italic))
italicsButton.addTarget(self, action: #selector(tappedItalics), for: .touchUpInside)
italicsButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonItalics
- referenceButton.setImage(WKSFSymbolIcon.for(symbol: .quoteOpening), for: .normal)
+ referenceButton.setImage(WKSFSymbolIcon.for(symbol: .quoteOpening))
referenceButton.addTarget(self, action: #selector(tappedReference), for: .touchUpInside)
referenceButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonCitation
- linkButton.setImage(WKSFSymbolIcon.for(symbol: .link), for: .normal)
+ linkButton.setImage(WKSFSymbolIcon.for(symbol: .link))
linkButton.addTarget(self, action: #selector(tappedLink), for: .touchUpInside)
linkButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonLink
- templateButton.setImage(WKSFSymbolIcon.for(symbol: .curlybraces), for: .normal)
+ templateButton.setImage(WKSFSymbolIcon.for(symbol: .curlybraces))
templateButton.addTarget(self, action: #selector(tappedTemplate), for: .touchUpInside)
templateButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonTemplate
showMoreButton.setImage(WKSFSymbolIcon.for(symbol: .plusCircleFill), for: .normal)
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorHeaderSelectButton.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorHeaderSelectButton.swift
new file mode 100644
index 00000000000..b46a1ae4df4
--- /dev/null
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorHeaderSelectButton.swift
@@ -0,0 +1,124 @@
+import Foundation
+import UIKit
+
+final class WKEditorHeaderSelectButton: WKComponentView {
+
+ // MARK: - Nested Types
+
+ struct Configuration {
+ let title: String
+ let font: UIFont
+ }
+
+ // MARK: - Properties
+
+ let configuration: Configuration
+ var tapAction: (() -> Void)?
+ private var button: UIButton?
+
+ var isSelected: Bool {
+ get {
+ button?.isSelected ?? false
+ }
+ set {
+ button?.isSelected = newValue
+ }
+ }
+
+ // MARK: - Lifecycle
+
+ init(configuration: Configuration) {
+ self.configuration = configuration
+ super.init(frame: .zero)
+ setup()
+ }
+
+ public required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ // MARK: - Overrides
+
+ override var intrinsicContentSize: CGSize {
+ return button?.intrinsicContentSize ?? .zero
+ }
+
+ override func sizeThatFits(_ size: CGSize) -> CGSize {
+ return button?.sizeThatFits(size) ?? .zero
+ }
+
+ override func appEnvironmentDidChange() {
+
+ guard let button else {
+ return
+ }
+
+ let buttonConfig = createButtonConfig()
+ button.configuration = buttonConfig
+ button.configurationUpdateHandler = buttonConfigurationUpdateHandler(button:)
+ }
+
+ // MARK: - Private
+
+ private func setup() {
+
+ button = createButton()
+
+ guard let button else {
+ return
+ }
+
+ button.translatesAutoresizingMaskIntoConstraints = false
+ addSubview(button)
+ NSLayoutConstraint.activate([
+ topAnchor.constraint(equalTo: button.topAnchor),
+ leadingAnchor.constraint(equalTo: button.leadingAnchor),
+ trailingAnchor.constraint(equalTo: button.trailingAnchor),
+ bottomAnchor.constraint(equalTo: button.bottomAnchor)
+ ])
+ }
+
+ private func createButtonConfig() -> UIButton.Configuration {
+ var buttonConfig = UIButton.Configuration.plain()
+
+ var container = AttributeContainer()
+ container.font = configuration.font
+ container.foregroundColor = theme.text
+
+ buttonConfig.attributedTitle = AttributedString(configuration.title, attributes: container)
+ buttonConfig.baseForegroundColor = theme.text
+ buttonConfig.contentInsets = NSDirectionalEdgeInsets(top: 19, leading: 12, bottom: 19, trailing: 12)
+ buttonConfig.background.cornerRadius = 10
+
+ return buttonConfig
+ }
+
+ private func createButtonAction() -> UIAction {
+ return UIAction(title: configuration.title, handler: { [weak self] _ in
+ self?.tapAction?()
+ })
+ }
+
+ private func buttonConfigurationUpdateHandler(button: UIButton) {
+ var buttonConfig = button.configuration
+ buttonConfig?.background.backgroundColor = button.isSelected ? self.theme.link : self.theme.paperBackground
+
+ var container = AttributeContainer()
+ container.font = self.configuration.font
+ container.foregroundColor = button.isSelected ? self.theme.paperBackground : self.theme.text
+
+ buttonConfig?.attributedTitle = AttributedString(self.configuration.title, attributes: container)
+
+ button.configuration = buttonConfig
+ }
+
+ private func createButton() -> UIButton {
+
+ let buttonConfig = createButtonConfig()
+ let action = createButtonAction()
+ let button = UIButton(configuration: buttonConfig, primaryAction: action)
+ button.configurationUpdateHandler = buttonConfigurationUpdateHandler(button:)
+
+ return button
+ }
+}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorHeaderSelectScrollView.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorHeaderSelectScrollView.swift
new file mode 100644
index 00000000000..1df48927083
--- /dev/null
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorHeaderSelectScrollView.swift
@@ -0,0 +1,135 @@
+import Foundation
+import UIKit
+
+protocol WKEditorHeaderSelectScrollViewDelegate: AnyObject {
+ func didSelectIndex(_ index: Int, headerSelectScrollView: WKEditorHeaderSelectScrollView)
+}
+
+final class WKEditorHeaderSelectScrollView: WKComponentView {
+
+ // MARK: - Properties
+
+ private weak var delegate: WKEditorHeaderSelectScrollViewDelegate?
+ private var buttons: [WKEditorHeaderSelectButton] = []
+ private let configurations: [WKEditorHeaderSelectButton.Configuration]
+
+ private lazy var scrollView: UIScrollView = {
+ let scrollView = UIScrollView()
+ scrollView.translatesAutoresizingMaskIntoConstraints = false
+ scrollView.showsHorizontalScrollIndicator = false
+ scrollView.showsVerticalScrollIndicator = false
+ return scrollView
+ }()
+
+ private lazy var stackView: UIStackView = {
+ let stackView = UIStackView()
+ stackView.translatesAutoresizingMaskIntoConstraints = false
+ stackView.axis = .horizontal
+ stackView.distribution = .fill
+ stackView.alignment = .fill
+ return stackView
+ }()
+
+ // MARK: - Lifecycle
+
+ init(configurations: [WKEditorHeaderSelectButton.Configuration], delegate: WKEditorHeaderSelectScrollViewDelegate?) {
+ self.configurations = configurations
+ self.delegate = delegate
+ super.init(frame: .zero)
+ setup()
+ }
+
+ public required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ private func setup() {
+
+ addButtonsToStackView(stackView)
+ setupButtonTapActions()
+
+ scrollView.addSubview(stackView)
+
+ // pin stack view to scroll view content guide
+ // ensure it only scrolls horizontally
+ // set scroll view height to largest button height
+ NSLayoutConstraint.activate([
+ scrollView.contentLayoutGuide.topAnchor.constraint(equalTo: stackView.topAnchor),
+ stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor, constant: 16),
+ scrollView.contentLayoutGuide.trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: 16),
+ scrollView.contentLayoutGuide.bottomAnchor.constraint(equalTo: stackView.bottomAnchor),
+ scrollView.contentLayoutGuide.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor),
+ scrollView.heightAnchor.constraint(equalToConstant: largestButtonHeight)
+ ])
+
+ // Add scroll view to self, pin to edges
+ addSubview(scrollView)
+ NSLayoutConstraint.activate([
+ scrollView.frameLayoutGuide.topAnchor.constraint(equalTo: topAnchor),
+ scrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: leadingAnchor),
+ scrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: trailingAnchor),
+ scrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: bottomAnchor)
+ ])
+ }
+
+ // MARK: - Internal
+
+ func selectIndex(_ index: Int) {
+ guard buttons.count > index else {
+ return
+ }
+
+ buttons.forEach { $0.isSelected = false }
+
+ buttons[index].isSelected = true
+ }
+
+ // MARK: - Private
+
+ private func addButtonsToStackView(_ stackView: UIStackView) {
+
+ var buttons: [WKEditorHeaderSelectButton] = []
+
+ for configuration in configurations {
+ let button = WKEditorHeaderSelectButton(configuration: configuration)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ buttons.append(button)
+
+ stackView.addArrangedSubview(button)
+ }
+
+ self.buttons = buttons
+ }
+
+ private func setupButtonTapActions() {
+ for (index, button) in buttons.enumerated() {
+ button.tapAction = { [weak self] in
+
+ guard let self else {
+ return
+ }
+
+ for innerButton in self.buttons {
+ if button != innerButton {
+ innerButton.isSelected = false
+ } else {
+ innerButton.isSelected = true
+ self.delegate?.didSelectIndex(index, headerSelectScrollView: self)
+ }
+ }
+ }
+ }
+ }
+
+ private var largestButtonHeight: CGFloat {
+ var largestButtonHeight: CGFloat = 0
+ for button in buttons {
+ let buttonHeight = button.sizeThatFits(CGSize(width: .max, height: .max)).height
+ if buttonHeight > largestButtonHeight {
+ largestButtonHeight = buttonHeight
+ }
+ }
+
+ return largestButtonHeight
+ }
+}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorInputView.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorInputView.swift
index e7793b0cdb6..85f80be61fe 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorInputView.swift
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorInputView.swift
@@ -20,6 +20,7 @@ protocol WKEditorInputViewDelegate: AnyObject {
func didTapComment(isSelected: Bool)
}
+
class WKEditorInputView: WKComponentView {
// MARK: - Nested Types
@@ -42,6 +43,14 @@ class WKEditorInputView: WKComponentView {
case .subheading4: return WKSourceEditorLocalizedStrings.current.inputViewSubheading4
}
}
+
+ func font(traitCollection: UITraitCollection) -> UIFont {
+ switch self {
+ case .paragraph: return WKFont.for(.body, compatibleWith: traitCollection)
+ default:
+ return WKFont.for(.headline, compatibleWith: traitCollection)
+ }
+ }
}
// MARK: - Properties
@@ -59,7 +68,7 @@ class WKEditorInputView: WKComponentView {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.adjustsFontForContentSizeCategory = true
- label.font = WKFont.for(.headline, compatibleWith: appEnvironment.traitCollection)
+ label.font = WKFont.for(.boldTitle3, compatibleWith: appEnvironment.traitCollection)
label.text = WKSourceEditorLocalizedStrings.current.inputViewTextFormatting
label.setContentHuggingPriority(.defaultLow, for: .horizontal)
return label
@@ -68,16 +77,20 @@ class WKEditorInputView: WKComponentView {
private lazy var closeButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
- button.setImage(WKSFSymbolIcon.for(symbol: .multiplyCircleFill), for: .normal)
+ setCloseButtonImage(button: button)
button.addTarget(self, action: #selector(close(_:)), for: .touchUpInside)
button.accessibilityIdentifier = WKSourceEditorAccessibilityIdentifiers.current?.closeButton
button.accessibilityLabel = WKSourceEditorLocalizedStrings.current.accessibilityLabelButtonCloseMainInputView
+ button.setContentHuggingPriority(.required, for: .horizontal)
return button
}()
private lazy var containerScrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
+ scrollView.bounces = false
+ scrollView.clipsToBounds = true
+ scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
return scrollView
}()
@@ -87,51 +100,148 @@ class WKEditorInputView: WKComponentView {
stackView.axis = .vertical
stackView.distribution = .fill
stackView.alignment = .fill
+ stackView.spacing = 8
return stackView
}()
- private lazy var headingScrollView: UIScrollView = {
- let scrollView = UIScrollView()
- scrollView.translatesAutoresizingMaskIntoConstraints = false
- return scrollView
+ private lazy var headingButtonTypes: [HeadingButtonType] = {
+ return [.paragraph, .heading, .subheading1, .subheading2, .subheading3, .subheading4]
+ }()
+
+ private lazy var headerSelectScrollView: WKEditorHeaderSelectScrollView = {
+ let configurations: [WKEditorHeaderSelectButton.Configuration] = headingButtonTypes.map {
+
+ let title = $0.title
+ let font = $0.font(traitCollection: traitCollection)
+ let item = WKEditorHeaderSelectButton.Configuration(title: title, font: font)
+
+ return item
+ }
+
+ let scrollingChoiceView = WKEditorHeaderSelectScrollView(configurations: configurations, delegate: self)
+ scrollingChoiceView.translatesAutoresizingMaskIntoConstraints = false
+ return scrollingChoiceView
}()
- private lazy var headingStackView: UIStackView = {
+ private lazy var multiSelectStackView1: UIStackView = {
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .horizontal
- stackView.distribution = .fill
+ stackView.distribution = .fillEqually
stackView.alignment = .fill
+ stackView.spacing = 8
+ stackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
+ stackView.isLayoutMarginsRelativeArrangement = true
return stackView
}()
- private lazy var plainToolbarView: WKEditorToolbarPlainView = {
- let view = UINib(nibName: String(describing: WKEditorToolbarPlainView.self), bundle: Bundle.module).instantiate(withOwner: nil).first as! WKEditorToolbarPlainView
- view.delegate = delegate
- view.translatesAutoresizingMaskIntoConstraints = false
- return view
+ private lazy var multiSelectStackView2: UIStackView = {
+ let stackView = UIStackView()
+ stackView.translatesAutoresizingMaskIntoConstraints = false
+ stackView.axis = .horizontal
+ stackView.distribution = .fillEqually
+ stackView.alignment = .fill
+ stackView.spacing = 8
+ stackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
+ stackView.isLayoutMarginsRelativeArrangement = true
+ return stackView
}()
- private lazy var groupedToolbarView: WKEditorToolbarGroupedView = {
- let view = UINib(nibName: String(describing: WKEditorToolbarGroupedView.self), bundle: Bundle.module).instantiate(withOwner: nil).first as! WKEditorToolbarGroupedView
- view.delegate = delegate
- view.translatesAutoresizingMaskIntoConstraints = false
- return view
+ private lazy var accessibilityMultiSelectStackView: UIStackView = {
+ let stackView = UIStackView()
+ stackView.translatesAutoresizingMaskIntoConstraints = false
+ stackView.axis = .vertical
+ stackView.distribution = .fillEqually
+ stackView.alignment = .fill
+ stackView.spacing = 8
+ stackView.directionalLayoutMargins = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
+ stackView.isLayoutMarginsRelativeArrangement = true
+ return stackView
}()
- // Heading Buttons
- private var paragraphButton: UIButton!
- private var headerButton: UIButton!
- private var subheader1Button: UIButton!
- private var subheader2Button: UIButton!
- private var subheader3Button: UIButton!
- private var subheader4Button: UIButton!
+ private lazy var multiButtonBoldItalic: WKEditorMultiButton = {
+
+ let configuration = WKEditorMultiButton.Configuration(icons: [
+ WKSFSymbolIcon.for(symbol: .bold),
+ WKSFSymbolIcon.for(symbol: .italic)
+ ])
+
+ let button = WKEditorMultiButton(configuration: configuration, delegate: self)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ return button
+ }()
- var headingButtons: [UIButton] {
- return [paragraphButton, headerButton, subheader1Button, subheader2Button, subheader3Button, subheader4Button]
- }
+ private lazy var multiButtonUnderlineStrikethrough: WKEditorMultiButton = {
+
+ let configuration = WKEditorMultiButton.Configuration(icons: [
+ WKSFSymbolIcon.for(symbol: .underline),
+ WKSFSymbolIcon.for(symbol: .strikethrough)
+ ])
+
+ let button = WKEditorMultiButton(configuration: configuration, delegate: self)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ return button
+ }()
+
+ private lazy var multiButtonReferenceLink: WKEditorMultiButton = {
+
+ let configuration = WKEditorMultiButton.Configuration(icons: [
+ WKSFSymbolIcon.for(symbol: .quoteOpening),
+ WKSFSymbolIcon.for(symbol: .link)
+ ])
+
+ let button = WKEditorMultiButton(configuration: configuration, delegate: self)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ return button
+ }()
- private var divViews: [UIView] = []
+ private lazy var multiButtonBulletNumberList: WKEditorMultiButton = {
+
+ let configuration = WKEditorMultiButton.Configuration(icons: [
+ WKSFSymbolIcon.for(symbol: .listBullet),
+ WKSFSymbolIcon.for(symbol: .listNumber)
+ ])
+
+ let button = WKEditorMultiButton(configuration: configuration, delegate: self)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ return button
+ }()
+
+ private lazy var multiButtonIndentIncreaseDecrease: WKEditorMultiButton = {
+
+ let configuration = WKEditorMultiButton.Configuration(icons: [
+ WKSFSymbolIcon.for(symbol: .decreaseIndent),
+ WKSFSymbolIcon.for(symbol: .increaseIndent)
+ ])
+
+ let button = WKEditorMultiButton(configuration: configuration, delegate: self)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ return button
+ }()
+
+ private lazy var multiButtonSubscriptSuperscript: WKEditorMultiButton = {
+
+ let configuration = WKEditorMultiButton.Configuration(icons: [
+ WKSFSymbolIcon.for(symbol: .textFormatSuperscript),
+ WKSFSymbolIcon.for(symbol: .textFormatSubscript)
+ ])
+
+ let button = WKEditorMultiButton(configuration: configuration, delegate: self)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ return button
+ }()
+
+ private lazy var multiButtonTemplateComment: WKEditorMultiButton = {
+
+ let configuration = WKEditorMultiButton.Configuration(icons: [
+ WKSFSymbolIcon.for(symbol: .curlybraces),
+ WKSFSymbolIcon.for(symbol: .exclamationMarkCircle)
+ ])
+
+ let button = WKEditorMultiButton(configuration: configuration, delegate: self)
+ button.translatesAutoresizingMaskIntoConstraints = false
+ return button
+ }()
private weak var delegate: WKEditorInputViewDelegate?
@@ -160,54 +270,37 @@ class WKEditorInputView: WKComponentView {
safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: navigationStackView.trailingAnchor, constant: 16)
])
- // ---- Headings ----
-
- self.paragraphButton = headingButton(type: .paragraph)
- self.paragraphButton.isSelected = true
- self.headerButton = headingButton(type: .heading)
- self.subheader1Button = headingButton(type: .subheading1)
- self.subheader2Button = headingButton(type: .subheading2)
- self.subheader3Button = headingButton(type: .subheading3)
- self.subheader4Button = headingButton(type: .subheading4)
-
- headingStackView.addArrangedSubview(paragraphButton)
- headingStackView.addArrangedSubview(headerButton)
- headingStackView.addArrangedSubview(subheader1Button)
- headingStackView.addArrangedSubview(subheader2Button)
- headingStackView.addArrangedSubview(subheader3Button)
- headingStackView.addArrangedSubview(subheader4Button)
-
- headingScrollView.addSubview(headingStackView)
-
- let headerButtonSize = headerButton.sizeThatFits(bounds.size)
-
- // pin heading stack to heading scroll view content guide
- // ensure it only scrolls horizontally
- // set heading scroll view height to largest button height
- NSLayoutConstraint.activate([
- headingScrollView.contentLayoutGuide.topAnchor.constraint(equalTo: headingStackView.topAnchor),
- headingStackView.leadingAnchor.constraint(equalTo: headingScrollView.contentLayoutGuide.leadingAnchor, constant: 16),
- headingScrollView.contentLayoutGuide.trailingAnchor.constraint(equalTo: headingStackView.trailingAnchor, constant: 16),
- headingScrollView.contentLayoutGuide.bottomAnchor.constraint(equalTo: headingStackView.bottomAnchor),
- headingScrollView.contentLayoutGuide.heightAnchor.constraint(equalTo: headingScrollView.frameLayoutGuide.heightAnchor),
- headingScrollView.heightAnchor.constraint(equalToConstant: headerButtonSize.height)
- ])
-
// ---- Container ----
- containerStackView.addArrangedSubview(headingScrollView)
- let divView1 = divView()
- containerStackView.addArrangedSubview(divView1)
- containerStackView.addArrangedSubview(plainToolbarView)
- let divView2 = divView()
- containerStackView.addArrangedSubview(divView1)
- containerStackView.addArrangedSubview(groupedToolbarView)
- let divView3 = divView()
- containerStackView.addArrangedSubview(divView3)
- containerScrollView.addSubview(containerStackView)
-
- self.divViews = [divView1, divView2, divView3]
+ containerStackView.addArrangedSubview(headerSelectScrollView)
+ if traitCollection.preferredContentSizeCategory.isAccessibilityCategory {
+ accessibilityMultiSelectStackView.addArrangedSubview(multiButtonBoldItalic)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiButtonUnderlineStrikethrough)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiButtonReferenceLink)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiButtonBulletNumberList)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiButtonIndentIncreaseDecrease)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiButtonSubscriptSuperscript)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiButtonTemplateComment)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiSelectStackView1)
+ accessibilityMultiSelectStackView.addArrangedSubview(multiSelectStackView1)
+ containerStackView.addArrangedSubview(accessibilityMultiSelectStackView)
+ } else {
+ multiSelectStackView1.addArrangedSubview(multiButtonBoldItalic)
+ multiSelectStackView1.addArrangedSubview(multiButtonUnderlineStrikethrough)
+ multiSelectStackView1.addArrangedSubview(multiButtonReferenceLink)
+ containerStackView.addArrangedSubview(multiSelectStackView1)
+
+ multiSelectStackView2.addArrangedSubview(multiButtonBulletNumberList)
+ multiSelectStackView2.addArrangedSubview(multiButtonIndentIncreaseDecrease)
+ multiSelectStackView2.addArrangedSubview(multiButtonSubscriptSuperscript)
+ multiSelectStackView2.addArrangedSubview(multiButtonTemplateComment)
+ containerStackView.addArrangedSubview(multiSelectStackView2)
+ }
+
+ addSubview(containerScrollView)
+ containerScrollView.addSubview(containerStackView)
+
// pin container stack view to container scroll view content guide
NSLayoutConstraint.activate([
containerScrollView.contentLayoutGuide.topAnchor.constraint(equalTo: containerStackView.topAnchor),
@@ -216,14 +309,12 @@ class WKEditorInputView: WKComponentView {
containerScrollView.contentLayoutGuide.bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor)
])
- addSubview(containerScrollView)
-
- // pin scroll view frame guide to outer views
+ // pin scroll view to outer views
NSLayoutConstraint.activate([
- containerScrollView.frameLayoutGuide.topAnchor.constraint(equalTo: navigationStackView.bottomAnchor, constant: 18),
- containerScrollView.frameLayoutGuide.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
- containerScrollView.frameLayoutGuide.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
- containerScrollView.frameLayoutGuide.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
+ containerScrollView.topAnchor.constraint(equalTo: navigationStackView.bottomAnchor, constant: 18),
+ containerScrollView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor),
+ containerScrollView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor),
+ containerScrollView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor)
])
// Ensure it only scrolls vertically
@@ -243,7 +334,46 @@ class WKEditorInputView: WKComponentView {
return
}
- configure(selectionState: selectionState)
+ // Headers
+ if selectionState.isHeading {
+ headerSelectScrollView.selectIndex(1)
+ } else if selectionState.isSubheading1 {
+ headerSelectScrollView.selectIndex(2)
+ } else if selectionState.isSubheading2 {
+ headerSelectScrollView.selectIndex(3)
+ } else if selectionState.isSubheading3 {
+ headerSelectScrollView.selectIndex(4)
+ } else if selectionState.isSubheading4 {
+ headerSelectScrollView.selectIndex(5)
+ } else {
+ headerSelectScrollView.selectIndex(0) // Paragraph
+ }
+
+ // Top row
+ multiButtonBoldItalic.toggleSelectionIndex(0, shouldSelect: selectionState.isBold)
+ multiButtonBoldItalic.toggleSelectionIndex(1, shouldSelect: selectionState.isItalics)
+
+ multiButtonUnderlineStrikethrough.toggleSelectionIndex(0, shouldSelect: selectionState.isUnderline)
+ multiButtonUnderlineStrikethrough.toggleSelectionIndex(1, shouldSelect: selectionState.isStrikethrough)
+
+ multiButtonReferenceLink.toggleSelectionIndex(0, shouldSelect: selectionState.isHorizontalReference)
+ multiButtonReferenceLink.toggleSelectionIndex(1, shouldSelect: selectionState.isSimpleLink)
+
+ // Bottom row
+ multiButtonBulletNumberList.toggleSelectionIndex(0, shouldSelect: selectionState.isBulletSingleList || selectionState.isBulletMultipleList)
+ multiButtonBulletNumberList.toggleEnableIndex(0, shouldEnable: !selectionState.isNumberSingleList && !selectionState.isNumberMultipleList)
+
+ multiButtonBulletNumberList.toggleSelectionIndex(1, shouldSelect: selectionState.isNumberSingleList || selectionState.isNumberMultipleList)
+ multiButtonBulletNumberList.toggleEnableIndex(1, shouldEnable: !selectionState.isBulletSingleList && !selectionState.isBulletMultipleList)
+
+ multiButtonIndentIncreaseDecrease.toggleEnableIndex(0, shouldEnable: selectionState.isBulletMultipleList || selectionState.isNumberMultipleList)
+ multiButtonIndentIncreaseDecrease.toggleEnableIndex(1, shouldEnable: selectionState.isBulletSingleList || selectionState.isBulletMultipleList || selectionState.isNumberSingleList || selectionState.isNumberMultipleList)
+
+ multiButtonSubscriptSuperscript.toggleSelectionIndex(0, shouldSelect: selectionState.isSuperscript)
+ multiButtonSubscriptSuperscript.toggleSelectionIndex(1, shouldSelect: selectionState.isSubscript)
+
+ multiButtonTemplateComment.toggleSelectionIndex(0, shouldSelect: selectionState.isHorizontalTemplate)
+ multiButtonTemplateComment.toggleSelectionIndex(1, shouldSelect: selectionState.isComment)
}
// MARK: - Overrides
@@ -252,6 +382,11 @@ class WKEditorInputView: WKComponentView {
updateColors()
}
+ override func layoutSubviews() {
+ super.layoutSubviews()
+ containerScrollView.flashScrollIndicators()
+ }
+
// MARK: - Button Actions
@objc private func close(_ sender: UIBarButtonItem) {
@@ -261,85 +396,106 @@ class WKEditorInputView: WKComponentView {
// MARK: - Private Helpers
private func updateColors() {
- backgroundColor = WKAppEnvironment.current.theme.accessoryBackground
- titleLabel.textColor = WKAppEnvironment.current.theme.text
- closeButton.tintColor = WKAppEnvironment.current.theme.inputAccessoryButtonTint
- divViews.forEach { view in
- view.backgroundColor = WKAppEnvironment.current.theme.border
- }
+ backgroundColor = theme.paperBackground
+ titleLabel.textColor = theme.text
+ setCloseButtonImage(button: closeButton)
+
+ layer.shadowOffset = CGSize(width: 0, height: -2)
+ layer.shadowRadius = 10
+ layer.shadowOpacity = 1.0
+ layer.shadowColor = theme.editorKeyboardShadow.cgColor
}
- private func divView() -> UIView {
- let view = UIView()
- view.translatesAutoresizingMaskIntoConstraints = false
- view.heightAnchor.constraint(equalToConstant: 0.5).isActive = true
- return view
+ private func setCloseButtonImage(button: UIButton) {
+ let image = WKSFSymbolIcon.for(symbol: .multiplyCircleFill, font: .title1, paletteColors: [theme.secondaryText, theme.midBackground])
+ button.setImage(image, for: .normal)
}
-
- private func headingButton(type: HeadingButtonType) -> UIButton {
-
- let font: UIFont
- switch type {
- case .paragraph: font = WKFont.for(.body, compatibleWith: traitCollection)
- case .heading: font = WKFont.for(.headline, compatibleWith: traitCollection)
- default: font = WKFont.for(.subheadline, compatibleWith: traitCollection)
+}
+
+// MARK: - WKEditorHeaderSelectScrollViewDelegate
+
+extension WKEditorInputView: WKEditorHeaderSelectScrollViewDelegate {
+ func didSelectIndex(_ index: Int, headerSelectScrollView: WKEditorHeaderSelectScrollView) {
+ guard headingButtonTypes.count > index else {
+ return
}
- var configuration = UIButton.Configuration.plain()
- configuration.titleTextAttributesTransformer =
- UIConfigurationTextAttributesTransformer { incoming in
- var outgoing = incoming
- outgoing.font = font
- outgoing.foregroundColor = WKAppEnvironment.current.theme.text
- return outgoing
- }
- configuration.contentInsets = NSDirectionalEdgeInsets(top: 19, leading: 12, bottom: 19, trailing: 12)
- let action = UIAction(title: type.title, handler: { [weak self] _ in
-
- guard let self else {
- return
+ let headingType = headingButtonTypes[index]
+ delegate?.didTapHeading(type: headingType)
+ }
+}
+
+// MARK: - WKEditorHeaderSelectScrollViewDelegate
+
+extension WKEditorInputView: WKEditorMultiSelectButtonDelegate {
+ func didSelectIndex(_ index: Int, isSelected: Bool, multiSelectButton: WKEditorMultiButton) {
+
+ switch multiSelectButton {
+ case multiButtonBoldItalic:
+ switch index {
+ case 0:
+ delegate?.didTapBold(isSelected: isSelected)
+ case 1:
+ delegate?.didTapItalics(isSelected: isSelected)
+ default:
+ break
}
-
- self.headingButtons.forEach { button in
- button.isSelected = false
+ case multiButtonUnderlineStrikethrough:
+ switch index {
+ case 0:
+ delegate?.didTapUnderline(isSelected: isSelected)
+ case 1:
+ delegate?.didTapStrikethrough(isSelected: isSelected)
+ default:
+ break
}
-
- switch type {
- case .paragraph:
- paragraphButton.isSelected = true
- case .heading:
- headerButton.isSelected = true
- case .subheading1:
- subheader1Button.isSelected = true
- case .subheading2:
- subheader2Button.isSelected = true
- case .subheading3:
- subheader3Button.isSelected = true
- case .subheading4:
- subheader4Button.isSelected = true
+ case multiButtonReferenceLink:
+ switch index {
+ case 0:
+ delegate?.didTapReference(isSelected: isSelected)
+ case 1:
+ delegate?.didTapLink(isSelected: isSelected)
+ default:
+ break
}
-
- delegate?.didTapHeading(type: type)
- })
-
- return UIButton(configuration: configuration, primaryAction: action)
- }
-
- func configure(selectionState: WKSourceEditorSelectionState) {
- headingButtons.forEach { $0.isSelected = false }
-
- if selectionState.isHeading {
- headerButton.isSelected = true
- } else if selectionState.isSubheading1 {
- subheader1Button.isSelected = true
- } else if selectionState.isSubheading2 {
- subheader2Button.isSelected = true
- } else if selectionState.isSubheading3 {
- subheader3Button.isSelected = true
- } else if selectionState.isSubheading4 {
- subheader4Button.isSelected = true
- } else {
- paragraphButton.isSelected = true
+ case multiButtonBulletNumberList:
+ switch index {
+ case 0:
+ delegate?.didTapBulletList(isSelected: isSelected)
+ case 1:
+ delegate?.didTapNumberList(isSelected: isSelected)
+ default:
+ break
+ }
+ case multiButtonIndentIncreaseDecrease:
+ switch index {
+ case 0:
+ delegate?.didTapDecreaseIndent()
+ case 1:
+ delegate?.didTapIncreaseIndent()
+ default:
+ break
+ }
+ case multiButtonSubscriptSuperscript:
+ switch index {
+ case 0:
+ delegate?.didTapSuperscript(isSelected: isSelected)
+ case 1:
+ delegate?.didTapSubscript(isSelected: isSelected)
+ default:
+ break
+ }
+ case multiButtonTemplateComment:
+ switch index {
+ case 0:
+ delegate?.didTapTemplate(isSelected: isSelected)
+ case 1:
+ delegate?.didTapComment(isSelected: isSelected)
+ default:
+ break
+ }
+ default:
+ break
}
}
}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorMultiButton.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorMultiButton.swift
new file mode 100644
index 00000000000..084b680fbd9
--- /dev/null
+++ b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorMultiButton.swift
@@ -0,0 +1,143 @@
+import Foundation
+import UIKit
+
+protocol WKEditorMultiSelectButtonDelegate: AnyObject {
+ func didSelectIndex(_ index: Int, isSelected: Bool, multiSelectButton: WKEditorMultiButton)
+}
+
+final class WKEditorMultiButton: WKComponentView {
+
+ // MARK: - Nested Types
+
+ struct Configuration {
+ let icons: [UIImage?]
+ }
+
+ // MARK: - Properties
+
+ private let configuration: Configuration
+ private var buttons: [UIButton] = []
+ private weak var delegate: WKEditorMultiSelectButtonDelegate?
+
+ private lazy var stackView: UIStackView = {
+ let stackView = UIStackView()
+ stackView.translatesAutoresizingMaskIntoConstraints = false
+ stackView.axis = .horizontal
+ stackView.distribution = .fillEqually
+ stackView.alignment = .center
+ stackView.spacing = 2
+ return stackView
+ }()
+
+ // MARK: - Lifecycle
+
+ init(configuration: Configuration, delegate: WKEditorMultiSelectButtonDelegate) {
+ self.configuration = configuration
+ self.delegate = delegate
+ super.init(frame: .zero)
+ setup()
+ }
+
+ public required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ private func setup() {
+
+ createAndAddButtonsToStackView()
+
+ addSubview(stackView)
+ NSLayoutConstraint.activate([
+ topAnchor.constraint(equalTo: stackView.topAnchor),
+ leadingAnchor.constraint(equalTo: stackView.leadingAnchor),
+ trailingAnchor.constraint(equalTo: stackView.trailingAnchor),
+ bottomAnchor.constraint(equalTo: stackView.bottomAnchor)
+ ])
+
+ layer.cornerRadius = 10
+ layer.masksToBounds = true
+ }
+
+ // MARK: - Overrides
+
+ override func appEnvironmentDidChange() {
+
+ for (icon, button) in zip(configuration.icons, buttons) {
+ let buttonConfig = createButtonConfig(image: icon)
+ button.configuration = buttonConfig
+ button.configurationUpdateHandler = buttonConfigurationUpdateHandler(button:)
+ }
+ }
+
+ // MARK: - Internal
+
+ func toggleSelectionIndex(_ index: Int, shouldSelect: Bool) {
+ guard buttons.count > index else {
+ return
+ }
+
+ buttons[index].isSelected = shouldSelect
+ }
+
+ func toggleEnableIndex(_ index: Int, shouldEnable: Bool) {
+ guard buttons.count > index else {
+ return
+ }
+
+ buttons[index].isEnabled = shouldEnable
+ }
+
+ // MARK: - Private
+
+ private func createAndAddButtonsToStackView() {
+ var buttons: [UIButton] = []
+ for (index, icon) in configuration.icons.enumerated() {
+ let button = createButton(icon: icon, tapAction: { [weak self] in
+ guard let self else {
+ return
+ }
+ let isSelected = buttons[index].isSelected
+ delegate?.didSelectIndex(index, isSelected: isSelected, multiSelectButton: self)
+ })
+ buttons.append(button)
+ stackView.addArrangedSubview(button)
+ }
+ self.buttons = buttons
+ }
+
+ private func createButtonConfig(image: UIImage?) -> UIButton.Configuration {
+ var buttonConfig = UIButton.Configuration.plain()
+
+ buttonConfig.baseForegroundColor = theme.text
+ buttonConfig.contentInsets = NSDirectionalEdgeInsets(top: 19, leading: 19, bottom: 19, trailing: 19)
+ buttonConfig.background.cornerRadius = 0
+ buttonConfig.image = image
+
+ return buttonConfig
+ }
+
+ private func createButtonAction(action: @escaping () -> Void) -> UIAction {
+ return UIAction(title: "", handler: { _ in
+ action()
+ })
+ }
+
+ private func buttonConfigurationUpdateHandler(button: UIButton) {
+ var buttonConfig = button.configuration
+
+ buttonConfig?.background.backgroundColor = button.isSelected ? self.theme.editorMultiButtonSelectedBackground : self.theme.midBackground
+
+ button.configuration = buttonConfig
+ }
+
+ private func createButton(icon: UIImage?, tapAction: @escaping () -> Void) -> UIButton {
+
+ let buttonConfig = createButtonConfig(image: icon)
+ let action = createButtonAction(action: tapAction)
+ let button = UIButton(configuration: buttonConfig, primaryAction: action)
+ button.configurationUpdateHandler = buttonConfigurationUpdateHandler(button:)
+ button.translatesAutoresizingMaskIntoConstraints = false
+
+ return button
+ }
+}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarGroupedView.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarGroupedView.swift
deleted file mode 100644
index a77124d43a4..00000000000
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarGroupedView.swift
+++ /dev/null
@@ -1,127 +0,0 @@
-import Foundation
-
-class WKEditorToolbarGroupedView: WKEditorToolbarView {
-
- // MARK: - Properties
-
- @IBOutlet private weak var unorderedListButton: WKEditorToolbarButton!
- @IBOutlet private weak var orderedListButton: WKEditorToolbarButton!
- @IBOutlet private weak var decreaseIndentButton: WKEditorToolbarButton!
- @IBOutlet private weak var increaseIndentButton: WKEditorToolbarButton!
- @IBOutlet private weak var superscriptButton: WKEditorToolbarButton!
- @IBOutlet private weak var subscriptButton: WKEditorToolbarButton!
- @IBOutlet private weak var underlineButton: WKEditorToolbarButton!
- @IBOutlet private weak var strikethroughButton: WKEditorToolbarButton!
-
- weak var delegate: WKEditorInputViewDelegate?
-
- // MARK: - Lifecycle
-
- override func awakeFromNib() {
- super.awakeFromNib()
-
- unorderedListButton.setImage(WKSFSymbolIcon.for(symbol: .listBullet), for: .normal)
- unorderedListButton.addTarget(self, action: #selector(tappedUnorderedList), for: .touchUpInside)
- unorderedListButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonListUnordered
-
- orderedListButton.setImage(WKSFSymbolIcon.for(symbol: .listNumber), for: .normal)
- orderedListButton.addTarget(self, action: #selector(tappedOrderedList), for: .touchUpInside)
- orderedListButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonListOrdered
-
- decreaseIndentButton.setImage(WKSFSymbolIcon.for(symbol: .decreaseIndent), for: .normal)
- decreaseIndentButton.addTarget(self, action: #selector(tappedDecreaseIndent), for: .touchUpInside)
- decreaseIndentButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonDecreaseIndent
- decreaseIndentButton.isEnabled = false
-
- increaseIndentButton.setImage(WKSFSymbolIcon.for(symbol: .increaseIndent), for: .normal)
- increaseIndentButton.addTarget(self, action: #selector(tappedIncreaseIndent), for: .touchUpInside)
- increaseIndentButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonInceaseIndent
- increaseIndentButton.isEnabled = false
-
- superscriptButton.setImage(WKSFSymbolIcon.for(symbol: .textFormatSuperscript), for: .normal)
- superscriptButton.addTarget(self, action: #selector(tappedSuperscript), for: .touchUpInside)
- superscriptButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonSuperscript
-
- subscriptButton.setImage(WKSFSymbolIcon.for(symbol: .textFormatSubscript), for: .normal)
- subscriptButton.addTarget(self, action: #selector(tappedSubscript), for: .touchUpInside)
- subscriptButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonSubscript
-
- underlineButton.setImage(WKSFSymbolIcon.for(symbol: .underline), for: .normal)
- underlineButton.addTarget(self, action: #selector(tappedUnderline), for: .touchUpInside)
- underlineButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonUnderline
-
- strikethroughButton.setImage(WKSFSymbolIcon.for(symbol: .strikethrough), for: .normal)
- strikethroughButton.addTarget(self, action: #selector(tappedStrikethrough), for: .touchUpInside)
- strikethroughButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonStrikethrough
-
- NotificationCenter.default.addObserver(self, selector: #selector(updateButtonSelectionState(_:)), name: Notification.WKSourceEditorSelectionState, object: nil)
- }
-
- // MARK: - Notifications
-
- @objc private func updateButtonSelectionState(_ notification: NSNotification) {
- guard let selectionState = notification.userInfo?[Notification.WKSourceEditorSelectionStateKey] as? WKSourceEditorSelectionState else {
- return
- }
-
- unorderedListButton.isSelected = selectionState.isBulletSingleList || selectionState.isBulletMultipleList
- unorderedListButton.isEnabled = !selectionState.isNumberSingleList && !selectionState.isNumberMultipleList
-
- orderedListButton.isSelected = selectionState.isNumberSingleList || selectionState.isNumberMultipleList
- orderedListButton.isEnabled = !selectionState.isBulletSingleList && !selectionState.isBulletMultipleList
-
- decreaseIndentButton.isEnabled = false
- if selectionState.isBulletMultipleList || selectionState.isNumberMultipleList {
- decreaseIndentButton.isEnabled = true
- }
-
- if selectionState.isBulletSingleList ||
- selectionState.isBulletMultipleList ||
- selectionState.isNumberSingleList ||
- selectionState.isNumberMultipleList {
- increaseIndentButton.isEnabled = true
- } else {
- increaseIndentButton.isEnabled = false
- }
-
- strikethroughButton.isSelected = selectionState.isStrikethrough
- subscriptButton.isSelected = selectionState.isSubscript
- superscriptButton.isSelected = selectionState.isSuperscript
- underlineButton.isSelected = selectionState.isUnderline
- }
-
- // MARK: - Button Actions
-
- @objc private func tappedIncreaseIndent() {
- delegate?.didTapIncreaseIndent()
- }
-
- @objc private func tappedDecreaseIndent() {
- delegate?.didTapDecreaseIndent()
- }
-
- @objc private func tappedUnorderedList() {
- delegate?.didTapBulletList(isSelected: unorderedListButton.isSelected)
- }
-
- @objc private func tappedOrderedList() {
- delegate?.didTapNumberList(isSelected: orderedListButton.isSelected)
- }
-
- @objc private func tappedSuperscript() {
- delegate?.didTapSuperscript(isSelected: superscriptButton.isSelected)
- }
-
- @objc private func tappedSubscript() {
- delegate?.didTapSubscript(isSelected: subscriptButton.isSelected)
- }
-
- @objc private func tappedUnderline() {
- delegate?.didTapUnderline(isSelected: underlineButton.isSelected)
- }
-
- @objc private func tappedStrikethrough() {
- delegate?.didTapStrikethrough(isSelected: strikethroughButton.isSelected)
- }
-
-}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarGroupedView.xib b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarGroupedView.xib
deleted file mode 100644
index 4de041a4125..00000000000
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarGroupedView.xib
+++ /dev/null
@@ -1,138 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarPlainView.swift b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarPlainView.swift
deleted file mode 100644
index c04248ff088..00000000000
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarPlainView.swift
+++ /dev/null
@@ -1,88 +0,0 @@
-import Foundation
-
-class WKEditorToolbarPlainView: WKEditorToolbarView {
-
- // MARK: Properties
-
- @IBOutlet private weak var boldButton: WKEditorToolbarButton!
- @IBOutlet private weak var italicsButton: WKEditorToolbarButton!
- @IBOutlet private weak var referenceButton: WKEditorToolbarButton!
- @IBOutlet private weak var linkButton: WKEditorToolbarButton!
- @IBOutlet private weak var templateButton: WKEditorToolbarButton!
- @IBOutlet private weak var commentButton: WKEditorToolbarButton!
-
- weak var delegate: WKEditorInputViewDelegate?
-
- // MARK: Lifecycle
-
- override func awakeFromNib() {
- super.awakeFromNib()
-
- boldButton.setImage(WKSFSymbolIcon.for(symbol: .bold), for: .normal)
- boldButton.addTarget(self, action: #selector(tappedBold), for: .touchUpInside)
- boldButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonBold
-
- italicsButton.setImage(WKSFSymbolIcon.for(symbol: .italic), for: .normal)
- italicsButton.addTarget(self, action: #selector(tappedItalics), for: .touchUpInside)
- italicsButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonItalics
-
- referenceButton.setImage(WKSFSymbolIcon.for(symbol: .quoteOpening), for: .normal)
- referenceButton.addTarget(self, action: #selector(tappedReference), for: .touchUpInside)
- referenceButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonCitation
-
- linkButton.setImage(WKIcon.link, for: .normal)
- linkButton.addTarget(self, action: #selector(tappedLink), for: .touchUpInside)
- linkButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonLink
-
- templateButton.setImage(WKSFSymbolIcon.for(symbol: .curlybraces), for: .normal)
- templateButton.addTarget(self, action: #selector(tappedTemplate), for: .touchUpInside)
- templateButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonTemplate
-
- commentButton.setImage(WKIcon.exclamationPointCircle, for: .normal)
- commentButton.addTarget(self, action: #selector(tappedComment), for: .touchUpInside)
- commentButton.accessibilityLabel = WKSourceEditorLocalizedStrings.current?.accessibilityLabelButtonComment
-
- NotificationCenter.default.addObserver(self, selector: #selector(updateButtonSelectionState(_:)), name: Notification.WKSourceEditorSelectionState, object: nil)
- }
-
- // MARK: - Notifications
-
- @objc private func updateButtonSelectionState(_ notification: NSNotification) {
- guard let selectionState = notification.userInfo?[Notification.WKSourceEditorSelectionStateKey] as? WKSourceEditorSelectionState else {
- return
- }
-
- boldButton.isSelected = selectionState.isBold
- italicsButton.isSelected = selectionState.isItalics
- templateButton.isSelected = selectionState.isHorizontalTemplate
- referenceButton.isSelected = selectionState.isHorizontalReference
- linkButton.isSelected = selectionState.isSimpleLink
- commentButton.isSelected = selectionState.isComment
- }
-
- // MARK: Button Actions
-
- @objc private func tappedBold() {
- delegate?.didTapBold(isSelected: boldButton.isSelected)
- }
-
- @objc private func tappedItalics() {
- delegate?.didTapItalics(isSelected: italicsButton.isSelected)
- }
-
- @objc private func tappedReference() {
- delegate?.didTapReference(isSelected: referenceButton.isSelected)
- }
-
- @objc private func tappedTemplate() {
- delegate?.didTapTemplate(isSelected: templateButton.isSelected)
- }
-
- @objc private func tappedComment() {
- delegate?.didTapComment(isSelected: commentButton.isSelected)
- }
-
- @objc private func tappedLink() {
- delegate?.didTapLink(isSelected: linkButton.isSelected)
- }
-}
diff --git a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarPlainView.xib b/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarPlainView.xib
deleted file mode 100644
index 61d1e9b3fb0..00000000000
--- a/Components/Sources/Components/Components/Editors/Common Views/Input Views/WKEditorToolbarPlainView.xib
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Components/Sources/Components/Components/Editors/Common Views/WKEditorToolbarNavigatorButton.swift b/Components/Sources/Components/Components/Editors/Common Views/WKEditorToolbarNavigatorButton.swift
index 2f11153f3a1..c5b9f627650 100644
--- a/Components/Sources/Components/Components/Editors/Common Views/WKEditorToolbarNavigatorButton.swift
+++ b/Components/Sources/Components/Components/Editors/Common Views/WKEditorToolbarNavigatorButton.swift
@@ -4,11 +4,9 @@ import UIKit
class WKEditorToolbarNavigatorButton: WKComponentView {
// MARK: - Properties
-
- private lazy var button: UIButton = {
- let button = UIButton(type: .custom)
- return button
- }()
+
+ private var button: UIButton?
+ private var image: UIImage?
// MARK: - Lifecycle
@@ -23,6 +21,12 @@ class WKEditorToolbarNavigatorButton: WKComponentView {
}
private func setup() {
+ button = createButton()
+
+ guard let button else {
+ return
+ }
+
isAccessibilityElement = true
accessibilityTraits = [.button]
button.isAccessibilityElement = false
@@ -36,21 +40,69 @@ class WKEditorToolbarNavigatorButton: WKComponentView {
button.topAnchor.constraint(equalTo: topAnchor),
button.bottomAnchor.constraint(equalTo: bottomAnchor)
])
+ }
+
+ // MARK: - Overrides
+
+ override var intrinsicContentSize: CGSize {
+ // Increase touch targets & make widths more consistent
+ let superSize = super.intrinsicContentSize
+ return CGSize(width: max(superSize.width, 36), height: max(superSize.height, 36))
+ }
+
+ override func appEnvironmentDidChange() {
+
+ guard let button else {
+ return
+ }
- button.imageView?.contentMode = .scaleAspectFit
+ let buttonConfig = createButtonConfig(image: image)
+ button.configuration = buttonConfig
}
// MARK: - Button passthrough methods
func setImage(_ image: UIImage?, for state: UIControl.State) {
- button.setImage(image, for: state)
+
+ guard let button else {
+ return
+ }
+
+ self.image = image
+
+ var buttonConfig = button.configuration
+ buttonConfig?.image = image
+ button.configuration = buttonConfig
}
func addTarget(_ target: Any?, action: Selector, for controlEvent: UIControl.Event) {
- button.addTarget(target, action: action, for: controlEvent)
+ button?.addTarget(target, action: action, for: controlEvent)
}
func removeTarget(_ target: Any?, action: Selector?, for controlEvent: UIControl.Event) {
- button.removeTarget(target, action: action, for: controlEvent)
+ button?.removeTarget(target, action: action, for: controlEvent)
+ }
+
+ // MARK: - Private Helpers
+
+ private func createButtonConfig(image: UIImage? = nil) -> UIButton.Configuration {
+ var buttonConfig = UIButton.Configuration.plain()
+
+ buttonConfig.baseForegroundColor = theme.link
+ buttonConfig.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0)
+ buttonConfig.background.cornerRadius = 0
+ if let image {
+ buttonConfig.image = image
+ }
+
+ return buttonConfig
+ }
+
+ private func createButton() -> UIButton {
+
+ let buttonConfig = createButtonConfig()
+ let button = UIButton(configuration: buttonConfig)
+
+ return button
}
}
diff --git a/Components/Sources/Components/Components/Editors/Source Editor/WKSourceEditorViewController.swift b/Components/Sources/Components/Components/Editors/Source Editor/WKSourceEditorViewController.swift
index 1afcdae0f11..c794aef101b 100644
--- a/Components/Sources/Components/Components/Editors/Source Editor/WKSourceEditorViewController.swift
+++ b/Components/Sources/Components/Components/Editors/Source Editor/WKSourceEditorViewController.swift
@@ -267,6 +267,10 @@ public class WKSourceEditorViewController: WKComponentViewController {
public func redo() {
textView.undoManager?.redo()
}
+
+ public func removeFocus() {
+ textView.resignFirstResponder()
+ }
}
// MARK: - Private
diff --git a/Components/Sources/Components/Components/Onboarding/WKOnboardingView.swift b/Components/Sources/Components/Components/Onboarding/WKOnboardingView.swift
index 3d91b738309..bafb1334f3f 100644
--- a/Components/Sources/Components/Components/Onboarding/WKOnboardingView.swift
+++ b/Components/Sources/Components/Components/Onboarding/WKOnboardingView.swift
@@ -25,7 +25,7 @@ public struct WKOnboardingView: View {
ScrollView(showsIndicators: true) {
VStack {
Text(viewModel.title)
- .font(Font(WKFont.for(.boldTitle)))
+ .font(Font(WKFont.for(.boldTitle1)))
.foregroundColor(Color(appEnvironment.theme.text))
.padding([.bottom, .top], 44)
.multilineTextAlignment(.center)
diff --git a/Components/Sources/Components/Components/Shared/WKCheckmarkView.swift b/Components/Sources/Components/Components/Shared/WKCheckmarkView.swift
index c94ccf268e7..cc3b29c2779 100644
--- a/Components/Sources/Components/Components/Shared/WKCheckmarkView.swift
+++ b/Components/Sources/Components/Components/Shared/WKCheckmarkView.swift
@@ -23,7 +23,7 @@ struct WKCheckmarkView: View {
private var uiImage: UIImage? {
switch configuration.style {
case .checkbox:
- return isSelected ? WKSFSymbolIcon.for(symbol: .checkmarkSquareFill, font: .subheadline) : WKSFSymbolIcon.for(symbol: .square, font: .subheadline)
+ return isSelected ? WKSFSymbolIcon.for(symbol: .checkmarkSquareFill) : WKSFSymbolIcon.for(symbol: .square)
case .`default`:
return isSelected ? WKSFSymbolIcon.for(symbol: .checkmark, font: .boldFootnote) : nil
}
diff --git a/Components/Sources/Components/Components/Shared/WKPriceTextField.swift b/Components/Sources/Components/Components/Shared/WKPriceTextField.swift
index 29661a007fb..dd0b92c232c 100644
--- a/Components/Sources/Components/Components/Shared/WKPriceTextField.swift
+++ b/Components/Sources/Components/Components/Shared/WKPriceTextField.swift
@@ -22,7 +22,7 @@ struct WKPriceTextField: View {
var body: some View {
TextField("", value: $amount, format: .currency(code: configuration.currencyCode))
.keyboardType(.decimalPad)
- .font(Font(WKFont.for(.boldTitle)))
+ .font(Font(WKFont.for(.boldTitle1)))
.foregroundColor(Color(appEnvironment.theme.text))
.padding(5)
.background(
diff --git a/Components/Sources/Components/Style/WKFont.swift b/Components/Sources/Components/Style/WKFont.swift
index fd8b50b5d1b..8286dd8aa78 100644
--- a/Components/Sources/Components/Style/WKFont.swift
+++ b/Components/Sources/Components/Style/WKFont.swift
@@ -4,8 +4,9 @@ import SwiftUI
public enum WKFont {
case headline
- case title
- case boldTitle
+ case title1
+ case boldTitle1
+ case boldTitle3
case body
case boldBody
case italicsBody
@@ -28,9 +29,14 @@ public enum WKFont {
switch font {
case .headline:
return UIFont.preferredFont(forTextStyle: .headline, compatibleWith: traitCollection)
- case .title:
+ case .title1:
return UIFont.preferredFont(forTextStyle: .title1, compatibleWith: traitCollection)
- case .boldTitle:
+ case .boldTitle3:
+ guard let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .title3, compatibleWith: traitCollection).withSymbolicTraits(.traitBold) else {
+ fatalError()
+ }
+ return UIFont(descriptor: descriptor, size: 0)
+ case .boldTitle1:
guard let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .title1, compatibleWith: traitCollection).withSymbolicTraits(.traitBold) else {
fatalError()
}
diff --git a/Components/Sources/Components/Style/WKIcon.swift b/Components/Sources/Components/Style/WKIcon.swift
index a08796dd175..7b9ccf37b70 100644
--- a/Components/Sources/Components/Style/WKIcon.swift
+++ b/Components/Sources/Components/Style/WKIcon.swift
@@ -20,8 +20,7 @@ public enum WKIcon {
static let userContributions = UIImage(named: "user-contributions", in: .module, with: nil)
// Editor-specific icons
- static let formatText = UIImage(named: "editor/format-text", in: .module, with: nil)//
- static let formatHeading = UIImage(named: "editor/format-heading", in: .module, with: nil)//
+ public static let separator = UIImage(named: "separator", in: .module, with: nil)
// Project icons
static let commons = UIImage(named: "project-icons/commons", in: .module, with: nil)
@@ -29,6 +28,7 @@ public enum WKIcon {
}
public enum WKSFSymbolIcon {
+
case checkmark
case checkmarkSquareFill
case square
@@ -55,6 +55,7 @@ public enum WKSFSymbolIcon {
case bold
case italic
case exclamationMarkCircle
+ case exclamationMarkCircleFill
case textFormatSuperscript
case textFormatSubscript
case underline
@@ -65,86 +66,108 @@ public enum WKSFSymbolIcon {
case ellipsis
case pencil
case plusCircleFill
+ case undo
+ case redo
+ case textFormatSize
+ case textFormat
- public static func `for`(symbol: WKSFSymbolIcon, font: WKFont = .body, compatibleWith traitCollection: UITraitCollection = WKAppEnvironment.current.traitCollection) -> UIImage? {
+ public static func `for`(symbol: WKSFSymbolIcon, font: WKFont = .subheadline, compatibleWith traitCollection: UITraitCollection = WKAppEnvironment.current.traitCollection, renderingMode: UIImage.RenderingMode = .alwaysTemplate, paletteColors: [UIColor]? = nil) -> UIImage? {
let font = WKFont.for(font)
let configuration = UIImage.SymbolConfiguration(font: font)
+ var image: UIImage?
switch symbol {
case .checkmark:
- return UIImage(systemName: "checkmark", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "checkmark", withConfiguration: configuration)
case .checkmarkSquareFill:
- return UIImage(systemName: "checkmark.square.fill", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "checkmark.square.fill", withConfiguration: configuration)
case .square:
- return UIImage(systemName: "square", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "square", withConfiguration: configuration)
case .star:
- return UIImage(systemName: "star", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "star", withConfiguration: configuration)
case .person:
- return UIImage(systemName: "person", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "person", withConfiguration: configuration)
case .personFilled:
- return UIImage(systemName: "person.fill", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "person.fill", withConfiguration: configuration)
case .starLeadingHalfFilled:
- return UIImage(systemName: "star.leadinghalf.filled", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "star.leadinghalf.filled", withConfiguration: configuration)
case .heart:
- return UIImage(systemName: "heart", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "heart", withConfiguration: configuration)
case .conversation:
- return UIImage(systemName: "bubble.left.and.bubble.right", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "bubble.left.and.bubble.right", withConfiguration: configuration)
case .quoteOpening:
- return UIImage(systemName: "quote.opening", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "quote.opening", withConfiguration: configuration)
case .link:
- return UIImage(systemName: "link", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "link", withConfiguration: configuration)
case .curlybraces:
- return UIImage(systemName: "curlybraces", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "curlybraces", withConfiguration: configuration)
case .photo:
- return UIImage(systemName: "photo", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "photo", withConfiguration: configuration)
case .docTextMagnifyingGlass:
- return UIImage(systemName: "doc.text.magnifyingglass", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "doc.text.magnifyingglass", withConfiguration: configuration)
case .magnifyingGlass:
- return UIImage(systemName: "magnifyingglass", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "magnifyingglass", withConfiguration: configuration)
case .listBullet:
- return UIImage(systemName: "list.bullet", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "list.bullet", withConfiguration: configuration)
case .listNumber:
- return UIImage(systemName: "list.number", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "list.number", withConfiguration: configuration)
case .increaseIndent:
- return UIImage(systemName: "increase.indent", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate).imageFlippedForRightToLeftLayoutDirection()
+ image = UIImage(systemName: "increase.indent", withConfiguration: configuration)?.imageFlippedForRightToLeftLayoutDirection()
case .decreaseIndent:
- return UIImage(systemName: "decrease.indent", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate).imageFlippedForRightToLeftLayoutDirection()
+ image = UIImage(systemName: "decrease.indent", withConfiguration: configuration)?.imageFlippedForRightToLeftLayoutDirection()
case .chevronUp:
- return UIImage(systemName: "chevron.up", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "chevron.up", withConfiguration: configuration)
case .chevronDown:
- return UIImage(systemName: "chevron.down", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "chevron.down", withConfiguration: configuration)
case .chevronBackward:
- return UIImage(systemName: "chevron.backward", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "chevron.backward", withConfiguration: configuration)
case .chevronForward:
- return UIImage(systemName: "chevron.forward", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "chevron.forward", withConfiguration: configuration)
case .bold:
- return UIImage(systemName: "bold", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "bold", withConfiguration: configuration)
case .italic:
- return UIImage(systemName: "italic", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "italic", withConfiguration: configuration)
case .exclamationMarkCircle:
- return UIImage(systemName: "exclamationmark.circle", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "exclamationmark.circle", withConfiguration: configuration)
+ case .exclamationMarkCircleFill:
+ image = UIImage(systemName: "exclamationmark.circle.fill", withConfiguration: configuration)
case .textFormatSuperscript:
- return UIImage(systemName: "textformat.superscript", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "textformat.superscript", withConfiguration: configuration)
case .textFormatSubscript:
- return UIImage(systemName: "textformat.subscript", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "textformat.subscript", withConfiguration: configuration)
case .underline:
- return UIImage(systemName: "underline", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "underline", withConfiguration: configuration)
case .strikethrough:
- return UIImage(systemName: "strikethrough", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "strikethrough", withConfiguration: configuration)
case .multiplyCircleFill:
- return UIImage(systemName: "multiply.circle.fill", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "multiply.circle.fill", withConfiguration: configuration)
case .chevronRightCircle:
- return UIImage(systemName: "chevron.right.circle.fill", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate).imageFlippedForRightToLeftLayoutDirection()
+ image = UIImage(systemName: "chevron.right.circle.fill", withConfiguration: configuration)?.imageFlippedForRightToLeftLayoutDirection()
case .close:
- return UIImage(systemName: "multiply", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "multiply", withConfiguration: configuration)
case .ellipsis:
- return UIImage(systemName: "ellipsis", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "ellipsis", withConfiguration: configuration)
case .pencil:
- return UIImage(systemName: "pencil", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
+ image = UIImage(systemName: "pencil", withConfiguration: configuration)
case .plusCircleFill:
- return UIImage(systemName: "plus.circle.fill", withConfiguration: configuration)?.withRenderingMode(.alwaysTemplate)
-
+ image = UIImage(systemName: "plus.circle.fill", withConfiguration: configuration)
+ case .undo:
+ image = UIImage(systemName: "arrow.uturn.backward", withConfiguration: configuration)
+ case .redo:
+ image = UIImage(systemName: "arrow.uturn.forward", withConfiguration: configuration)
+ case .textFormatSize:
+ image = UIImage(systemName: "textformat.size", withConfiguration: configuration)
+ case .textFormat:
+ image = UIImage(systemName: "textformat", withConfiguration: configuration)
+ }
+
+ image = image?.withRenderingMode(.alwaysTemplate)
+ if let paletteColors {
+ let paletteSymbolConfiguration = UIImage.SymbolConfiguration(paletteColors: paletteColors)
+ image = image?.applyingSymbolConfiguration(paletteSymbolConfiguration)
}
+
+ return image
}
}
diff --git a/Components/Sources/Components/Style/WKTheme.swift b/Components/Sources/Components/Style/WKTheme.swift
index 6e0b766fec3..e04449e88f8 100644
--- a/Components/Sources/Components/Style/WKTheme.swift
+++ b/Components/Sources/Components/Style/WKTheme.swift
@@ -33,6 +33,8 @@ public struct WKTheme: Equatable {
public let editorMatchBackground: UIColor
public let editorSelectedMatchBackground: UIColor
public let editorReplacedMatchBackground: UIColor
+ public let editorMultiButtonSelectedBackground: UIColor
+ public let editorKeyboardShadow: UIColor
public static let light = WKTheme(
name: "Light",
@@ -64,7 +66,9 @@ public struct WKTheme: Equatable {
editorMatchForeground: .black,
editorMatchBackground: WKColor.lightMatchBackground,
editorSelectedMatchBackground: WKColor.yellow600,
- editorReplacedMatchBackground: WKColor.matchReplacedBackground
+ editorReplacedMatchBackground: WKColor.matchReplacedBackground,
+ editorMultiButtonSelectedBackground: WKColor.gray200,
+ editorKeyboardShadow: WKColor.gray200
)
public static let sepia = WKTheme(
@@ -97,7 +101,9 @@ public struct WKTheme: Equatable {
editorMatchForeground: .black,
editorMatchBackground: WKColor.lightMatchBackground,
editorSelectedMatchBackground: WKColor.yellow600,
- editorReplacedMatchBackground: WKColor.matchReplacedBackground
+ editorReplacedMatchBackground: WKColor.matchReplacedBackground,
+ editorMultiButtonSelectedBackground: WKColor.beige400,
+ editorKeyboardShadow: WKColor.taupe200
)
public static let dark = WKTheme(
@@ -130,7 +136,9 @@ public struct WKTheme: Equatable {
editorMatchForeground: .black,
editorMatchBackground: WKColor.darkMatchBackground,
editorSelectedMatchBackground: WKColor.yellow600,
- editorReplacedMatchBackground: WKColor.matchReplacedBackground
+ editorReplacedMatchBackground: WKColor.matchReplacedBackground,
+ editorMultiButtonSelectedBackground: WKColor.gray600,
+ editorKeyboardShadow: WKColor.gray800
)
public static let black = WKTheme(
@@ -163,7 +171,9 @@ public struct WKTheme: Equatable {
editorMatchForeground: .black,
editorMatchBackground: WKColor.darkMatchBackground,
editorSelectedMatchBackground: WKColor.yellow600,
- editorReplacedMatchBackground: WKColor.matchReplacedBackground
+ editorReplacedMatchBackground: WKColor.matchReplacedBackground,
+ editorMultiButtonSelectedBackground: WKColor.gray600,
+ editorKeyboardShadow: WKColor.gray700
)
}
diff --git a/Wikipedia/Code/FocusNavigationView.swift b/Wikipedia/Code/FocusNavigationView.swift
index 240ee38021a..c1e50d63dd4 100644
--- a/Wikipedia/Code/FocusNavigationView.swift
+++ b/Wikipedia/Code/FocusNavigationView.swift
@@ -1,4 +1,5 @@
import UIKit
+import Components
protocol FocusNavigationViewDelegate: AnyObject {
func focusNavigationViewDidTapClose(_ focusNavigationView: FocusNavigationView)
@@ -13,6 +14,13 @@ final class FocusNavigationView: UIView {
weak var delegate: FocusNavigationViewDelegate?
+ override func awakeFromNib() {
+ super.awakeFromNib()
+
+ closeButton.imageView?.contentMode = .center
+ closeButton.setImage(WKSFSymbolIcon.for(symbol: .multiplyCircleFill), for: .normal)
+ }
+
func configure(titleText: String, closeButtonAccessibilityText: String, traitCollection: UITraitCollection, isTitleAccessible: Bool = false) {
titleLabel.text = titleText
diff --git a/Wikipedia/Code/FocusNavigationView.xib b/Wikipedia/Code/FocusNavigationView.xib
index 6b0cd6c1c08..347e91da5f0 100644
--- a/Wikipedia/Code/FocusNavigationView.xib
+++ b/Wikipedia/Code/FocusNavigationView.xib
@@ -1,11 +1,9 @@
-
-
-
-
+
+
-
+
@@ -17,18 +15,13 @@
-
+
@@ -53,7 +47,6 @@
-
@@ -64,7 +57,4 @@
-
-
-
diff --git a/Wikipedia/Code/PageEditorViewController.swift b/Wikipedia/Code/PageEditorViewController.swift
index dc269adb5a7..42049cfdbaf 100644
--- a/Wikipedia/Code/PageEditorViewController.swift
+++ b/Wikipedia/Code/PageEditorViewController.swift
@@ -369,7 +369,7 @@ extension PageEditorViewController: WKSourceEditorViewControllerDelegate {
extension PageEditorViewController: SectionEditorNavigationItemControllerDelegate {
func sectionEditorNavigationItemController(_ sectionEditorNavigationItemController: SectionEditorNavigationItemController, didTapProgressButton progressButton: UIBarButtonItem) {
- sourceEditor.resignFirstResponder()
+ sourceEditor.removeFocus()
switch editFlow {
case .editorSavePreview:
@@ -404,6 +404,7 @@ extension PageEditorViewController: SectionEditorNavigationItemControllerDelegat
}
func sectionEditorNavigationItemController(_ sectionEditorNavigationItemController: SectionEditorNavigationItemController, didTapReadingThemesControlsButton readingThemesControlsButton: UIBarButtonItem) {
+ sourceEditor.removeFocus()
showReadingThemesControlsPopup(on: self, responder: self, theme: theme)
}
@@ -435,6 +436,10 @@ extension PageEditorViewController: ReadingThemesControlsResponding {
// MARK: - ReadingThemesControlsPresenting
extension PageEditorViewController: ReadingThemesControlsPresenting {
+ var needsExtraTopSpacing: Bool {
+ return true
+ }
+
var shouldPassthroughNavBar: Bool {
return false
}
diff --git a/Wikipedia/Code/ReadingThemesControlsProtocols.swift b/Wikipedia/Code/ReadingThemesControlsProtocols.swift
index 226f7fa34ba..64fbd723d67 100644
--- a/Wikipedia/Code/ReadingThemesControlsProtocols.swift
+++ b/Wikipedia/Code/ReadingThemesControlsProtocols.swift
@@ -22,6 +22,7 @@ protocol ReadingThemesControlsPresenting: UIPopoverPresentationControllerDelegat
var readingThemesControlsToolbarItem: UIBarButtonItem { get }
var shouldPassthroughNavBar: Bool { get }
var showsSyntaxHighlighting: Bool { get }
+ var needsExtraTopSpacing: Bool { get }
}
protocol ReadingThemesControlsResponding: WMFReadingThemesControlsViewControllerDelegate {
@@ -42,6 +43,7 @@ extension ReadingThemesControlsPresenting {
readingThemesControlsViewController.delegate = responder
readingThemesControlsViewController.setValuesWithSteps(fontSizes.count, current: index)
readingThemesControlsViewController.showsSyntaxHighlighting = showsSyntaxHighlighting
+ readingThemesControlsViewController.needsExtraTopSpacing = needsExtraTopSpacing
apply(presentationTheme: theme)
@@ -93,6 +95,10 @@ extension WMFReadingThemesControlsViewControllerDelegate where Self: ReadingThem
@objc(WMFReadingThemesControlsArticlePresenter)
class ReadingThemesControlsArticlePresenter: NSObject, ReadingThemesControlsPresenting {
+ var needsExtraTopSpacing: Bool {
+ return false
+ }
+
var shouldPassthroughNavBar: Bool {
return true
}
diff --git a/Wikipedia/Code/ReadingThemesControlsViewController.swift b/Wikipedia/Code/ReadingThemesControlsViewController.swift
index c7b6a4e60fc..80b1310b5d6 100644
--- a/Wikipedia/Code/ReadingThemesControlsViewController.swift
+++ b/Wikipedia/Code/ReadingThemesControlsViewController.swift
@@ -36,6 +36,7 @@ class ReadingThemesControlsViewController: UIViewController {
@IBOutlet weak var tSmallImageView: UIImageView!
@IBOutlet weak var tLargeImageView: UIImageView!
+ @IBOutlet weak var tLargeImageViewTopConstraint: NSLayoutConstraint!
@IBOutlet var stackView: UIStackView!
@@ -52,6 +53,12 @@ class ReadingThemesControlsViewController: UIViewController {
}
}
+ var needsExtraTopSpacing: Bool = false {
+ didSet {
+ tLargeImageViewTopConstraint.constant = needsExtraTopSpacing ? 26 : 13
+ }
+ }
+
open weak var delegate: WMFReadingThemesControlsViewControllerDelegate?
open override func viewDidLoad() {
diff --git a/Wikipedia/Code/ReadingThemesControlsViewController.xib b/Wikipedia/Code/ReadingThemesControlsViewController.xib
index 45eec57d5c3..c76b401fc47 100644
--- a/Wikipedia/Code/ReadingThemesControlsViewController.xib
+++ b/Wikipedia/Code/ReadingThemesControlsViewController.xib
@@ -1,11 +1,9 @@
-
-
-
-
+
+
-
+
@@ -26,6 +24,7 @@
+
@@ -45,28 +44,29 @@
-
+
-
+
-
+
-
+
-
-
+
+
+
-
+
@@ -95,20 +95,20 @@
-
+
-
+
-
+
@@ -126,7 +126,7 @@
-
+
@@ -143,24 +143,24 @@
-
+
-
+
-
+
-
-
+
+
@@ -179,12 +179,12 @@
-
+
-
-
+
+
@@ -203,12 +203,12 @@
-
+
-
-
+
+
@@ -227,12 +227,12 @@
-
+
-
-
+
+
@@ -262,14 +262,14 @@
-
+
-
+
+
+
+
+
+
diff --git a/Wikipedia/Code/SectionEditorNavigationItemController.swift b/Wikipedia/Code/SectionEditorNavigationItemController.swift
index 7cd3203b1ee..bdc828bedd5 100644
--- a/Wikipedia/Code/SectionEditorNavigationItemController.swift
+++ b/Wikipedia/Code/SectionEditorNavigationItemController.swift
@@ -1,3 +1,4 @@
+import WMF
import Components
protocol SectionEditorNavigationItemControllerDelegate: AnyObject {
@@ -23,82 +24,58 @@ class SectionEditorNavigationItemController: NSObject, Themeable {
}
func apply(theme: Theme) {
- for case let barButonItem as BarButtonItem in navigationItem?.rightBarButtonItems ?? [] {
- barButonItem.apply(theme: theme)
- }
- for case let barButonItem as BarButtonItem in navigationItem?.leftBarButtonItems ?? [] {
- barButonItem.apply(theme: theme)
- }
+ closeButton.tintColor = theme.colors.chromeText
+ undoButton.tintColor = theme.colors.inputAccessoryButtonTint
+ redoButton.tintColor = theme.colors.inputAccessoryButtonTint
+ readingThemesControlsButton.tintColor = theme.colors.inputAccessoryButtonTint
+ editNoticesButton.tintColor = theme.colors.inputAccessoryButtonTint
+ separatorButton.tintColor = theme.colors.chromeText
+ progressButton.tintColor = theme.colors.link
}
weak var delegate: SectionEditorNavigationItemControllerDelegate?
-
- class BarButtonItem: UIBarButtonItem, Themeable {
- var tintColorKeyPath: KeyPath?
-
- convenience init(title: String?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, tintColorKeyPath: KeyPath) {
- self.init(title: title, style: style, target: target, action: action)
- self.tintColorKeyPath = tintColorKeyPath
- }
-
- convenience init(image: UIImage?, style: UIBarButtonItem.Style, target: Any?, action: Selector?, tintColorKeyPath: KeyPath, accessibilityLabel: String? = nil, size: CGSize? = nil) {
- let button = UIButton(type: .system)
- button.setImage(image, for: .normal)
- if let size {
- button.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height)
- }
- if let target = target, let action = action {
- button.addTarget(target, action: action, for: .touchUpInside)
- }
- self.init(customView: button)
- self.tintColorKeyPath = tintColorKeyPath
- self.accessibilityLabel = accessibilityLabel
- }
-
- func apply(theme: Theme) {
- guard let tintColorKeyPath = tintColorKeyPath else {
- return
- }
- let newTintColor = theme[keyPath: tintColorKeyPath]
- if customView == nil {
- tintColor = newTintColor
- } else if let button = customView as? UIButton {
- button.tintColor = newTintColor
- }
- }
- }
- private(set) lazy var closeButton: BarButtonItem = {
- let closeButton = BarButtonItem(image: #imageLiteral(resourceName: "close"), style: .plain, target: self, action: #selector(close(_ :)), tintColorKeyPath: \Theme.colors.chromeText)
+ private(set) lazy var closeButton: UIBarButtonItem = {
+ let closeButton = UIBarButtonItem(image: WKSFSymbolIcon.for(symbol: .close), style: .plain, target: self, action: #selector(close(_ :)))
closeButton.accessibilityLabel = CommonStrings.closeButtonAccessibilityLabel
return closeButton
}()
- private(set) lazy var progressButton: BarButtonItem = {
- return BarButtonItem(title: CommonStrings.nextTitle, style: .done, target: self, action: #selector(progress(_:)), tintColorKeyPath: \Theme.colors.link)
+ private(set) lazy var progressButton: UIBarButtonItem = {
+ let button = UIBarButtonItem(title: CommonStrings.nextTitle, style: .done, target: self, action: #selector(progress(_:)))
+ return button
}()
- private(set) lazy var redoButton: BarButtonItem = {
- return BarButtonItem(image: #imageLiteral(resourceName: "redo"), style: .plain, target: self, action: #selector(redo(_ :)), tintColorKeyPath: \Theme.colors.inputAccessoryButtonTint, accessibilityLabel: CommonStrings.redo)
+ private(set) lazy var redoButton: UIBarButtonItem = {
+ let redoButton = UIBarButtonItem(image: WKSFSymbolIcon.for(symbol: .redo), style: .plain, target: self, action: #selector(redo(_ :)))
+ redoButton.accessibilityLabel = CommonStrings.redo
+ return redoButton
}()
- private(set) lazy var undoButton: BarButtonItem = {
- return BarButtonItem(image: #imageLiteral(resourceName: "undo"), style: .plain, target: self, action: #selector(undo(_ :)), tintColorKeyPath: \Theme.colors.inputAccessoryButtonTint, accessibilityLabel: CommonStrings.undo)
+ private(set) lazy var undoButton: UIBarButtonItem = {
+ let undoButton = UIBarButtonItem(image: WKSFSymbolIcon.for(symbol: .undo), style: .plain, target: self, action: #selector(undo(_ :)))
+ undoButton.accessibilityLabel = CommonStrings.undo
+ return undoButton
}()
- private lazy var editNoticesButton: BarButtonItem = {
- return BarButtonItem(image: UIImage(systemName: "exclamationmark.circle.fill") , style: .plain, target: self, action: #selector(editNotices(_ :)), tintColorKeyPath: \Theme.colors.inputAccessoryButtonTint, accessibilityLabel: CommonStrings.editNotices)
+ private lazy var editNoticesButton: UIBarButtonItem = {
+ let button = UIBarButtonItem(image: WKSFSymbolIcon.for(symbol: .exclamationMarkCircleFill), style: .plain, target: self, action: #selector(editNotices(_ :)))
+ button.accessibilityLabel = CommonStrings.editNotices
+ return button
}()
- private lazy var readingThemesControlsButton: BarButtonItem = {
- return BarButtonItem(image: #imageLiteral(resourceName: "settings-appearance"), style: .plain, target: self, action: #selector(showReadingThemesControls(_ :)), tintColorKeyPath: \Theme.colors.inputAccessoryButtonTint, accessibilityLabel: CommonStrings.readingThemesControls)
+ private lazy var readingThemesControlsButton: UIBarButtonItem = {
+ let button = UIBarButtonItem(image: WKSFSymbolIcon.for(symbol: .textFormatSize), style: .plain, target: self, action: #selector(showReadingThemesControls(_ :)))
+ button.accessibilityLabel = CommonStrings.readingThemesControls
+ return button
}()
- private lazy var separatorButton: BarButtonItem = {
- let button = BarButtonItem(image: #imageLiteral(resourceName: "separator"), style: .plain, target: nil, action: nil, tintColorKeyPath: \Theme.colors.chromeText)
+ private lazy var separatorButton: UIBarButtonItem = {
+ let button = UIButton(type: .system)
+ button.setImage(WKIcon.separator, for: .normal)
button.isEnabled = false
button.isAccessibilityElement = false
- return button
+ return UIBarButtonItem(customView: button)
}()
@objc private func progress(_ sender: UIBarButtonItem) {
@@ -127,23 +104,20 @@ class SectionEditorNavigationItemController: NSObject, Themeable {
func addEditNoticesButton() {
navigationItem?.rightBarButtonItems?.append(contentsOf: [
- UIBarButtonItem.wmf_barButtonItem(ofFixedWidth: 20),
editNoticesButton
])
}
private func configureNavigationButtonItems() {
+
navigationItem?.leftBarButtonItem = closeButton
navigationItem?.rightBarButtonItems = [
progressButton,
- UIBarButtonItem.wmf_barButtonItem(ofFixedWidth: 20),
+ UIBarButtonItem.wmf_barButtonItem(ofFixedWidth: 16),
separatorButton,
- UIBarButtonItem.wmf_barButtonItem(ofFixedWidth: 20),
readingThemesControlsButton,
- UIBarButtonItem.wmf_barButtonItem(ofFixedWidth: 20),
redoButton,
- UIBarButtonItem.wmf_barButtonItem(ofFixedWidth: 20),
undoButton
]
}
diff --git a/Wikipedia/Code/SectionEditorViewController.swift b/Wikipedia/Code/SectionEditorViewController.swift
index 762834eb58f..e12eb28b24a 100644
--- a/Wikipedia/Code/SectionEditorViewController.swift
+++ b/Wikipedia/Code/SectionEditorViewController.swift
@@ -728,6 +728,10 @@ extension SectionEditorViewController: EditPreviewViewControllerDelegate {
}
extension SectionEditorViewController: ReadingThemesControlsPresenting {
+ var needsExtraTopSpacing: Bool {
+ return false
+ }
+
var shouldPassthroughNavBar: Bool {
return false