-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] 와블 컴포넌트(액션 시트, 404, 로딩뷰, 사진 상세, CTA버튼) 구현 #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
2c9a4d5
[Feat] #119 - 와블 버튼 구현
JinUng41 b595661
[Delete] #119 - 빈 파일 삭제
JinUng41 a1eced2
[Feat] #119 - PhotoDetailVC 구현
JinUng41 fb6f390
[Feat] #119 - NotFoundVC 구현
JinUng41 f872e57
[Feat] #119 - LoadingVC 구현
JinUng41 b6e02db
[Feat] #119 - WableActionSheetVC 구현
JinUng41 68b116c
[Refactor] #119 - 모달을 OverFullScreen으로 열리게끔 수정
JinUng41 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
122 changes: 122 additions & 0 deletions
122
Wable-iOS/Presentation/WableComponent/Jinung/LoadingViewController.swift
This file contains hidden or 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 @@ | ||
| // | ||
| // LoadingViewController.swift | ||
| // Wable-iOS | ||
| // | ||
| // Created by 김진웅 on 3/14/25. | ||
| // | ||
|
|
||
| import UIKit | ||
|
|
||
| import Lottie | ||
| import SnapKit | ||
| import Then | ||
|
|
||
| final class LoadingViewController: UIViewController { | ||
|
|
||
| // MARK: - UIComponent | ||
|
|
||
| private let loadingAnimationView = LottieAnimationView( | ||
| name: LottieType.loading.rawValue | ||
| ).then{ | ||
| $0.contentMode = .scaleAspectFit | ||
| $0.loopMode = .playOnce | ||
| } | ||
|
|
||
| private lazy var messageLabel = UILabel().then { | ||
| $0.attributedText = Self.messages.randomElement()?.pretendardString(with: .head1) | ||
| $0.textAlignment = .center | ||
| $0.numberOfLines = 0 | ||
| } | ||
|
|
||
| // MARK: - Property | ||
|
|
||
| private let loadingDuration: TimeInterval = 1.6 | ||
|
|
||
| // MARK: - Initializer | ||
|
|
||
| init() { | ||
| super.init(nibName: nil, bundle: nil) | ||
|
|
||
| modalTransitionStyle = .crossDissolve | ||
| modalPresentationStyle = .overFullScreen | ||
| } | ||
|
|
||
| required init?(coder: NSCoder) { | ||
| fatalError("init(coder:) has not been implemented") | ||
| } | ||
|
|
||
| // MARK: - Life Cycle | ||
|
|
||
| override func viewDidLoad() { | ||
| super.viewDidLoad() | ||
|
|
||
| setupView() | ||
| setupConstraint() | ||
| } | ||
|
|
||
| override func viewDidAppear(_ animated: Bool) { | ||
| super.viewDidAppear(animated) | ||
|
|
||
| startAnimationAndDismiss() | ||
| } | ||
|
|
||
| private func startAnimationAndDismiss() { | ||
| loadingAnimationView.play() | ||
|
|
||
| DispatchQueue.main.asyncAfter(deadline: .now() + loadingDuration) { | ||
| self.loadingAnimationView.pause() | ||
| self.dismiss(animated: true) | ||
| } | ||
| } | ||
|
Comment on lines
+63
to
+70
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 ... 다른 뷰컨에서도 쓸 수 있을 것 같은데 익스텐션으로 분리해보는 것도 좋을 것 같아요! |
||
| } | ||
|
|
||
| // MARK: - Setup Method | ||
|
|
||
| private extension LoadingViewController { | ||
| func setupView() { | ||
| view.backgroundColor = .wableWhite | ||
|
|
||
| view.addSubviews( | ||
| loadingAnimationView, | ||
| messageLabel | ||
| ) | ||
| } | ||
|
|
||
| func setupConstraint() { | ||
| loadingAnimationView.snp.makeConstraints { make in | ||
| make.top.equalToSuperview().offset(252) | ||
| make.centerX.equalToSuperview() | ||
| make.adjustedWidthEqualTo(160) | ||
| make.height.equalTo(loadingAnimationView.snp.width) | ||
| } | ||
|
|
||
| messageLabel.snp.makeConstraints { make in | ||
| make.top.equalTo(loadingAnimationView.snp.bottom).offset(36) | ||
| make.horizontalEdges.equalToSuperview().inset(30) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Messages | ||
|
|
||
| private extension LoadingViewController { | ||
| static let messages: [String] = [ | ||
| "경기 보고 어디서 모여?\n와블에서", | ||
| "와블와블", | ||
| "팬으로서 저의가 해야 할 건\n끊임없는 응원이에요", | ||
| "우리는 선수와 팀을 대표하는 얼굴이에요", | ||
| "선수들을 응원하되 스포츠의 시각으로\n바라봐주세요", | ||
| "온화함을 해치는 글에 슬며시 투명도를\n눌러주세요", | ||
| "이기면 함께 축하하고, 지면 다음에\n잘하면 된다고 격려해 주세요", | ||
| "일부 팬의 행동으로 전체 팬을\n욕하지 말아주세요", | ||
| "말하기 전에 항상\n다시 한번 생각하기 약속!", | ||
| "숨어있는 롤잘알분들 나와주세요", | ||
| "함께 경기 볼 사람들은 여기로 모여~", | ||
| "유쾌하면서도 편안할 수 있는 공간\n함께 만들어 주실 거죠?", | ||
| "'나는 와블해'라고 말할 수 있는\n커뮤니티가 되고 싶어요!", | ||
| "와블은 온화한 LCK 팬들이\n모이는 공간을 지향해요", | ||
| "와블이라는 이름은 새가 부르는 노래라는\n뜻을 가진 Warble에서 유래했어요", | ||
| "경기 라이브로 챙겨 본 후, 하이라이트\n보고, BJ 경기 후기, 전문가 평가까지\n싹 찾아보는 사람 손~!", | ||
| "와글와글" | ||
| ] | ||
| } | ||
117 changes: 117 additions & 0 deletions
117
Wable-iOS/Presentation/WableComponent/Jinung/NotFoundViewController.swift
This file contains hidden or 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,117 @@ | ||
| // | ||
| // NotFoundViewController.swift | ||
| // Wable-iOS | ||
| // | ||
| // Created by 김진웅 on 3/13/25. | ||
| // | ||
|
|
||
| import UIKit | ||
|
|
||
| import SnapKit | ||
| import Then | ||
|
|
||
| final class NotFoundViewController: UIViewController { | ||
|
|
||
| // MARK: - UIComponent | ||
|
|
||
| private let notFoundImageView = UIImageView().then { | ||
| $0.image = .imgError | ||
| $0.contentMode = .scaleAspectFit | ||
| } | ||
|
|
||
| private let titleLabel = UILabel().then { | ||
| $0.attributedText = "이런!".pretendardString(with: .head0) | ||
| $0.textAlignment = .center | ||
| $0.textColor = .wableBlack | ||
| } | ||
|
|
||
| private let subtitleLabel = UILabel().then { | ||
| $0.attributedText = "현재 요청하신 페이지를 찾을 수 없어요!".pretendardString(with: .head2) | ||
| $0.textAlignment = .center | ||
| $0.textColor = .wableBlack | ||
| } | ||
|
|
||
| private let backToHomeButton = WableButton(style: .black).then { | ||
| var config = $0.configuration | ||
| config?.attributedTitle = "홈으로 가기".pretendardString(with: .body1) | ||
| $0.configuration = config | ||
| } | ||
|
|
||
| // MARK: - Property | ||
|
|
||
| private let backToHomeAction: () -> Void | ||
|
|
||
| // MARK: - Initializer | ||
|
|
||
| init(backToHomeAction: @escaping () -> Void) { | ||
| self.backToHomeAction = backToHomeAction | ||
|
|
||
| super.init(nibName: nil, bundle: nil) | ||
|
|
||
| modalTransitionStyle = .crossDissolve | ||
| modalPresentationStyle = .overFullScreen | ||
| } | ||
|
|
||
| required init?(coder: NSCoder) { | ||
| fatalError("init(coder:) has not been implemented") | ||
| } | ||
|
|
||
| // MARK: - Life Cycle | ||
|
|
||
| override func viewDidLoad() { | ||
| super.viewDidLoad() | ||
|
|
||
| setupView() | ||
| setupConstraint() | ||
| setupAction() | ||
| } | ||
| } | ||
|
|
||
| // MARK: - Setup Method | ||
|
|
||
| private extension NotFoundViewController { | ||
| func setupView() { | ||
| view.backgroundColor = .wableWhite | ||
|
|
||
| view.addSubviews( | ||
| notFoundImageView, | ||
| titleLabel, | ||
| subtitleLabel, | ||
| backToHomeButton | ||
| ) | ||
| } | ||
|
|
||
| func setupConstraint() { | ||
| notFoundImageView.snp.makeConstraints { make in | ||
| make.top.equalToSuperview().offset(196) | ||
| make.centerX.equalToSuperview() | ||
| make.adjustedWidthEqualTo(220) | ||
| make.height.equalTo(notFoundImageView.snp.width) | ||
| } | ||
|
|
||
| titleLabel.snp.makeConstraints { make in | ||
| make.top.equalTo(notFoundImageView.snp.bottom).offset(12) | ||
| make.horizontalEdges.equalToSuperview().inset(16) | ||
| } | ||
|
|
||
| subtitleLabel.snp.makeConstraints { make in | ||
| make.top.equalTo(titleLabel.snp.bottom).offset(16) | ||
| make.horizontalEdges.equalTo(titleLabel) | ||
| } | ||
|
|
||
| backToHomeButton.snp.makeConstraints { make in | ||
| make.top.equalTo(subtitleLabel.snp.bottom).offset(44) | ||
| make.horizontalEdges.equalToSuperview().inset(48) | ||
| make.height.equalTo(backToHomeButton.snp.width).multipliedBy(48.0/280.0) | ||
| } | ||
| } | ||
|
|
||
| func setupAction() { | ||
| let dismissAction = UIAction { [weak self] _ in | ||
| self?.backToHomeAction() | ||
| self?.dismiss(animated: true) | ||
| } | ||
|
|
||
| backToHomeButton.addAction(dismissAction, for: .touchUpInside) | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
init()도 LifeCycle에 포함되는데 따로 분리하신 이유가 궁금해요 !!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
물론 이니셜라이저도 라이프 사이클에 포함되나, 의존성 주입이나 객체 구성 방식을 결정하며 이니셜라이저는 외부에서 명시적으로 호출됩니다.
그렇기 때문에 라이프 사이클의 다른 메서드와는 특징이 다르다고 생각하는데요.
그러한 이유로 저는 별도의 마크 주석으로 작성하고 있습니다.