Skip to content

Commit

Permalink
iOS: Refactor StepQuizFeedbackView
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-magda committed Nov 23, 2023
1 parent f97a54b commit 3ba58f2
Showing 1 changed file with 25 additions and 181 deletions.
Original file line number Diff line number Diff line change
@@ -1,193 +1,37 @@
import SnapKit
import SwiftUI
import UIKit

struct StepQuizFeedbackView: UIViewRepresentable {
typealias UIViewType = StepQuizFeedbackUIKitView

var text: String

func makeUIView(context: Context) -> StepQuizFeedbackUIKitView {
StepQuizFeedbackUIKitView()
}

func updateUIView(_ uiView: StepQuizFeedbackUIKitView, context: Context) {
uiView.setText(text)
struct StepQuizFeedbackView: View {
let text: String

var body: some View {
VStack(alignment: .leading, spacing: LayoutInsets.smallInset) {
Text(Strings.StepQuiz.feedbackTitle)
.font(.caption)
.foregroundColor(.tertiaryText)
.frame(maxWidth: .infinity, alignment: .leading)

LatexView(
text: text,
configuration: .quizContent(
textFont: .monospacedSystemFont(ofSize: 14, weight: .regular),
textColor: .primaryText,
backgroundColor: .clear
)
)
}
.padding()
.background(Color.background)
.addBorder()
}
}

struct StepQuizFeedbackView_Previews: PreviewProvider {
static var previews: some View {
#Preview {
ScrollView {
StepQuizFeedbackView(
text: """
That's right! Since any comparison results in a boolean value, there is no need to write everything twice.
"""
)
.padding()
}
}

// MARK: - StepQuizFeedbackUIKitView -

extension StepQuizFeedbackUIKitView {
struct Appearance {
let titleLabelTextFont = UIFont.preferredFont(forTextStyle: .caption1)
let titleLabelTextColor = UIColor.tertiaryText

let processedContentTextFont = UIFont.monospacedSystemFont(ofSize: 14, weight: .regular)
let processedContentTextColor = UIColor.primaryText

let padding = LayoutInsets.defaultInset
let spacing = LayoutInsets.smallInset

let borderColor = ColorPalette.onSurfaceAlpha12
let borderWidth: CGFloat = 1
let borderCornerRadius: CGFloat = 8

let backgroundColor = ColorPalette.background
}
}

final class StepQuizFeedbackUIKitView: UIView {
let appearance: Appearance

private lazy var titleLabel: UILabel = {
let label = UILabel()
label.font = appearance.titleLabelTextFont
label.textColor = appearance.titleLabelTextColor
label.numberOfLines = 1
label.text = Strings.StepQuiz.feedbackTitle
return label
}()

private lazy var processedContentView: ProcessedContentView = {
let processedContentViewAppearance = ProcessedContentView.Appearance(
labelFont: appearance.processedContentTextFont,
backgroundColor: .clear
)

let contentProcessor = ContentProcessor(
injections: ContentProcessor.defaultInjections + [
FontInjection(font: appearance.processedContentTextFont),
TextColorInjection(dynamicColor: appearance.processedContentTextColor)
]
)

let processedContentView = ProcessedContentView(
frame: .zero,
appearance: processedContentViewAppearance,
contentProcessor: contentProcessor,
htmlToAttributedStringConverter: HTMLToAttributedStringConverter(
font: appearance.processedContentTextFont
)
)
processedContentView.delegate = self

return processedContentView
}()

override var intrinsicContentSize: CGSize {
let titleLabelHeight = titleLabel.intrinsicContentSize.height
let processedContentViewHeight = processedContentView.intrinsicContentSize.height

let height =
appearance.padding + titleLabelHeight + appearance.spacing + processedContentViewHeight + appearance.padding

return CGSize(width: UIView.noIntrinsicMetric, height: height)
}

init(
frame: CGRect = .zero,
appearance: Appearance = Appearance()
) {
self.appearance = appearance
super.init(frame: frame)

setupView()
addSubviews()
makeConstraints()
}

@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func layoutSubviews() {
clipsToBounds = true
layer.cornerRadius = appearance.borderCornerRadius
layer.borderColor = appearance.borderColor.cgColor
layer.borderWidth = appearance.borderWidth
}

func setText(_ text: String) {
processedContentView.setText(text)
}
}

// MARK: - StepQuizFeedbackUIKitView: ProgrammaticallyInitializableViewProtocol -

extension StepQuizFeedbackUIKitView: ProgrammaticallyInitializableViewProtocol {
func setupView() {
backgroundColor = appearance.backgroundColor
}

func addSubviews() {
addSubview(titleLabel)
addSubview(processedContentView)
}

func makeConstraints() {
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(appearance.padding)
make.leading.equalToSuperview().offset(appearance.padding)
make.trailing.lessThanOrEqualToSuperview().offset(-appearance.padding)
}

processedContentView.translatesAutoresizingMaskIntoConstraints = false
processedContentView.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(appearance.spacing)
make.leading.equalToSuperview().offset(appearance.padding)
make.bottom.equalToSuperview().offset(-appearance.padding)
make.trailing.equalToSuperview().offset(-appearance.padding)
}
}
}

// MARK: - StepQuizFeedbackUIKitView: ProcessedContentViewDelegate -

extension StepQuizFeedbackUIKitView: ProcessedContentViewDelegate {
func processedContentViewDidLoadContent(_ view: ProcessedContentView) {
invalidateLayout()
}

func processedContentView(_ view: ProcessedContentView, didReportNewHeight height: Int) {
invalidateLayout()
}

func processedContentView(_ view: ProcessedContentView, didOpenImageURL url: URL) {
openURLInTheWeb(url)
}

func processedContentView(_ view: ProcessedContentView, didOpenLink url: URL) {
openURLInTheWeb(url)
}

// MARK: Private Helpers

private func invalidateLayout() {
DispatchQueue.main.async {
self.layoutIfNeeded()
self.invalidateIntrinsicContentSize()
}
}

private func openURLInTheWeb(_ url: URL) {
WebControllerManager.shared.presentWebControllerWithURL(
url,
withKey: .externalLink,
controllerType: .inAppSafari
)
}
.padding()
}

0 comments on commit 3ba58f2

Please sign in to comment.