-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6b522f6
commit c9561ef
Showing
5 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
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
103 changes: 103 additions & 0 deletions
103
.Demo/Classes/View/Components/Divider/UIKit/DividerComponentUIView.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,103 @@ | ||
// | ||
// DividerComponentUIView.swift | ||
// SparkDemo | ||
// | ||
// Created by louis.borlee on 31/07/2024. | ||
// Copyright © 2024 Adevinta. All rights reserved. | ||
// | ||
|
||
import Combine | ||
import UIKit | ||
@_spi(SI_SPI) import SparkCommon | ||
|
||
final class DividerComponentUIView: ComponentUIView { | ||
|
||
// MARK: - Components | ||
private let componentView: DividerUIView | ||
|
||
// MARK: - Properties | ||
|
||
private let viewModel: DividerComponentUIViewModel | ||
private var cancellables: Set<AnyCancellable> = [] | ||
|
||
private var heightConstraint = NSLayoutConstraint() | ||
|
||
// MARK: - Initializer | ||
init(viewModel: DividerComponentUIViewModel) { | ||
self.viewModel = viewModel | ||
|
||
let divider = DividerUIView( | ||
theme: self.viewModel.theme, | ||
intent: self.viewModel.intent | ||
) | ||
divider.label.text = self.viewModel.text | ||
divider.label.numberOfLines = 0 | ||
divider.axis = self.viewModel.axis | ||
divider.alignment = self.viewModel.alignment | ||
|
||
self.componentView = divider | ||
|
||
super.init( | ||
viewModel: viewModel, | ||
integrationStackViewAlignment: .fill, | ||
componentView: self.componentView | ||
) | ||
|
||
// Setup | ||
self.setupSubscriptions() | ||
} | ||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
// MARK: - Subscribe | ||
private func setupSubscriptions() { | ||
self.viewModel.$theme.subscribe(in: &self.cancellables) { [weak self] theme in | ||
guard let self = self else { return } | ||
let themes = self.viewModel.themes | ||
let themeTitle: String? = theme is SparkTheme ? themes.first?.title : themes.last?.title | ||
|
||
self.viewModel.themeConfigurationItemViewModel.buttonTitle = themeTitle | ||
self.viewModel.configurationViewModel.update(theme: theme) | ||
|
||
self.componentView.theme = theme | ||
} | ||
|
||
self.viewModel.$intent.subscribe(in: &self.cancellables) { [weak self] intent in | ||
guard let self = self else { return } | ||
self.viewModel.intentConfigurationItemViewModel.buttonTitle = intent.name | ||
self.componentView.intent = intent | ||
} | ||
|
||
self.viewModel.$axis.subscribe(in: &self.cancellables) { [weak self] axis in | ||
guard let self = self else { return } | ||
self.viewModel.axisConfigurationItemViewModel.buttonTitle = axis.name | ||
self.componentView.axis = axis | ||
if axis == .vertical { | ||
self.heightConstraint = self.componentView.heightAnchor.constraint(equalToConstant: 300) | ||
self.heightConstraint.isActive = true | ||
} else { | ||
self.heightConstraint.isActive = false | ||
self.componentView.removeConstraint(self.heightConstraint) | ||
} | ||
} | ||
|
||
self.viewModel.$alignment.subscribe(in: &self.cancellables) { [weak self] alignment in | ||
guard let self = self else { return } | ||
self.viewModel.alignmentConfigurationItemViewModel.buttonTitle = alignment.name | ||
self.componentView.alignment = alignment | ||
} | ||
|
||
self.viewModel.$text.subscribe(in: &self.cancellables) { [weak self] text in | ||
guard let self = self else { return } | ||
self.viewModel.textConfigurationItemViewModel.buttonTitle = text | ||
self.componentView.label.text = text | ||
if let text, text.isEmpty == false { | ||
self.componentView.showLabel = true | ||
} else { | ||
self.componentView.showLabel = false | ||
} | ||
} | ||
} | ||
} |
128 changes: 128 additions & 0 deletions
128
.Demo/Classes/View/Components/Divider/UIKit/DividerComponentUIViewController.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,128 @@ | ||
// | ||
// DividerComponentUIViewController.swift | ||
// SparkDemo | ||
// | ||
// Created by louis.borlee on 31/07/2024. | ||
// Copyright © 2024 Adevinta. All rights reserved. | ||
// | ||
|
||
import Combine | ||
import SparkCore | ||
import SwiftUI | ||
import UIKit | ||
@_spi(SI_SPI) import SparkCommon | ||
|
||
final class DividerComponentUIViewController: UIViewController { | ||
|
||
// MARK: - Published Properties | ||
@ObservedObject private var themePublisher = SparkThemePublisher.shared | ||
|
||
// MARK: - Properties | ||
let componentView: DividerComponentUIView | ||
let viewModel: DividerComponentUIViewModel | ||
private var cancellables: Set<AnyCancellable> = [] | ||
|
||
// MARK: - Initializer | ||
init(viewModel: DividerComponentUIViewModel) { | ||
self.viewModel = viewModel | ||
self.componentView = DividerComponentUIView(viewModel: viewModel) | ||
super.init(nibName: nil, bundle: nil) | ||
|
||
self.componentView.viewController = self | ||
} | ||
|
||
required init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
// MARK: - Lifecycle | ||
override func loadView() { | ||
super.loadView() | ||
view = componentView | ||
} | ||
|
||
// MARK: - ViewDidLoad | ||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
self.navigationItem.title = "Divider" | ||
self.addPublisher() | ||
} | ||
|
||
// MARK: - Add Publishers | ||
private func addPublisher() { | ||
|
||
self.themePublisher | ||
.$theme | ||
.sink { [weak self] theme in | ||
guard let self = self else { return } | ||
self.viewModel.theme = theme | ||
self.navigationController?.navigationBar.tintColor = theme.colors.main.main.uiColor | ||
} | ||
.store(in: &self.cancellables) | ||
|
||
self.viewModel.showThemeSheet.subscribe(in: &self.cancellables) { intents in | ||
self.presentThemeActionSheet(intents) | ||
} | ||
|
||
self.viewModel.showIntentSheet.subscribe(in: &self.cancellables) { intents in | ||
self.presentIntentActionSheet(intents) | ||
} | ||
|
||
self.viewModel.showAxisSheet.subscribe(in: &self.cancellables) { axis in | ||
self.presentAxisActionSheet(axis) | ||
} | ||
|
||
self.viewModel.showAlignmentSheet.subscribe(in: &self.cancellables) { alignments in | ||
self.presentAlignmentActionSheet(alignments) | ||
} | ||
} | ||
} | ||
|
||
// MARK: - Builder | ||
extension DividerComponentUIViewController { | ||
|
||
static func build() -> DividerComponentUIViewController { | ||
let viewModel = DividerComponentUIViewModel(theme: SparkThemePublisher.shared.theme) | ||
return DividerComponentUIViewController(viewModel: viewModel) | ||
} | ||
} | ||
|
||
// MARK: - Navigation | ||
extension DividerComponentUIViewController { | ||
|
||
private func presentThemeActionSheet(_ themes: [ThemeCellModel]) { | ||
let actionSheet = SparkActionSheet<Theme>.init( | ||
values: themes.map { $0.theme }, | ||
texts: themes.map { $0.title }) { theme in | ||
self.themePublisher.theme = theme | ||
} | ||
self.present(actionSheet, isAnimated: true) | ||
} | ||
|
||
private func presentIntentActionSheet(_ intents: [DividerIntent]) { | ||
let actionSheet = SparkActionSheet<DividerIntent>.init( | ||
values: intents, | ||
texts: intents.map { $0.name }) { intent in | ||
self.viewModel.intent = intent | ||
} | ||
self.present(actionSheet, isAnimated: true) | ||
} | ||
|
||
private func presentAxisActionSheet(_ axis: [DividerAxis]) { | ||
let actionSheet = SparkActionSheet<DividerAxis>.init( | ||
values: axis, | ||
texts: axis.map { $0.name }) { axis in | ||
self.viewModel.axis = axis | ||
} | ||
self.present(actionSheet, isAnimated: true) | ||
} | ||
|
||
private func presentAlignmentActionSheet(_ alignments: [DividerAlignment]) { | ||
let actionSheet = SparkActionSheet<DividerAlignment>.init( | ||
values: alignments, | ||
texts: alignments.map { $0.name }) { alignment in | ||
self.viewModel.alignment = alignment | ||
} | ||
self.present(actionSheet, isAnimated: true) | ||
} | ||
} |
122 changes: 122 additions & 0 deletions
122
.Demo/Classes/View/Components/Divider/UIKit/DividerComponentUIViewModel.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,122 @@ | ||
// | ||
// DividerComponentUIViewModel.swift | ||
// SparkDemo | ||
// | ||
// Created by louis.borlee on 31/07/2024. | ||
// Copyright © 2024 Adevinta. All rights reserved. | ||
// | ||
|
||
import UIKit | ||
import Combine | ||
|
||
final class DividerComponentUIViewModel: ComponentUIViewModel, ObservableObject { | ||
|
||
let themes = ThemeCellModel.themes | ||
|
||
@Published var theme: Theme | ||
@Published var text: String? | ||
@Published var intent = DividerIntent.outline | ||
@Published var axis = DividerAxis.horizontal | ||
@Published var alignment = DividerAlignment.center | ||
|
||
// MARK: - Published Properties | ||
var showThemeSheet: AnyPublisher<[ThemeCellModel], Never> { | ||
self.showThemeSheetSubject | ||
.eraseToAnyPublisher() | ||
} | ||
var showIntentSheet: AnyPublisher<[DividerIntent], Never> { | ||
self.showIntentSheetSubject | ||
.eraseToAnyPublisher() | ||
} | ||
var showAxisSheet: AnyPublisher<[DividerAxis], Never> { | ||
self.showAxisSheetSubject | ||
.eraseToAnyPublisher() | ||
} | ||
var showAlignmentSheet: AnyPublisher<[DividerAlignment], Never> { | ||
self.showAlignmentSheetSubject | ||
.eraseToAnyPublisher() | ||
} | ||
|
||
private var showThemeSheetSubject: PassthroughSubject<[ThemeCellModel], Never> = .init() | ||
private var showIntentSheetSubject: PassthroughSubject<[DividerIntent], Never> = .init() | ||
private var showAxisSheetSubject: PassthroughSubject<[DividerAxis], Never> = .init() | ||
private var showAlignmentSheetSubject: PassthroughSubject<[DividerAlignment], Never> = .init() | ||
|
||
lazy var themeConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { | ||
return .init( | ||
name: "Theme", | ||
type: .button, | ||
target: (source: self, action: #selector(self.presentThemeSheet)) | ||
) | ||
}() | ||
|
||
lazy var intentConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { | ||
return .init( | ||
name: "Intent", | ||
type: .button, | ||
target: (source: self, action: #selector(self.presentIntentSheet)) | ||
) | ||
}() | ||
|
||
lazy var axisConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { | ||
return .init( | ||
name: "Axis", | ||
type: .button, | ||
target: (source: self, action: #selector(self.presentAxisSheet)) | ||
) | ||
}() | ||
|
||
lazy var alignmentConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { | ||
return .init( | ||
name: "Alignment", | ||
type: .button, | ||
target: (source: self, action: #selector(self.presentAlignmentSheet)) | ||
) | ||
}() | ||
|
||
lazy var textConfigurationItemViewModel: ComponentsConfigurationItemUIViewModel = { | ||
return .init( | ||
name: "Text", | ||
type: .input(text: self.text), | ||
target: (source: self, action: #selector(self.textChanged(_:)))) | ||
}() | ||
|
||
override func configurationItemsViewModel() -> [ComponentsConfigurationItemUIViewModel] { | ||
return [ | ||
self.themeConfigurationItemViewModel, | ||
self.intentConfigurationItemViewModel, | ||
self.axisConfigurationItemViewModel, | ||
self.alignmentConfigurationItemViewModel, | ||
self.textConfigurationItemViewModel | ||
] | ||
} | ||
|
||
init(theme: any Theme) { | ||
self.theme = theme | ||
super.init(identifier: "Divider") | ||
} | ||
|
||
@objc func presentThemeSheet() { | ||
self.showThemeSheetSubject.send(self.themes) | ||
} | ||
|
||
@objc func presentIntentSheet() { | ||
self.showIntentSheetSubject.send(DividerIntent.allCases) | ||
} | ||
|
||
@objc func presentAxisSheet() { | ||
self.showAxisSheetSubject.send(DividerAxis.allCases) | ||
} | ||
|
||
@objc func presentAlignmentSheet() { | ||
self.showAlignmentSheetSubject.send(DividerAlignment.allCases) | ||
} | ||
|
||
@objc func textChanged(_ textField: UITextField) { | ||
if textField.text?.isEmpty == false { | ||
self.text = textField.text | ||
} else { | ||
self.text = nil | ||
} | ||
} | ||
} |