-
-
Notifications
You must be signed in to change notification settings - Fork 762
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4906 from wikimedia/alt-text-sheet-first-part
[ALT TEXT] Bottom sheet - part 1
- Loading branch information
Showing
10 changed files
with
316 additions
and
17 deletions.
There are no files selected for viewing
218 changes: 218 additions & 0 deletions
218
...ents/Components/Suggested Edits/Alt Text Experiment/AltTextExperimentModalSheetView.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,218 @@ | ||
import UIKit | ||
|
||
final class AltTextExperimentModalSheetView: WKComponentView { | ||
|
||
// MARK: Properties | ||
|
||
weak var viewModel: AltTextExperimentModalSheetViewModel? | ||
|
||
private lazy var scrollView: UIScrollView = { | ||
let scrollView = UIScrollView() | ||
scrollView.translatesAutoresizingMaskIntoConstraints = false | ||
return scrollView | ||
}() | ||
|
||
private lazy var stackView: UIStackView = { | ||
let stackView = UIStackView() | ||
stackView.translatesAutoresizingMaskIntoConstraints = false | ||
stackView.setContentHuggingPriority(.required, for: .vertical) | ||
stackView.setContentCompressionResistancePriority(.required, for: .vertical) | ||
stackView.alignment = .fill | ||
stackView.spacing = padding | ||
stackView.axis = .vertical | ||
return stackView | ||
}() | ||
|
||
private lazy var headerStackView: UIStackView = { | ||
let stackView = UIStackView() | ||
stackView.translatesAutoresizingMaskIntoConstraints = false | ||
stackView.setContentHuggingPriority(.required, for: .vertical) | ||
stackView.setContentCompressionResistancePriority(.required, for: .vertical) | ||
stackView.distribution = .equalSpacing | ||
stackView.alignment = .fill | ||
stackView.axis = .horizontal | ||
return stackView | ||
}() | ||
|
||
private lazy var imageAndTitleStackView: UIStackView = { | ||
let stackView = UIStackView() | ||
stackView.translatesAutoresizingMaskIntoConstraints = false | ||
stackView.setContentHuggingPriority(.required, for: .vertical) | ||
stackView.setContentCompressionResistancePriority(.required, for: .vertical) | ||
stackView.distribution = .fill | ||
stackView.spacing = basePadding | ||
stackView.alignment = .fill | ||
stackView.axis = .horizontal | ||
return stackView | ||
}() | ||
|
||
private lazy var iconImageContainerView: UIView = { | ||
let view = UIView() | ||
view.setContentCompressionResistancePriority(.required, for: .vertical) | ||
view.setContentHuggingPriority(.required, for: .vertical) | ||
return view | ||
}() | ||
|
||
private lazy var iconImageView: UIImageView = { | ||
let icon = WKSFSymbolIcon.for(symbol: .plusCircleFill) // temp waiting for design | ||
let imageView = UIImageView(image: icon) | ||
imageView.translatesAutoresizingMaskIntoConstraints = false | ||
imageView.setContentCompressionResistancePriority(.required, for: .vertical) | ||
imageView.setContentHuggingPriority(.required, for: .vertical) | ||
imageView.contentMode = .scaleAspectFit | ||
return imageView | ||
}() | ||
|
||
private lazy var titleLabel: UILabel = { | ||
let label = UILabel() | ||
label.translatesAutoresizingMaskIntoConstraints = false | ||
label.setContentCompressionResistancePriority(.required, for: .vertical) | ||
label.setContentHuggingPriority(.required, for: .vertical) | ||
label.numberOfLines = 0 | ||
label.lineBreakMode = .byWordWrapping | ||
return label | ||
}() | ||
|
||
private lazy var textView: UITextView = { | ||
let textfield = UITextView(frame: .zero) | ||
textfield.translatesAutoresizingMaskIntoConstraints = false | ||
textfield.layer.cornerRadius = 10 | ||
return textfield | ||
}() | ||
|
||
private lazy var placeholder: UILabel = { | ||
let label = UILabel() | ||
label.translatesAutoresizingMaskIntoConstraints = false | ||
return label | ||
}() | ||
|
||
lazy var nextButton: UIButton = { | ||
let button = UIButton() | ||
button.translatesAutoresizingMaskIntoConstraints = false | ||
return button | ||
}() | ||
|
||
private let basePadding: CGFloat = 8 | ||
private let padding: CGFloat = 16 | ||
|
||
// MARK: Lifecycle | ||
|
||
public init(frame: CGRect, viewModel: AltTextExperimentModalSheetViewModel) { | ||
self.viewModel = viewModel | ||
super.init(frame: frame) | ||
textView.delegate = self | ||
setup() | ||
} | ||
|
||
public required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
// MARK: Methods | ||
|
||
public override func appEnvironmentDidChange() { | ||
super.appEnvironmentDidChange() | ||
configure() | ||
} | ||
|
||
func updateColors() { | ||
backgroundColor = theme.midBackground | ||
titleLabel.textColor = theme.text | ||
textView.backgroundColor = theme.paperBackground | ||
iconImageView.tintColor = theme.link | ||
nextButton.setTitleColor(theme.link, for: .normal) | ||
nextButton.setTitleColor(theme.secondaryText, for: .disabled) | ||
placeholder.textColor = theme.secondaryText | ||
textView.textColor = theme.text | ||
} | ||
|
||
func configure() { | ||
updateColors() | ||
updateNextButtonState() | ||
updatePlaceholderVisibility() | ||
|
||
titleLabel.text = viewModel?.localizedStrings.title | ||
nextButton.setTitle(viewModel?.localizedStrings.buttonTitle, for: .normal) | ||
placeholder.text = viewModel?.localizedStrings.textViewPlaceholder | ||
|
||
textView.font = WKFont.for(.callout, compatibleWith: traitCollection) | ||
|
||
titleLabel.font = WKFont.for(.boldTitle3, compatibleWith: traitCollection) | ||
nextButton.titleLabel?.font = WKFont.for(.semiboldHeadline, compatibleWith: traitCollection) | ||
placeholder.font = WKFont.for(.callout, compatibleWith: traitCollection) | ||
} | ||
|
||
func setup() { | ||
configure() | ||
|
||
textView.addSubview(placeholder) | ||
iconImageContainerView.addSubview(iconImageView) | ||
|
||
imageAndTitleStackView.addArrangedSubview(iconImageContainerView) | ||
imageAndTitleStackView.addArrangedSubview(titleLabel) | ||
|
||
headerStackView.addArrangedSubview(imageAndTitleStackView) | ||
headerStackView.addArrangedSubview(nextButton) | ||
|
||
stackView.addArrangedSubview(headerStackView) | ||
stackView.addArrangedSubview(textView) | ||
|
||
scrollView.addSubview(stackView) | ||
addSubview(scrollView) | ||
|
||
NSLayoutConstraint.activate([ | ||
|
||
scrollView.leadingAnchor.constraint(equalTo: leadingAnchor), | ||
scrollView.trailingAnchor.constraint(equalTo: trailingAnchor), | ||
scrollView.topAnchor.constraint(equalTo: topAnchor), | ||
scrollView.bottomAnchor.constraint(equalTo: bottomAnchor), | ||
scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor), | ||
|
||
stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor, constant: padding), | ||
stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor, constant: -padding), | ||
stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor, constant: basePadding), | ||
stackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor, constant: -padding), | ||
|
||
textView.leadingAnchor.constraint(equalTo: stackView.leadingAnchor), | ||
textView.trailingAnchor.constraint(equalTo: stackView.trailingAnchor), | ||
textView.heightAnchor.constraint(equalToConstant: 125), | ||
|
||
nextButton.heightAnchor.constraint(equalToConstant:44), | ||
|
||
placeholder.topAnchor.constraint(equalTo: textView.topAnchor, constant: basePadding), | ||
placeholder.leadingAnchor.constraint(equalTo: textView.leadingAnchor, constant: basePadding), | ||
|
||
|
||
iconImageContainerView.centerXAnchor.constraint(equalTo: iconImageView.centerXAnchor), | ||
iconImageView.leadingAnchor.constraint(equalTo: iconImageContainerView.leadingAnchor), | ||
iconImageView.trailingAnchor.constraint(equalTo: iconImageContainerView.trailingAnchor), | ||
iconImageView.topAnchor.constraint(equalTo: iconImageContainerView.topAnchor), | ||
iconImageView.bottomAnchor.constraint(equalTo: iconImageContainerView.bottomAnchor), | ||
iconImageContainerView.topAnchor.constraint(equalTo: titleLabel.topAnchor) | ||
]) | ||
} | ||
|
||
private func updateNextButtonState() { | ||
nextButton.isEnabled = !textView.text.isEmpty | ||
} | ||
|
||
private func updatePlaceholderVisibility() { | ||
placeholder.isHidden = !textView.text.isEmpty | ||
} | ||
} | ||
|
||
extension AltTextExperimentModalSheetView: UITextViewDelegate { | ||
func textViewDidChange(_ textView: UITextView) { | ||
updateNextButtonState() | ||
updatePlaceholderVisibility() | ||
} | ||
|
||
func textViewDidBeginEditing(_ textView: UITextView) { | ||
placeholder.isHidden = true | ||
} | ||
|
||
func textViewDidEndEditing(_ textView: UITextView) { | ||
updatePlaceholderVisibility() | ||
} | ||
|
||
} |
24 changes: 24 additions & 0 deletions
24
...nents/Suggested Edits/Alt Text Experiment/AltTextExperimentModalSheetViewController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import UIKit | ||
|
||
final public class AltTextExperimentModalSheetViewController: WKCanvasViewController { | ||
|
||
weak var viewModel: AltTextExperimentModalSheetViewModel? | ||
|
||
public init(viewModel: AltTextExperimentModalSheetViewModel?) { | ||
self.viewModel = viewModel | ||
super.init() | ||
} | ||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
override public func viewWillAppear(_ animated: Bool) { | ||
super.viewWillAppear(animated) | ||
guard let viewModel else { return } | ||
let view = AltTextExperimentModalSheetView(frame: UIScreen.main.bounds, viewModel: viewModel) | ||
addComponent(view, pinToEdges: true) | ||
} | ||
|
||
} | ||
|
24 changes: 24 additions & 0 deletions
24
...Components/Suggested Edits/Alt Text Experiment/AltTextExperimentModalSheetViewModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import Foundation | ||
|
||
@objc final public class AltTextExperimentModalSheetViewModel: NSObject { | ||
public var altTextViewModel: AltTextExperimentViewModel | ||
public var localizedStrings: LocalizedStrings | ||
|
||
public struct LocalizedStrings { | ||
public var title: String | ||
public var buttonTitle: String | ||
public var textViewPlaceholder: String | ||
|
||
public init(title: String, buttonTitle: String, textViewPlaceholder: String) { | ||
self.title = title | ||
self.buttonTitle = buttonTitle | ||
self.textViewPlaceholder = textViewPlaceholder | ||
} | ||
} | ||
|
||
public init(altTextViewModel: AltTextExperimentViewModel, localizedStrings: LocalizedStrings) { | ||
self.altTextViewModel = altTextViewModel | ||
self.localizedStrings = localizedStrings | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.