-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- ReportAction enum 커스텀 - title, message, contentView, 왼쪽, 오른쪽, dim action 추가 함수 구현 - UIViewController에서 경고창 표시하는 함수 구현 - Color -> Image로 변환 함수 구현 => button에 State에 따른 색상을 넣기 위함 - addAction Custom -> button 혹은 view에서 동작 구현을 위함
- Loading branch information
Showing
5 changed files
with
437 additions
and
0 deletions.
There are no files selected for viewing
241 changes: 241 additions & 0 deletions
241
Projects/Modules/DesignSystem/Src/UIComponent/TFAlertViewController.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,241 @@ | ||
// | ||
// TFAlertViewController.swift | ||
// DSKit | ||
// | ||
// Created by SeungMin on 4/3/24. | ||
// | ||
|
||
import UIKit | ||
|
||
public enum ReportAction { | ||
case complaints, block, withdraw | ||
|
||
var title: String { | ||
switch self { | ||
case .complaints: | ||
return "차단할까요?" | ||
case .block: | ||
return "어떤 문제가 있나요?" | ||
case .withdraw: | ||
return "계정 탈퇴하기" | ||
} | ||
} | ||
|
||
var message: String? { | ||
switch self { | ||
case .block: | ||
return "해당 사용자와 서로 차단됩니다." | ||
case .withdraw: | ||
return "정말 탈퇴하시겠어요? 회원님의 모든 정보 및\n사용 내역은 복구 불가합니다. 블링 환불 관련 문의는\n[email protected] 으로 부탁드립니다." | ||
default: | ||
return nil | ||
} | ||
} | ||
|
||
var leftActionTitle: String { | ||
switch self { | ||
case .complaints: | ||
return "차단할까요?" | ||
case .block: | ||
return "차단하기" | ||
case .withdraw: | ||
return "탈퇴하기" | ||
} | ||
} | ||
|
||
var rightActionTitle: String { | ||
switch self { | ||
default: | ||
return "취소" | ||
} | ||
} | ||
} | ||
|
||
public final class TFAlertViewController: TFBaseViewController { | ||
private var titleText: String? | ||
private var messageText: String? | ||
private var contentView: UIView? | ||
|
||
private lazy var dimView: UIView = { | ||
let view = UIView() | ||
view.backgroundColor = DSKitAsset.Color.DimColor.default.color | ||
return view | ||
}() | ||
|
||
private lazy var containerStackView: UIStackView = { | ||
let stackView = UIStackView() | ||
stackView.axis = .vertical | ||
stackView.alignment = .center | ||
stackView.backgroundColor = DSKitAsset.Color.neutral600.color | ||
stackView.layer.cornerRadius = 8 | ||
stackView.transform = CGAffineTransform(scaleX: 1.1, y: 1.1) | ||
stackView.layoutMargins = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0) | ||
stackView.isLayoutMarginsRelativeArrangement = true | ||
return stackView | ||
}() | ||
|
||
private lazy var labelStackView: UIStackView = { | ||
let stackView = UIStackView() | ||
stackView.axis = .vertical | ||
stackView.spacing = 6 | ||
stackView.alignment = .center | ||
return stackView | ||
}() | ||
|
||
private lazy var buttonStackView: UIStackView = { | ||
let stackView = UIStackView() | ||
stackView.axis = .vertical | ||
stackView.spacing = 16.0 | ||
stackView.alignment = .center | ||
return stackView | ||
}() | ||
|
||
private lazy var titleLabel: UILabel? = { | ||
guard titleText != nil else { return nil } | ||
|
||
let label = UILabel() | ||
label.text = titleText | ||
label.font = UIFont.thtH5Sb | ||
label.textAlignment = .center | ||
label.textColor = DSKitAsset.Color.neutral50.color | ||
label.numberOfLines = 0 | ||
return label | ||
}() | ||
|
||
private lazy var messageLabel: UILabel? = { | ||
guard messageText != nil else { return nil } | ||
|
||
let label = UILabel() | ||
label.text = messageText | ||
label.font = UIFont.thtP1R | ||
label.textAlignment = .center | ||
label.textColor = DSKitAsset.Color.neutral300.color | ||
label.numberOfLines = 0 | ||
return label | ||
}() | ||
|
||
let separatorView: UIView = { | ||
let view = UIView() | ||
view.backgroundColor = DSKitAsset.Color.neutral400.color | ||
return view | ||
}() | ||
|
||
init( | ||
titleText: String? = nil, | ||
messageText: String? = nil | ||
) { | ||
super.init(nibName: nil, bundle: nil) | ||
self.titleText = titleText | ||
self.messageText = messageText | ||
|
||
modalPresentationStyle = .overFullScreen | ||
} | ||
|
||
convenience init(contentView: UIView) { | ||
self.init() | ||
|
||
self.contentView = contentView | ||
modalPresentationStyle = .overFullScreen | ||
} | ||
|
||
required public init?(coder: NSCoder) { | ||
fatalError("init(coder:) has not been implemented") | ||
} | ||
|
||
public override func viewWillAppear(_ animated: Bool) { | ||
super.viewWillAppear(animated) | ||
|
||
// curveEaseOut: 시작은 천천히, 끝날 땐 빠르게 | ||
UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveEaseOut) { [weak self] in | ||
self?.containerStackView.transform = .identity | ||
self?.containerStackView.isHidden = false | ||
} | ||
} | ||
|
||
public override func viewWillDisappear(_ animated: Bool) { | ||
super.viewWillDisappear(animated) | ||
|
||
// curveEaseIn: 시작은 빠르게, 끝날 땐 천천히 | ||
UIView.animate(withDuration: 0.1, delay: 0.0, options: .curveEaseIn) { [weak self] in | ||
self?.containerStackView.transform = .identity | ||
self?.containerStackView.isHidden = true | ||
} | ||
} | ||
|
||
public override func makeUI() { | ||
view.addSubviews([dimView, containerStackView]) | ||
containerStackView.addArrangedSubviews([labelStackView, buttonStackView]) | ||
|
||
dimView.snp.makeConstraints { | ||
$0.edges.equalToSuperview() | ||
} | ||
|
||
containerStackView.snp.makeConstraints { | ||
$0.centerY.equalToSuperview() | ||
$0.leading.trailing.equalToSuperview().inset(28) | ||
} | ||
|
||
labelStackView.snp.makeConstraints { | ||
$0.width.equalToSuperview() | ||
} | ||
|
||
buttonStackView.snp.makeConstraints { | ||
$0.width.equalToSuperview() | ||
} | ||
|
||
if let titleLabel = titleLabel { | ||
labelStackView.addArrangedSubview(titleLabel) | ||
|
||
} | ||
|
||
if let messageLabel = messageLabel { | ||
labelStackView.addArrangedSubview(messageLabel) | ||
} | ||
|
||
if !labelStackView.subviews.isEmpty { | ||
containerStackView.setCustomSpacing(20, after: labelStackView) | ||
} | ||
|
||
separatorView.snp.makeConstraints { | ||
$0.width.equalToSuperview() | ||
$0.height.equalTo(1.5) | ||
} | ||
} | ||
|
||
public func addActionToButton( | ||
title: String? = nil, | ||
completion: (() -> Void)? = nil | ||
) { | ||
guard let title = title else { return } | ||
|
||
let button = UIButton() | ||
button.titleLabel?.font = UIFont.thtSubTitle2Sb | ||
|
||
// enable | ||
button.setTitle(title, for: .normal) | ||
button.setTitleColor(DSKitAsset.Color.neutral50.color, for: .normal) | ||
button.setBackgroundImage(DSKitAsset.Color.neutral600.color.image(), for: .normal) | ||
|
||
// disable | ||
button.setTitleColor(DSKitAsset.Color.neutral50.color, for: .disabled) | ||
button.setBackgroundImage(DSKitAsset.Color.neutral300.color.image(), for: .disabled) | ||
|
||
button.addAction(for: .touchUpInside) { _ in | ||
completion?() | ||
} | ||
|
||
if let _ = buttonStackView.subviews.first { | ||
buttonStackView.addArrangedSubview(separatorView) | ||
} | ||
|
||
buttonStackView.addArrangedSubview(button) | ||
button.snp.makeConstraints { $0.width.equalToSuperview() } | ||
} | ||
|
||
public func addActionToDim(completion: (() -> Void)? = nil) { | ||
let tapGestureRecognizer = UITapGestureRecognizer() | ||
tapGestureRecognizer.addAction(closure: { _ in completion?() }) | ||
|
||
dimView.addGestureRecognizer(tapGestureRecognizer) | ||
} | ||
} |
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,18 @@ | ||
// | ||
// UIColor+Util.swift | ||
// DSKit | ||
// | ||
// Created by SeungMin on 4/20/24. | ||
// | ||
|
||
import UIKit | ||
|
||
extension UIColor { | ||
/// Convert color to image | ||
func image(_ size: CGSize = CGSize(width: 1, height: 1)) -> UIImage { | ||
return UIGraphicsImageRenderer(size: size).image { rendererContext in | ||
self.setFill() | ||
rendererContext.fill(CGRect(origin: .zero, size: size)) | ||
} | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
Projects/Modules/DesignSystem/Src/Util/UIControl+Util.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,45 @@ | ||
// | ||
// UIControl+Util.swift | ||
// DSKit | ||
// | ||
// Created by SeungMin on 4/20/24. | ||
// | ||
|
||
import UIKit | ||
|
||
extension UIControl { | ||
public typealias UIControlTargetClosure = (UIControl) -> () | ||
|
||
private class UIControlClosureWrapper: NSObject { | ||
let closure: UIControlTargetClosure | ||
init(_ closure: @escaping UIControlTargetClosure) { | ||
self.closure = closure | ||
} | ||
} | ||
|
||
private struct AssociatedKeys { | ||
static var targetClosure = "targetClosure" | ||
} | ||
|
||
private var targetClosure: UIControlTargetClosure? { | ||
get { | ||
guard let closureWrapper = objc_getAssociatedObject(self, &AssociatedKeys.targetClosure) as? UIControlClosureWrapper else { return nil } | ||
return closureWrapper.closure | ||
|
||
} set(newValue) { | ||
guard let newValue = newValue else { return } | ||
objc_setAssociatedObject(self, &AssociatedKeys.targetClosure, UIControlClosureWrapper(newValue), | ||
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
@objc func closureAction() { | ||
guard let targetClosure = targetClosure else { return } | ||
targetClosure(self) | ||
} | ||
|
||
public func addAction(for event: UIControl.Event, closure: @escaping UIControlTargetClosure) { | ||
targetClosure = closure | ||
addTarget(self, action: #selector(UIControl.closureAction), for: event) | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
Projects/Modules/DesignSystem/Src/Util/UITapGestureRecognizer.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,51 @@ | ||
// | ||
// UITapGestureRecognizer.swift | ||
// DSKit | ||
// | ||
// Created by SeungMin on 4/20/24. | ||
// | ||
|
||
import UIKit | ||
|
||
extension UITapGestureRecognizer { | ||
public typealias UITapGestureTargetClosure = (UITapGestureRecognizer) -> () | ||
|
||
private class UITapGestureClosureWrapper: NSObject { | ||
let closure: UITapGestureTargetClosure | ||
init(_ closure: @escaping UITapGestureTargetClosure) { | ||
self.closure = closure | ||
} | ||
} | ||
|
||
private struct AssociatedKeys { | ||
static var targetClosure = "targetClosure" | ||
} | ||
|
||
private var targetClosure: UITapGestureTargetClosure? { | ||
get { | ||
guard let closureWrapper = objc_getAssociatedObject( | ||
self, | ||
&AssociatedKeys.targetClosure | ||
) as? UITapGestureClosureWrapper else { return nil } | ||
return closureWrapper.closure | ||
|
||
} set(newValue) { | ||
guard let newValue = newValue else { return } | ||
objc_setAssociatedObject( | ||
self, | ||
&AssociatedKeys.targetClosure, | ||
UITapGestureClosureWrapper(newValue), | ||
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
@objc func closureAction() { | ||
guard let targetClosure = targetClosure else { return } | ||
targetClosure(self) | ||
} | ||
|
||
public func addAction(closure: @escaping UITapGestureTargetClosure) { | ||
targetClosure = closure | ||
addTarget(self, action: #selector(UITapGestureRecognizer.closureAction)) | ||
} | ||
} |
Oops, something went wrong.