From 3e9ce98254d57e1adc03184ceee8c257e1ad7598 Mon Sep 17 00:00:00 2001 From: hyerin Date: Sat, 3 Jun 2023 17:36:11 +0900 Subject: [PATCH 001/106] =?UTF-8?q?feat:=20DesignSystemType=20case=20chip?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/DemoApp/Sources/DesignSystemViewController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift index 64447805..9097da5a 100644 --- a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift +++ b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift @@ -17,6 +17,7 @@ fileprivate enum DesignSystemType: String, case button case card case modal + case chip } final class DesignSystemViewController: UITableViewController { From c44fd3e7f593b8b93661eb73145680e327f77790 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 4 Jun 2023 23:21:54 +0900 Subject: [PATCH 002/106] =?UTF-8?q?feat:=20NavigationBar=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITNavigationViewController.swift | 9 + .../NavigationBar/MOITNavigationBar.swift | 159 ++++++++++++++++++ .../NavigationBar/NavigationItem.swift | 26 +++ .../NavigationBar/NavigationItemType.swift | 35 ++++ DesignSystem/Sources/a.swift | 10 -- ResourceKit/Sources/Font.swift | 1 - 6 files changed, 229 insertions(+), 11 deletions(-) create mode 100644 DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift create mode 100644 DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift create mode 100644 DesignSystem/Sources/NavigationBar/NavigationItem.swift create mode 100644 DesignSystem/Sources/NavigationBar/NavigationItemType.swift delete mode 100644 DesignSystem/Sources/a.swift diff --git a/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift b/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift new file mode 100644 index 00000000..1d0ff55a --- /dev/null +++ b/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift @@ -0,0 +1,9 @@ +// +// MOITNavigationViewController.swift +// DesignSystemDemoApp +// +// Created by kimchansoo on 2023/06/04. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation diff --git a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift new file mode 100644 index 00000000..3e710be8 --- /dev/null +++ b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift @@ -0,0 +1,159 @@ +// +// MOITNavigationBar.swift +// DesignSystem +// +// Created by kimchansoo on 2023/06/03. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import FlexLayout +import PinLayout +import RxSwift + + +public final class MOITNavigationBar: UIView { + + // MARK: - UI + private let flexRootView = UIView() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.textColor = ResourceKitAsset.Color.gray900.color + label.textAlignment = .center + label.font = ResourceKitFontFamily.h6 + return label + }() + + + // MARK: - Properties + public let leftItems: [NavigationItem] +// let titleText: String? + public let rightItems: [NavigationItem] + + // MARK: - Initializers + /// leftItems와 rightItems에 좌우측에 들어갈 item을 정의합니다. + /// MOITNavigationBar.leftItems[n].rx.tap으로 이벤트를 받아올 수 있습니다. + public init( + leftItems: [NavigationItemType], + title: String?, + rightItems: [NavigationItemType], + backgroundColor: UIColor, + tintColor: UIColor + ) { + self.leftItems = leftItems.map { NavigationItem(type: $0)} + self.rightItems = rightItems.map { NavigationItem(type: $0)} + + super.init(frame: .zero) + + self.configureLeftItems(self.leftItems) + self.configureTitle(title) + self.configureRightItems(self.rightItems) + self.configureLayout() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("can not init from coder") + } + + // MARK: - Lifecycle + + public override func layoutSubviews() { + super.layoutSubviews() + + self.flexRootView.pin.all() + self.flexRootView.flex.layout(mode: .fitContainer) + + self.flexRootView.backgroundColor = .systemPink + } + + // MARK: - Methods +} + +// MARK: - Private Functions + +extension MOITNavigationBar { + + private func configureFlexRootView() { +// self.flexRootView.backgroundColor = _backgroundColor + self.flexRootView.clipsToBounds = true + } + + private func configureLeftItems(_ leftItems: [NavigationItem]) { + + } + + private func configureTitle(_ title: String?) { + self.titleLabel.text = title + } + + private func configureRightItems(_ rightItems: [NavigationItem]) { + + } +// +// private func configureLayout() { +// self.addSubview(flexRootView) +// +// self.flexRootView.flex +// .height(56) +// .width(100%) +// .direction(.row) +// .justifyContent(.spaceBetween) +// .alignItems(.center) +// .define { flex in +// flex.addItem() +// .direction(.row) +// .define { flex in +// self.leftItems.forEach { flex.addItem($0).size(24)} +// } +// .marginLeft(16) +// // 여백 생성 코드 +// +// +// flex.addItem(self.titleLabel).grow(1) +// flex.addItem() +// .direction(.row) +// .define { flex in +// self.rightItems.forEach { flex.addItem($0).size(24).marginLeft(20)} +// } +// .marginRight(16) +// } +// } + private func configureLayout() { + self.addSubview(flexRootView) + + self.flexRootView.flex + .height(56) +// .width(100%) + .direction(.row) + .alignItems(.center) + .define { flex in + flex.addItem() + .direction(.row) + .grow(1) + .justifyContent(.start) + .define { flex in + self.leftItems.forEach { flex.addItem($0).size(24)} + } + .marginLeft(16) + + flex.addItem(self.titleLabel) + +// .alignSelf(.center) + + flex.addItem() + .direction(.row) + .grow(1) + .justifyContent(.end) + .define { flex in + self.rightItems.forEach { flex.addItem($0).size(24).marginLeft(20)} + } + .marginRight(16) + } + } + +} diff --git a/DesignSystem/Sources/NavigationBar/NavigationItem.swift b/DesignSystem/Sources/NavigationBar/NavigationItem.swift new file mode 100644 index 00000000..b31838b1 --- /dev/null +++ b/DesignSystem/Sources/NavigationBar/NavigationItem.swift @@ -0,0 +1,26 @@ +// +// MOITNavigationItem.swift +// DesignSystem +// +// Created by kimchansoo on 2023/06/04. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import RxSwift +import RxGesture + +public final class NavigationItem: UIButton { + + public init(type: NavigationItemType) { + super.init(frame: .zero) + self.setImage(type.icon, for: .normal) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} diff --git a/DesignSystem/Sources/NavigationBar/NavigationItemType.swift b/DesignSystem/Sources/NavigationBar/NavigationItemType.swift new file mode 100644 index 00000000..b7a50e9d --- /dev/null +++ b/DesignSystem/Sources/NavigationBar/NavigationItemType.swift @@ -0,0 +1,35 @@ +// +// NavigationItemType.swift +// DesignSystem +// +// Created by kimchansoo on 2023/06/04. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +public enum NavigationItemType { + case close + case back + case share + case setting + case alarm + + var icon: UIImage? { + switch self { + case .close: + return ResourceKitAsset.Icon.x.image + case .back: + return ResourceKitAsset.Icon.arrowLeft.image + case .share: + return ResourceKitAsset.Icon.share.image + case .setting: + return ResourceKitAsset.Icon.settings.image + case .alarm: + return ResourceKitAsset.Icon.bell.image + } + } + +} diff --git a/DesignSystem/Sources/a.swift b/DesignSystem/Sources/a.swift deleted file mode 100644 index f77c58ae..00000000 --- a/DesignSystem/Sources/a.swift +++ /dev/null @@ -1,10 +0,0 @@ -// - - -import ResourceKit - -final class A { - func test() { - ResourceKitAsset.Color.black - } -} diff --git a/ResourceKit/Sources/Font.swift b/ResourceKit/Sources/Font.swift index 5bd8f6ea..9debabe4 100644 --- a/ResourceKit/Sources/Font.swift +++ b/ResourceKit/Sources/Font.swift @@ -20,4 +20,3 @@ extension ResourceKitFontFamily { public static let p3 = Pretendard.regular.font(size: 14) public static let caption = Pretendard.medium.font(size: 12) } - From 210c9aa9beb8eb59ab0125ae0365d6b9649c4047 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 4 Jun 2023 23:22:14 +0900 Subject: [PATCH 003/106] =?UTF-8?q?feat:=20Navigationdemo=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DesignSystemViewController.swift | 5 +- .../MOITNavigationViewController.swift | 62 ++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift index 64447805..26cbf556 100644 --- a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift +++ b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift @@ -12,7 +12,7 @@ fileprivate enum DesignSystemType: String, CaseIterable { case navigation case list - case control_tab + case controlTab case input case button case card @@ -61,6 +61,9 @@ final class DesignSystemViewController: UITableViewController { let designSystem = self.designSystems[indexPath.item] switch designSystem { // TODO: 여기에서 각자 화면 만드시오 ! + case .navigation: + let viewController = MOITNavigationViewController() + self.navigationController?.pushViewController(viewController, animated: true) default: return } } diff --git a/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift b/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift index 1d0ff55a..800a0f12 100644 --- a/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift +++ b/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift @@ -6,4 +6,64 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // -import Foundation +import UIKit + +import DesignSystem + +import PinLayout +import FlexLayout +import RxSwift + +final class MOITNavigationViewController: UIViewController { + + // MARK: - UI + private let moitNavigationBar = MOITNavigationBar( + leftItems: [ + .back, + ], + title: "MOIT Design System", + rightItems: [ + .share, + .close, + ], + backgroundColor: .white, + tintColor: .black + ) + private let flexRootView = UIView() + + // MARK: - Properties + private let disposeBag = DisposeBag() + + // MARK: - Initializers + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + self.view.addSubview(self.flexRootView) + self.configureLayouts() + self.view.backgroundColor = .white + self.navigationController?.navigationItem.title = "MOITNavigationBar" + + self.moitNavigationBar.leftItems[0].rx.tap.subscribe(onNext: { [weak self] in + self?.navigationController?.popViewController(animated: true) + }).disposed(by: self.disposeBag) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + self.flexRootView.pin.all(self.view.pin.safeArea) + self.flexRootView.flex.layout(mode: .fitContainer) + } + + private func configureLayouts() { + self.flexRootView.backgroundColor = .systemCyan + self.flexRootView.flex + .direction(.column) + .define { flex in + flex.addItem(self.moitNavigationBar) + .width(100%) + } + } + // MARK: - Methods +} From 1f06a302ab581fde5c8015c7f5576bccaa33b9cb Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 5 Jun 2023 09:14:07 +0900 Subject: [PATCH 004/106] =?UTF-8?q?fix:=20NavigationDemoViewController=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DemoApp/Sources/DesignSystemViewController.swift | 2 +- ...ller.swift => NavigationDemoViewController.swift} | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) rename DesignSystem/DemoApp/Sources/NavigationBar/{MOITNavigationViewController.swift => NavigationDemoViewController.swift} (86%) diff --git a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift index 26cbf556..558cf9e9 100644 --- a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift +++ b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift @@ -62,7 +62,7 @@ final class DesignSystemViewController: UITableViewController { switch designSystem { // TODO: 여기에서 각자 화면 만드시오 ! case .navigation: - let viewController = MOITNavigationViewController() + let viewController = MOITNavigationDemoViewController() self.navigationController?.pushViewController(viewController, animated: true) default: return } diff --git a/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift b/DesignSystem/DemoApp/Sources/NavigationBar/NavigationDemoViewController.swift similarity index 86% rename from DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift rename to DesignSystem/DemoApp/Sources/NavigationBar/NavigationDemoViewController.swift index 800a0f12..b6315fe4 100644 --- a/DesignSystem/DemoApp/Sources/NavigationBar/MOITNavigationViewController.swift +++ b/DesignSystem/DemoApp/Sources/NavigationBar/NavigationDemoViewController.swift @@ -1,5 +1,5 @@ // -// MOITNavigationViewController.swift +// MOITNavigationDemoViewController.swift // DesignSystemDemoApp // // Created by kimchansoo on 2023/06/04. @@ -13,21 +13,21 @@ import DesignSystem import PinLayout import FlexLayout import RxSwift +import RxGesture -final class MOITNavigationViewController: UIViewController { +final class MOITNavigationDemoViewController: UIViewController { // MARK: - UI private let moitNavigationBar = MOITNavigationBar( leftItems: [ .back, ], - title: "MOIT Design System", + title: "MOIT NavigationBar", rightItems: [ .share, .close, ], - backgroundColor: .white, - tintColor: .black + colorType: .reverse ) private let flexRootView = UIView() @@ -42,7 +42,6 @@ final class MOITNavigationViewController: UIViewController { super.viewDidLoad() self.view.addSubview(self.flexRootView) self.configureLayouts() - self.view.backgroundColor = .white self.navigationController?.navigationItem.title = "MOITNavigationBar" self.moitNavigationBar.leftItems[0].rx.tap.subscribe(onNext: { [weak self] in @@ -65,5 +64,6 @@ final class MOITNavigationViewController: UIViewController { .width(100%) } } + // MARK: - Methods } From 0834bce478ab876effd98f4eec99e5584fa5f343 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 5 Jun 2023 09:15:23 +0900 Subject: [PATCH 005/106] =?UTF-8?q?fix:=20NavigationBar=20titleLabel=20?= =?UTF-8?q?=EC=A4=91=EC=95=99=20=EC=A0=95=EB=A0=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NavigationBar/MOITNavigationBar.swift | 78 +++++++------------ 1 file changed, 27 insertions(+), 51 deletions(-) diff --git a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift index 3e710be8..568b3d26 100644 --- a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift +++ b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift @@ -31,9 +31,10 @@ public final class MOITNavigationBar: UIView { // MARK: - Properties public let leftItems: [NavigationItem] -// let titleText: String? public let rightItems: [NavigationItem] + private let colorType: NavigationColorType + // MARK: - Initializers /// leftItems와 rightItems에 좌우측에 들어갈 item을 정의합니다. /// MOITNavigationBar.leftItems[n].rx.tap으로 이벤트를 받아올 수 있습니다. @@ -41,18 +42,18 @@ public final class MOITNavigationBar: UIView { leftItems: [NavigationItemType], title: String?, rightItems: [NavigationItemType], - backgroundColor: UIColor, - tintColor: UIColor + colorType: NavigationColorType = .normal ) { self.leftItems = leftItems.map { NavigationItem(type: $0)} self.rightItems = rightItems.map { NavigationItem(type: $0)} + self.colorType = colorType super.init(frame: .zero) - self.configureLeftItems(self.leftItems) self.configureTitle(title) - self.configureRightItems(self.rightItems) self.configureLayout() + self.configureColor() + } @available(*, unavailable) @@ -67,8 +68,6 @@ public final class MOITNavigationBar: UIView { self.flexRootView.pin.all() self.flexRootView.flex.layout(mode: .fitContainer) - - self.flexRootView.backgroundColor = .systemPink } // MARK: - Methods @@ -79,62 +78,25 @@ public final class MOITNavigationBar: UIView { extension MOITNavigationBar { private func configureFlexRootView() { -// self.flexRootView.backgroundColor = _backgroundColor self.flexRootView.clipsToBounds = true } - private func configureLeftItems(_ leftItems: [NavigationItem]) { - - } - private func configureTitle(_ title: String?) { self.titleLabel.text = title } - - private func configureRightItems(_ rightItems: [NavigationItem]) { - - } -// -// private func configureLayout() { -// self.addSubview(flexRootView) -// -// self.flexRootView.flex -// .height(56) -// .width(100%) -// .direction(.row) -// .justifyContent(.spaceBetween) -// .alignItems(.center) -// .define { flex in -// flex.addItem() -// .direction(.row) -// .define { flex in -// self.leftItems.forEach { flex.addItem($0).size(24)} -// } -// .marginLeft(16) -// // 여백 생성 코드 -// -// -// flex.addItem(self.titleLabel).grow(1) -// flex.addItem() -// .direction(.row) -// .define { flex in -// self.rightItems.forEach { flex.addItem($0).size(24).marginLeft(20)} -// } -// .marginRight(16) -// } -// } + private func configureLayout() { self.addSubview(flexRootView) self.flexRootView.flex .height(56) -// .width(100%) .direction(.row) .alignItems(.center) + .backgroundColor(colorType.backgroundColor) .define { flex in flex.addItem() .direction(.row) - .grow(1) + .width(80) .justifyContent(.start) .define { flex in self.leftItems.forEach { flex.addItem($0).size(24)} @@ -142,12 +104,12 @@ extension MOITNavigationBar { .marginLeft(16) flex.addItem(self.titleLabel) - -// .alignSelf(.center) - + .grow(1) + .alignSelf(.center) + flex.addItem() .direction(.row) - .grow(1) + .width(80) .justifyContent(.end) .define { flex in self.rightItems.forEach { flex.addItem($0).size(24).marginLeft(20)} @@ -155,5 +117,19 @@ extension MOITNavigationBar { .marginRight(16) } } + + private func configureColor() { + + + leftItems.forEach { $0.tintColor = self.colorType.tintColor} + rightItems.forEach { $0.tintColor = self.colorType.tintColor} + titleLabel.textColor = colorType.tintColor + + leftItems.forEach { $0.backgroundColor = self.colorType.backgroundColor} + rightItems.forEach { $0.backgroundColor = self.colorType.backgroundColor} + titleLabel.backgroundColor = colorType.backgroundColor + + self.backgroundColor = colorType.backgroundColor + } } From 9d4534f10b62ee648fb90bb022358676780aa2bf Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 5 Jun 2023 09:16:08 +0900 Subject: [PATCH 006/106] =?UTF-8?q?feat:=20NavigationColorType=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 두가지 case로 나눠서 각각 tintcolor와 backgroundcolor 설정할 수 있도록 함 --- .../NavigationBar/NavigationColorType.swift | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 DesignSystem/Sources/NavigationBar/NavigationColorType.swift diff --git a/DesignSystem/Sources/NavigationBar/NavigationColorType.swift b/DesignSystem/Sources/NavigationBar/NavigationColorType.swift new file mode 100644 index 00000000..f99312e9 --- /dev/null +++ b/DesignSystem/Sources/NavigationBar/NavigationColorType.swift @@ -0,0 +1,35 @@ +// +// NavigationColorType.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/05. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +public enum NavigationColorType { + case normal + case reverse + + var tintColor: UIColor { + switch self { + case .normal: + return ResourceKitAsset.Color.gray900.color + case .reverse: + return ResourceKitAsset.Color.white.color + } + } + + var backgroundColor: UIColor { + switch self { + case .normal: + return ResourceKitAsset.Color.white.color + case .reverse: + return ResourceKitAsset.Color.gray500.color + } + } + +} From 5f6afeb3df69f35f376ec6399a5a2eb84524dedb Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 5 Jun 2023 09:16:35 +0900 Subject: [PATCH 007/106] =?UTF-8?q?feat:=20=EB=B2=84=ED=8A=BC=20tintcolor?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD=20=EC=9C=84=ED=95=B4=20=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81=20=EB=AA=A8=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/NavigationBar/NavigationItem.swift | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/DesignSystem/Sources/NavigationBar/NavigationItem.swift b/DesignSystem/Sources/NavigationBar/NavigationItem.swift index b31838b1..1e30e353 100644 --- a/DesignSystem/Sources/NavigationBar/NavigationItem.swift +++ b/DesignSystem/Sources/NavigationBar/NavigationItem.swift @@ -11,16 +11,27 @@ import UIKit import ResourceKit import RxSwift -import RxGesture public final class NavigationItem: UIButton { + let type: NavigationItemType + public init(type: NavigationItemType) { + self.type = type super.init(frame: .zero) - self.setImage(type.icon, for: .normal) + configureIcon(icon: type.icon) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + private func configureIcon(icon: UIImage?) { + guard let tintedImage = type.icon?.withRenderingMode(.alwaysTemplate) else { + self.setImage(type.icon, for: .normal) + return + } + + self.setImage(tintedImage, for: .normal) + } } From 92ce6c0b9454f37e988f23b26c285e283aca8df8 Mon Sep 17 00:00:00 2001 From: chansooooo Date: Mon, 5 Jun 2023 15:46:05 +0900 Subject: [PATCH 008/106] =?UTF-8?q?add:=20`MOITTabPager`=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/TapPager/MOITTabPager.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 DesignSystem/Sources/TapPager/MOITTabPager.swift diff --git a/DesignSystem/Sources/TapPager/MOITTabPager.swift b/DesignSystem/Sources/TapPager/MOITTabPager.swift new file mode 100644 index 00000000..dbb29c18 --- /dev/null +++ b/DesignSystem/Sources/TapPager/MOITTabPager.swift @@ -0,0 +1,26 @@ +// +// MOITTabPager.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/05. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import RxSwift +import RxGesture + +final class MOITTabPager: UIViewController { + // MARK: - UI + + // MARK: - Properties + + // MARK: - Initializers + + // MARK: - Lifecycle + + // MARK: - Functions +} From 106cda4d7710c887b0628dcde1806e36ff442cb1 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 5 Jun 2023 15:57:27 +0900 Subject: [PATCH 009/106] =?UTF-8?q?add:=20`MOITTabPager`=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/TapPager/MOITTabPager.swift | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 DesignSystem/Sources/TapPager/MOITTabPager.swift diff --git a/DesignSystem/Sources/TapPager/MOITTabPager.swift b/DesignSystem/Sources/TapPager/MOITTabPager.swift new file mode 100644 index 00000000..dbb29c18 --- /dev/null +++ b/DesignSystem/Sources/TapPager/MOITTabPager.swift @@ -0,0 +1,26 @@ +// +// MOITTabPager.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/05. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import RxSwift +import RxGesture + +final class MOITTabPager: UIViewController { + // MARK: - UI + + // MARK: - Properties + + // MARK: - Initializers + + // MARK: - Lifecycle + + // MARK: - Functions +} From 6e5b27c5e0869df2d3041d9f605bc47614651c64 Mon Sep 17 00:00:00 2001 From: hyerin Date: Tue, 6 Jun 2023 00:42:57 +0900 Subject: [PATCH 010/106] =?UTF-8?q?remove:=20dummy=20file=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/a.swift | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 DesignSystem/Sources/a.swift diff --git a/DesignSystem/Sources/a.swift b/DesignSystem/Sources/a.swift deleted file mode 100644 index f77c58ae..00000000 --- a/DesignSystem/Sources/a.swift +++ /dev/null @@ -1,10 +0,0 @@ -// - - -import ResourceKit - -final class A { - func test() { - ResourceKitAsset.Color.black - } -} From 0a39410bf48181c6f2c43302938fa311bc482136 Mon Sep 17 00:00:00 2001 From: hyerin Date: Tue, 6 Jun 2023 00:43:12 +0900 Subject: [PATCH 011/106] =?UTF-8?q?feat:=20MOITChipType=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Chip/MOITChipType.swift | 95 ++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 DesignSystem/Sources/Chip/MOITChipType.swift diff --git a/DesignSystem/Sources/Chip/MOITChipType.swift b/DesignSystem/Sources/Chip/MOITChipType.swift new file mode 100644 index 00000000..ad0f3588 --- /dev/null +++ b/DesignSystem/Sources/Chip/MOITChipType.swift @@ -0,0 +1,95 @@ +// +// MOITChipType.swift +// DesignSystem +// +// Created by 최혜린 on 2023/06/05. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +public enum MOITChipType { + case attend + case late + case absent + case dueDate(date: Int) + case finish + + var cornerRadius: CGFloat { + switch self { + case .attend, .late, .absent: + return 15 + case .dueDate(_), .finish: + return 9 + } + } + + var title: String { + switch self { + case .attend: + return "출석" + case .late: + return "지각" + case .absent: + return "결석" + case .dueDate(let date): + return "D-\(date)" + case .finish: + return "종료" + } + } + + var backgroundColor: UIColor { + switch self { + case .attend: + return ResourceKitAsset.Color.blue800.color + case .late: + return ResourceKitAsset.Color.blue200.color + case .absent: + // TODO: Secondary Color 확정된 후 수정 필요 + return ResourceKitAsset.Color.blue200.color + case .dueDate(_), .finish: + return ResourceKitAsset.Color.gray200.color + } + } + + var textColor: UIColor { + switch self { + case .attend: + return ResourceKitAsset.Color.white.color + case .absent: + return ResourceKitAsset.Color.white.color + case .late, .dueDate(_), .finish: + return ResourceKitAsset.Color.gray900.color + } + } + + var height: CGFloat { + switch self { + case .attend, .late, .absent: + return 30 + case .dueDate(_), .finish: + return 18 + } + } + + var marginHorizontal: CGFloat { + switch self { + case .attend, .late, .absent: + return 12 + case .dueDate(_), .finish: + return 10 + } + } + + var font: UIFont { + switch self { + case .attend, .late, .absent: + return ResourceKitFontFamily.p3 + case .dueDate(_), .finish: + return ResourceKitFontFamily.caption + } + } +} From b84115716dd13cf506b5a1df10c5696872dcd99f Mon Sep 17 00:00:00 2001 From: hyerin Date: Tue, 6 Jun 2023 00:44:06 +0900 Subject: [PATCH 012/106] =?UTF-8?q?feat:=20MOITChip=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Chip/MOITChip.swift | 70 ++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 DesignSystem/Sources/Chip/MOITChip.swift diff --git a/DesignSystem/Sources/Chip/MOITChip.swift b/DesignSystem/Sources/Chip/MOITChip.swift new file mode 100644 index 00000000..b3b0ae3d --- /dev/null +++ b/DesignSystem/Sources/Chip/MOITChip.swift @@ -0,0 +1,70 @@ +// +// MOITChip.swift +// DesignSystem +// +// Created by 최혜린 on 2023/06/03. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import FlexLayout +import PinLayout + +public final class MOITChip: UIView { + + private let flexRootView = UIView() + private let titleLabel = UILabel() + + private let type: MOITChipType + + public init( + type: MOITChipType + ) { + self.type = type + + super.init(frame: .zero) + + configureFlexRootView() + configureComponent() + configureLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override public func layoutSubviews() { + super.layoutSubviews() + + flexRootView.pin.all() + flexRootView.flex.layout(mode: .adjustWidth) + } + + private func configureFlexRootView() { + flexRootView.backgroundColor = type.backgroundColor + flexRootView.layer.cornerRadius = type.cornerRadius + flexRootView.clipsToBounds = true + } + + private func configureComponent() { + titleLabel.textColor = type.textColor + titleLabel.text = type.title + titleLabel.font = type.font + } + + private func configureLayout() { + addSubview(flexRootView) + + flexRootView.flex + .alignItems(.center) + .justifyContent(.center) + .direction(.row) + .define { flex in + flex.addItem(titleLabel).marginHorizontal(type.marginHorizontal) + } + .height(type.height) + } +} From 701af15936aff2a5d68d4849c52b69e688ff6a34 Mon Sep 17 00:00:00 2001 From: hyerin Date: Tue, 6 Jun 2023 00:44:50 +0900 Subject: [PATCH 013/106] =?UTF-8?q?feat:=20MOITChipDemoViewController=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/MOITChipDemoViewController.swift | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 DesignSystem/DemoApp/Sources/MOITChipDemoViewController.swift diff --git a/DesignSystem/DemoApp/Sources/MOITChipDemoViewController.swift b/DesignSystem/DemoApp/Sources/MOITChipDemoViewController.swift new file mode 100644 index 00000000..8b8f2757 --- /dev/null +++ b/DesignSystem/DemoApp/Sources/MOITChipDemoViewController.swift @@ -0,0 +1,81 @@ +// +// MOITChipDemoViewController.swift +// DesignSystemDemoApp +// +// Created by 최혜린 on 2023/06/03. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import DesignSystem + +import FlexLayout +import PinLayout + +public final class MOITChipDemoViewController: UIViewController { + + private let flexRootContainer = UIView() + + override public func viewDidLoad() { + super.viewDidLoad() + + configure() + } + + override public func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + flexRootContainer.pin.all(view.pin.safeArea) + flexRootContainer.flex.layout(mode: .adjustWidth) + } + + private func configure() { + view.addSubview(flexRootContainer) + view.backgroundColor = . white + + addChips() + } + + private func addChips() { + self.flexRootContainer.flex.define { (flex) in + flex.addItem(attendChip()) + .margin(10) + + flex.addItem(lateChip()) + .margin(10) + + flex.addItem(absentChip()) + .margin(10) + + flex.addItem(dueDateChip(date: 10)) + .margin(10) + + flex.addItem(dueDateChip(date: 1000000)) + .margin(10) + + flex.addItem(finishChip()) + .margin(10) + } + } + + private func attendChip() -> MOITChip { + MOITChip(type: .attend) + } + + private func lateChip() -> MOITChip { + MOITChip(type: .late) + } + + private func absentChip() -> MOITChip { + MOITChip(type: .absent) + } + + private func dueDateChip(date: Int) -> MOITChip { + MOITChip(type: .dueDate(date: date)) + } + + private func finishChip() -> MOITChip { + MOITChip(type: .finish) + } +} From f4717d22840046539744ad158194fa4d8fde561a Mon Sep 17 00:00:00 2001 From: hyerin Date: Tue, 6 Jun 2023 00:45:02 +0900 Subject: [PATCH 014/106] =?UTF-8?q?feat:=20DemoViewController=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/DemoApp/Sources/DesignSystemViewController.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift index 9097da5a..25e713bd 100644 --- a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift +++ b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift @@ -61,9 +61,11 @@ final class DesignSystemViewController: UITableViewController { ) { let designSystem = self.designSystems[indexPath.item] switch designSystem { - // TODO: 여기에서 각자 화면 만드시오 ! + case .chip: + self.navigationController?.pushViewController(MOITChipDemoViewController(), animated: true) default: return } } } + From a7af07b30cec1a2ffeb9d4ffa4b3a140b4300a5e Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 7 Jun 2023 16:51:46 +0900 Subject: [PATCH 015/106] =?UTF-8?q?feat:=20PagerType=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/TapPager/TapPagerType.swift | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 DesignSystem/Sources/TapPager/TapPagerType.swift diff --git a/DesignSystem/Sources/TapPager/TapPagerType.swift b/DesignSystem/Sources/TapPager/TapPagerType.swift new file mode 100644 index 00000000..9f26b703 --- /dev/null +++ b/DesignSystem/Sources/TapPager/TapPagerType.swift @@ -0,0 +1,44 @@ +// +// TapPagerType.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/07. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +public enum PagerType { + case underline + case segment + + var enableColor: UIColor { + switch self { + case .underline: + return ResourceKitAsset.Color.gray800.color + case .segment: + return ResourceKitAsset.Color.gray800.color + } + } + + var disableColor: UIColor { + switch self { + case .underline: + return ResourceKitAsset.Color.gray500.color + case .segment: + return ResourceKitAsset.Color.gray600.color + } + } + + var font: UIFont { + switch self { + case .underline: + return ResourceKitFontFamily.h4 + case .segment: + return ResourceKitFontFamily.p2 + } + } + +} From c8394dd7efb24698d27aab6b54619e87b45d53b2 Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 7 Jun 2023 16:52:06 +0900 Subject: [PATCH 016/106] =?UTF-8?q?feat:=20TapPager=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/TapPager/MOITTabPager.swift | 130 +++++++++++++++++- 1 file changed, 126 insertions(+), 4 deletions(-) diff --git a/DesignSystem/Sources/TapPager/MOITTabPager.swift b/DesignSystem/Sources/TapPager/MOITTabPager.swift index dbb29c18..86834f3b 100644 --- a/DesignSystem/Sources/TapPager/MOITTabPager.swift +++ b/DesignSystem/Sources/TapPager/MOITTabPager.swift @@ -13,14 +13,136 @@ import ResourceKit import RxSwift import RxGesture -final class MOITTabPager: UIViewController { + +public final class MOITTabPager: UIView { + // MARK: - UI - + private let flexRootView = UIView() + fileprivate lazy var pages: [UILabel] = [] + + private lazy var underline: UIView = { + let view = UIView() + view.backgroundColor = ResourceKitAsset.Color.gray800.color + return view + }() + + // MARK: - Properties - + let pagerType: PagerType = .underline + + private let disposebag = DisposeBag() + // MARK: - Initializers - + public init( + pages: [String] + ) { + super.init(frame: .zero) + + configurePages(pages: pages) + configureUI() + configureLayout() + congifureUnderline() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: - Lifecycle + public override func layoutSubviews() { + super.layoutSubviews() + + self.flexRootView.pin.all() + self.flexRootView.flex.layout(mode: .fitContainer) + updateSelected(with: 0) + } // MARK: - Functions + private func configureUI() { + + } + + private func configureLayout() { + self.addSubview(flexRootView) + + self.flexRootView.flex + .height(84) + .alignItems(.start) + .justifyContent(.start) + .direction(.column) + .padding(20) + .define { flex in + flex.addItem() + .direction(.row) + .define { flex in + self.pages.forEach { flex.addItem($0).marginHorizontal(12)} + } + .marginBottom(5) + + flex.addItem(underline) + .width(100) + .height(2) + } + } + + private func configurePages(pages: [String]) { + self.pages = pages.map { self.configureLabel(text: $0) } + } + + private func configureLabel(text: String?) -> UILabel { + let label = UILabel() + label.font = pagerType.font + label.text = text + label.textColor = pagerType.disableColor + return label + } + + private func congifureUnderline() { + self.rx.tapIndex + .withUnretained(self) + .subscribe(onNext: { owner, index in + owner.updateSelected(with: index) + }) + .disposed(by: disposebag) + } + + private func updateSelected(with index: Int) { + let selectedLabel = pages[index] + selectedLabel.textColor = self.pagerType.enableColor + pages.filter { $0 != selectedLabel }.forEach { $0.textColor = self.pagerType.disableColor } + + let xPosition = selectedLabel.frame.origin.x + let width = selectedLabel.frame.width + + self.moveUnderline(xPosition: xPosition, width: width) + UIView.animate(withDuration: 0.25) { + self.flexRootView.flex.layout() + } + } + + private func moveUnderline(xPosition: CGFloat, width: CGFloat) { + self.underline.flex + .define { flex in + flex.marginLeft(xPosition) + .width(width) + .height(2) + .marginBottom(6) + } + } +} + +// MARK: - Reactive +extension Reactive where Base: MOITTabPager { + + public var tapIndex: Observable { + + let observables = base.pages.enumerated().map { index, label in + label.rx.tapGesture() + .when(.recognized) + .map { _ in index } + } + + return Observable.merge(observables) + } } From cde95e76a563002fab239d5e55d3461cff617727 Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 7 Jun 2023 16:52:17 +0900 Subject: [PATCH 017/106] =?UTF-8?q?feat:=20SegmentPager=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/TapPager/MOITSegmentPager.swift | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 DesignSystem/Sources/TapPager/MOITSegmentPager.swift diff --git a/DesignSystem/Sources/TapPager/MOITSegmentPager.swift b/DesignSystem/Sources/TapPager/MOITSegmentPager.swift new file mode 100644 index 00000000..2dfd9d41 --- /dev/null +++ b/DesignSystem/Sources/TapPager/MOITSegmentPager.swift @@ -0,0 +1,147 @@ +// +// MOITSegmentPager.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/07. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import RxSwift +import RxGesture + +public final class MOITSegmentPager: UIView { + + // MARK: - UI + private let flexRootView = UIView() + fileprivate lazy var pages: [UILabel] = [] + + private let selectedCircle: UIView = { + let view = UIView() + view.backgroundColor = ResourceKitAsset.Color.white.color + return view + }() + + // MARK: - Properties + let pagerType: PagerType = .segment + + private let disposebag = DisposeBag() + + // MARK: - Initializers + public init( + pages: [String] + ) { + super.init(frame: .zero) + + configurePages(pages: pages) + configureLayout() + congifureSelectedCircle() + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Lifecycle + public override func layoutSubviews() { + super.layoutSubviews() + + self.flexRootView.pin.all() + self.flexRootView.flex.layout(mode: .fitContainer) + updateSelected(with: 0) + } + + // MARK: - Functions + + private func configureLayout() { + self.addSubview(flexRootView) + + self.flexRootView.flex + .height(42) + .cornerRadius(21) + .alignItems(.center) + .justifyContent(.spaceAround) + .direction(.row) + .backgroundColor(ResourceKitAsset.Color.gray300.color) + .define { flex in + flex.addItem(self.selectedCircle) + .position(.absolute) + .alignSelf(.center) + + flex.addItem() + .direction(.row) + .marginHorizontal(4) + .define { flex in + self.pages.forEach { flex.addItem($0).grow(1) } + } + .grow(1) + } + } + + private func configurePages(pages: [String]) { + self.pages = pages.map { self.configureLabel(text: $0) } + } + + private func configureLabel(text: String?) -> UILabel { + let label = UILabel() + label.font = pagerType.font + label.text = text + label.textAlignment = .center + label.textColor = pagerType.disableColor + return label + } + + private func congifureSelectedCircle() { + + self.rx.tapIndex + .withUnretained(self) + .subscribe(onNext: { owner, index in + owner.updateSelected(with: index) + }) + .disposed(by: disposebag) + } + + private func updateSelected(with index: Int) { + let selectedLabel = pages[index] + selectedLabel.textColor = self.pagerType.enableColor + pages.filter { $0 != selectedLabel }.forEach { $0.textColor = self.pagerType.disableColor } + + let xPosition = selectedLabel.frame.origin.x + 4 + let width = selectedLabel.frame.width + let height = selectedLabel.frame.height + + self.moveCircle(xPosition: xPosition, width: width, height: height) + UIView.animate(withDuration: 0.25) { + self.flexRootView.flex.layout() + } + } + + private func moveCircle(xPosition: CGFloat, width: CGFloat, height: CGFloat) { + self.selectedCircle.flex + .define { flex in + flex.marginLeft(xPosition) + .width(width) + .height(34) + .cornerRadius(17) + } + } +} + +// MARK: - Reactive +extension Reactive where Base: MOITSegmentPager { + + public var tapIndex: Observable { + + let observables = base.pages.enumerated().map { index, label in + label.rx.tapGesture() + .when(.recognized) + .map { _ in index } + } + + return Observable.merge(observables) + } +} From 969315622f46e9ea8e98fd2b077561f4b378f333 Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 7 Jun 2023 16:52:34 +0900 Subject: [PATCH 018/106] =?UTF-8?q?feat:=20PagerDemoViewController=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DesignSystemViewController.swift | 3 + .../TapPager/TapPagerDemoViewController.swift | 105 ++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 DesignSystem/DemoApp/Sources/TapPager/TapPagerDemoViewController.swift diff --git a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift index 558cf9e9..752ff197 100644 --- a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift +++ b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift @@ -64,6 +64,9 @@ final class DesignSystemViewController: UITableViewController { case .navigation: let viewController = MOITNavigationDemoViewController() self.navigationController?.pushViewController(viewController, animated: true) + case .controlTab: + let viewController = MOITTapPagerDemoViewController() + self.navigationController?.pushViewController(viewController, animated: true) default: return } } diff --git a/DesignSystem/DemoApp/Sources/TapPager/TapPagerDemoViewController.swift b/DesignSystem/DemoApp/Sources/TapPager/TapPagerDemoViewController.swift new file mode 100644 index 00000000..610758ec --- /dev/null +++ b/DesignSystem/DemoApp/Sources/TapPager/TapPagerDemoViewController.swift @@ -0,0 +1,105 @@ +// +// TapPagerDemoViewController.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/07. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import DesignSystem + +import PinLayout +import FlexLayout +import RxSwift +import RxGesture + +final class MOITTapPagerDemoViewController: UIViewController { + + // MARK: - UI + + private let moitTapPager = MOITTabPager( + pages: ["안녕", "나는", "찬수"] + ) + + private let tapResultLabel: UILabel = { + let label = UILabel() + label.text = "0번째" + return label + }() + + private let moitSegmentPager = MOITSegmentPager( + pages: ["안녕", "나는", "찬수"] + ) + + private let segmentResultLabel: UILabel = { + let label = UILabel() + label.text = "0번째" + return label + }() + + private let flexRootView = UIView() + + // MARK: - Properties + private let disposebag = DisposeBag() + + // MARK: - Initializers + init() {super.init(nibName: nil, bundle: nil)} + + @available (*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + self.view.addSubview(self.flexRootView) + self.configureLayouts() + self.navigationController?.navigationItem.title = "MOIT Tap Pager" + self.moitTapPager.rx.tapIndex + .subscribe(onNext: { index in + self.tapResultLabel.text = "\(index)번쨰" + }) + .disposed(by: disposebag) + + self.moitSegmentPager.rx.tapIndex + .subscribe(onNext: { index in + self.segmentResultLabel.text = "\(index)번쨰" + }) + .disposed(by: disposebag) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + self.flexRootView.pin.all(self.view.pin.safeArea) + self.flexRootView.flex.layout() + } + + private func configureLayouts() { + self.flexRootView.backgroundColor = .white + self.flexRootView.flex + .padding(20) + .direction(.column) + .define { flex in + + flex.addItem(self.moitTapPager) + .width(100%) + .marginBottom(10) + + flex.addItem(self.tapResultLabel) + .marginBottom(30) + + flex.addItem(self.moitSegmentPager) + .width(100%) + .marginBottom(10) + + flex.addItem(self.segmentResultLabel) + } + } + + // MARK: - Methods +} + From 309f29cd0a7379f9911301f0729cde0e57a0c956 Mon Sep 17 00:00:00 2001 From: hyerin Date: Thu, 8 Jun 2023 10:43:25 +0900 Subject: [PATCH 019/106] =?UTF-8?q?fix:=20unavailable=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Chip/MOITChip.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/DesignSystem/Sources/Chip/MOITChip.swift b/DesignSystem/Sources/Chip/MOITChip.swift index b3b0ae3d..9d1d3482 100644 --- a/DesignSystem/Sources/Chip/MOITChip.swift +++ b/DesignSystem/Sources/Chip/MOITChip.swift @@ -32,6 +32,7 @@ public final class MOITChip: UIView { configureLayout() } + @available (*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } From 11dabdd1f248635ccacb0279067ce737852b2e9a Mon Sep 17 00:00:00 2001 From: hyerin Date: Thu, 8 Jun 2023 10:44:07 +0900 Subject: [PATCH 020/106] =?UTF-8?q?feat:=20DemoApp=20Chip=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DemoApp/Sources/{ => Chip}/MOITChipDemoViewController.swift | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename DesignSystem/DemoApp/Sources/{ => Chip}/MOITChipDemoViewController.swift (100%) diff --git a/DesignSystem/DemoApp/Sources/MOITChipDemoViewController.swift b/DesignSystem/DemoApp/Sources/Chip/MOITChipDemoViewController.swift similarity index 100% rename from DesignSystem/DemoApp/Sources/MOITChipDemoViewController.swift rename to DesignSystem/DemoApp/Sources/Chip/MOITChipDemoViewController.swift From 9cb5246df75a53760f654cf39e792633cfecf823 Mon Sep 17 00:00:00 2001 From: hyerin Date: Thu, 8 Jun 2023 10:45:52 +0900 Subject: [PATCH 021/106] =?UTF-8?q?fix:=20enum=20case=20AssociatedValue=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Chip/MOITChipType.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/DesignSystem/Sources/Chip/MOITChipType.swift b/DesignSystem/Sources/Chip/MOITChipType.swift index ad0f3588..59682c60 100644 --- a/DesignSystem/Sources/Chip/MOITChipType.swift +++ b/DesignSystem/Sources/Chip/MOITChipType.swift @@ -21,7 +21,7 @@ public enum MOITChipType { switch self { case .attend, .late, .absent: return 15 - case .dueDate(_), .finish: + case .dueDate, .finish: return 9 } } @@ -50,7 +50,7 @@ public enum MOITChipType { case .absent: // TODO: Secondary Color 확정된 후 수정 필요 return ResourceKitAsset.Color.blue200.color - case .dueDate(_), .finish: + case .dueDate, .finish: return ResourceKitAsset.Color.gray200.color } } @@ -70,7 +70,7 @@ public enum MOITChipType { switch self { case .attend, .late, .absent: return 30 - case .dueDate(_), .finish: + case .dueDate, .finish: return 18 } } @@ -79,7 +79,7 @@ public enum MOITChipType { switch self { case .attend, .late, .absent: return 12 - case .dueDate(_), .finish: + case .dueDate, .finish: return 10 } } @@ -88,7 +88,7 @@ public enum MOITChipType { switch self { case .attend, .late, .absent: return ResourceKitFontFamily.p3 - case .dueDate(_), .finish: + case .dueDate, .finish: return ResourceKitFontFamily.caption } } From f9554886ad98c5bbebfd6d8ba08f00fe5ce5b52c Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 8 Jun 2023 15:59:43 +0900 Subject: [PATCH 022/106] =?UTF-8?q?feat:=20StudyPreview=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=EC=A4=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DesignSystemViewController.swift | 8 ++ .../StudyPreviewDemoViewController.swift | 65 +++++++++ DesignSystem/Project.swift | 1 + .../StudyPreview/ConfigurableCell.swift | 14 ++ .../StudyPreview/MOITStudyPreview.swift | 117 ++++++++++++++++ .../StudyPreview/StudyPreviewModel.swift | 40 ++++++ .../StudyPreview/SwipeTableViewCell.swift | 132 ++++++++++++++++++ .../StudyPreview/TableViewAdapter.swift | 49 +++++++ Scripts/SwiftLintRunScript.sh | 24 ++-- Tuist/Dependencies.swift | 1 - 10 files changed, 438 insertions(+), 13 deletions(-) create mode 100644 DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift create mode 100644 DesignSystem/Sources/StudyPreview/ConfigurableCell.swift create mode 100644 DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift create mode 100644 DesignSystem/Sources/StudyPreview/StudyPreviewModel.swift create mode 100644 DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift create mode 100644 DesignSystem/Sources/StudyPreview/TableViewAdapter.swift diff --git a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift index 818c9091..c5f2703c 100644 --- a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift +++ b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift @@ -18,6 +18,7 @@ fileprivate enum DesignSystemType: String, case card case modal case chip + case studyPreview } final class DesignSystemViewController: UITableViewController { @@ -68,6 +69,13 @@ final class DesignSystemViewController: UITableViewController { case .controlTab: let viewController = MOITTapPagerDemoViewController() self.navigationController?.pushViewController(viewController, animated: true) + case .button: + self.navigationController?.pushViewController(ButtonDemoViewController(), animated: true) + case .chip: + self.navigationController?.pushViewController(MOITChipDemoViewController(), animated: true) + case .studyPreview: + self.navigationController?.pushViewController(StudyPreviewDemoViewController(), animated: true) + default: return } } diff --git a/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift new file mode 100644 index 00000000..088472b8 --- /dev/null +++ b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift @@ -0,0 +1,65 @@ +// +// StudyPreviewDemoViewController.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/08. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import DesignSystem + +import PinLayout +import FlexLayout +import RxSwift +import RxGesture + +final class StudyPreviewDemoViewController: UIViewController { + + // MARK: - UI + private let studyPreview = MOITStudyPreview() + private let flexRootView = UIView() + + // MARK: - Properties + private let disposeBag = DisposeBag() + + // MARK: - Initializers + + // MARK: - Lifecycle + + override func viewDidLoad() { + super.viewDidLoad() + self.view.addSubview(self.flexRootView) + self.configureLayouts() +// self.navigationController?.navigationItem.title = "MOITNavigationBar" + self.configurePreview() +// self.moitNavigationBar.leftItems[0].rx.tap.subscribe(onNext: { [weak self] in +// self?.navigationController?.popViewController(animated: true) +// }).disposed(by: self.disposeBag) + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + self.flexRootView.pin.all(self.view.pin.safeArea) + self.flexRootView.flex.layout(mode: .fitContainer) + } + + private func configureLayouts() { + self.flexRootView.backgroundColor = .systemCyan + self.flexRootView.flex + .direction(.column) + .define { flex in + flex.addItem(self.studyPreview) + .width(100%) + .height(100) + .backgroundColor(.systemPink) + } + } + + private func configurePreview() { + self.studyPreview.configure(remainingDate: "D-19", profileURL: URL(string: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4"), studyName: "공부스터디", studyProgressDescription: "공부스터디") + } + + // MARK: - Methods +} diff --git a/DesignSystem/Project.swift b/DesignSystem/Project.swift index 0223d038..f0d3b12f 100644 --- a/DesignSystem/Project.swift +++ b/DesignSystem/Project.swift @@ -36,6 +36,7 @@ let project = Project( .ThirdParty.RxCocoa, .ThirdParty.RxSwift, .ThirdParty.RxGesture, + .ThirdParty.Kingfisher, ]), Target( name: "DesignSystemDemoApp", diff --git a/DesignSystem/Sources/StudyPreview/ConfigurableCell.swift b/DesignSystem/Sources/StudyPreview/ConfigurableCell.swift new file mode 100644 index 00000000..d6e41126 --- /dev/null +++ b/DesignSystem/Sources/StudyPreview/ConfigurableCell.swift @@ -0,0 +1,14 @@ +// +// ConfigurableCell.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/08. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public protocol ConfigurableCell { + associatedtype DataType: Hashable + func configure(with data: DataType) +} diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift new file mode 100644 index 00000000..e9e68482 --- /dev/null +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -0,0 +1,117 @@ +// +// StudyPreview.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/08. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import FlexLayout +import Kingfisher +import RxSwift +import RxGesture + +public final class MOITStudyPreview: UIView { + + let flexRootView = UIView() + + let remainingDateLabel = UILabel() + let profileImageView = UIImageView() + let studyNameLabel = UILabel() + let studyProgressDescriptionLabel = UILabel() + let actionButton: UIButton = { + let button = UIButton() + button.layer.cornerRadius = 40 + return button + }() + + private var disposebag = DisposeBag() + + + public init() { + super.init(frame: .zero) + + + + configureLayout() + setupGesture() + } + + @available (*, unavailable) + required init?(coder: NSCoder) { + super.init(coder: coder) + configureLayout() + setupGesture() + } + + + private func setupGesture() { + let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))) + flexRootView.addGestureRecognizer(panGestureRecognizer) + } + + public override func layoutSubviews() { + super.layoutSubviews() + + self.addSubview(flexRootView) + self.flexRootView.pin.all() + self.flexRootView.flex.layout(mode: .fitContainer) + } + + private func configureLayout() { + + + self.flexRootView.flex + .direction(.row) + .define { (flex) in + flex.addItem(profileImageView).size(50).aspectRatio(1.0) + flex.addItem(remainingDateLabel) + flex.addItem(studyNameLabel).margin(UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)) + flex.addItem(studyProgressDescriptionLabel).margin(UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)) + flex.addItem(actionButton).backgroundColor(.black).size(100).margin(UIEdgeInsets(top: 20, left: 20, bottom: 0, right: 20)) + } + actionButton.isHidden = true + } + + public func configure(remainingDate: String?, profileURL: URL?, studyName: String?, studyProgressDescription: String?) { + remainingDateLabel.text = remainingDate + profileImageView.kf.setImage(with: profileURL) + studyNameLabel.text = studyName + studyProgressDescriptionLabel.text = studyProgressDescription + self.flexRootView.flex.markDirty() + self.layoutIfNeeded() + + } + + @objc func onPan(_ gestureRecognizer: UIPanGestureRecognizer) { + let translation = gestureRecognizer.translation(in: flexRootView) + let velocity = gestureRecognizer.velocity(in: flexRootView) + // TODO: 뷰 길게 뽑고 안보이는 오른쪽에 버튼(뷰) 붙이기 + switch gestureRecognizer.state { + case .began, .changed: + if translation.x < 0 { // If swiping to the left + // Move the frontView to reveal the backView + flexRootView.transform = CGAffineTransform(translationX: translation.x, y: 0) + } + case .ended: + if velocity.x < 0 { // If swipe to the left + UIView.animate(withDuration: 0.2) { + // Fully reveal the backView + self.flexRootView.transform = CGAffineTransform(translationX: -self.actionButton.frame.width, y: 0) + } + } else { + UIView.animate(withDuration: 0.2) { + // Hide the backView + self.flexRootView.transform = CGAffineTransform.identity + } + } + default: + break + } + } + +} diff --git a/DesignSystem/Sources/StudyPreview/StudyPreviewModel.swift b/DesignSystem/Sources/StudyPreview/StudyPreviewModel.swift new file mode 100644 index 00000000..86048895 --- /dev/null +++ b/DesignSystem/Sources/StudyPreview/StudyPreviewModel.swift @@ -0,0 +1,40 @@ +// +// StudyPreviewModel.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/08. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public struct StudyPreviewModel { + let remainingDate: String + let profileURL: URL + let studyName: String + let studyProgressDescription: String + + public init(remainingDate: String, profileURL: URL, studyName: String, studyProgressDescription: String) { + self.remainingDate = remainingDate + self.profileURL = profileURL + self.studyName = studyName + self.studyProgressDescription = studyProgressDescription + } +} + +extension StudyPreviewModel: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(studyName) + hasher.combine(remainingDate) + hasher.combine(profileURL) + hasher.combine(studyProgressDescription) + } + + public static func == (lhs: StudyPreviewModel, rhs: StudyPreviewModel) -> Bool { + return lhs.studyName == rhs.studyName && + lhs.remainingDate == rhs.remainingDate && + lhs.profileURL == rhs.profileURL && + lhs.studyProgressDescription == rhs.studyProgressDescription + } +} + diff --git a/DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift b/DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift new file mode 100644 index 00000000..8e4a64a1 --- /dev/null +++ b/DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift @@ -0,0 +1,132 @@ +// +// SwipeTableViewCell.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/08. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import RxSwift +import FlexLayout +import PinLayout + +class SwipeTableViewCell: UITableViewCell { + + // MARK: - UI + let swipeActionView = UIView() + let deleteButton = UIButton() + + let remainingDateLabel = UILabel() + let profileImageView = UIImageView() + let studyNameLabel = UILabel() + let studyProgressDescriptionLabel = UILabel() + + // MARK: - Properties + let deleteButtonTapped = PublishSubject() + + // Setup your cell components and layout + + // MARK: - Initializers + + // MARK: - Lifecycle + + // MARK: - Functions + func configure(with model: StudyPreviewModel) { + remainingDateLabel.text = model.remainingDate +// profileImageView.kf.setImage(with: model.profileURL) // Using Kingfisher library for image loading + studyNameLabel.text = model.studyName + studyProgressDescriptionLabel.text = model.studyProgressDescription + } + + // rest of your SwipeTableViewCell code... +} + + +extension SwipeTableViewCell: ConfigurableCell { + typealias DataType = StudyPreviewModel +} + + + + +public final class CustomTableViewCell: UITableViewCell { + + private let containerView: UIView = { + let view = UIView() + view.backgroundColor = .white + return view + }() + + private let revealView: UIView = { + let view = UIView() + view.layer.cornerRadius = 40 + view.backgroundColor = .gray // Adjust as needed + return view + }() + + private let disposebag = DisposeBag() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + selectionStyle = .none + + setupUI() + setupGesture() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + contentView.addSubview(revealView) + contentView.addSubview(containerView) + + contentView.flex.direction(.row).define { (flex) in + flex.addItem(revealView).width(100%) + flex.addItem(containerView).width(100%) + } + } + + private func setupGesture() { + let panGesture = containerView.rx.panGesture().when(.changed, .ended) + panGesture.subscribe(onNext: { [weak self] pan in + guard let self = self else { return } + + let translation = pan.translation(in: self.containerView) + if pan.state == .changed { + if translation.x < -20 { + self.containerView.pin.right(translation.x).vCenter() + } + } else if pan.state == .ended { + if translation.x < -20 { + UIView.animate(withDuration: 0.2) { + self.containerView.pin.right(20).vCenter() + self.layoutIfNeeded() + } + } else { + UIView.animate(withDuration: 0.2) { + self.containerView.pin.right().vCenter() + self.layoutIfNeeded() + } + } + } + }).disposed(by: disposebag) + } + + public override func layoutSubviews() { + super.layoutSubviews() + contentView.pin.all() + contentView.flex.layout(mode: .adjustHeight) + } +} + +extension CustomTableViewCell: ConfigurableCell { + public func configure(with data: StudyPreviewModel) { + + } + + public typealias DataType = StudyPreviewModel +} diff --git a/DesignSystem/Sources/StudyPreview/TableViewAdapter.swift b/DesignSystem/Sources/StudyPreview/TableViewAdapter.swift new file mode 100644 index 00000000..a70c9fab --- /dev/null +++ b/DesignSystem/Sources/StudyPreview/TableViewAdapter.swift @@ -0,0 +1,49 @@ +// +// TableViewAdapter.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/08. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import RxSwift + +public final class TableViewAdapter: NSObject where CellType: UITableViewCell, CellType: ReactiveCompatible { + typealias Snapshot = NSDiffableDataSourceSnapshot + typealias DataSource = UITableViewDiffableDataSource + + enum Section { + case main + } + + var dataSource: DataSource! + private var cellDeleteSubjects = [PublishSubject]() + + var deleteEvents: Observable { + return Observable.merge( + cellDeleteSubjects.enumerated().map { index, subject in + subject.map { _ in index } + } + ) + } + + public func setupDataSource(for tableView: UITableView) { + dataSource = DataSource(tableView: tableView) { (tableView, indexPath, item) -> UITableViewCell? in + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CellType + cell.configure(with: item) +// self.cellDeleteSubjects[indexPath.row] = (cell as! CustomTableViewCell).deleteButtonTapped + return cell + } + + dataSource.defaultRowAnimation = .automatic + } + + public func applySnapshot(data: [CellType.DataType], animatingDifferences: Bool = true) { + var snapshot = Snapshot() + snapshot.appendSections([.main]) + snapshot.appendItems(data) + dataSource.apply(snapshot, animatingDifferences: animatingDifferences) + } +} diff --git a/Scripts/SwiftLintRunScript.sh b/Scripts/SwiftLintRunScript.sh index 33e98c94..445a96aa 100755 --- a/Scripts/SwiftLintRunScript.sh +++ b/Scripts/SwiftLintRunScript.sh @@ -1,14 +1,14 @@ -#!/bin/sh +# #!/bin/sh -# SwiftLintRunScript.sh -# Manifests -# -# Created by 김찬수 on 2023/04/28. -# +# # SwiftLintRunScript.sh +# # Manifests +# # +# # Created by 김찬수 on 2023/04/28. +# # -export PATH="$PATH:/opt/homebrew/bin" -if which swiftlint >/dev/null; then - swiftlint -else - echo "warning: SwiftLint not installed, download form https://github.com/realm/SwiftLint" -fi +# export PATH="$PATH:/opt/homebrew/bin" +# if which swiftlint >/dev/null; then +# swiftlint +# else +# echo "warning: SwiftLint not installed, download form https://github.com/realm/SwiftLint" +# fi diff --git a/Tuist/Dependencies.swift b/Tuist/Dependencies.swift index 55f73ac0..7829067e 100644 --- a/Tuist/Dependencies.swift +++ b/Tuist/Dependencies.swift @@ -27,7 +27,6 @@ let spm = SwiftPackageManagerDependencies( .remote(url: "https://github.com/airbnb/lottie-ios", requirement: .upToNextMajor(from: "4.2.0")), .remote(url: "https://github.com/Quick/Nimble", requirement: .upToNextMajor(from: "9.2.0")), .remote(url: "https://github.com/Quick/Quick", requirement: .upToNextMajor(from: "5.0.0")), - ], productTypes: [ "RIBs": .framework, From 5cbb61a7acc60083c3d7f0b3bf88fe7942c637c5 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 8 Jun 2023 23:40:49 +0900 Subject: [PATCH 023/106] =?UTF-8?q?feat:=20=EC=8A=A4=EC=99=80=EC=9D=B4?= =?UTF-8?q?=ED=94=84=20->=20=20=EC=82=AD=EC=A0=9C=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreviewDemoViewController.swift | 19 ++- .../StudyPreview/MOITStudyPreview.swift | 108 +++++++++++++----- 2 files changed, 87 insertions(+), 40 deletions(-) diff --git a/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift index 088472b8..94d31dac 100644 --- a/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift +++ b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift @@ -18,7 +18,13 @@ import RxGesture final class StudyPreviewDemoViewController: UIViewController { // MARK: - UI - private let studyPreview = MOITStudyPreview() + private let studyPreview = MOITStudyPreview( + remainingDate: 19, + profileURL: URL(string: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4")!, + studyName: "공부스터디", + studyProgressDescription: "공부스터디" + ) + private let flexRootView = UIView() // MARK: - Properties @@ -32,11 +38,7 @@ final class StudyPreviewDemoViewController: UIViewController { super.viewDidLoad() self.view.addSubview(self.flexRootView) self.configureLayouts() -// self.navigationController?.navigationItem.title = "MOITNavigationBar" - self.configurePreview() -// self.moitNavigationBar.leftItems[0].rx.tap.subscribe(onNext: { [weak self] in -// self?.navigationController?.popViewController(animated: true) -// }).disposed(by: self.disposeBag) +// self.configurePreview() } override func viewDidLayoutSubviews() { @@ -56,10 +58,7 @@ final class StudyPreviewDemoViewController: UIViewController { .backgroundColor(.systemPink) } } - - private func configurePreview() { - self.studyPreview.configure(remainingDate: "D-19", profileURL: URL(string: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4"), studyName: "공부스터디", studyProgressDescription: "공부스터디") - } + // MARK: - Methods } diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index e9e68482..ee00bf5c 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -17,38 +17,61 @@ import RxGesture public final class MOITStudyPreview: UIView { - let flexRootView = UIView() + // MARK: - UI + private let flexRootView = UIView() - let remainingDateLabel = UILabel() - let profileImageView = UIImageView() - let studyNameLabel = UILabel() - let studyProgressDescriptionLabel = UILabel() - let actionButton: UIButton = { + private var remainingDateLabel: MOITChip? + private let profileImageView = UIImageView() + private let studyNameLabel: UILabel = { + let label = UILabel() + label.font = ResourceKitFontFamily.h5 + label.textColor = ResourceKitAsset.Color.gray800.color + return label + }() + + private let studyDescriptionLabel: UILabel = { + let label = UILabel() + label.font = ResourceKitFontFamily.p3 + label.textColor = ResourceKitAsset.Color.gray600.color + return label + }() + + private let deleteButton: UIButton = { let button = UIButton() - button.layer.cornerRadius = 40 + button.setImage(ResourceKitAsset.Icon.trash.image.withTintColor(.white), for: .normal) return button }() - + + // MARK: - Properties private var disposebag = DisposeBag() - - public init() { + // MARK: - Initializers + public init(remainingDate: Int, + profileURL: URL, + studyName: String, + studyProgressDescription: String? + ){ super.init(frame: .zero) - - + configureAttributes( + remainingDate: remainingDate, + profileURL: profileURL, + studyName: studyName, + studyProgressDescription: studyProgressDescription + ) configureLayout() setupGesture() } @available (*, unavailable) required init?(coder: NSCoder) { - super.init(coder: coder) - configureLayout() - setupGesture() + fatalError() } + // MARK: - Lifecycle + + // MARK: - Methods private func setupGesture() { let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))) flexRootView.addGestureRecognizer(panGestureRecognizer) @@ -68,40 +91,65 @@ public final class MOITStudyPreview: UIView { self.flexRootView.flex .direction(.row) .define { (flex) in - flex.addItem(profileImageView).size(50).aspectRatio(1.0) - flex.addItem(remainingDateLabel) - flex.addItem(studyNameLabel).margin(UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)) - flex.addItem(studyProgressDescriptionLabel).margin(UIEdgeInsets(top: 10, left: 0, bottom: 0, right: 0)) - flex.addItem(actionButton).backgroundColor(.black).size(100).margin(UIEdgeInsets(top: 20, left: 20, bottom: 0, right: 20)) + flex.addItem() +// .marginVertical(19.5) + .paddingLeft(16) + .marginRight(10) + .width(100%) + .backgroundColor(.green) +// .alignItems(.center) // 얘 하면 왜 iamge 사라짐..? + .direction(.row) + .define { flex in + flex.addItem(profileImageView) +// .marginLeft(16) + .marginVertical(19.5) + .aspectRatio(1.0) + .marginRight(10) + + flex.addItem() + .direction(.column) + .marginVertical(14) + .justifyContent(.spaceBetween) + .alignItems(.start) +// .alignSelf(.start) + .define { flex in + flex.addItem(remainingDateLabel ?? UILabel()) + flex.addItem(studyNameLabel) + flex.addItem(studyDescriptionLabel) + } + } + + + flex.addItem(deleteButton) + .backgroundColor(.orange) + .aspectRatio(0.77) + .cornerRadius(self.deleteButton.bounds.height / 2) } - actionButton.isHidden = true } - public func configure(remainingDate: String?, profileURL: URL?, studyName: String?, studyProgressDescription: String?) { - remainingDateLabel.text = remainingDate + private func configureAttributes(remainingDate: Int, profileURL: URL, studyName: String, studyProgressDescription: String?) { + remainingDateLabel = MOITChip(type: .dueDate(date: remainingDate)) profileImageView.kf.setImage(with: profileURL) studyNameLabel.text = studyName - studyProgressDescriptionLabel.text = studyProgressDescription + studyDescriptionLabel.text = studyProgressDescription self.flexRootView.flex.markDirty() self.layoutIfNeeded() - } @objc func onPan(_ gestureRecognizer: UIPanGestureRecognizer) { let translation = gestureRecognizer.translation(in: flexRootView) let velocity = gestureRecognizer.velocity(in: flexRootView) - // TODO: 뷰 길게 뽑고 안보이는 오른쪽에 버튼(뷰) 붙이기 + switch gestureRecognizer.state { case .began, .changed: - if translation.x < 0 { // If swiping to the left - // Move the frontView to reveal the backView + if translation.x < 0 { flexRootView.transform = CGAffineTransform(translationX: translation.x, y: 0) } case .ended: - if velocity.x < 0 { // If swipe to the left + if velocity.x < 0 { UIView.animate(withDuration: 0.2) { // Fully reveal the backView - self.flexRootView.transform = CGAffineTransform(translationX: -self.actionButton.frame.width, y: 0) + self.flexRootView.transform = CGAffineTransform(translationX: -(self.deleteButton.frame.width + 10), y: 0) } } else { UIView.animate(withDuration: 0.2) { From c3f71b473fd298de625ee29a87fe7e44a70b8eee Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 08:46:20 +0900 Subject: [PATCH 024/106] =?UTF-8?q?add:=20secondary=20color=20set=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Orange100.colorset/Contents.json | 20 +++++++++++++++++++ .../Orange200.colorset/Contents.json | 20 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 ResourceKit/Resources/Color.xcassets/Orange100.colorset/Contents.json create mode 100644 ResourceKit/Resources/Color.xcassets/Orange200.colorset/Contents.json diff --git a/ResourceKit/Resources/Color.xcassets/Orange100.colorset/Contents.json b/ResourceKit/Resources/Color.xcassets/Orange100.colorset/Contents.json new file mode 100644 index 00000000..29eda92a --- /dev/null +++ b/ResourceKit/Resources/Color.xcassets/Orange100.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x01", + "green" : "0x5D", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ResourceKit/Resources/Color.xcassets/Orange200.colorset/Contents.json b/ResourceKit/Resources/Color.xcassets/Orange200.colorset/Contents.json new file mode 100644 index 00000000..b146ea45 --- /dev/null +++ b/ResourceKit/Resources/Color.xcassets/Orange200.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0x8A", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} From 2135af4f03aaa45cdd0b1df558ff0244c7bdfc37 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 08:47:01 +0900 Subject: [PATCH 025/106] =?UTF-8?q?remove:=20=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=ED=8C=8C=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreview/ConfigurableCell.swift | 14 -- .../StudyPreview/SwipeTableViewCell.swift | 132 ------------------ .../StudyPreview/TableViewAdapter.swift | 49 ------- 3 files changed, 195 deletions(-) delete mode 100644 DesignSystem/Sources/StudyPreview/ConfigurableCell.swift delete mode 100644 DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift delete mode 100644 DesignSystem/Sources/StudyPreview/TableViewAdapter.swift diff --git a/DesignSystem/Sources/StudyPreview/ConfigurableCell.swift b/DesignSystem/Sources/StudyPreview/ConfigurableCell.swift deleted file mode 100644 index d6e41126..00000000 --- a/DesignSystem/Sources/StudyPreview/ConfigurableCell.swift +++ /dev/null @@ -1,14 +0,0 @@ -// -// ConfigurableCell.swift -// DesignSystem -// -// Created by 김찬수 on 2023/06/08. -// Copyright © 2023 chansoo.MOIT. All rights reserved. -// - -import Foundation - -public protocol ConfigurableCell { - associatedtype DataType: Hashable - func configure(with data: DataType) -} diff --git a/DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift b/DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift deleted file mode 100644 index 8e4a64a1..00000000 --- a/DesignSystem/Sources/StudyPreview/SwipeTableViewCell.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// SwipeTableViewCell.swift -// DesignSystem -// -// Created by 김찬수 on 2023/06/08. -// Copyright © 2023 chansoo.MOIT. All rights reserved. -// - -import UIKit - -import RxSwift -import FlexLayout -import PinLayout - -class SwipeTableViewCell: UITableViewCell { - - // MARK: - UI - let swipeActionView = UIView() - let deleteButton = UIButton() - - let remainingDateLabel = UILabel() - let profileImageView = UIImageView() - let studyNameLabel = UILabel() - let studyProgressDescriptionLabel = UILabel() - - // MARK: - Properties - let deleteButtonTapped = PublishSubject() - - // Setup your cell components and layout - - // MARK: - Initializers - - // MARK: - Lifecycle - - // MARK: - Functions - func configure(with model: StudyPreviewModel) { - remainingDateLabel.text = model.remainingDate -// profileImageView.kf.setImage(with: model.profileURL) // Using Kingfisher library for image loading - studyNameLabel.text = model.studyName - studyProgressDescriptionLabel.text = model.studyProgressDescription - } - - // rest of your SwipeTableViewCell code... -} - - -extension SwipeTableViewCell: ConfigurableCell { - typealias DataType = StudyPreviewModel -} - - - - -public final class CustomTableViewCell: UITableViewCell { - - private let containerView: UIView = { - let view = UIView() - view.backgroundColor = .white - return view - }() - - private let revealView: UIView = { - let view = UIView() - view.layer.cornerRadius = 40 - view.backgroundColor = .gray // Adjust as needed - return view - }() - - private let disposebag = DisposeBag() - - override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { - super.init(style: style, reuseIdentifier: reuseIdentifier) - selectionStyle = .none - - setupUI() - setupGesture() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func setupUI() { - contentView.addSubview(revealView) - contentView.addSubview(containerView) - - contentView.flex.direction(.row).define { (flex) in - flex.addItem(revealView).width(100%) - flex.addItem(containerView).width(100%) - } - } - - private func setupGesture() { - let panGesture = containerView.rx.panGesture().when(.changed, .ended) - panGesture.subscribe(onNext: { [weak self] pan in - guard let self = self else { return } - - let translation = pan.translation(in: self.containerView) - if pan.state == .changed { - if translation.x < -20 { - self.containerView.pin.right(translation.x).vCenter() - } - } else if pan.state == .ended { - if translation.x < -20 { - UIView.animate(withDuration: 0.2) { - self.containerView.pin.right(20).vCenter() - self.layoutIfNeeded() - } - } else { - UIView.animate(withDuration: 0.2) { - self.containerView.pin.right().vCenter() - self.layoutIfNeeded() - } - } - } - }).disposed(by: disposebag) - } - - public override func layoutSubviews() { - super.layoutSubviews() - contentView.pin.all() - contentView.flex.layout(mode: .adjustHeight) - } -} - -extension CustomTableViewCell: ConfigurableCell { - public func configure(with data: StudyPreviewModel) { - - } - - public typealias DataType = StudyPreviewModel -} diff --git a/DesignSystem/Sources/StudyPreview/TableViewAdapter.swift b/DesignSystem/Sources/StudyPreview/TableViewAdapter.swift deleted file mode 100644 index a70c9fab..00000000 --- a/DesignSystem/Sources/StudyPreview/TableViewAdapter.swift +++ /dev/null @@ -1,49 +0,0 @@ -// -// TableViewAdapter.swift -// DesignSystem -// -// Created by 김찬수 on 2023/06/08. -// Copyright © 2023 chansoo.MOIT. All rights reserved. -// - -import UIKit - -import RxSwift - -public final class TableViewAdapter: NSObject where CellType: UITableViewCell, CellType: ReactiveCompatible { - typealias Snapshot = NSDiffableDataSourceSnapshot - typealias DataSource = UITableViewDiffableDataSource - - enum Section { - case main - } - - var dataSource: DataSource! - private var cellDeleteSubjects = [PublishSubject]() - - var deleteEvents: Observable { - return Observable.merge( - cellDeleteSubjects.enumerated().map { index, subject in - subject.map { _ in index } - } - ) - } - - public func setupDataSource(for tableView: UITableView) { - dataSource = DataSource(tableView: tableView) { (tableView, indexPath, item) -> UITableViewCell? in - let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CellType - cell.configure(with: item) -// self.cellDeleteSubjects[indexPath.row] = (cell as! CustomTableViewCell).deleteButtonTapped - return cell - } - - dataSource.defaultRowAnimation = .automatic - } - - public func applySnapshot(data: [CellType.DataType], animatingDifferences: Bool = true) { - var snapshot = Snapshot() - snapshot.appendSections([.main]) - snapshot.appendItems(data) - dataSource.apply(snapshot, animatingDifferences: animatingDifferences) - } -} From 683e54fd85ff5c347353bf75ccc60dfc7367a9e9 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 08:47:41 +0900 Subject: [PATCH 026/106] =?UTF-8?q?feat:=20optinal=EC=9D=B8=20view=20addIt?= =?UTF-8?q?em=20=EC=89=BD=EA=B2=8C=20=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Common/Flex+.swift | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 DesignSystem/Sources/Common/Flex+.swift diff --git a/DesignSystem/Sources/Common/Flex+.swift b/DesignSystem/Sources/Common/Flex+.swift new file mode 100644 index 00000000..35ea13f6 --- /dev/null +++ b/DesignSystem/Sources/Common/Flex+.swift @@ -0,0 +1,22 @@ +// +// Flex+.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/12. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation +import FlexLayout + +public extension FlexLayout.Flex { + + @discardableResult + func addOptionalItem(_ view: UIView?) -> Flex { + if let view { + self.addItem(view) + } + + return self + } +} From e6a8d2c619ee0e5e91a75b9a9870ccfae0f95524 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 08:49:16 +0900 Subject: [PATCH 027/106] =?UTF-8?q?refactor:=20=EC=8A=A4=EC=99=80=EC=9D=B4?= =?UTF-8?q?=ED=94=84,=20=ED=83=AD=20=EB=B6=80=EB=93=9C=EB=9F=BD=EA=B2=8C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreview/MOITStudyPreview.swift | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index ee00bf5c..46cf163d 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -74,7 +74,11 @@ public final class MOITStudyPreview: UIView { // MARK: - Methods private func setupGesture() { let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))) + let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTap(_:))) + tapGestureRecognizer.delegate = self + panGestureRecognizer.delegate = self flexRootView.addGestureRecognizer(panGestureRecognizer) + flexRootView.addGestureRecognizer(tapGestureRecognizer) } public override func layoutSubviews() { @@ -128,6 +132,9 @@ public final class MOITStudyPreview: UIView { } private func configureAttributes(remainingDate: Int, profileURL: URL, studyName: String, studyProgressDescription: String?) { + deleteButton.addTarget(self, action: #selector(didTapDelete), for: .touchUpInside) + flexRootView.button = deleteButton + remainingDateLabel = MOITChip(type: .dueDate(date: remainingDate)) profileImageView.kf.setImage(with: profileURL) studyNameLabel.text = studyName @@ -136,10 +143,10 @@ public final class MOITStudyPreview: UIView { self.layoutIfNeeded() } - @objc func onPan(_ gestureRecognizer: UIPanGestureRecognizer) { + @objc private func onPan(_ gestureRecognizer: UIPanGestureRecognizer) { let translation = gestureRecognizer.translation(in: flexRootView) let velocity = gestureRecognizer.velocity(in: flexRootView) - + switch gestureRecognizer.state { case .began, .changed: if translation.x < 0 { @@ -161,5 +168,51 @@ public final class MOITStudyPreview: UIView { break } } + + @objc private func didTap(_ gestureRecognizer: UITapGestureRecognizer) { + // didTap 이벤트를 방출 + self.didTapSubject.onNext(()) + } + + @objc private func didTapDelete() { + let alert = UIAlertController( + title: "\(self.studyNameLabel.text ?? "") 스터디를 삭제할까요?", + message: "스터디를 삭제하면 해당 데이터도 모두 삭제됩니다.", + preferredStyle: .alert + ) + let confirmAction = UIAlertAction(title: "확인", style: .default) { action in + self.deleteConfirmSubject.onNext(()) + } + let cancelAction = UIAlertAction(title: "취소", style: .destructive) + alert.addAction(confirmAction) + alert.addAction(cancelAction) + self.window?.rootViewController?.present(alert, animated: true) + } + +} +// MARK: - UIGestureRecognizerDelegate +extension MOITStudyPreview: UIGestureRecognizerDelegate { + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + return false + } + + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { + if gestureRecognizer is UIPanGestureRecognizer { + return otherGestureRecognizer is UITapGestureRecognizer + } + return false + } +} + +// MARK: - Reactive +public extension Reactive where Base: MOITStudyPreview { + + var didConfirmDelete: Observable { + return base.deleteConfirmSubject.asObservable() + } + + var didTap: Observable { + return base.didTapSubject.asObservable() + } } From 094e8853776e3126dac84c55874a3b54003f347f Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 08:49:40 +0900 Subject: [PATCH 028/106] =?UTF-8?q?fix:=20StudyPreview=20UI=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreview/MOITStudyPreview.swift | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index 46cf163d..34572f21 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -18,7 +18,7 @@ import RxGesture public final class MOITStudyPreview: UIView { // MARK: - UI - private let flexRootView = UIView() + fileprivate let flexRootView = TouchThroughView() private var remainingDateLabel: MOITChip? private let profileImageView = UIImageView() @@ -36,15 +36,19 @@ public final class MOITStudyPreview: UIView { return label }() - private let deleteButton: UIButton = { + private lazy var deleteButton: UIButton = { let button = UIButton() button.setImage(ResourceKitAsset.Icon.trash.image.withTintColor(.white), for: .normal) + button.addTarget(self, action: #selector(didTapDelete), for: .touchUpInside) return button }() - + // MARK: - Properties private var disposebag = DisposeBag() + fileprivate let deleteConfirmSubject = PublishSubject() + fileprivate let didTapSubject = PublishSubject() + // MARK: - Initializers public init(remainingDate: Int, profileURL: URL, @@ -86,58 +90,63 @@ public final class MOITStudyPreview: UIView { self.addSubview(flexRootView) self.flexRootView.pin.all() - self.flexRootView.flex.layout(mode: .fitContainer) + self.flexRootView.flex.layout() + self.clipsToBounds = true } private func configureLayout() { - self.flexRootView.flex .direction(.row) .define { (flex) in - flex.addItem() -// .marginVertical(19.5) + flex.addItem() // 보이는 뷰 .paddingLeft(16) .marginRight(10) .width(100%) - .backgroundColor(.green) -// .alignItems(.center) // 얘 하면 왜 iamge 사라짐..? + .height(100) + .cornerRadius(30) + .backgroundColor(.white) + .alignItems(.center) .direction(.row) .define { flex in flex.addItem(profileImageView) -// .marginLeft(16) - .marginVertical(19.5) - .aspectRatio(1.0) + .size(60) .marginRight(10) flex.addItem() .direction(.column) .marginVertical(14) - .justifyContent(.spaceBetween) + .paddingRight(16) + .height(71) .alignItems(.start) -// .alignSelf(.start) .define { flex in - flex.addItem(remainingDateLabel ?? UILabel()) - flex.addItem(studyNameLabel) + flex.addOptionalItem(remainingDateLabel).marginBottom(4) + flex.addItem(studyNameLabel).marginBottom(0) flex.addItem(studyDescriptionLabel) } } - - flex.addItem(deleteButton) - .backgroundColor(.orange) + + flex.addItem(deleteButton) // 옆에 버튼 + .backgroundColor(ResourceKitAsset.Color.orange100.color) .aspectRatio(0.77) - .cornerRadius(self.deleteButton.bounds.height / 2) + .cornerRadius(20) } } private func configureAttributes(remainingDate: Int, profileURL: URL, studyName: String, studyProgressDescription: String?) { + deleteButton.setImage(ResourceKitAsset.Icon.trash.image.withTintColor(.white), for: .normal) deleteButton.addTarget(self, action: #selector(didTapDelete), for: .touchUpInside) flexRootView.button = deleteButton remainingDateLabel = MOITChip(type: .dueDate(date: remainingDate)) - profileImageView.kf.setImage(with: profileURL) + + profileImageView.kf.setImage( + with: profileURL, + options: [.processor(RoundCornerImageProcessor(cornerRadius: 20))] + ) studyNameLabel.text = studyName + studyDescriptionLabel.text = studyProgressDescription self.flexRootView.flex.markDirty() self.layoutIfNeeded() From 62cb634d26e2c9054bf6c2b7ddbabb07e3af4cb6 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 08:50:04 +0900 Subject: [PATCH 029/106] =?UTF-8?q?feat:=20=EB=B2=84=ED=8A=BC=20=EB=88=84?= =?UTF-8?q?=EB=A5=BC=20=EC=88=98=20=EC=9E=88=EB=8A=94=20=EB=B7=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreview/TouchThroughView.swift | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 DesignSystem/Sources/StudyPreview/TouchThroughView.swift diff --git a/DesignSystem/Sources/StudyPreview/TouchThroughView.swift b/DesignSystem/Sources/StudyPreview/TouchThroughView.swift new file mode 100644 index 00000000..8084c8aa --- /dev/null +++ b/DesignSystem/Sources/StudyPreview/TouchThroughView.swift @@ -0,0 +1,20 @@ +// +// TouchThroughView.swift +// DesignSystem +// +// Created by 김찬수 on 2023/06/09. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +class TouchThroughView: UIView { + var button: UIButton? = nil + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + if let button = self.button { + return self.bounds.contains(point) || button.frame.contains(point) + } else { + return super.point(inside: point, with: event) + } + } +} From e1c2b6a55e4bbe7e677ba3de4ca531b62370e819 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 08:50:46 +0900 Subject: [PATCH 030/106] =?UTF-8?q?fix:=20StudyPreviewDemoViewController?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/DesignSystemViewController.swift | 7 +-- .../StudyPreviewDemoViewController.swift | 50 ++++++++++++++++--- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift index db2cca97..05f0db96 100644 --- a/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift +++ b/DesignSystem/DemoApp/Sources/DesignSystemViewController.swift @@ -19,6 +19,7 @@ fileprivate enum DesignSystemType: String, case modal case chip case studyPreview + case alarmView } final class DesignSystemViewController: UITableViewController { @@ -65,12 +66,8 @@ final class DesignSystemViewController: UITableViewController { case .navigation: let viewController = MOITNavigationDemoViewController() self.navigationController?.pushViewController(viewController, animated: true) - case .input: + case .input: self.navigationController?.pushViewController(MOITTextFieldDemoViewController(), animated: true) - // TODO: 여기에서 각자 화면 만드시오 ! - case .navigation: - let viewController = MOITNavigationDemoViewController() - self.navigationController?.pushViewController(viewController, animated: true) case .controlTab: let viewController = MOITTapPagerDemoViewController() self.navigationController?.pushViewController(viewController, animated: true) diff --git a/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift index 94d31dac..35625b8b 100644 --- a/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift +++ b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift @@ -22,7 +22,7 @@ final class StudyPreviewDemoViewController: UIViewController { remainingDate: 19, profileURL: URL(string: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4")!, studyName: "공부스터디", - studyProgressDescription: "공부스터디" + studyProgressDescription: "격주 금요일 17:00 - 20:00" ) private let flexRootView = UIView() @@ -31,14 +31,22 @@ final class StudyPreviewDemoViewController: UIViewController { private let disposeBag = DisposeBag() // MARK: - Initializers - + public init() { + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() self.view.addSubview(self.flexRootView) self.configureLayouts() -// self.configurePreview() + bind() } override func viewDidLayoutSubviews() { @@ -46,19 +54,45 @@ final class StudyPreviewDemoViewController: UIViewController { self.flexRootView.pin.all(self.view.pin.safeArea) self.flexRootView.flex.layout(mode: .fitContainer) } - + + // MARK: - Methods + private func configureLayouts() { - self.flexRootView.backgroundColor = .systemCyan + self.flexRootView.backgroundColor = .darkGray self.flexRootView.flex .direction(.column) + .alignItems(.center) .define { flex in flex.addItem(self.studyPreview) - .width(100%) + .marginTop(40) + .width(80%) .height(100) - .backgroundColor(.systemPink) } } + private func bind() { + self.studyPreview.rx.didTap + .subscribe(onNext: { + self.showAlert(message: "didtap") + }) + .disposed(by: disposeBag) + + self.studyPreview.rx.didConfirmDelete + .subscribe(onNext: { + self.showAlert(message: "delete") + }) + .disposed(by: disposeBag) + } - // MARK: - Methods + private func showAlert(message: String) { + let alert = UIAlertController( + title: message, + message: nil, + preferredStyle: .alert + ) + let confirmAction = UIAlertAction(title: "확인", style: .default) + alert.addAction(confirmAction) + self.present(alert, animated: true) + } + } From 8326914b8d6fdd3d5fd6cc8dc6eefbc59b21c679 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 22:06:16 +0900 Subject: [PATCH 031/106] =?UTF-8?q?refactor:=20StudyPreview=20UI=20Center?= =?UTF-8?q?=20=EB=A7=9E=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreview/MOITStudyPreview.swift | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index 34572f21..e3b0df2d 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -115,18 +115,19 @@ public final class MOITStudyPreview: UIView { flex.addItem() .direction(.column) - .marginVertical(14) - .paddingRight(16) - .height(71) + .height(66) .alignItems(.start) + .justifyContent(.spaceBetween) .define { flex in - flex.addOptionalItem(remainingDateLabel).marginBottom(4) - flex.addItem(studyNameLabel).marginBottom(0) - flex.addItem(studyDescriptionLabel) + flex.addOptionalItem(remainingDateLabel) + flex.addItem() + .define { flex in + flex.addItem(studyNameLabel) + flex.addItem(studyDescriptionLabel) + } } } - flex.addItem(deleteButton) // 옆에 버튼 .backgroundColor(ResourceKitAsset.Color.orange100.color) .aspectRatio(0.77) @@ -134,7 +135,12 @@ public final class MOITStudyPreview: UIView { } } - private func configureAttributes(remainingDate: Int, profileURL: URL, studyName: String, studyProgressDescription: String?) { + private func configureAttributes( + remainingDate: Int, + profileURL: URL, + studyName: String, + studyProgressDescription: String? + ) { deleteButton.setImage(ResourceKitAsset.Icon.trash.image.withTintColor(.white), for: .normal) deleteButton.addTarget(self, action: #selector(didTapDelete), for: .touchUpInside) flexRootView.button = deleteButton @@ -179,7 +185,6 @@ public final class MOITStudyPreview: UIView { } @objc private func didTap(_ gestureRecognizer: UITapGestureRecognizer) { - // didTap 이벤트를 방출 self.didTapSubject.onNext(()) } From 508c6dad47549d8398fd2df6f03d53058ab6bdaa Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 12 Jun 2023 22:34:51 +0900 Subject: [PATCH 032/106] =?UTF-8?q?refactor:=20panGesture=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreview/MOITStudyPreview.swift | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index e3b0df2d..517fd88c 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -157,28 +157,34 @@ public final class MOITStudyPreview: UIView { self.flexRootView.flex.markDirty() self.layoutIfNeeded() } - + @objc private func onPan(_ gestureRecognizer: UIPanGestureRecognizer) { + var originalTransform: CGAffineTransform? + let translation = gestureRecognizer.translation(in: flexRootView) let velocity = gestureRecognizer.velocity(in: flexRootView) - + switch gestureRecognizer.state { - case .began, .changed: - if translation.x < 0 { - flexRootView.transform = CGAffineTransform(translationX: translation.x, y: 0) + case .began: + originalTransform = flexRootView.transform + case .changed: + if let originalTransform = originalTransform { + let totalTranslationX = originalTransform.tx + translation.x + if totalTranslationX < 0 && totalTranslationX > -(self.deleteButton.frame.width + 10) { + flexRootView.transform = CGAffineTransform(translationX: totalTranslationX, y: 0) + } } case .ended: if velocity.x < 0 { UIView.animate(withDuration: 0.2) { - // Fully reveal the backView self.flexRootView.transform = CGAffineTransform(translationX: -(self.deleteButton.frame.width + 10), y: 0) } } else { UIView.animate(withDuration: 0.2) { - // Hide the backView self.flexRootView.transform = CGAffineTransform.identity } } + originalTransform = nil default: break } @@ -210,7 +216,7 @@ extension MOITStudyPreview: UIGestureRecognizerDelegate { public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { return false } - + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool { if gestureRecognizer is UIPanGestureRecognizer { return otherGestureRecognizer is UITapGestureRecognizer @@ -225,7 +231,7 @@ public extension Reactive where Base: MOITStudyPreview { var didConfirmDelete: Observable { return base.deleteConfirmSubject.asObservable() } - + var didTap: Observable { return base.didTapSubject.asObservable() } From aa43302623d602270188fa103be359008930ea47 Mon Sep 17 00:00:00 2001 From: chansooo Date: Tue, 13 Jun 2023 12:16:44 +0900 Subject: [PATCH 033/106] =?UTF-8?q?refactor:=20final=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/StudyPreview/TouchThroughView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DesignSystem/Sources/StudyPreview/TouchThroughView.swift b/DesignSystem/Sources/StudyPreview/TouchThroughView.swift index 8084c8aa..8a1f004f 100644 --- a/DesignSystem/Sources/StudyPreview/TouchThroughView.swift +++ b/DesignSystem/Sources/StudyPreview/TouchThroughView.swift @@ -8,7 +8,7 @@ import UIKit -class TouchThroughView: UIView { +final class TouchThroughView: UIView { var button: UIButton? = nil override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { if let button = self.button { From c2c499179a3aff87a123c9b3b5411050fc905004 Mon Sep 17 00:00:00 2001 From: chansooo Date: Tue, 13 Jun 2023 12:17:02 +0900 Subject: [PATCH 034/106] =?UTF-8?q?redactor:=20`layoutIfNeeded`=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index 517fd88c..43f8a4f9 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -155,7 +155,6 @@ public final class MOITStudyPreview: UIView { studyDescriptionLabel.text = studyProgressDescription self.flexRootView.flex.markDirty() - self.layoutIfNeeded() } @objc private func onPan(_ gestureRecognizer: UIPanGestureRecognizer) { From 3abddcadfc38084a52fdc540811099ee1205c823 Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 14 Jun 2023 15:56:37 +0900 Subject: [PATCH 035/106] =?UTF-8?q?feat:=20SignUp=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EC=84=B8=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignUp/SignUpData/Implement/dummy.swift | 4 ++ .../SignUp/SignUpData/Interface/dummy.swift | 4 ++ Features/SignUp/SignUpData/Project.swift | 22 ++++++++++ Features/SignUp/SignUpData/Tests/dummy.swift | 4 ++ .../SignUp/SignUpDomain/Implement/dummy.swift | 4 ++ .../SignUp/SignUpDomain/Interface/dummy.swift | 4 ++ Features/SignUp/SignUpDomain/Project.swift | 22 ++++++++++ .../SignUp/SignUpDomain/Tests/dummy.swift | 4 ++ .../DemoApp/Resources/LaunchScreen.storyboard | 26 +++++++++++ .../SignUpUserInterfaceAppDelegate.swift | 22 ++++++++++ .../SignUpUserInterfaceViewController.swift | 18 ++++++++ .../Implement/SignUpBuilder.swift | 33 ++++++++++++++ .../Implement/SignUpInteractor.swift | 44 +++++++++++++++++++ .../Implement/SignUpRouter.swift | 29 ++++++++++++ .../Implement/SignUpViewController.swift | 24 ++++++++++ .../Interface/SignUpBuildable.swift | 15 +++++++ .../Interface/SignUpDependency.swift | 16 +++++++ .../Interface/SignUpListener.swift | 15 +++++++ .../SignUp/SignUpUserInterface/Project.swift | 32 ++++++++++++++ .../SignUpUserInterface/Tests/dummy.swift | 3 ++ .../Dependency+Project.swift | 28 +++++++++++- 21 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 Features/SignUp/SignUpData/Implement/dummy.swift create mode 100644 Features/SignUp/SignUpData/Interface/dummy.swift create mode 100644 Features/SignUp/SignUpData/Project.swift create mode 100644 Features/SignUp/SignUpData/Tests/dummy.swift create mode 100644 Features/SignUp/SignUpDomain/Implement/dummy.swift create mode 100644 Features/SignUp/SignUpDomain/Interface/dummy.swift create mode 100644 Features/SignUp/SignUpDomain/Project.swift create mode 100644 Features/SignUp/SignUpDomain/Tests/dummy.swift create mode 100644 Features/SignUp/SignUpUserInterface/DemoApp/Resources/LaunchScreen.storyboard create mode 100644 Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift create mode 100644 Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift create mode 100644 Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift create mode 100644 Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift create mode 100644 Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift create mode 100644 Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift create mode 100644 Features/SignUp/SignUpUserInterface/Interface/SignUpBuildable.swift create mode 100644 Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift create mode 100644 Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift create mode 100644 Features/SignUp/SignUpUserInterface/Project.swift create mode 100644 Features/SignUp/SignUpUserInterface/Tests/dummy.swift diff --git a/Features/SignUp/SignUpData/Implement/dummy.swift b/Features/SignUp/SignUpData/Implement/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/SignUp/SignUpData/Implement/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/SignUp/SignUpData/Interface/dummy.swift b/Features/SignUp/SignUpData/Interface/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/SignUp/SignUpData/Interface/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/SignUp/SignUpData/Project.swift b/Features/SignUp/SignUpData/Project.swift new file mode 100644 index 00000000..b62c4eb7 --- /dev/null +++ b/Features/SignUp/SignUpData/Project.swift @@ -0,0 +1,22 @@ +// +// SignUpAppDelegate.swift +// +// SignUp +// +// Created by kimchansoo +// + +import ProjectDescription +import ProjectDescriptionHelpers +import UtilityPlugin + +let project = Project.invertedDualTargetProject( + name: "SignUpData", + platform: .iOS, + iOSTargetVersion: "15.0.0", + interfaceDependencies: [ + ], + implementDependencies: [ + ] +) + diff --git a/Features/SignUp/SignUpData/Tests/dummy.swift b/Features/SignUp/SignUpData/Tests/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/SignUp/SignUpData/Tests/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/SignUp/SignUpDomain/Implement/dummy.swift b/Features/SignUp/SignUpDomain/Implement/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/SignUp/SignUpDomain/Implement/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/SignUp/SignUpDomain/Interface/dummy.swift b/Features/SignUp/SignUpDomain/Interface/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/SignUp/SignUpDomain/Interface/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/SignUp/SignUpDomain/Project.swift b/Features/SignUp/SignUpDomain/Project.swift new file mode 100644 index 00000000..e7142521 --- /dev/null +++ b/Features/SignUp/SignUpDomain/Project.swift @@ -0,0 +1,22 @@ +// +// SignUpAppDelegate.swift +// +// SignUp +// +// Created by kimchansoo +// + +import ProjectDescription +import ProjectDescriptionHelpers +import UtilityPlugin + +let project = Project.invertedDualTargetProject( + name: "SignUpDomain", + platform: .iOS, + iOSTargetVersion: "15.0.0", + interfaceDependencies: [ + ], + implementDependencies: [ + ] +) + diff --git a/Features/SignUp/SignUpDomain/Tests/dummy.swift b/Features/SignUp/SignUpDomain/Tests/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/SignUp/SignUpDomain/Tests/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Resources/LaunchScreen.storyboard b/Features/SignUp/SignUpUserInterface/DemoApp/Resources/LaunchScreen.storyboard new file mode 100644 index 00000000..eae8f562 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/DemoApp/Resources/LaunchScreen.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift new file mode 100644 index 00000000..898e64ef --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift @@ -0,0 +1,22 @@ +// +// SignUpAppDelegate.swift +// +// SignUp +// +// Created by kimchansoo on . +// + +import UIKit + +@main +final class SignUpAppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + let window = UIWindow(frame: UIScreen.main.bounds) + window.rootViewController = SignUpUserInterfaceViewController() + window.makeKeyAndVisible() + self.window = window + return true + } +} + diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift new file mode 100644 index 00000000..c19ad04f --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift @@ -0,0 +1,18 @@ +// +// ViewController.swift +// +// MOIT +// +// Created by kimchansoo on . +// + +import UIKit + +final class SignUpUserInterfaceViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + self.view.backgroundColor = .systemPink + } +} + diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift new file mode 100644 index 00000000..95adac45 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift @@ -0,0 +1,33 @@ +// +// SignUpBuilder.swift +// SignUpUserInterfaceImpl +// +// Created by 김찬수 on 2023/06/14. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import SignUpUserInterface + +import RIBs + +final class SignUpComponent: Component { + + // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. +} + +// MARK: - Builder + +final class SignUpBuilder: Builder, SignUpBuildable { + + override init(dependency: SignUpDependency) { + super.init(dependency: dependency) + } + + func build(withListener listener: SignUpListener) -> ViewableRouting { + let component = SignUpComponent(dependency: dependency) + let viewController = SignUpViewController() + let interactor = SignUpInteractor(presenter: viewController) + interactor.listener = listener + return SignUpRouter(interactor: interactor, viewController: viewController) + } +} diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift new file mode 100644 index 00000000..e8884442 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift @@ -0,0 +1,44 @@ +// +// SignUpInteractor.swift +// SignUpUserInterfaceImpl +// +// Created by 김찬수 on 2023/06/14. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import SignUpUserInterface + +import RIBs +import RxSwift + +protocol SignUpRouting: ViewableRouting { + // TODO: Declare methods the interactor can invoke to manage sub-tree via the router. +} + +protocol SignUpPresentable: Presentable { + var listener: SignUpPresentableListener? { get set } + // TODO: Declare methods the interactor can invoke the presenter to present data. +} + +final class SignUpInteractor: PresentableInteractor, SignUpInteractable, SignUpPresentableListener { + + weak var router: SignUpRouting? + weak var listener: SignUpListener? + + // TODO: Add additional dependencies to constructor. Do not perform any logic + // in constructor. + override init(presenter: SignUpPresentable) { + super.init(presenter: presenter) + presenter.listener = self + } + + override func didBecomeActive() { + super.didBecomeActive() + // TODO: Implement business logic here. + } + + override func willResignActive() { + super.willResignActive() + // TODO: Pause any business logic. + } +} diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift new file mode 100644 index 00000000..c221671b --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift @@ -0,0 +1,29 @@ +// +// SignUpRouter.swift +// SignUpUserInterfaceImpl +// +// Created by 김찬수 on 2023/06/14. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import SignUpUserInterface + +import RIBs + +protocol SignUpInteractable: Interactable { + var router: SignUpRouting? { get set } + var listener: SignUpListener? { get set } +} + +protocol SignUpViewControllable: ViewControllable { + // TODO: Declare methods the router invokes to manipulate the view hierarchy. +} + +final class SignUpRouter: ViewableRouter, SignUpRouting { + + // TODO: Constructor inject child builder protocols to allow building children. + override init(interactor: SignUpInteractable, viewController: SignUpViewControllable) { + super.init(interactor: interactor, viewController: viewController) + interactor.router = self + } +} diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift new file mode 100644 index 00000000..60941978 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -0,0 +1,24 @@ +// +// SignUpViewController.swift +// SignUpUserInterfaceImpl +// +// Created by 김찬수 on 2023/06/14. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import SignUpUserInterface + +import RIBs +import RxSwift +import UIKit + +protocol SignUpPresentableListener: AnyObject { + // TODO: Declare properties and methods that the view controller can invoke to perform + // business logic, such as signIn(). This protocol is implemented by the corresponding + // interactor class. +} + +final class SignUpViewController: UIViewController, SignUpPresentable, SignUpViewControllable { + + weak var listener: SignUpPresentableListener? +} diff --git a/Features/SignUp/SignUpUserInterface/Interface/SignUpBuildable.swift b/Features/SignUp/SignUpUserInterface/Interface/SignUpBuildable.swift new file mode 100644 index 00000000..e6a841b3 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Interface/SignUpBuildable.swift @@ -0,0 +1,15 @@ +// +// SignUpBuildable.swift +// SignUpUserInterfaceImpl +// +// Created by 김찬수 on 2023/06/14. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import RIBs + +public protocol SignUpBuildable: Buildable { + func build(withListener listener: SignUpListener) -> ViewableRouting +} diff --git a/Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift b/Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift new file mode 100644 index 00000000..5e66b168 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift @@ -0,0 +1,16 @@ +// +// SignUpDependency.swift +// SignUpUserInterfaceImpl +// +// Created by 김찬수 on 2023/06/14. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import RIBs + +public protocol SignUpDependency: Dependency { + // TODO: Declare the set of dependencies required by this RIB, but cannot be + // created by this RIB. +} diff --git a/Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift b/Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift new file mode 100644 index 00000000..fc6eb365 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift @@ -0,0 +1,15 @@ +// +// SignUpListener.swift +// SignUpUserInterfaceImpl +// +// Created by 김찬수 on 2023/06/14. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import RIBs + +public protocol SignUpListener: AnyObject { + // TODO: Declare methods the interactor can invoke to communicate with other RIBs. +} diff --git a/Features/SignUp/SignUpUserInterface/Project.swift b/Features/SignUp/SignUpUserInterface/Project.swift new file mode 100644 index 00000000..adfb55b8 --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Project.swift @@ -0,0 +1,32 @@ +// +// SignUpAppDelegate.swift +// +// SignUp +// +// Created by kimchansoo +// + +import ProjectDescription +import ProjectDescriptionHelpers +import UtilityPlugin + +let project = Project.invertedDualTargetProjectWithDemoApp( + name: "SignUpUserInterface", + platform: .iOS, + iOSTargetVersion: "15.0.0", + interfaceDependencies: [ + .ThirdParty.RIBs, + .ThirdParty.RxSwift, + ], + implementDependencies: [ + .ThirdParty.RxGesture, + .ThirdParty.RxSwift, + .ThirdParty.RxCocoa, + .ThirdParty.RIBs, + + .ResourceKit, + .DesignSystem, + .Core.Utils, + ], + isUserInterface: true +) diff --git a/Features/SignUp/SignUpUserInterface/Tests/dummy.swift b/Features/SignUp/SignUpUserInterface/Tests/dummy.swift new file mode 100644 index 00000000..cfe6c36c --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/Tests/dummy.swift @@ -0,0 +1,3 @@ +// +// dummy.swift +// diff --git a/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift b/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift index b0ddec56..7b00c41b 100644 --- a/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift +++ b/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift @@ -10,7 +10,8 @@ extension TargetDependency { public struct Domain {} public struct UserInterface {} } - public struct MOITShare { + + public struct SignUp { public struct Data {} public struct Domain {} public struct UserInterface {} @@ -45,6 +46,7 @@ public extension TargetDependency.Core { } static let CSLogger = project(name: "CSLogger", isInterface: true) + static let Utils = project(name: "Utils", isInterface: true) } // MARK: - Features/Home @@ -71,6 +73,30 @@ public extension TargetDependency.Feature.Home.Data { static let Implement = TargetDependency.Feature.Home.project(name: "Data", isInterface: false) } +// MARK: - Features/SignUp +public extension TargetDependency.Feature.SignUp { + static let folderName = "SignUp" + static func project(name: String, isInterface: Bool) -> TargetDependency { + let postfix: String = isInterface ? "" : "Impl" + return .project(target: "\(folderName)\(name)\(postfix)", + path: .relativeToRoot("Features/\(folderName)/\(folderName)\(name)")) + }} + +public extension TargetDependency.Feature.SignUp.UserInterface { + static let Interface = TargetDependency.Feature.Home.project(name: "UserInterface", isInterface: true) + static let Implement = TargetDependency.Feature.Home.project(name: "UserInterface", isInterface: false) +} + +public extension TargetDependency.Feature.SignUp.Domain { + static let Interface = TargetDependency.Feature.Home.project(name: "Domain", isInterface: true) + static let Implement = TargetDependency.Feature.Home.project(name: "Domain", isInterface: false) +} + +public extension TargetDependency.Feature.SignUp.Data { + static let Interface = TargetDependency.Feature.Home.project(name: "Data", isInterface: true) + static let Implement = TargetDependency.Feature.Home.project(name: "Data", isInterface: false) +} + // MARK: - Network public extension TargetDependency.MOITNetwork { From d3e372978b19218592d4af1de708bdd261ba53fa Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 14 Jun 2023 15:57:02 +0900 Subject: [PATCH 036/106] =?UTF-8?q?feat:=20Utils=20Target=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Project.swift | 24 ++++--- Core/Utils/Base/BaseView.swift | 37 +++++++++++ Core/Utils/Base/BaseViewController.swift | 84 ++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 8 deletions(-) create mode 100644 Core/Utils/Base/BaseView.swift create mode 100644 Core/Utils/Base/BaseViewController.swift diff --git a/Core/Project.swift b/Core/Project.swift index a78a8381..d9d05adc 100644 --- a/Core/Project.swift +++ b/Core/Project.swift @@ -9,11 +9,19 @@ import ProjectDescription import ProjectDescriptionHelpers import UtilityPlugin -let project = Project(name: "Core", - targets: [ - Project.makeTarget( - name: "CSLogger", - dependencies: [ - ] - ), - ]) +let project = Project( + name: "Core", + targets: [ + Project.makeTarget( + name: "CSLogger", + dependencies: [] + ), + Project.makeTarget( + name: "Utils", + dependencies: [ + .DesignSystem, + .ResourceKit, + ] + ), + ] +) diff --git a/Core/Utils/Base/BaseView.swift b/Core/Utils/Base/BaseView.swift new file mode 100644 index 00000000..cfe4297e --- /dev/null +++ b/Core/Utils/Base/BaseView.swift @@ -0,0 +1,37 @@ +// +// BaseView.swift +// Utils +// +// Created by 김찬수 on 2023/06/14. +// + +import UIKit + +import RxSwift + +class BaseView: UIView { + + // MARK: - Properties + var disposeBag = DisposeBag() + + // MARK: - Methods + override init(frame: CGRect) { + super.init(frame: frame) + + self.backgroundColor = .white + configureAttributes() + configureHierarchy() + configureConstraints() + bind() + } + + func configureHierarchy() {} + func configureConstraints() {} + func configureAttributes() {} + func bind() {} + + @available(*, unavailable) + required init?(coder: NSCoder) { + fatalError("init(coder:) is called.") + } +} diff --git a/Core/Utils/Base/BaseViewController.swift b/Core/Utils/Base/BaseViewController.swift new file mode 100644 index 00000000..96249f7a --- /dev/null +++ b/Core/Utils/Base/BaseViewController.swift @@ -0,0 +1,84 @@ +// +// BaseViewController.swift +// Utils +// +// Created by 김찬수 on 2023/06/14. +// + +import UIKit + +import DesignSystem + +import RxSwift + +public class BaseViewController: UIViewController { + // MARK: - UI + let flexRootView = UIView() + + // TODO: - MOITNavigationBar optional로 만들고 configureNavigationBar에서 설정 + private lazy var navigationBar = MOITNavigationBar( + leftItems: <#T##[NavigationItemType]#>, + title: <#T##String?#>, + rightItems: <#T##[NavigationItemType]#> + ) + + // MARK: - Properties + var disposeBag = DisposeBag() + + private var indicator: UIActivityIndicatorView? + + // MARK: - LifeCycle + public override func viewDidLoad() { + super.viewDidLoad() + + self.view.backgroundColor = .white + + configureAttributes() + configureHierarchy() + configureConstraints() + bind() + } + + public override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + self.flexRootView.pin.all(self.view.pin.safeArea) + self.flexRootView.flex.layout() + } + + // MARK: - Methods + /// addSubView 하는 함수 + func configureHierarchy() {} + /// layout 잡는 함수 + func configureConstraints() {} + /// 값 설정하는 함수 + func configureAttributes() {} + /// bind하는 함수. (ribs라 필요한지 모르겠음) + func bind() {} + + /// navigationBar 사용하면 flexRootView에 추가해주는 함수 + func configureNavigationBar( + leftItems: [NavigationItemType], + title: String?, + rightItems: [NavigationItemType] + ) { + flexRootView.flex + .addItem(self.navigationBar) + // TODO: - configure함수 만들어주기 + navigationBar.configure( + leftItems: leftItems, + title: title, + rightItems: rightItems + ) + } + + + + @available(*, unavailable) + required init(coder: NSCoder) { + fatalError("init(coder:) is called.") + } + + init() { + super.init(nibName: nil, bundle: nil) + } +} From cf57aac0c6a2edc6ba7f9be472a7bb1ae05140f6 Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 14 Jun 2023 15:57:46 +0900 Subject: [PATCH 037/106] =?UTF-8?q?feat:=20SignUp=20=EC=A0=91=EA=B7=BC=20?= =?UTF-8?q?=EC=A0=9C=ED=95=9C=EC=9E=90=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignUpUserInterfaceAppDelegate.swift | 12 ++++++- .../Implement/SignUpBuilder.swift | 6 ++-- .../Implement/SignUpViewController.swift | 31 +++++++++++++++++-- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift index 898e64ef..4b578262 100644 --- a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift +++ b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift @@ -8,12 +8,22 @@ import UIKit +import SignUpUserInterfaceImpl +import SignUpUserInterface + +import RIBs + @main final class SignUpAppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let window = UIWindow(frame: UIScreen.main.bounds) - window.rootViewController = SignUpUserInterfaceViewController() + + + // RIBs 사용해서 signupbuilder로 build 실행 +// window.rootViewController = SignUpBuilder(dependency: AppComponent()).build() + window.rootViewController = SignUpViewController() + window.makeKeyAndVisible() self.window = window return true diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift index 95adac45..761b889d 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift @@ -10,20 +10,20 @@ import SignUpUserInterface import RIBs -final class SignUpComponent: Component { +public final class SignUpComponent: Component { // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. } // MARK: - Builder -final class SignUpBuilder: Builder, SignUpBuildable { +public final class SignUpBuilder: Builder, SignUpBuildable { override init(dependency: SignUpDependency) { super.init(dependency: dependency) } - func build(withListener listener: SignUpListener) -> ViewableRouting { + public func build(withListener listener: SignUpListener) -> ViewableRouting { let component = SignUpComponent(dependency: dependency) let viewController = SignUpViewController() let interactor = SignUpInteractor(presenter: viewController) diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift index 60941978..6f331fe3 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -5,20 +5,45 @@ // Created by 김찬수 on 2023/06/14. // Copyright © 2023 chansoo.MOIT. All rights reserved. // +import UIKit import SignUpUserInterface +import DesignSystem import RIBs import RxSwift -import UIKit protocol SignUpPresentableListener: AnyObject { // TODO: Declare properties and methods that the view controller can invoke to perform // business logic, such as signIn(). This protocol is implemented by the corresponding // interactor class. + func didSwipeBack() } -final class SignUpViewController: UIViewController, SignUpPresentable, SignUpViewControllable { - +public final class SignUpViewController: UIViewController, SignUpPresentable, SignUpViewControllable { + + // MARK: - UI + private let navigationBar: MOITNavigationBar + + // MARK: - Properties weak var listener: SignUpPresentableListener? + + // MARK: - Initializers + + // MARK: - Lifecycle + public override func viewDidLoad() { + super.viewDidLoad() + self.navigationController?.navigationBar.isHidden = true + } + + public override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + if self.isMovingFromParent { + self.listener?.didSwipeBack() + } + } + deinit { debugPrint("\(self) deinit") } + + // MARK: - Functions + } From 2d8411714d35b1f42b555a4c6e6933ef38c834ce Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 14 Jun 2023 23:23:45 +0900 Subject: [PATCH 038/106] =?UTF-8?q?feat:=20Utils=20=ED=83=80=EA=B2=9F?= =?UTF-8?q?=EC=97=90=20pinlayout,=20flexlayout=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Project.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/Project.swift b/Core/Project.swift index d9d05adc..e480e914 100644 --- a/Core/Project.swift +++ b/Core/Project.swift @@ -21,6 +21,9 @@ let project = Project( dependencies: [ .DesignSystem, .ResourceKit, + + .ThirdParty.PinLayout, + .ThirdParty.FlexLayout, ] ), ] From e43e1e32474fe6b96a35762166f3bb0b137e32a5 Mon Sep 17 00:00:00 2001 From: chansooo Date: Wed, 14 Jun 2023 23:24:41 +0900 Subject: [PATCH 039/106] =?UTF-8?q?feat:=20BaseViewController=20=EC=83=81?= =?UTF-8?q?=EC=86=8D=EB=B0=9B=EC=9D=84=20=EA=B2=BD=EC=9A=B0=20navigateBar?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95=20=ED=8E=B8=EB=A6=AC=ED=95=98=EA=B2=8C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Utils/Base/BaseView.swift | 6 +- Core/Utils/Base/BaseViewController.swift | 80 ++++++++++++------- .../NavigationBar/NavigationItem.swift | 2 +- .../Implement/SignUpInteractor.swift | 7 +- .../Implement/SignUpViewController.swift | 41 ++++++++-- 5 files changed, 97 insertions(+), 39 deletions(-) diff --git a/Core/Utils/Base/BaseView.swift b/Core/Utils/Base/BaseView.swift index cfe4297e..2c274b37 100644 --- a/Core/Utils/Base/BaseView.swift +++ b/Core/Utils/Base/BaseView.swift @@ -8,8 +8,10 @@ import UIKit import RxSwift +import FlexLayout +import PinLayout -class BaseView: UIView { +open class BaseView: UIView { // MARK: - Properties var disposeBag = DisposeBag() @@ -31,7 +33,7 @@ class BaseView: UIView { func bind() {} @available(*, unavailable) - required init?(coder: NSCoder) { + required public init?(coder: NSCoder) { fatalError("init(coder:) is called.") } } diff --git a/Core/Utils/Base/BaseViewController.swift b/Core/Utils/Base/BaseViewController.swift index 96249f7a..1b82ab12 100644 --- a/Core/Utils/Base/BaseViewController.swift +++ b/Core/Utils/Base/BaseViewController.swift @@ -10,16 +10,19 @@ import UIKit import DesignSystem import RxSwift +import PinLayout +import FlexLayout -public class BaseViewController: UIViewController { +open class BaseViewController: UIViewController { + // MARK: - UI - let flexRootView = UIView() + public let flexRootView = UIView() // TODO: - MOITNavigationBar optional로 만들고 configureNavigationBar에서 설정 - private lazy var navigationBar = MOITNavigationBar( - leftItems: <#T##[NavigationItemType]#>, - title: <#T##String?#>, - rightItems: <#T##[NavigationItemType]#> + public lazy var navigationBar = MOITNavigationBar( + leftItems: [.back], + title: "야야야", + rightItems: [.alarm, .setting] ) // MARK: - Properties @@ -27,8 +30,18 @@ public class BaseViewController: UIViewController { private var indicator: UIActivityIndicatorView? + // MARK: - Initializer + public init() { + super.init(nibName: nil, bundle: nil) + } + + @available(*, unavailable) + required public init(coder: NSCoder) { + fatalError("init(coder:) is called.") + } + // MARK: - LifeCycle - public override func viewDidLoad() { + open override func viewDidLoad() { super.viewDidLoad() self.view.backgroundColor = .white @@ -39,46 +52,55 @@ public class BaseViewController: UIViewController { bind() } - public override func viewDidLayoutSubviews() { + open override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() self.flexRootView.pin.all(self.view.pin.safeArea) self.flexRootView.flex.layout() + self.flexRootView.backgroundColor = .red } // MARK: - Methods /// addSubView 하는 함수 - func configureHierarchy() {} + public func configureHierarchy() { + self.view.addSubview(flexRootView) + } /// layout 잡는 함수 - func configureConstraints() {} + open func configureConstraints() {} /// 값 설정하는 함수 - func configureAttributes() {} + open func configureAttributes() {} /// bind하는 함수. (ribs라 필요한지 모르겠음) - func bind() {} + open func bind() {} /// navigationBar 사용하면 flexRootView에 추가해주는 함수 - func configureNavigationBar( + /// `viewDidLayoutSubviews`에 추가해야함 + public func configureNavigationBar( leftItems: [NavigationItemType], title: String?, rightItems: [NavigationItemType] ) { - flexRootView.flex - .addItem(self.navigationBar) + // TODO: - configure함수 만들어주기 - navigationBar.configure( - leftItems: leftItems, - title: title, - rightItems: rightItems - ) - } - - - - @available(*, unavailable) - required init(coder: NSCoder) { - fatalError("init(coder:) is called.") +// navigationBar.configure( +// leftItems: leftItems, +// title: title, +// rightItems: rightItems +// ) + view.addSubview(navigationBar) + + navigationBar.pin.top(self.view.pin.safeArea.top).horizontally() + configureRootView() + + guard let back = navigationBar.leftItems.first(where: { $0.type == .back }) else { return } + back.rx.tap + .subscribe(onNext: { [weak self] in + self?.navigationController?.popViewController(animated: true) + }) + .disposed(by: disposeBag) } - init() { - super.init(nibName: nil, bundle: nil) + private func configureRootView() { + self.flexRootView.pin.below(of: navigationBar).marginTop(10).left().right().bottom() + self.flexRootView.flex.layout() +// self.flexRootView.flex.markDirty() } } diff --git a/DesignSystem/Sources/NavigationBar/NavigationItem.swift b/DesignSystem/Sources/NavigationBar/NavigationItem.swift index d3d0470a..c9440dfd 100644 --- a/DesignSystem/Sources/NavigationBar/NavigationItem.swift +++ b/DesignSystem/Sources/NavigationBar/NavigationItem.swift @@ -14,7 +14,7 @@ import RxSwift public final class NavigationItem: UIButton { - let type: NavigationItemType + public let type: NavigationItemType public init(type: NavigationItemType) { self.type = type diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift index e8884442..0ba0afa2 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift @@ -21,7 +21,7 @@ protocol SignUpPresentable: Presentable { } final class SignUpInteractor: PresentableInteractor, SignUpInteractable, SignUpPresentableListener { - + weak var router: SignUpRouting? weak var listener: SignUpListener? @@ -41,4 +41,9 @@ final class SignUpInteractor: PresentableInteractor, SignUpIn super.willResignActive() // TODO: Pause any business logic. } + + func didSwipeBack() { + + } + } diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift index 6f331fe3..aecea103 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -9,31 +9,43 @@ import UIKit import SignUpUserInterface import DesignSystem +import Utils import RIBs import RxSwift +import FlexLayout +import PinLayout protocol SignUpPresentableListener: AnyObject { - // TODO: Declare properties and methods that the view controller can invoke to perform - // business logic, such as signIn(). This protocol is implemented by the corresponding - // interactor class. + func didSwipeBack() } -public final class SignUpViewController: UIViewController, SignUpPresentable, SignUpViewControllable { +public final class SignUpViewController: BaseViewController, SignUpPresentable, SignUpViewControllable { // MARK: - UI - private let navigationBar: MOITNavigationBar + // private let navigationBar: MOITNavigationBar + private let tempView = UIView() // MARK: - Properties weak var listener: SignUpPresentableListener? // MARK: - Initializers + public override init() { + super.init() + + } // MARK: - Lifecycle public override func viewDidLoad() { super.viewDidLoad() self.navigationController?.navigationBar.isHidden = true + + } + + public override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + } public override func viewDidDisappear(_ animated: Bool) { @@ -42,8 +54,25 @@ public final class SignUpViewController: UIViewController, SignUpPresentable, Si self.listener?.didSwipeBack() } } + + public override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + // TODO: - 꼭 여기에 들어가야 할까? + configureNavigationBar(leftItems: [], title: "hi", rightItems: []) + } + deinit { debugPrint("\(self) deinit") } // MARK: - Functions - + public override func configureConstraints() { + flexRootView.flex + .alignItems(.center) + .justifyContent(.center) + .define { flex in + flex.addItem(tempView) + .width(100%) + .height(50) + .backgroundColor(.orange) + } + } } From f969bed40060d312f41676386a168d3b641f887c Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 09:05:33 +0900 Subject: [PATCH 040/106] =?UTF-8?q?feat:=20StudyPreview=20configure=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../StudyPreviewDemoViewController.swift | 15 +++++- .../StudyPreview/MOITStudyPreview.swift | 47 ++++++++++++++----- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift index 35625b8b..6431a5b1 100644 --- a/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift +++ b/DesignSystem/DemoApp/Sources/StudyPreview/StudyPreviewDemoViewController.swift @@ -20,11 +20,13 @@ final class StudyPreviewDemoViewController: UIViewController { // MARK: - UI private let studyPreview = MOITStudyPreview( remainingDate: 19, - profileURL: URL(string: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4")!, + profileURLString: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4", studyName: "공부스터디", studyProgressDescription: "격주 금요일 17:00 - 20:00" ) + private let studyPreview2 = MOITStudyPreview() + private let flexRootView = UIView() // MARK: - Properties @@ -33,6 +35,12 @@ final class StudyPreviewDemoViewController: UIViewController { // MARK: - Initializers public init() { super.init(nibName: nil, bundle: nil) + studyPreview2.configure( + remainingDate: 20, + profileURL: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4", + studyName: "스터디스터디", + studyProgressDescription: "3주마다 토요일 15:00 - 23:00" + ) } @available(*, unavailable) @@ -67,6 +75,11 @@ final class StudyPreviewDemoViewController: UIViewController { .marginTop(40) .width(80%) .height(100) + flex.addItem(self.studyPreview2) + .marginTop(40) + .width(80%) + .height(100) + } } diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index 0eb4a14a..c5ec8e64 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -50,33 +50,51 @@ public final class MOITStudyPreview: UIView { fileprivate let didTapSubject = PublishSubject() // MARK: - Initializers + public init() { + super.init(frame: .zero) + } + public init( remainingDate: Int, - profileURL: URL, + profileURLString: String, studyName: String, studyProgressDescription: String? ) { super.init(frame: .zero) - - configureAttributes( + configure( remainingDate: remainingDate, - profileURL: profileURL, + profileURL: profileURLString, studyName: studyName, studyProgressDescription: studyProgressDescription ) - configureLayout() - setupGesture() } @available (*, unavailable) required init?(coder: NSCoder) { - fatalError() + fatalError("required init called") } // MARK: - Lifecycle // MARK: - Methods + public func configure( + remainingDate: Int, + profileURL: String, + studyName: String, + studyProgressDescription: String? + ) { + + configureAttributes( + remainingDate: remainingDate, + profileURLString: profileURL, + studyName: studyName, + studyProgressDescription: studyProgressDescription + ) + configureLayout() + setupGesture() + } + private func setupGesture() { let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(onPan(_:))) let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTap(_:))) @@ -99,7 +117,7 @@ public final class MOITStudyPreview: UIView { self.flexRootView.flex .direction(.row) - .define { (flex) in + .define { flex in flex.addItem() // 보이는 뷰 .paddingLeft(16) .marginRight(10) @@ -138,7 +156,7 @@ public final class MOITStudyPreview: UIView { private func configureAttributes( remainingDate: Int, - profileURL: URL, + profileURLString: String, studyName: String, studyProgressDescription: String? ) { @@ -148,10 +166,13 @@ public final class MOITStudyPreview: UIView { remainingDateLabel = MOITChip(type: .dueDate(date: remainingDate)) - profileImageView.kf.setImage( - with: profileURL, - options: [.processor(RoundCornerImageProcessor(cornerRadius: 20))] - ) + if let url = URL(string: profileURLString) { + profileImageView.kf.setImage( + with: url, + options: [.processor(RoundCornerImageProcessor(cornerRadius: 20))] + ) + } + studyNameLabel.text = studyName studyDescriptionLabel.text = studyProgressDescription From e6b5c665256dd9645aa4d6457d957caf607a18eb Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 09:12:16 +0900 Subject: [PATCH 041/106] =?UTF-8?q?feat:=20ProfileView=20image=20=EC=97=86?= =?UTF-8?q?=EC=9D=B4=20=EC=83=9D=EC=84=B1,=20configureImage=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Profile/ProfileDemoViewController.swift | 4 ++++ .../Sources/Profile/MOITProfileView.swift | 24 +++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift b/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift index 26aa5e2b..2a43831e 100644 --- a/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift +++ b/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift @@ -32,6 +32,8 @@ final class ProfileDemoViewController: UIViewController { profileType: .small ) + private lazy var lazyProfileView = MOITProfileView(profileType: .large) + private let flexRootView = UIView() // MARK: - Properties @@ -40,6 +42,7 @@ final class ProfileDemoViewController: UIViewController { // MARK: - Initializers public init() { super.init(nibName: nil, bundle: nil) + lazyProfileView.configureImage(with: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4") } @available(*, unavailable) @@ -75,6 +78,7 @@ final class ProfileDemoViewController: UIViewController { flex.addItem(largeProfileView) flex.addItem(mediumProfileView) flex.addItem(smallProfileView) + flex.addItem(lazyProfileView) } } diff --git a/DesignSystem/Sources/Profile/MOITProfileView.swift b/DesignSystem/Sources/Profile/MOITProfileView.swift index 92ec8503..4f497688 100644 --- a/DesignSystem/Sources/Profile/MOITProfileView.swift +++ b/DesignSystem/Sources/Profile/MOITProfileView.swift @@ -28,11 +28,25 @@ public final class MOITProfileView: UIView { }() // MARK: - Properties - private let urlString: String + private let urlString: String? private let profileType: ProfileType fileprivate let containAddButton: Bool // MARK: - Initializers + + public init ( + profileType: ProfileType, + addButton: Bool = false + ) { + self.profileType = profileType + self.containAddButton = addButton + urlString = nil + + super.init(frame: .zero) + + configureLayout() + } + public init ( urlString: String, profileType: ProfileType, @@ -44,7 +58,7 @@ public final class MOITProfileView: UIView { super.init(frame: .zero) - configureAttributes() + configureImage(with: urlString) configureLayout() } @@ -67,9 +81,11 @@ public final class MOITProfileView: UIView { // MARK: - Functions - private func configureAttributes() { + public func configureImage(with urlString: String) { + guard let url = URL(string: urlString) + else { return } profileImageView.kf.setImage( - with: URL(string: urlString), + with: url, placeholder: nil ) } From e2fd3a1db8adc443f5516f4a29667195d11bc943 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 10:28:15 +0900 Subject: [PATCH 042/106] =?UTF-8?q?refactor:=20=EB=A6=B0=ED=8A=B8=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NavigationBar/MOITNavigationBar.swift | 18 ++++++++---------- .../NavigationBar/NavigationColorType.swift | 1 - .../NavigationBar/NavigationItemType.swift | 1 - DesignSystem/Sources/Profile/ProfileType.swift | 1 - .../StudyPreview/MOITStudyPreview.swift | 8 +++++--- .../StudyPreview/TouchThroughView.swift | 4 +++- .../Sources/TapPager/MOITSegmentPager.swift | 2 +- .../Sources/TapPager/MOITTabPager.swift | 2 +- .../Sources/TapPager/TapPagerType.swift | 1 - 9 files changed, 18 insertions(+), 20 deletions(-) diff --git a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift index 568b3d26..419f5a96 100644 --- a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift +++ b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift @@ -44,8 +44,8 @@ public final class MOITNavigationBar: UIView { rightItems: [NavigationItemType], colorType: NavigationColorType = .normal ) { - self.leftItems = leftItems.map { NavigationItem(type: $0)} - self.rightItems = rightItems.map { NavigationItem(type: $0)} + self.leftItems = leftItems.map { NavigationItem(type: $0) } + self.rightItems = rightItems.map { NavigationItem(type: $0) } self.colorType = colorType super.init(frame: .zero) @@ -53,7 +53,6 @@ public final class MOITNavigationBar: UIView { self.configureTitle(title) self.configureLayout() self.configureColor() - } @available(*, unavailable) @@ -99,7 +98,7 @@ extension MOITNavigationBar { .width(80) .justifyContent(.start) .define { flex in - self.leftItems.forEach { flex.addItem($0).size(24)} + self.leftItems.forEach { flex.addItem($0).size(24) } } .marginLeft(16) @@ -112,7 +111,7 @@ extension MOITNavigationBar { .width(80) .justifyContent(.end) .define { flex in - self.rightItems.forEach { flex.addItem($0).size(24).marginLeft(20)} + self.rightItems.forEach { flex.addItem($0).size(24).marginLeft(20) } } .marginRight(16) } @@ -121,15 +120,14 @@ extension MOITNavigationBar { private func configureColor() { - leftItems.forEach { $0.tintColor = self.colorType.tintColor} - rightItems.forEach { $0.tintColor = self.colorType.tintColor} + leftItems.forEach { $0.tintColor = self.colorType.tintColor } + rightItems.forEach { $0.tintColor = self.colorType.tintColor } titleLabel.textColor = colorType.tintColor - leftItems.forEach { $0.backgroundColor = self.colorType.backgroundColor} - rightItems.forEach { $0.backgroundColor = self.colorType.backgroundColor} + leftItems.forEach { $0.backgroundColor = self.colorType.backgroundColor } + rightItems.forEach { $0.backgroundColor = self.colorType.backgroundColor } titleLabel.backgroundColor = colorType.backgroundColor self.backgroundColor = colorType.backgroundColor } - } diff --git a/DesignSystem/Sources/NavigationBar/NavigationColorType.swift b/DesignSystem/Sources/NavigationBar/NavigationColorType.swift index f99312e9..a35b2e54 100644 --- a/DesignSystem/Sources/NavigationBar/NavigationColorType.swift +++ b/DesignSystem/Sources/NavigationBar/NavigationColorType.swift @@ -31,5 +31,4 @@ public enum NavigationColorType { return ResourceKitAsset.Color.gray500.color } } - } diff --git a/DesignSystem/Sources/NavigationBar/NavigationItemType.swift b/DesignSystem/Sources/NavigationBar/NavigationItemType.swift index b7a50e9d..0c14d94a 100644 --- a/DesignSystem/Sources/NavigationBar/NavigationItemType.swift +++ b/DesignSystem/Sources/NavigationBar/NavigationItemType.swift @@ -31,5 +31,4 @@ public enum NavigationItemType { return ResourceKitAsset.Icon.bell.image } } - } diff --git a/DesignSystem/Sources/Profile/ProfileType.swift b/DesignSystem/Sources/Profile/ProfileType.swift index a54ca02b..47b89f73 100644 --- a/DesignSystem/Sources/Profile/ProfileType.swift +++ b/DesignSystem/Sources/Profile/ProfileType.swift @@ -33,6 +33,5 @@ public enum ProfileType { case .small: return 40 } - } } diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index c5ec8e64..fb107f01 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -198,7 +198,10 @@ public final class MOITStudyPreview: UIView { case .ended: if velocity.x < 0 { UIView.animate(withDuration: 0.2) { - self.flexRootView.transform = CGAffineTransform(translationX: -(self.deleteButton.frame.width + 10), y: 0) + self.flexRootView.transform = CGAffineTransform( + translationX: -(self.deleteButton.frame.width + 10), + y: 0 + ) } } else { UIView.animate(withDuration: 0.2) { @@ -221,7 +224,7 @@ public final class MOITStudyPreview: UIView { message: "스터디를 삭제하면 해당 데이터도 모두 삭제됩니다.", preferredStyle: .alert ) - let confirmAction = UIAlertAction(title: "확인", style: .default) { action in + let confirmAction = UIAlertAction(title: "확인", style: .default) { _ in self.deleteConfirmSubject.onNext(()) } let cancelAction = UIAlertAction(title: "취소", style: .destructive) @@ -229,7 +232,6 @@ public final class MOITStudyPreview: UIView { alert.addAction(cancelAction) self.window?.rootViewController?.present(alert, animated: true) } - } // MARK: - UIGestureRecognizerDelegate diff --git a/DesignSystem/Sources/StudyPreview/TouchThroughView.swift b/DesignSystem/Sources/StudyPreview/TouchThroughView.swift index 8a1f004f..21612d7c 100644 --- a/DesignSystem/Sources/StudyPreview/TouchThroughView.swift +++ b/DesignSystem/Sources/StudyPreview/TouchThroughView.swift @@ -9,7 +9,9 @@ import UIKit final class TouchThroughView: UIView { - var button: UIButton? = nil + + var button: UIButton? + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { if let button = self.button { return self.bounds.contains(point) || button.frame.contains(point) diff --git a/DesignSystem/Sources/TapPager/MOITSegmentPager.swift b/DesignSystem/Sources/TapPager/MOITSegmentPager.swift index d1e835a5..73aebed0 100644 --- a/DesignSystem/Sources/TapPager/MOITSegmentPager.swift +++ b/DesignSystem/Sources/TapPager/MOITSegmentPager.swift @@ -126,7 +126,7 @@ public final class MOITSegmentPager: UIView { flex.marginLeft(xPosition) .width(width) .height(height) - .cornerRadius(height/2) + .cornerRadius(height / 2) } } } diff --git a/DesignSystem/Sources/TapPager/MOITTabPager.swift b/DesignSystem/Sources/TapPager/MOITTabPager.swift index 78806f73..ad31c996 100644 --- a/DesignSystem/Sources/TapPager/MOITTabPager.swift +++ b/DesignSystem/Sources/TapPager/MOITTabPager.swift @@ -72,7 +72,7 @@ public final class MOITTabPager: UIView { flex.addItem() .direction(.row) .define { flex in - self.pages.forEach { flex.addItem($0).marginHorizontal(12)} + self.pages.forEach { flex.addItem($0).marginHorizontal(12) } } .marginBottom(5) diff --git a/DesignSystem/Sources/TapPager/TapPagerType.swift b/DesignSystem/Sources/TapPager/TapPagerType.swift index 9f26b703..543e0dc9 100644 --- a/DesignSystem/Sources/TapPager/TapPagerType.swift +++ b/DesignSystem/Sources/TapPager/TapPagerType.swift @@ -40,5 +40,4 @@ public enum PagerType { return ResourceKitFontFamily.p2 } } - } From 4c90a0a4c2de414303f3db6ad88d627f5c88c9f5 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 22:02:34 +0900 Subject: [PATCH 043/106] =?UTF-8?q?fix:=20navigationBar=EC=99=80=20flexRoo?= =?UTF-8?q?tView=20=EA=B2=B9=EC=B9=98=EC=A7=80=20=EC=95=8A=EA=B2=8C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NavigationDemoViewController.swift | 2 +- .../NavigationBar/MOITNavigationBar.swift | 47 +++++++++++++------ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/DesignSystem/DemoApp/Sources/NavigationBar/NavigationDemoViewController.swift b/DesignSystem/DemoApp/Sources/NavigationBar/NavigationDemoViewController.swift index f78a709a..295b7df0 100644 --- a/DesignSystem/DemoApp/Sources/NavigationBar/NavigationDemoViewController.swift +++ b/DesignSystem/DemoApp/Sources/NavigationBar/NavigationDemoViewController.swift @@ -44,7 +44,7 @@ final class MOITNavigationDemoViewController: UIViewController { self.configureLayouts() self.navigationController?.navigationItem.title = "MOITNavigationBar" self.view.backgroundColor = .white - self.moitNavigationBar.leftItems[0].rx.tap.subscribe(onNext: { [weak self] in + self.moitNavigationBar.leftItems?[0].rx.tap.subscribe(onNext: { [weak self] in self?.navigationController?.popViewController(animated: true) }).disposed(by: self.disposeBag) } diff --git a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift index 419f5a96..83f2876d 100644 --- a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift +++ b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift @@ -30,12 +30,17 @@ public final class MOITNavigationBar: UIView { // MARK: - Properties - public let leftItems: [NavigationItem] - public let rightItems: [NavigationItem] + public private(set) var leftItems: [NavigationItem]? + public private(set) var rightItems: [NavigationItem]? - private let colorType: NavigationColorType + private var colorType: NavigationColorType? // MARK: - Initializers + public init() { + + super.init(frame: .zero) + } + /// leftItems와 rightItems에 좌우측에 들어갈 item을 정의합니다. /// MOITNavigationBar.leftItems[n].rx.tap으로 이벤트를 받아올 수 있습니다. public init( @@ -70,6 +75,20 @@ public final class MOITNavigationBar: UIView { } // MARK: - Methods + public func configure( + leftItems: [NavigationItemType], + title: String?, + rightItems: [NavigationItemType], + colorType: NavigationColorType = .normal + ) { + self.leftItems = leftItems.map { NavigationItem(type: $0) } + self.rightItems = rightItems.map { NavigationItem(type: $0) } + self.colorType = colorType + + self.configureTitle(title) + self.configureLayout() + self.configureColor() + } } // MARK: - Private Functions @@ -91,14 +110,14 @@ extension MOITNavigationBar { .height(56) .direction(.row) .alignItems(.center) - .backgroundColor(colorType.backgroundColor) + .backgroundColor(colorType?.backgroundColor ?? .white) .define { flex in flex.addItem() .direction(.row) .width(80) .justifyContent(.start) .define { flex in - self.leftItems.forEach { flex.addItem($0).size(24) } + self.leftItems?.forEach { flex.addItem($0).size(24) } } .marginLeft(16) @@ -111,23 +130,21 @@ extension MOITNavigationBar { .width(80) .justifyContent(.end) .define { flex in - self.rightItems.forEach { flex.addItem($0).size(24).marginLeft(20) } + self.rightItems?.forEach { flex.addItem($0).size(24).marginLeft(20) } } .marginRight(16) } } private func configureColor() { + leftItems?.forEach { $0.tintColor = self.colorType?.tintColor } + rightItems?.forEach { $0.tintColor = self.colorType?.tintColor } + titleLabel.textColor = colorType?.tintColor + leftItems?.forEach { $0.backgroundColor = self.colorType?.backgroundColor } + rightItems?.forEach { $0.backgroundColor = self.colorType?.backgroundColor } + titleLabel.backgroundColor = colorType?.backgroundColor - leftItems.forEach { $0.tintColor = self.colorType.tintColor } - rightItems.forEach { $0.tintColor = self.colorType.tintColor } - titleLabel.textColor = colorType.tintColor - - leftItems.forEach { $0.backgroundColor = self.colorType.backgroundColor } - rightItems.forEach { $0.backgroundColor = self.colorType.backgroundColor } - titleLabel.backgroundColor = colorType.backgroundColor - - self.backgroundColor = colorType.backgroundColor + self.backgroundColor = colorType?.backgroundColor } } From 44fe3821f01fb108abcccf2d78607b21f5756cd9 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 22:03:20 +0900 Subject: [PATCH 044/106] =?UTF-8?q?feat:=20scrollView=20=EC=9E=90=EB=8F=99?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Utils/Base/BaseViewController.swift | 46 ++++++++++++------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/Core/Utils/Base/BaseViewController.swift b/Core/Utils/Base/BaseViewController.swift index 1b82ab12..167f2327 100644 --- a/Core/Utils/Base/BaseViewController.swift +++ b/Core/Utils/Base/BaseViewController.swift @@ -16,17 +16,12 @@ import FlexLayout open class BaseViewController: UIViewController { // MARK: - UI + public let scrollView = UIScrollView() public let flexRootView = UIView() + public lazy var navigationBar = MOITNavigationBar() - // TODO: - MOITNavigationBar optional로 만들고 configureNavigationBar에서 설정 - public lazy var navigationBar = MOITNavigationBar( - leftItems: [.back], - title: "야야야", - rightItems: [.alarm, .setting] - ) - - // MARK: - Properties - var disposeBag = DisposeBag() + // MARK: -Properties + public var disposebag = DisposeBag() private var indicator: UIActivityIndicatorView? @@ -54,15 +49,16 @@ open class BaseViewController: UIViewController { open override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - self.flexRootView.pin.all(self.view.pin.safeArea) - self.flexRootView.flex.layout() - self.flexRootView.backgroundColor = .red + scrollView.pin.all(view.pin.safeArea) + flexRootView.pin.all() + flexRootView.flex.layout(mode: .adjustHeight) + scrollView.contentSize = flexRootView.frame.size } - // MARK: - Methods /// addSubView 하는 함수 public func configureHierarchy() { - self.view.addSubview(flexRootView) + self.scrollView.addSubview(flexRootView) + self.view.addSubview(scrollView) } /// layout 잡는 함수 open func configureConstraints() {} @@ -78,29 +74,31 @@ open class BaseViewController: UIViewController { title: String?, rightItems: [NavigationItemType] ) { + navigationBar.configure( + leftItems: leftItems, + title: title, + rightItems: rightItems + ) - // TODO: - configure함수 만들어주기 -// navigationBar.configure( -// leftItems: leftItems, -// title: title, -// rightItems: rightItems -// ) view.addSubview(navigationBar) navigationBar.pin.top(self.view.pin.safeArea.top).horizontally() configureRootView() - guard let back = navigationBar.leftItems.first(where: { $0.type == .back }) else { return } + guard let back = navigationBar.leftItems?.first(where: { $0.type == .back }) else { return } back.rx.tap .subscribe(onNext: { [weak self] in self?.navigationController?.popViewController(animated: true) }) - .disposed(by: disposeBag) + .disposed(by: disposebag) } private func configureRootView() { - self.flexRootView.pin.below(of: navigationBar).marginTop(10).left().right().bottom() + self.scrollView.pin.top(self.view.pin.safeArea.top + 56).left().right().bottom() // How to solve it other than absolute value..? + // scrollview에 딱 맞게 flexRootView를 pinlayout으로 설정 + self.flexRootView.pin.all() +// flexRootView.backgroundColor = .red self.flexRootView.flex.layout() -// self.flexRootView.flex.markDirty() + self.flexRootView.flex.markDirty() } } From c9053cd02784f8f4b9b33cdf314c63082ae6d6bc Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 22:04:34 +0900 Subject: [PATCH 045/106] =?UTF-8?q?feat:=20=ED=83=AD=20=EC=8B=9C=20?= =?UTF-8?q?=ED=82=A4=EB=B3=B4=EB=93=9C=20=EC=82=AC=EB=9D=BC=EC=A7=80?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Utils/Base/BaseViewController.swift | 20 +++++++++++++++++--- Core/Utils/UIKit/UIViewController+.swift | 23 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 Core/Utils/UIKit/UIViewController+.swift diff --git a/Core/Utils/Base/BaseViewController.swift b/Core/Utils/Base/BaseViewController.swift index 167f2327..5dd85b4a 100644 --- a/Core/Utils/Base/BaseViewController.swift +++ b/Core/Utils/Base/BaseViewController.swift @@ -45,6 +45,18 @@ open class BaseViewController: UIViewController { configureHierarchy() configureConstraints() bind() + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil) + } + + @objc func keyboardWillShow(notification: NSNotification) { + if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue { + scrollView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height, right: 0) + } + } + + @objc func keyboardWillHide(notification: NSNotification) { + scrollView.contentInset = UIEdgeInsets.zero } open override func viewDidLayoutSubviews() { @@ -62,9 +74,11 @@ open class BaseViewController: UIViewController { } /// layout 잡는 함수 open func configureConstraints() {} - /// 값 설정하는 함수 - open func configureAttributes() {} - /// bind하는 함수. (ribs라 필요한지 모르겠음) + /// function to set the value + open func configureAttributes() { + hideKeyboardWhenTapped() + } + /// Function to bind. (I don't know if it's necessary because it's ribs) open func bind() {} /// navigationBar 사용하면 flexRootView에 추가해주는 함수 diff --git a/Core/Utils/UIKit/UIViewController+.swift b/Core/Utils/UIKit/UIViewController+.swift new file mode 100644 index 00000000..1d8b9408 --- /dev/null +++ b/Core/Utils/UIKit/UIViewController+.swift @@ -0,0 +1,23 @@ +// +// UIViewController+.swift +// Utils +// +// Created by 김찬수 on 2023/06/15. +// + +import UIKit + +extension UIViewController { + + func hideKeyboardWhenTapped() { + let tap = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard)) + tap.cancelsTouchesInView = false + // 기본값이 true이면 제스쳐 발동시 터치 이벤트가 뷰로 전달x + // 즉 제스쳐가 동작하면 뷰의 터치이벤트는 발생하지 않는것 false면 둘 다 작동한다는 뜻 + view.addGestureRecognizer(tap) + } + + @objc func dismissKeyboard() { + self.view.endEditing(true) + } +} From 2bdbc609ac3fe5f1b8b38c30c534f71fcddba79f Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 22:05:10 +0900 Subject: [PATCH 046/106] =?UTF-8?q?feat:=20SignUpViewController=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/SignUpViewController.swift | 74 +++++++++++++++---- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift index aecea103..749b159f 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -10,6 +10,7 @@ import UIKit import SignUpUserInterface import DesignSystem import Utils +import ResourceKit import RIBs import RxSwift @@ -24,8 +25,36 @@ protocol SignUpPresentableListener: AnyObject { public final class SignUpViewController: BaseViewController, SignUpPresentable, SignUpViewControllable { // MARK: - UI - // private let navigationBar: MOITNavigationBar - private let tempView = UIView() + private let titleLabel: UILabel = { + let label = UILabel() + label.numberOfLines = 2 + label.font = ResourceKitFontFamily.h4 + label.textColor = ResourceKitAsset.Color.black.color + var paragraphStyle = NSMutableParagraphStyle() + paragraphStyle.lineHeightMultiple = 1.34 + label.attributedText = NSMutableAttributedString( + string: "모잇에서 사용할\n프로필을 만들어 주세요.", + attributes: [ + NSAttributedString.Key.paragraphStyle: paragraphStyle + ] + ) + return label + }() + + private let profileView: MOITProfileView = { + // TODO: - url 아니라 int형으로 이미지 에셋 받으면 설정 + // 랜덤으로 띄워주기로 했었나.. + let profileView = MOITProfileView( + urlString: "https://avatars.githubusercontent.com/u/37873745?s=96&v=4", + profileType: .large, + addButton: true + ) + return profileView + }() + + private let nameTextField = MOITTextField(title: "이름 (필수)", placeHolder: "이름을 입력해주세요.") + + private let inviteCodeTextField = MOITTextField(title: "스터디 초대 코드 (선택)", placeHolder: "공유받은 스터디 초대코드를 입력하세요.") // MARK: - Properties weak var listener: SignUpPresentableListener? @@ -33,19 +62,12 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, // MARK: - Initializers public override init() { super.init() - } // MARK: - Lifecycle public override func viewDidLoad() { super.viewDidLoad() self.navigationController?.navigationBar.isHidden = true - - } - - public override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - } public override func viewDidDisappear(_ animated: Bool) { @@ -58,7 +80,7 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, public override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // TODO: - 꼭 여기에 들어가야 할까? - configureNavigationBar(leftItems: [], title: "hi", rightItems: []) + configureNavigationBar(leftItems: [.back], title: "", rightItems: []) } deinit { debugPrint("\(self) deinit") } @@ -66,13 +88,35 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, // MARK: - Functions public override func configureConstraints() { flexRootView.flex - .alignItems(.center) - .justifyContent(.center) + .alignItems(.start) + .paddingHorizontal(20) .define { flex in - flex.addItem(tempView) + flex.addItem(titleLabel) + .marginTop(20) +// .height(64) + flex.addItem(profileView) + .marginTop(20) + .alignSelf(.center) + flex.addItem(nameTextField) + .marginTop(20) + .width(100%) + flex.addItem(inviteCodeTextField) + .marginTop(20) .width(100%) - .height(50) - .backgroundColor(.orange) } } + + public override func bind() { + nameTextField.rx.text + .subscribe(onNext: { name in + print(name) + }) + .disposed(by: disposebag) + + inviteCodeTextField.rx.text + .subscribe(onNext: { inviteCode in + print(inviteCode) + }) + .disposed(by: disposebag) + } } From 4a4e3e1090f4e45946b84e25acf87259b79f2b40 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 15 Jun 2023 23:20:46 +0900 Subject: [PATCH 047/106] =?UTF-8?q?feat:=20=EB=8B=A4=EC=9D=8C=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/SignUpViewController.swift | 35 ++++++++++++++++--- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift index 749b159f..666a1ca9 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -52,9 +52,20 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, return profileView }() - private let nameTextField = MOITTextField(title: "이름 (필수)", placeHolder: "이름을 입력해주세요.") - - private let inviteCodeTextField = MOITTextField(title: "스터디 초대 코드 (선택)", placeHolder: "공유받은 스터디 초대코드를 입력하세요.") + private let nameTextField = MOITTextField( + title: "이름 (필수)", + placeHolder: "이름을 입력해주세요." + ) + private let inviteCodeTextField = MOITTextField( + title: "스터디 초대 코드 (선택)", + placeHolder: "공유받은 스터디 초대코드를 입력하세요." + ) + private let nextButton = MOITButton( + type: .large, + title: "다음", + titleColor: ResourceKitAsset.Color.white.color, + backgroundColor: ResourceKitAsset.Color.blue800.color + ) // MARK: - Properties weak var listener: SignUpPresentableListener? @@ -93,7 +104,6 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, .define { flex in flex.addItem(titleLabel) .marginTop(20) -// .height(64) flex.addItem(profileView) .marginTop(20) .alignSelf(.center) @@ -103,10 +113,21 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, flex.addItem(inviteCodeTextField) .marginTop(20) .width(100%) + flex.addItem() + .grow(1) + flex.addItem(nextButton) + .width(100%) + .marginBottom(36) } } public override func bind() { + profileView.rx.tap + .subscribe(onNext: { + print("profileTapped") + }) + .disposed(by: disposebag) + nameTextField.rx.text .subscribe(onNext: { name in print(name) @@ -118,5 +139,11 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, print(inviteCode) }) .disposed(by: disposebag) + + nextButton.rx.tap + .subscribe(onNext: { + print("nextButtonTapped") + }) + .disposed(by: disposebag) } } From 3bb2c0f1aee39e13c3c21e8a57ca4f34566a6d29 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sat, 17 Jun 2023 13:26:41 +0900 Subject: [PATCH 048/106] =?UTF-8?q?refactor:=20`MOITProfileView`=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=A1=9C=EB=93=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Profile/ProfileDemoViewController.swift | 8 ++--- .../Sources/Profile/MOITProfileView.swift | 19 ++++------- .../Sources/Profile/ProfileType.swift | 34 ++++++++++++++++++- .../Implement/SignUpViewController.swift | 2 +- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift b/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift index 2a43831e..94bd9ac7 100644 --- a/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift +++ b/DesignSystem/DemoApp/Sources/Profile/ProfileDemoViewController.swift @@ -17,18 +17,18 @@ final class ProfileDemoViewController: UIViewController { // MARK: - UI private let largeProfileView = MOITProfileView( - urlString: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4", + profileImageType: .one, profileType: .large, addButton: true ) private let mediumProfileView = MOITProfileView( - urlString: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4", + profileImageType: .one, profileType: .medium ) private let smallProfileView = MOITProfileView( - urlString: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4", + profileImageType: .one, profileType: .small ) @@ -42,7 +42,7 @@ final class ProfileDemoViewController: UIViewController { // MARK: - Initializers public init() { super.init(nibName: nil, bundle: nil) - lazyProfileView.configureImage(with: "https://avatars.githubusercontent.com/u/15011638?s=64&v=4") + lazyProfileView.configureImage(with: .one) } @available(*, unavailable) diff --git a/DesignSystem/Sources/Profile/MOITProfileView.swift b/DesignSystem/Sources/Profile/MOITProfileView.swift index 4f497688..59db492e 100644 --- a/DesignSystem/Sources/Profile/MOITProfileView.swift +++ b/DesignSystem/Sources/Profile/MOITProfileView.swift @@ -14,7 +14,6 @@ import FlexLayout import PinLayout import RxSwift import RxGesture -import Kingfisher public final class MOITProfileView: UIView { @@ -28,7 +27,7 @@ public final class MOITProfileView: UIView { }() // MARK: - Properties - private let urlString: String? + private var profileImageType: ProfileImageType? private let profileType: ProfileType fileprivate let containAddButton: Bool @@ -40,7 +39,6 @@ public final class MOITProfileView: UIView { ) { self.profileType = profileType self.containAddButton = addButton - urlString = nil super.init(frame: .zero) @@ -48,17 +46,17 @@ public final class MOITProfileView: UIView { } public init ( - urlString: String, + profileImageType: ProfileImageType, profileType: ProfileType, addButton: Bool = false ) { - self.urlString = urlString + self.profileImageType = profileImageType self.profileType = profileType self.containAddButton = addButton super.init(frame: .zero) - configureImage(with: urlString) + configureImage(with: profileImageType) configureLayout() } @@ -81,13 +79,8 @@ public final class MOITProfileView: UIView { // MARK: - Functions - public func configureImage(with urlString: String) { - guard let url = URL(string: urlString) - else { return } - profileImageView.kf.setImage( - with: url, - placeholder: nil - ) + public func configureImage(with profileImageType: ProfileImageType) { + profileImageView.image = profileImageType.image } private func configureLayout() { diff --git a/DesignSystem/Sources/Profile/ProfileType.swift b/DesignSystem/Sources/Profile/ProfileType.swift index 47b89f73..3e724982 100644 --- a/DesignSystem/Sources/Profile/ProfileType.swift +++ b/DesignSystem/Sources/Profile/ProfileType.swift @@ -6,7 +6,9 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // -import Foundation +import UIKit + +import ResourceKit public enum ProfileType { case large @@ -35,3 +37,33 @@ public enum ProfileType { } } } + +public enum ProfileImageType: Int { + case one = 0 + case two, three, four, five, six, seven, eight, nine, ten + // TODO: - 프로필 이미지 시안 나오면 변경 + var image: UIImage { + switch self { + case .one: + return ResourceKitAsset.Icon.apple.image + case .two: + return ResourceKitAsset.Icon.apple.image + case .three: + return ResourceKitAsset.Icon.apple.image + case .four: + return ResourceKitAsset.Icon.apple.image + case .five: + return ResourceKitAsset.Icon.apple.image + case .six: + return ResourceKitAsset.Icon.apple.image + case .seven: + return ResourceKitAsset.Icon.apple.image + case .eight: + return ResourceKitAsset.Icon.apple.image + case .nine: + return ResourceKitAsset.Icon.apple.image + case .ten: + return ResourceKitAsset.Icon.apple.image + } + } +} diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift index 666a1ca9..ef6b132a 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -45,7 +45,7 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, // TODO: - url 아니라 int형으로 이미지 에셋 받으면 설정 // 랜덤으로 띄워주기로 했었나.. let profileView = MOITProfileView( - urlString: "https://avatars.githubusercontent.com/u/37873745?s=96&v=4", + profileImageType: .one, profileType: .large, addButton: true ) From 104c95f47c9f1bc8ea79ae1f87889fe03ee15bb4 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sat, 17 Jun 2023 14:10:11 +0900 Subject: [PATCH 049/106] =?UTF-8?q?feat:=20NavigationBar=20logo=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/NavigationBar/MOITNavigationBar.swift | 12 +++++++++++- .../Sources/NavigationBar/NavigationItem.swift | 4 +++- .../Sources/NavigationBar/NavigationItemType.swift | 3 +++ DesignSystem/Sources/Profile/MOITProfileView.swift | 1 - .../Implement/SignUpViewController.swift | 6 +++++- .../Icon.xcassets/logo.imageset/Contents.json | 12 ++++++++++++ .../Resources/Icon.xcassets/logo.imageset/logo.svg | 9 +++++++++ 7 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 ResourceKit/Resources/Icon.xcassets/logo.imageset/Contents.json create mode 100644 ResourceKit/Resources/Icon.xcassets/logo.imageset/logo.svg diff --git a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift index 83f2876d..62722ca3 100644 --- a/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift +++ b/DesignSystem/Sources/NavigationBar/MOITNavigationBar.swift @@ -117,7 +117,17 @@ extension MOITNavigationBar { .width(80) .justifyContent(.start) .define { flex in - self.leftItems?.forEach { flex.addItem($0).size(24) } + self.leftItems?.forEach { item in + switch item.type { + case .logo: + flex.addItem(item) + .width(72) + .height(24) + default: + flex.addItem(item) + .size(24) + } + } } .marginLeft(16) diff --git a/DesignSystem/Sources/NavigationBar/NavigationItem.swift b/DesignSystem/Sources/NavigationBar/NavigationItem.swift index c9440dfd..64c26110 100644 --- a/DesignSystem/Sources/NavigationBar/NavigationItem.swift +++ b/DesignSystem/Sources/NavigationBar/NavigationItem.swift @@ -28,7 +28,9 @@ public final class NavigationItem: UIButton { } private func configureIcon(icon: UIImage?) { - guard let tintedImage = type.icon?.withRenderingMode(.alwaysTemplate) else { + guard let tintedImage = type.icon?.withRenderingMode(.alwaysTemplate), + self.type != .logo + else { self.setImage(type.icon, for: .normal) return } diff --git a/DesignSystem/Sources/NavigationBar/NavigationItemType.swift b/DesignSystem/Sources/NavigationBar/NavigationItemType.swift index 0c14d94a..7be079bc 100644 --- a/DesignSystem/Sources/NavigationBar/NavigationItemType.swift +++ b/DesignSystem/Sources/NavigationBar/NavigationItemType.swift @@ -11,6 +11,7 @@ import UIKit import ResourceKit public enum NavigationItemType { + case logo case close case back case share @@ -19,6 +20,8 @@ public enum NavigationItemType { var icon: UIImage? { switch self { + case .logo: + return ResourceKitAsset.Icon.logo.image case .close: return ResourceKitAsset.Icon.x.image case .back: diff --git a/DesignSystem/Sources/Profile/MOITProfileView.swift b/DesignSystem/Sources/Profile/MOITProfileView.swift index 59db492e..99971b7d 100644 --- a/DesignSystem/Sources/Profile/MOITProfileView.swift +++ b/DesignSystem/Sources/Profile/MOITProfileView.swift @@ -87,7 +87,6 @@ public final class MOITProfileView: UIView { addSubview(profileImageView) profileImageView.layer.cornerRadius = profileType.radius profileImageView.clipsToBounds = true - profileImageView.backgroundColor = ResourceKitAsset.Color.blue700.color profileImageView.flex.size(profileType.size) } diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift index ef6b132a..3b2c0579 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -91,7 +91,11 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, public override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // TODO: - 꼭 여기에 들어가야 할까? - configureNavigationBar(leftItems: [.back], title: "", rightItems: []) + configureNavigationBar( + leftItems: [.back], + title: "", + rightItems: [] + ) } deinit { debugPrint("\(self) deinit") } diff --git a/ResourceKit/Resources/Icon.xcassets/logo.imageset/Contents.json b/ResourceKit/Resources/Icon.xcassets/logo.imageset/Contents.json new file mode 100644 index 00000000..ad42a58d --- /dev/null +++ b/ResourceKit/Resources/Icon.xcassets/logo.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "logo.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ResourceKit/Resources/Icon.xcassets/logo.imageset/logo.svg b/ResourceKit/Resources/Icon.xcassets/logo.imageset/logo.svg new file mode 100644 index 00000000..3ec6aa49 --- /dev/null +++ b/ResourceKit/Resources/Icon.xcassets/logo.imageset/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + From 59e86debabe413b9a2aadd8480b9dd7505f2894f Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 11:16:05 +0900 Subject: [PATCH 050/106] =?UTF-8?q?feat:=20ViewControllable=20extension=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Utils/RIBs/ViewControllable+.swift | 62 +++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 Core/Utils/RIBs/ViewControllable+.swift diff --git a/Core/Utils/RIBs/ViewControllable+.swift b/Core/Utils/RIBs/ViewControllable+.swift new file mode 100644 index 00000000..d6aa021c --- /dev/null +++ b/Core/Utils/RIBs/ViewControllable+.swift @@ -0,0 +1,62 @@ +// +// ViewControllable+.swift +// CSLogger +// +// Created by 김찬수 on 2023/06/16. +// + +import UIKit + +import RIBs + +public extension ViewControllable { + + func present(_ viewControllable: ViewControllable, animated: Bool, completion: (() -> Void)?) { + self.uiviewController.present(viewControllable.uiviewController, animated: animated, completion: completion) + } + + func dismiss(completion: (() -> Void)?) { + self.uiviewController.dismiss(animated: true, completion: completion) + } + + func pushViewController(_ viewControllable: ViewControllable, animated: Bool) { + if let nav = self.uiviewController as? UINavigationController { + nav.pushViewController(viewControllable.uiviewController, animated: animated) + } else { + self.uiviewController.navigationController?.pushViewController(viewControllable.uiviewController, animated: animated) + } + } + + func popViewController(animated: Bool) { + if let nav = self.uiviewController as? UINavigationController { + nav.popViewController(animated: animated) + } else { + self.uiviewController.navigationController?.popViewController(animated: animated) + } + } + + func popToRoot(animated: Bool) { + if let nav = self.uiviewController as? UINavigationController { + nav.popToRootViewController(animated: animated) + } else { + self.uiviewController.navigationController?.popToRootViewController(animated: animated) + } + } + + func setViewControllers(_ viewControllerables: [ViewControllable]) { + if let nav = self.uiviewController as? UINavigationController { + nav.setViewControllers(viewControllerables.map(\.uiviewController), animated: true) + } else { + self.uiviewController.navigationController?.setViewControllers(viewControllerables.map(\.uiviewController), animated: true) + } + } + + var topViewControllable: ViewControllable { + var top: ViewControllable = self + + while let presented = top.uiviewController.presentedViewController as? ViewControllable { + top = presented + } + return top + } +} From 4e898d97a6a8d42517ee26ab3d816fb08c8d3ace Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 11:16:47 +0900 Subject: [PATCH 051/106] =?UTF-8?q?feat:=20StudyList=20shortcut=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dependency+Project.swift | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift b/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift index 7b00c41b..caea3e46 100644 --- a/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift +++ b/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift @@ -5,7 +5,7 @@ import ProjectDescription extension TargetDependency { public struct Feature { - public struct Home { + public struct StudyList { public struct Data {} public struct Domain {} public struct UserInterface {} @@ -50,27 +50,27 @@ public extension TargetDependency.Core { } // MARK: - Features/Home -public extension TargetDependency.Feature.Home { - static let folderName = "Home" +public extension TargetDependency.Feature.StudyList { + static let folderName = "StudyList" static func project(name: String, isInterface: Bool) -> TargetDependency { let postfix: String = isInterface ? "" : "Impl" return .project(target: "\(folderName)\(name)\(postfix)", path: .relativeToRoot("Features/\(folderName)/\(folderName)\(name)")) }} -public extension TargetDependency.Feature.Home.UserInterface { - static let Interface = TargetDependency.Feature.Home.project(name: "UserInterface", isInterface: true) - static let Implement = TargetDependency.Feature.Home.project(name: "UserInterface", isInterface: false) +public extension TargetDependency.Feature.StudyList.UserInterface { + static let Interface = TargetDependency.Feature.StudyList.project(name: "UserInterface", isInterface: true) + static let Implement = TargetDependency.Feature.StudyList.project(name: "UserInterface", isInterface: false) } -public extension TargetDependency.Feature.Home.Domain { - static let Interface = TargetDependency.Feature.Home.project(name: "Domain", isInterface: true) - static let Implement = TargetDependency.Feature.Home.project(name: "Domain", isInterface: false) +public extension TargetDependency.Feature.StudyList.Domain { + static let Interface = TargetDependency.Feature.StudyList.project(name: "Domain", isInterface: true) + static let Implement = TargetDependency.Feature.StudyList.project(name: "Domain", isInterface: false) } -public extension TargetDependency.Feature.Home.Data { - static let Interface = TargetDependency.Feature.Home.project(name: "Data", isInterface: true) - static let Implement = TargetDependency.Feature.Home.project(name: "Data", isInterface: false) +public extension TargetDependency.Feature.StudyList.Data { + static let Interface = TargetDependency.Feature.StudyList.project(name: "Data", isInterface: true) + static let Implement = TargetDependency.Feature.StudyList.project(name: "Data", isInterface: false) } // MARK: - Features/SignUp @@ -83,18 +83,18 @@ public extension TargetDependency.Feature.SignUp { }} public extension TargetDependency.Feature.SignUp.UserInterface { - static let Interface = TargetDependency.Feature.Home.project(name: "UserInterface", isInterface: true) - static let Implement = TargetDependency.Feature.Home.project(name: "UserInterface", isInterface: false) + static let Interface = TargetDependency.Feature.SignUp.project(name: "UserInterface", isInterface: true) + static let Implement = TargetDependency.Feature.SignUp.project(name: "UserInterface", isInterface: false) } public extension TargetDependency.Feature.SignUp.Domain { - static let Interface = TargetDependency.Feature.Home.project(name: "Domain", isInterface: true) - static let Implement = TargetDependency.Feature.Home.project(name: "Domain", isInterface: false) + static let Interface = TargetDependency.Feature.SignUp.project(name: "Domain", isInterface: true) + static let Implement = TargetDependency.Feature.SignUp.project(name: "Domain", isInterface: false) } public extension TargetDependency.Feature.SignUp.Data { - static let Interface = TargetDependency.Feature.Home.project(name: "Data", isInterface: true) - static let Implement = TargetDependency.Feature.Home.project(name: "Data", isInterface: false) + static let Interface = TargetDependency.Feature.SignUp.project(name: "Data", isInterface: true) + static let Implement = TargetDependency.Feature.SignUp.project(name: "Data", isInterface: false) } From b79d5e75341aceb96a5ed8bf766f92f2983797af Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 11:17:04 +0900 Subject: [PATCH 052/106] =?UTF-8?q?feat:=20dependency=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Features/SignUp/SignUpUserInterface/Project.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Features/SignUp/SignUpUserInterface/Project.swift b/Features/SignUp/SignUpUserInterface/Project.swift index adfb55b8..061a9e33 100644 --- a/Features/SignUp/SignUpUserInterface/Project.swift +++ b/Features/SignUp/SignUpUserInterface/Project.swift @@ -27,6 +27,9 @@ let project = Project.invertedDualTargetProjectWithDemoApp( .ResourceKit, .DesignSystem, .Core.Utils, + + .Feature.SignUp.Domain.Interface, + .Feature.SignUp.Data.Interface, ], isUserInterface: true ) From b9e38f3431390089e45edd2ce78b721bf22eeebc Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 11:17:48 +0900 Subject: [PATCH 053/106] =?UTF-8?q?feat:=20SignUp=20=EA=B4=80=EB=A0=A8=20U?= =?UTF-8?q?seCase=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FetchRandomNumberUseCaseImpl.swift | 18 +++++++++++ .../Implement/PostJoinInfoUseCaseImpl.swift | 31 +++++++++++++++++++ .../SignUp/SignUpDomain/Implement/dummy.swift | 4 --- .../Interface/FetchRandomNumberUseCase.swift | 13 ++++++++ .../Interface/PostJoinInfoUseCase.swift | 15 +++++++++ .../SignUp/SignUpDomain/Interface/dummy.swift | 4 --- 6 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift create mode 100644 Features/SignUp/SignUpDomain/Implement/PostJoinInfoUseCaseImpl.swift delete mode 100644 Features/SignUp/SignUpDomain/Implement/dummy.swift create mode 100644 Features/SignUp/SignUpDomain/Interface/FetchRandomNumberUseCase.swift create mode 100644 Features/SignUp/SignUpDomain/Interface/PostJoinInfoUseCase.swift delete mode 100644 Features/SignUp/SignUpDomain/Interface/dummy.swift diff --git a/Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift b/Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift new file mode 100644 index 00000000..2b64a65b --- /dev/null +++ b/Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift @@ -0,0 +1,18 @@ +// +// FetchRandomNumberUseCaseImpl.swift +// SignUpDomain +// +// Created by 김찬수 on 2023/06/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import SignUpDomain + +public final class FetchRandomNumberUseCaseImpl: FetchRandomNumberUseCase { + + public func execute(with range: Range) -> Int { + return Int.random(in: range) + } +} diff --git a/Features/SignUp/SignUpDomain/Implement/PostJoinInfoUseCaseImpl.swift b/Features/SignUp/SignUpDomain/Implement/PostJoinInfoUseCaseImpl.swift new file mode 100644 index 00000000..1534f4de --- /dev/null +++ b/Features/SignUp/SignUpDomain/Implement/PostJoinInfoUseCaseImpl.swift @@ -0,0 +1,31 @@ +// +// PostJoinInfoUseCaseImpl.swift +// SignUpDomain +// +// Created by 김찬수 on 2023/06/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import SignUpData +import SignUpDomain + +import RxSwift + +public final class PostJoinInfoUseCaseImpl: PostJoinInfoUseCase { + // MARK: - UI + + // MARK: - Properties + private let joinRepository: JoinRepository + + // MARK: - Initializers + public init(joinRepository: JoinRepository) { + self.joinRepository = joinRepository + } + + // MARK: - Functions + public func execute(name: String, inviteCode: String?) -> Single { + return joinRepository.post(name: name, inviteCode: inviteCode) + } +} diff --git a/Features/SignUp/SignUpDomain/Implement/dummy.swift b/Features/SignUp/SignUpDomain/Implement/dummy.swift deleted file mode 100644 index 9997fb44..00000000 --- a/Features/SignUp/SignUpDomain/Implement/dummy.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// dummy.swift -// - diff --git a/Features/SignUp/SignUpDomain/Interface/FetchRandomNumberUseCase.swift b/Features/SignUp/SignUpDomain/Interface/FetchRandomNumberUseCase.swift new file mode 100644 index 00000000..48ca5a49 --- /dev/null +++ b/Features/SignUp/SignUpDomain/Interface/FetchRandomNumberUseCase.swift @@ -0,0 +1,13 @@ +// +// FetchRandomNumberUseCase.swift +// SignUpDomain +// +// Created by 김찬수 on 2023/06/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public protocol FetchRandomNumberUseCase { + func execute(with range: Range) -> Int +} diff --git a/Features/SignUp/SignUpDomain/Interface/PostJoinInfoUseCase.swift b/Features/SignUp/SignUpDomain/Interface/PostJoinInfoUseCase.swift new file mode 100644 index 00000000..7fc320f3 --- /dev/null +++ b/Features/SignUp/SignUpDomain/Interface/PostJoinInfoUseCase.swift @@ -0,0 +1,15 @@ +// +// PostJoinInfoUseCase.swift +// SignUpDomain +// +// Created by 김찬수 on 2023/06/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +public protocol PostJoinInfoUseCase { + func execute(name: String, inviteCode: String?) -> Single +} diff --git a/Features/SignUp/SignUpDomain/Interface/dummy.swift b/Features/SignUp/SignUpDomain/Interface/dummy.swift deleted file mode 100644 index 9997fb44..00000000 --- a/Features/SignUp/SignUpDomain/Interface/dummy.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// dummy.swift -// - From fefab8a7f27cd5db4b846dd16f4f261674c5164d Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 11:18:03 +0900 Subject: [PATCH 054/106] =?UTF-8?q?feat:=20SignUpRepository=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignUpData/Interface/JoinRepository.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Features/SignUp/SignUpData/Interface/JoinRepository.swift diff --git a/Features/SignUp/SignUpData/Interface/JoinRepository.swift b/Features/SignUp/SignUpData/Interface/JoinRepository.swift new file mode 100644 index 00000000..83129797 --- /dev/null +++ b/Features/SignUp/SignUpData/Interface/JoinRepository.swift @@ -0,0 +1,15 @@ +// +// JoinRepository.swift +// SignUpData +// +// Created by 김찬수 on 2023/06/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +public protocol JoinRepository { + func post(name: String, inviteCode: String?) -> Single +} From 14e6116340cd0070a98911a82d98242479899886 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 11:35:08 +0900 Subject: [PATCH 055/106] =?UTF-8?q?fix:=20`MOITProfileView`=20border=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Profile/MOITProfileView.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/DesignSystem/Sources/Profile/MOITProfileView.swift b/DesignSystem/Sources/Profile/MOITProfileView.swift index 99971b7d..634a6486 100644 --- a/DesignSystem/Sources/Profile/MOITProfileView.swift +++ b/DesignSystem/Sources/Profile/MOITProfileView.swift @@ -87,7 +87,8 @@ public final class MOITProfileView: UIView { addSubview(profileImageView) profileImageView.layer.cornerRadius = profileType.radius profileImageView.clipsToBounds = true - + profileImageView.layer.borderWidth = 1 + profileImageView.layer.borderColor = ResourceKitAsset.Color.gray100.color.cgColor profileImageView.flex.size(profileType.size) } } From d1a585ff126390c2716e70fa686de709eff0fb33 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 15:33:48 +0900 Subject: [PATCH 056/106] =?UTF-8?q?fix:=20SignUpDemoApp=20RIBs=20=EA=B8=B0?= =?UTF-8?q?=EB=B0=98=EC=9C=BC=EB=A1=9C=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DemoApp/Sources/AppRoot.swift | 38 +++++++++++++++++++ .../SignUpUserInterfaceAppDelegate.swift | 14 ++++--- 2 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift new file mode 100644 index 00000000..5deb2aff --- /dev/null +++ b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift @@ -0,0 +1,38 @@ +// +// AppRoot.swift +// SignUpUserInterfaceDemoApp +// +// Created by 김찬수 on 2023/06/19. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import SignUpUserInterface +import SignUpUserInterfaceImpl +import SignUpDomain +import SignUpDomainImpl +import SignUpData +import SignUpDataImpl + +import RIBs +import RxSwift + +final class MOCKSignUpComponent: Component, SignUpDependency { + + + init() { + super.init(dependency: EmptyComponent()) + } + + var fetchRandomNumberUseCase: FetchRandomNumberUseCase = FetchRandomNumberUseCaseImpl() + + var postJoinInfoUseCase: PostJoinInfoUseCase = PostJoinInfoUseCaseImpl(joinRepository: JoinRepositoryMock()) +} + +final class JoinRepositoryMock: JoinRepository { + + func post(name: String, inviteCode: String?) -> Single { + Single.just(3) + } +} diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift index 4b578262..a5d873ec 100644 --- a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift +++ b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceAppDelegate.swift @@ -14,19 +14,23 @@ import SignUpUserInterface import RIBs @main -final class SignUpAppDelegate: UIResponder, UIApplicationDelegate { +final class SignUpAppDelegate: UIResponder, UIApplicationDelegate, SignUpListener { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let window = UIWindow(frame: UIScreen.main.bounds) + let signUpBuilder = SignUpBuilder(dependency: MOCKSignUpComponent()) + let router = signUpBuilder.build(withListener: MOCKMOITSignUpListener()) +// let launchRouter = LaunchRouter(interactor: router, viewController: router.viewControllable) + router.load() + window.rootViewController = router.viewControllable.uiviewController - // RIBs 사용해서 signupbuilder로 build 실행 -// window.rootViewController = SignUpBuilder(dependency: AppComponent()).build() - window.rootViewController = SignUpViewController() - window.makeKeyAndVisible() self.window = window return true } + + private final class MOCKMOITSignUpListener: SignUpListener {} } + From 48a73767e9fa57a438911c4d51a72a0710761464 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 15:34:12 +0900 Subject: [PATCH 057/106] =?UTF-8?q?fix:=20DemoApp=20Dependency=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tuist/ProjectDescriptionHelpers/Project+Templates.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tuist/ProjectDescriptionHelpers/Project+Templates.swift b/Tuist/ProjectDescriptionHelpers/Project+Templates.swift index f3165b93..ebb59586 100644 --- a/Tuist/ProjectDescriptionHelpers/Project+Templates.swift +++ b/Tuist/ProjectDescriptionHelpers/Project+Templates.swift @@ -108,6 +108,7 @@ extension Project { iOSTargetVersion: String = "15.0.0", interfaceDependencies: [TargetDependency] = [], implementDependencies: [TargetDependency] = [], + demoAppDependencies: [TargetDependency] = [], useTestTarget: Bool = true, infoPlist: InfoPlist = .default, isUserInterface: Bool = true @@ -153,7 +154,7 @@ extension Project { [ .target(name: name), .target(name: "\(name)Impl"), - ] + ] + demoAppDependencies ) let testTarget = makeTestTarget(name: name, From 849e1a2448c52ae3531a1de10adde37c9c603f1f Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 15:34:25 +0900 Subject: [PATCH 058/106] =?UTF-8?q?fix:=20DemoApp=20Dependency=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Features/SignUp/SignUpUserInterface/Project.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Features/SignUp/SignUpUserInterface/Project.swift b/Features/SignUp/SignUpUserInterface/Project.swift index 061a9e33..e8620790 100644 --- a/Features/SignUp/SignUpUserInterface/Project.swift +++ b/Features/SignUp/SignUpUserInterface/Project.swift @@ -31,5 +31,9 @@ let project = Project.invertedDualTargetProjectWithDemoApp( .Feature.SignUp.Domain.Interface, .Feature.SignUp.Data.Interface, ], + demoAppDependencies: [ + .Feature.SignUp.Domain.Implement, + .Feature.SignUp.Data.Implement, + ], isUserInterface: true ) From 5a53f8f314b3b976e62ff33ba862f43268340622 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 15:35:26 +0900 Subject: [PATCH 059/106] =?UTF-8?q?feat:=20SignUpDependency=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SignUpUserInterface/Implement/SignUpBuilder.swift | 9 ++++++--- .../SignUpUserInterface/Implement/SignUpInteractor.swift | 7 ++++++- .../SignUpUserInterface/Interface/SignUpDependency.swift | 7 +++++-- .../SignUpUserInterface/Interface/SignUpListener.swift | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift index 761b889d..cc5f9385 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift @@ -8,11 +8,14 @@ import SignUpUserInterface -import RIBs +import SignUpDomain -public final class SignUpComponent: Component { +import RIBs - // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. +public final class SignUpComponent: Component, SignUpInteractorDependency { + + var fetchRandomNumberUseCase: FetchRandomNumberUseCase { dependency.fetchRandomNumberUseCase } + var postJoinInfoUseCase: PostJoinInfoUseCase { dependency.postJoinInfoUseCase } } // MARK: - Builder diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift index 0ba0afa2..b9082a5a 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift @@ -20,7 +20,12 @@ protocol SignUpPresentable: Presentable { // TODO: Declare methods the interactor can invoke the presenter to present data. } -final class SignUpInteractor: PresentableInteractor, SignUpInteractable, SignUpPresentableListener { +protocol SignUpInteractorDependency { + var fetchRandomNumberUseCase: FetchRandomNumberUseCase { get } + var postJoinInfoUseCase: PostJoinInfoUseCase { get } +} + +final class SignUpInteractor: PresentableInteractor, SignUpInteractable { weak var router: SignUpRouting? weak var listener: SignUpListener? diff --git a/Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift b/Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift index 5e66b168..53bca11f 100644 --- a/Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift +++ b/Features/SignUp/SignUpUserInterface/Interface/SignUpDependency.swift @@ -8,9 +8,12 @@ import UIKit +import SignUpDomain + import RIBs public protocol SignUpDependency: Dependency { - // TODO: Declare the set of dependencies required by this RIB, but cannot be - // created by this RIB. + + var fetchRandomNumberUseCase: FetchRandomNumberUseCase { get } + var postJoinInfoUseCase: PostJoinInfoUseCase { get } } diff --git a/Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift b/Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift index fc6eb365..ebcf6f44 100644 --- a/Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift +++ b/Features/SignUp/SignUpUserInterface/Interface/SignUpListener.swift @@ -11,5 +11,5 @@ import UIKit import RIBs public protocol SignUpListener: AnyObject { - // TODO: Declare methods the interactor can invoke to communicate with other RIBs. + } From 40defae5449aa3ed3477d9553e23873742497fbe Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 15:35:58 +0900 Subject: [PATCH 060/106] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=B0=8F=20=EC=BD=94=EB=93=9C=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FetchRandomNumberUseCaseImpl.swift | 3 +++ .../Implement/SignUpBuilder.swift | 4 ++-- .../Implement/SignUpRouter.swift | 16 ++++++++++++++- .../Implement/SignUpViewController.swift | 20 ++++++++++++++++--- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift b/Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift index 2b64a65b..6bc0d23a 100644 --- a/Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift +++ b/Features/SignUp/SignUpDomain/Implement/FetchRandomNumberUseCaseImpl.swift @@ -12,6 +12,9 @@ import SignUpDomain public final class FetchRandomNumberUseCaseImpl: FetchRandomNumberUseCase { + public init() { + } + public func execute(with range: Range) -> Int { return Int.random(in: range) } diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift index cc5f9385..d79f050b 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpBuilder.swift @@ -22,14 +22,14 @@ public final class SignUpComponent: Component, SignUpInteracto public final class SignUpBuilder: Builder, SignUpBuildable { - override init(dependency: SignUpDependency) { + public override init(dependency: SignUpDependency) { super.init(dependency: dependency) } public func build(withListener listener: SignUpListener) -> ViewableRouting { let component = SignUpComponent(dependency: dependency) let viewController = SignUpViewController() - let interactor = SignUpInteractor(presenter: viewController) + let interactor = SignUpInteractor(presenter: viewController, dependency: component) interactor.listener = listener return SignUpRouter(interactor: interactor, viewController: viewController) } diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift index c221671b..a02dc4cb 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpRouter.swift @@ -20,10 +20,24 @@ protocol SignUpViewControllable: ViewControllable { } final class SignUpRouter: ViewableRouter, SignUpRouting { - + + // MARK: - UI + + // MARK: - Properties + + // MARK: - Initializers // TODO: Constructor inject child builder protocols to allow building children. override init(interactor: SignUpInteractable, viewController: SignUpViewControllable) { super.init(interactor: interactor, viewController: viewController) interactor.router = self } + + // MARK: - Functions + func attachMOITList() { + print(#function) + } + + func attachProfileSelect() { + print(#function) + } } diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift index 3b2c0579..59221412 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpViewController.swift @@ -20,10 +20,14 @@ import PinLayout protocol SignUpPresentableListener: AnyObject { func didSwipeBack() + func didTapNextButton() + func didTapProfileView() + func didTypeName(name: String) + func didTypeInviteCode(inviteCode: String) } -public final class SignUpViewController: BaseViewController, SignUpPresentable, SignUpViewControllable { - +public final class SignUpViewController: BaseViewController, SignUpViewControllable { + // MARK: - UI private let titleLabel: UILabel = { let label = UILabel() @@ -98,7 +102,10 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, ) } - deinit { debugPrint("\(self) deinit") } + deinit { + disposebag = DisposeBag() + debugPrint("\(self) deinit") + } // MARK: - Functions public override func configureConstraints() { @@ -151,3 +158,10 @@ public final class SignUpViewController: BaseViewController, SignUpPresentable, .disposed(by: disposebag) } } + +extension SignUpViewController: SignUpPresentable { + + func updateProfileIndex(index: Int) { + // 뷰 업데이트 + } +} From faf06de08a8464ae5e2b0f776cb2d87c902670c4 Mon Sep 17 00:00:00 2001 From: chansooo Date: Mon, 19 Jun 2023 15:36:15 +0900 Subject: [PATCH 061/106] =?UTF-8?q?feat:=20SignUp=20=EB=B9=84=EC=A6=88?= =?UTF-8?q?=EB=8B=88=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/SignUpInteractor.swift | 86 ++++++++++++++++--- 1 file changed, 76 insertions(+), 10 deletions(-) diff --git a/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift index b9082a5a..098005dd 100644 --- a/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift +++ b/Features/SignUp/SignUpUserInterface/Implement/SignUpInteractor.swift @@ -7,17 +7,24 @@ // import SignUpUserInterface +import SignUpData +import SignUpDomain import RIBs import RxSwift +import RxCocoa protocol SignUpRouting: ViewableRouting { - // TODO: Declare methods the interactor can invoke to manage sub-tree via the router. + + func attachMOITList() + func attachProfileSelect() } protocol SignUpPresentable: Presentable { + var listener: SignUpPresentableListener? { get set } - // TODO: Declare methods the interactor can invoke the presenter to present data. + + func updateProfileIndex(index: Int) } protocol SignUpInteractorDependency { @@ -27,28 +34,87 @@ protocol SignUpInteractorDependency { final class SignUpInteractor: PresentableInteractor, SignUpInteractable { + // MARK: - Properties weak var router: SignUpRouting? weak var listener: SignUpListener? - - // TODO: Add additional dependencies to constructor. Do not perform any logic - // in constructor. - override init(presenter: SignUpPresentable) { + + private let dependency: SignUpInteractorDependency + + private let nickName = PublishRelay() + private let inviteCode = PublishRelay() + private let nextButtonTapped = PublishRelay() + + // MARK: - Initializers + public init( + presenter: SignUpPresentable, + dependency: SignUpInteractorDependency + ) { + self.dependency = dependency super.init(presenter: presenter) presenter.listener = self } - + + // MARK: - Lifecycle override func didBecomeActive() { super.didBecomeActive() - // TODO: Implement business logic here. + + bind() + presenter.updateProfileIndex(index: dependency.fetchRandomNumberUseCase.execute(with: 0 ..< 8)) } - + override func willResignActive() { super.willResignActive() // TODO: Pause any business logic. } + // MARK: - Functions + private func bind() { + // nextButtonTapped가 발동 시 nickname과 inviteCode 스트림을 합쳐서 postJoinInfoUseCase에 전달 + nextButtonTapped + .withLatestFrom(Observable.combineLatest(nickName, inviteCode)) + .flatMap { [weak self] nickName, inviteCode -> Single in + guard let self = self else { return } + // id 반환 + print("nickname: \(nickName)") + print("inviteCode: \(inviteCode)") + // TODO: - 받은 내 ID 저장 + return self.dependency.postJoinInfoUseCase.execute(name: nickName, inviteCode: inviteCode) + } + .subscribe(onNext: {}) +// .subscribe(onNext: { [weak self] nickName, inviteCode in +// guard let self = self else { return } +// // id 반환 +// print("nickname: \(nickName)") +// print("inviteCode: \(inviteCode)") +// // TODO: - 받은 내 ID 저장 +// self.dependency.postJoinInfoUseCase.execute(name: nickName, inviteCode: inviteCode) +// }) + .disposeOnDeactivate(interactor: self) + + } +} + +// MARK: - SignUpPresentableListener +extension SignUpInteractor: SignUpPresentableListener { + func didSwipeBack() { } - + + func didTapNextButton() { + nextButtonTapped.accept(()) + } + + func didTapProfileView() { + router?.attachProfileSelect() + } + + func didTypeName(name: String) { + self.nickName.accept(name) + } + + func didTypeInviteCode(inviteCode: String) { + self.inviteCode.accept(inviteCode) + } } + From 3d24a7a6fa8b932324890b7bfad61bd21b8c94ba Mon Sep 17 00:00:00 2001 From: chansooo Date: Sat, 15 Jul 2023 15:14:47 +0900 Subject: [PATCH 062/106] =?UTF-8?q?feat:=20MOITList=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITListData/Implement/dummy.swift | 4 ++ .../MOITListData/Interface/dummy.swift | 4 ++ Features/MOITList/MOITListData/Project.swift | 24 ++++++++++ .../MOITList/MOITListData/Tests/dummy.swift | 4 ++ .../MOITListDomain/Implement/dummy.swift | 4 ++ .../MOITListDomain/Interface/dummy.swift | 4 ++ .../MOITList/MOITListDomain/Project.swift | 24 ++++++++++ .../MOITList/MOITListDomain/Tests/dummy.swift | 4 ++ .../DemoApp/Resources/LaunchScreen.storyboard | 26 +++++++++++ .../MOITListUserInterfaceAppDelegate.swift | 22 +++++++++ ...MOITListUserInterfaceViewController.swift} | 2 +- .../Implement/MOITListBuilder.swift | 40 ++++++++++++++++ .../Implement/MOITListInteractor.swift | 46 +++++++++++++++++++ .../Implement/MOITListRouter.swift | 27 +++++++++++ .../Implement/MOITListViewController.swift | 31 +++++++++++++ .../Interface/dummy.swift | 4 ++ .../MOITListUserInterface/Project.swift | 32 +++++++++++++ .../MOITListUserInterface/Tests/dummy.swift | 4 ++ .../DemoApp/Sources/AppRoot.swift | 38 --------------- 19 files changed, 305 insertions(+), 39 deletions(-) create mode 100644 Features/MOITList/MOITListData/Implement/dummy.swift create mode 100644 Features/MOITList/MOITListData/Interface/dummy.swift create mode 100644 Features/MOITList/MOITListData/Project.swift create mode 100644 Features/MOITList/MOITListData/Tests/dummy.swift create mode 100644 Features/MOITList/MOITListDomain/Implement/dummy.swift create mode 100644 Features/MOITList/MOITListDomain/Interface/dummy.swift create mode 100644 Features/MOITList/MOITListDomain/Project.swift create mode 100644 Features/MOITList/MOITListDomain/Tests/dummy.swift create mode 100644 Features/MOITList/MOITListUserInterface/DemoApp/Resources/LaunchScreen.storyboard create mode 100644 Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift rename Features/{SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift => MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift} (75%) create mode 100644 Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift create mode 100644 Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift create mode 100644 Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift create mode 100644 Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift create mode 100644 Features/MOITList/MOITListUserInterface/Interface/dummy.swift create mode 100644 Features/MOITList/MOITListUserInterface/Project.swift create mode 100644 Features/MOITList/MOITListUserInterface/Tests/dummy.swift delete mode 100644 Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift diff --git a/Features/MOITList/MOITListData/Implement/dummy.swift b/Features/MOITList/MOITListData/Implement/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListData/Implement/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/MOITList/MOITListData/Interface/dummy.swift b/Features/MOITList/MOITListData/Interface/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListData/Interface/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/MOITList/MOITListData/Project.swift b/Features/MOITList/MOITListData/Project.swift new file mode 100644 index 00000000..52215ce0 --- /dev/null +++ b/Features/MOITList/MOITListData/Project.swift @@ -0,0 +1,24 @@ +// +// MOITListAppDelegate.swift +// +// MOITList +// +// Created by kimchansoo +// + +import ProjectDescription +import ProjectDescriptionHelpers +import UtilityPlugin + +let project = Project.invertedDualTargetProject( + name: "MOITListData", + platform: .iOS, + iOSTargetVersion: "15.0.0", + interfaceDependencies: [ + .ThirdParty.RxSwift, + ], + implementDependencies: [ + .ThirdParty.RxSwift, + ] +) + diff --git a/Features/MOITList/MOITListData/Tests/dummy.swift b/Features/MOITList/MOITListData/Tests/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListData/Tests/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/MOITList/MOITListDomain/Implement/dummy.swift b/Features/MOITList/MOITListDomain/Implement/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Implement/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/MOITList/MOITListDomain/Interface/dummy.swift b/Features/MOITList/MOITListDomain/Interface/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Interface/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/MOITList/MOITListDomain/Project.swift b/Features/MOITList/MOITListDomain/Project.swift new file mode 100644 index 00000000..20cf3723 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Project.swift @@ -0,0 +1,24 @@ +// +// MOITListAppDelegate.swift +// +// MOITList +// +// Created by kimchansoo +// + +import ProjectDescription +import ProjectDescriptionHelpers +import UtilityPlugin + +let project = Project.invertedDualTargetProject( + name: "MOITListDomain", + platform: .iOS, + iOSTargetVersion: "15.0.0", + interfaceDependencies: [ + .ThirdParty.RxSwift, + ], + implementDependencies: [ + .ThirdParty.RxSwift, + ] +) + diff --git a/Features/MOITList/MOITListDomain/Tests/dummy.swift b/Features/MOITList/MOITListDomain/Tests/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Tests/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Resources/LaunchScreen.storyboard b/Features/MOITList/MOITListUserInterface/DemoApp/Resources/LaunchScreen.storyboard new file mode 100644 index 00000000..eae8f562 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Resources/LaunchScreen.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift new file mode 100644 index 00000000..e3c7cc49 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift @@ -0,0 +1,22 @@ +// +// MOITListAppDelegate.swift +// +// MOITList +// +// Created by kimchansoo on . +// + +import UIKit + +@main +final class MOITListAppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + let window = UIWindow(frame: UIScreen.main.bounds) + window.rootViewController = MOITListUserInterfaceViewController() + window.makeKeyAndVisible() + self.window = window + return true + } +} + diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift similarity index 75% rename from Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift rename to Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift index c19ad04f..ada0ec8f 100644 --- a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/SignUpUserInterfaceViewController.swift +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift @@ -8,7 +8,7 @@ import UIKit -final class SignUpUserInterfaceViewController: UIViewController { +final class MOITListUserInterfaceViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift new file mode 100644 index 00000000..84d52a2e --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift @@ -0,0 +1,40 @@ +// +// MOITListBuilder.swift +// MOITListUserInterfaceImpl +// +// Created by kimchansoo on 2023/06/25. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import RIBs + +protocol MOITListDependency: Dependency { + // TODO: Declare the set of dependencies required by this RIB, but cannot be + // created by this RIB. +} + +final class MOITListComponent: Component { + + // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. +} + +// MARK: - Builder + +protocol MOITListBuildable: Buildable { + func build(withListener listener: MOITListListener) -> MOITListRouting +} + +final class MOITListBuilder: Builder, MOITListBuildable { + + override init(dependency: MOITListDependency) { + super.init(dependency: dependency) + } + + func build(withListener listener: MOITListListener) -> MOITListRouting { + let component = MOITListComponent(dependency: dependency) + let viewController = MOITListViewController() + let interactor = MOITListInteractor(presenter: viewController) + interactor.listener = listener + return MOITListRouter(interactor: interactor, viewController: viewController) + } +} diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift new file mode 100644 index 00000000..143a4191 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift @@ -0,0 +1,46 @@ +// +// MOITListInteractor.swift +// MOITListUserInterfaceImpl +// +// Created by kimchansoo on 2023/06/25. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import RIBs +import RxSwift + +protocol MOITListRouting: ViewableRouting { + // TODO: Declare methods the interactor can invoke to manage sub-tree via the router. +} + +protocol MOITListPresentable: Presentable { + var listener: MOITListPresentableListener? { get set } + // TODO: Declare methods the interactor can invoke the presenter to present data. +} + +protocol MOITListListener: AnyObject { + // TODO: Declare methods the interactor can invoke to communicate with other RIBs. +} + +final class MOITListInteractor: PresentableInteractor, MOITListInteractable, MOITListPresentableListener { + + weak var router: MOITListRouting? + weak var listener: MOITListListener? + + // TODO: Add additional dependencies to constructor. Do not perform any logic + // in constructor. + override init(presenter: MOITListPresentable) { + super.init(presenter: presenter) + presenter.listener = self + } + + override func didBecomeActive() { + super.didBecomeActive() + // TODO: Implement business logic here. + } + + override func willResignActive() { + super.willResignActive() + // TODO: Pause any business logic. + } +} diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift new file mode 100644 index 00000000..dac13dd5 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift @@ -0,0 +1,27 @@ +// +// MOITListRouter.swift +// MOITListUserInterfaceImpl +// +// Created by kimchansoo on 2023/06/25. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import RIBs + +protocol MOITListInteractable: Interactable { + var router: MOITListRouting? { get set } + var listener: MOITListListener? { get set } +} + +protocol MOITListViewControllable: ViewControllable { + // TODO: Declare methods the router invokes to manipulate the view hierarchy. +} + +final class MOITListRouter: ViewableRouter, MOITListRouting { + + // TODO: Constructor inject child builder protocols to allow building children. + override init(interactor: MOITListInteractable, viewController: MOITListViewControllable) { + super.init(interactor: interactor, viewController: viewController) + interactor.router = self + } +} diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift new file mode 100644 index 00000000..84b29b85 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift @@ -0,0 +1,31 @@ +// +// MOITListViewController.swift +// MOITListUserInterfaceImpl +// +// Created by kimchansoo on 2023/06/25. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import RIBs +import RxSwift +import UIKit + +protocol MOITListPresentableListener: AnyObject { + // TODO: Declare properties and methods that the view controller can invoke to perform + // business logic, such as signIn(). This protocol is implemented by the corresponding + // interactor class. +} + +final class MOITListViewController: UIViewController, MOITListPresentable, MOITListViewControllable { + + // MARK: - UI + + // MARK: - Properties + weak var listener: MOITListPresentableListener? + + // MARK: - Initializers + + // MARK: - Lifecycle + + // MARK: - Methods +} diff --git a/Features/MOITList/MOITListUserInterface/Interface/dummy.swift b/Features/MOITList/MOITListUserInterface/Interface/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Interface/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/MOITList/MOITListUserInterface/Project.swift b/Features/MOITList/MOITListUserInterface/Project.swift new file mode 100644 index 00000000..cc0c87d8 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Project.swift @@ -0,0 +1,32 @@ +// +// MOITListAppDelegate.swift +// +// MOITList +// +// Created by kimchansoo +// + +import ProjectDescription +import ProjectDescriptionHelpers +import UtilityPlugin + +let project = Project.invertedDualTargetProjectWithDemoApp( + name: "MOITListUserInterface", + platform: .iOS, + iOSTargetVersion: "15.0.0", + interfaceDependencies: [ + .ThirdParty.RxSwift, + .ThirdParty.RIBs, + ], + implementDependencies: [ + .ThirdParty.RxSwift, + .ThirdParty.RxCocoa, + .ThirdParty.RxRelay, + .ThirdParty.RIBs, + .ThirdParty.PinLayout, + .ThirdParty.FlexLayout, + .ThirdParty.RxGesture, + ], + isUserInterface: true +) + diff --git a/Features/MOITList/MOITListUserInterface/Tests/dummy.swift b/Features/MOITList/MOITListUserInterface/Tests/dummy.swift new file mode 100644 index 00000000..9997fb44 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Tests/dummy.swift @@ -0,0 +1,4 @@ +// +// dummy.swift +// + diff --git a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift b/Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift deleted file mode 100644 index 5deb2aff..00000000 --- a/Features/SignUp/SignUpUserInterface/DemoApp/Sources/AppRoot.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// AppRoot.swift -// SignUpUserInterfaceDemoApp -// -// Created by 김찬수 on 2023/06/19. -// Copyright © 2023 chansoo.MOIT. All rights reserved. -// - -import Foundation - -import SignUpUserInterface -import SignUpUserInterfaceImpl -import SignUpDomain -import SignUpDomainImpl -import SignUpData -import SignUpDataImpl - -import RIBs -import RxSwift - -final class MOCKSignUpComponent: Component, SignUpDependency { - - - init() { - super.init(dependency: EmptyComponent()) - } - - var fetchRandomNumberUseCase: FetchRandomNumberUseCase = FetchRandomNumberUseCaseImpl() - - var postJoinInfoUseCase: PostJoinInfoUseCase = PostJoinInfoUseCaseImpl(joinRepository: JoinRepositoryMock()) -} - -final class JoinRepositoryMock: JoinRepository { - - func post(name: String, inviteCode: String?) -> Single { - Single.just(3) - } -} From fe599775b05c485d2cd63f4b7dd1838e7e5672e9 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sat, 15 Jul 2023 15:36:08 +0900 Subject: [PATCH 063/106] =?UTF-8?q?fix:=20MOITList=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EB=B2=84=EC=A0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Features/MOITList/MOITListData/Project.swift | 2 +- Features/MOITList/MOITListDomain/Project.swift | 2 +- Features/MOITList/MOITListUserInterface/Project.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Features/MOITList/MOITListData/Project.swift b/Features/MOITList/MOITListData/Project.swift index 52215ce0..1224391c 100644 --- a/Features/MOITList/MOITListData/Project.swift +++ b/Features/MOITList/MOITListData/Project.swift @@ -13,7 +13,7 @@ import UtilityPlugin let project = Project.invertedDualTargetProject( name: "MOITListData", platform: .iOS, - iOSTargetVersion: "15.0.0", + iOSTargetVersion: "16.0.0", interfaceDependencies: [ .ThirdParty.RxSwift, ], diff --git a/Features/MOITList/MOITListDomain/Project.swift b/Features/MOITList/MOITListDomain/Project.swift index 20cf3723..e4bd2b3a 100644 --- a/Features/MOITList/MOITListDomain/Project.swift +++ b/Features/MOITList/MOITListDomain/Project.swift @@ -13,7 +13,7 @@ import UtilityPlugin let project = Project.invertedDualTargetProject( name: "MOITListDomain", platform: .iOS, - iOSTargetVersion: "15.0.0", + iOSTargetVersion: "16.0.0", interfaceDependencies: [ .ThirdParty.RxSwift, ], diff --git a/Features/MOITList/MOITListUserInterface/Project.swift b/Features/MOITList/MOITListUserInterface/Project.swift index cc0c87d8..ab0d8cd9 100644 --- a/Features/MOITList/MOITListUserInterface/Project.swift +++ b/Features/MOITList/MOITListUserInterface/Project.swift @@ -13,7 +13,7 @@ import UtilityPlugin let project = Project.invertedDualTargetProjectWithDemoApp( name: "MOITListUserInterface", platform: .iOS, - iOSTargetVersion: "15.0.0", + iOSTargetVersion: "16.0.0", interfaceDependencies: [ .ThirdParty.RxSwift, .ThirdParty.RIBs, From 5bc2a70a7bb5d538acc8c3eff765fe936ab7d2fa Mon Sep 17 00:00:00 2001 From: chansooo Date: Sat, 15 Jul 2023 15:36:55 +0900 Subject: [PATCH 064/106] =?UTF-8?q?refactor:=20MOITListUseInterface=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EB=B0=8F=20=ED=8C=8C=EC=9D=BC=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListBuilder.swift | 17 +++++------------ .../Implement/MOITListInteractor.swift | 6 ++---- .../Implement/MOITListRouter.swift | 2 ++ .../Implement/MOITListViewController.swift | 13 ++++++++++++- .../Interface/MOITListBuildable.swift | 13 +++++++++++++ .../Interface/MOITListDependency.swift | 14 ++++++++++++++ .../Interface/MOITListListener.swift | 13 +++++++++++++ .../MOITListUserInterface/Interface/dummy.swift | 4 ---- 8 files changed, 61 insertions(+), 21 deletions(-) create mode 100644 Features/MOITList/MOITListUserInterface/Interface/MOITListBuildable.swift create mode 100644 Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift create mode 100644 Features/MOITList/MOITListUserInterface/Interface/MOITListListener.swift delete mode 100644 Features/MOITList/MOITListUserInterface/Interface/dummy.swift diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift index 84d52a2e..ace836c8 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift @@ -6,12 +6,9 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // -import RIBs +import MOITListUserInterface -protocol MOITListDependency: Dependency { - // TODO: Declare the set of dependencies required by this RIB, but cannot be - // created by this RIB. -} +import RIBs final class MOITListComponent: Component { @@ -20,17 +17,13 @@ final class MOITListComponent: Component { // MARK: - Builder -protocol MOITListBuildable: Buildable { - func build(withListener listener: MOITListListener) -> MOITListRouting -} - -final class MOITListBuilder: Builder, MOITListBuildable { +public final class MOITListBuilder: Builder, MOITListBuildable { - override init(dependency: MOITListDependency) { + public override init(dependency: MOITListDependency) { super.init(dependency: dependency) } - func build(withListener listener: MOITListListener) -> MOITListRouting { + public func build(withListener listener: MOITListListener) -> ViewableRouting { let component = MOITListComponent(dependency: dependency) let viewController = MOITListViewController() let interactor = MOITListInteractor(presenter: viewController) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift index 143a4191..7140e90d 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift @@ -6,6 +6,8 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // +import MOITListUserInterface + import RIBs import RxSwift @@ -18,10 +20,6 @@ protocol MOITListPresentable: Presentable { // TODO: Declare methods the interactor can invoke the presenter to present data. } -protocol MOITListListener: AnyObject { - // TODO: Declare methods the interactor can invoke to communicate with other RIBs. -} - final class MOITListInteractor: PresentableInteractor, MOITListInteractable, MOITListPresentableListener { weak var router: MOITListRouting? diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift index dac13dd5..205f0e98 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListRouter.swift @@ -6,6 +6,8 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // +import MOITListUserInterface + import RIBs protocol MOITListInteractable: Interactable { diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift index 84b29b85..28a68325 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift @@ -6,6 +6,9 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // +import MOITListUserInterface +import Utils + import RIBs import RxSwift import UIKit @@ -16,7 +19,7 @@ protocol MOITListPresentableListener: AnyObject { // interactor class. } -final class MOITListViewController: UIViewController, MOITListPresentable, MOITListViewControllable { +final class MOITListViewController: BaseViewController, MOITListPresentable, MOITListViewControllable { // MARK: - UI @@ -24,8 +27,16 @@ final class MOITListViewController: UIViewController, MOITListPresentable, MOITL weak var listener: MOITListPresentableListener? // MARK: - Initializers + public init(listener: MOITListPresentableListener? = nil) { + self.listener = listener + super.init() + } // MARK: - Lifecycle + override func viewDidLoad() { + self.view.backgroundColor = .cyan + self.flexRootView.backgroundColor = .systemBlue + } // MARK: - Methods } diff --git a/Features/MOITList/MOITListUserInterface/Interface/MOITListBuildable.swift b/Features/MOITList/MOITListUserInterface/Interface/MOITListBuildable.swift new file mode 100644 index 00000000..ca3f0732 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Interface/MOITListBuildable.swift @@ -0,0 +1,13 @@ +// +// MOITListBuildable.swift +// MOITListUserInterface +// +// Created by kimchansoo on 2023/07/15. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import RIBs + +public protocol MOITListBuildable: Buildable { + func build(withListener listener: MOITListListener) -> ViewableRouting +} diff --git a/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift b/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift new file mode 100644 index 00000000..77eb828a --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift @@ -0,0 +1,14 @@ +// +// MOITListDependency.swift +// MOITListUserInterface +// +// Created by kimchansoo on 2023/07/15. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import RIBs + +public protocol MOITListDependency: Dependency { + // TODO: Declare the set of dependencies required by this RIB, but cannot be + // created by this RIB. +} diff --git a/Features/MOITList/MOITListUserInterface/Interface/MOITListListener.swift b/Features/MOITList/MOITListUserInterface/Interface/MOITListListener.swift new file mode 100644 index 00000000..7823139b --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Interface/MOITListListener.swift @@ -0,0 +1,13 @@ +// +// MOITListListener.swift +// MOITListUserInterface +// +// Created by kimchansoo on 2023/07/15. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public protocol MOITListListener: AnyObject { + // TODO: Declare methods the interactor can invoke to communicate with other RIBs. +} diff --git a/Features/MOITList/MOITListUserInterface/Interface/dummy.swift b/Features/MOITList/MOITListUserInterface/Interface/dummy.swift deleted file mode 100644 index 9997fb44..00000000 --- a/Features/MOITList/MOITListUserInterface/Interface/dummy.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// dummy.swift -// - From a4c0a05f9a6a2b37ab3ca08285edb9c1b5c703ca Mon Sep 17 00:00:00 2001 From: chansooo Date: Sat, 15 Jul 2023 15:37:17 +0900 Subject: [PATCH 065/106] =?UTF-8?q?feat:=20MOITListDemoApp=20DemoApp=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITListUserInterfaceAppDelegate.swift | 25 ++++++++++++++++++- .../MOITListUserInterfaceViewController.swift | 18 ------------- 2 files changed, 24 insertions(+), 19 deletions(-) delete mode 100644 Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift index e3c7cc49..00c47f4b 100644 --- a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift @@ -8,15 +8,38 @@ import UIKit +import MOITListUserInterface +import MOITListUserInterfaceImpl + +import RIBs + @main final class MOITListAppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + private var router: ViewableRouting? + let dependency = MockMOITListDependency() + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let window = UIWindow(frame: UIScreen.main.bounds) - window.rootViewController = MOITListUserInterfaceViewController() + + self.router = MOITListBuilder(dependency: dependency) + .build(withListener: MOCKMOITListListener()) + self.router?.load() + self.router?.interactable.activate() + window.rootViewController = self.router?.viewControllable.uiviewController window.makeKeyAndVisible() self.window = window return true } + } +extension MOITListAppDelegate { + + final class MockMOITListDependency: MOITListDependency { + + } + private final class MOCKMOITListListener: MOITListListener { + } +} diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift deleted file mode 100644 index ada0ec8f..00000000 --- a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceViewController.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// ViewController.swift -// -// MOIT -// -// Created by kimchansoo on . -// - -import UIKit - -final class MOITListUserInterfaceViewController: UIViewController { - - override func viewDidLoad() { - super.viewDidLoad() - self.view.backgroundColor = .systemPink - } -} - From 82f701dd494868695869b496fa2935baff276cff Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 18:59:04 +0900 Subject: [PATCH 066/106] =?UTF-8?q?refactor:=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20MOITList=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Dependency+Project.swift | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift b/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift index 29f76a34..b6b4619c 100644 --- a/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift +++ b/Plugins/UtilityPlugin/ProjectDescriptionHelpers/Dependency+Project.swift @@ -5,7 +5,7 @@ import ProjectDescription extension TargetDependency { public struct Feature { - public struct StudyList { + public struct MOITList { public struct Data {} public struct Domain {} public struct UserInterface {} @@ -62,8 +62,8 @@ public extension TargetDependency.Core { } // MARK: - Features/Home -public extension TargetDependency.Feature.StudyList { - static let folderName = "StudyList" +public extension TargetDependency.Feature.MOITList { + static let folderName = "MOITList" static func project(name: String, isInterface: Bool) -> TargetDependency { let postfix: String = isInterface ? "" : "Impl" return .project(target: "\(folderName)\(name)\(postfix)", @@ -71,19 +71,19 @@ public extension TargetDependency.Feature.StudyList { } } -public extension TargetDependency.Feature.StudyList.UserInterface { - static let Interface = TargetDependency.Feature.StudyList.project(name: "UserInterface", isInterface: true) - static let Implement = TargetDependency.Feature.StudyList.project(name: "UserInterface", isInterface: false) +public extension TargetDependency.Feature.MOITList.UserInterface { + static let Interface = TargetDependency.Feature.MOITList.project(name: "UserInterface", isInterface: true) + static let Implement = TargetDependency.Feature.MOITList.project(name: "UserInterface", isInterface: false) } -public extension TargetDependency.Feature.StudyList.Domain { - static let Interface = TargetDependency.Feature.StudyList.project(name: "Domain", isInterface: true) - static let Implement = TargetDependency.Feature.StudyList.project(name: "Domain", isInterface: false) +public extension TargetDependency.Feature.MOITList.Domain { + static let Interface = TargetDependency.Feature.MOITList.project(name: "Domain", isInterface: true) + static let Implement = TargetDependency.Feature.MOITList.project(name: "Domain", isInterface: false) } -public extension TargetDependency.Feature.StudyList.Data { - static let Interface = TargetDependency.Feature.StudyList.project(name: "Data", isInterface: true) - static let Implement = TargetDependency.Feature.StudyList.project(name: "Data", isInterface: false) +public extension TargetDependency.Feature.MOITList.Data { + static let Interface = TargetDependency.Feature.MOITList.project(name: "Data", isInterface: true) + static let Implement = TargetDependency.Feature.MOITList.project(name: "Data", isInterface: false) } // MARK: - Features/SignUp From f1433180dc7550f27ae64e722f3be6dabff104df Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 18:59:29 +0900 Subject: [PATCH 067/106] =?UTF-8?q?fix:=20MOITList=20dependency=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Features/MOITList/MOITListUserInterface/Project.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Features/MOITList/MOITListUserInterface/Project.swift b/Features/MOITList/MOITListUserInterface/Project.swift index ab0d8cd9..518339df 100644 --- a/Features/MOITList/MOITListUserInterface/Project.swift +++ b/Features/MOITList/MOITListUserInterface/Project.swift @@ -26,6 +26,17 @@ let project = Project.invertedDualTargetProjectWithDemoApp( .ThirdParty.PinLayout, .ThirdParty.FlexLayout, .ThirdParty.RxGesture, + + .ResourceKit, + .DesignSystem, + .Core.Utils, + + .Feature.MOITList.Domain.Interface, + ], + demoAppDependencies: [ + .Feature.MOITList.Domain.Implement, + .Feature.MOITList.Data.Implement, + ], isUserInterface: true ) From a06c232ee1a5d9d3043fc98cb39bcb36b605d7df Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 18:59:55 +0900 Subject: [PATCH 068/106] =?UTF-8?q?chore:=20dummy=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Features/MOITList/MOITListData/Interface/dummy.swift | 4 ---- Features/MOITList/MOITListDomain/Implement/dummy.swift | 4 ---- Features/MOITList/MOITListDomain/Interface/dummy.swift | 4 ---- 3 files changed, 12 deletions(-) delete mode 100644 Features/MOITList/MOITListData/Interface/dummy.swift delete mode 100644 Features/MOITList/MOITListDomain/Implement/dummy.swift delete mode 100644 Features/MOITList/MOITListDomain/Interface/dummy.swift diff --git a/Features/MOITList/MOITListData/Interface/dummy.swift b/Features/MOITList/MOITListData/Interface/dummy.swift deleted file mode 100644 index 9997fb44..00000000 --- a/Features/MOITList/MOITListData/Interface/dummy.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// dummy.swift -// - diff --git a/Features/MOITList/MOITListDomain/Implement/dummy.swift b/Features/MOITList/MOITListDomain/Implement/dummy.swift deleted file mode 100644 index 9997fb44..00000000 --- a/Features/MOITList/MOITListDomain/Implement/dummy.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// dummy.swift -// - diff --git a/Features/MOITList/MOITListDomain/Interface/dummy.swift b/Features/MOITList/MOITListDomain/Interface/dummy.swift deleted file mode 100644 index 9997fb44..00000000 --- a/Features/MOITList/MOITListDomain/Interface/dummy.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// dummy.swift -// - From 968abff7c8ea49bc68922e1aaeb40873c65c5ee7 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:00:33 +0900 Subject: [PATCH 069/106] =?UTF-8?q?feat:=20MOITList=EC=97=90=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20model=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITListDomain/Interface/Model/MOIT.swift | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Features/MOITList/MOITListDomain/Interface/Model/MOIT.swift diff --git a/Features/MOITList/MOITListDomain/Interface/Model/MOIT.swift b/Features/MOITList/MOITListDomain/Interface/Model/MOIT.swift new file mode 100644 index 00000000..d521e25e --- /dev/null +++ b/Features/MOITList/MOITListDomain/Interface/Model/MOIT.swift @@ -0,0 +1,43 @@ +// +// MOIT.swift +// MOITListDomain +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public struct MOIT { + public let id: Int + public let name: String + public let profileUrl: String? + public let isEnd: Bool + public let repeatCycle: String + public let dayOfWeeks: [String] + public let startTime: String + public let endTime: String + public let dday: Int + + public init( + id: Int, + name: String, + profileUrl: String?, + isEnd: Bool, + repeatCycle: String, + dayOfWeeks: [String], + startTime: String, + endTime: String, + dday: Int + ) { + self.id = id + self.name = name + self.profileUrl = profileUrl + self.isEnd = isEnd + self.repeatCycle = repeatCycle + self.dayOfWeeks = dayOfWeeks + self.startTime = startTime + self.endTime = endTime + self.dday = dday + } +} From 3fec2c32841810e80c5c0bc89de08a4d6dec25b0 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:00:47 +0900 Subject: [PATCH 070/106] =?UTF-8?q?feat:=20MOITList=EC=97=90=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20usecase=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UseCase/FetchLeftTimeUseCase.swift | 19 +++++++++++++++++++ .../UseCase/FetchMoitListUseCase.swift | 15 +++++++++++++++ .../UseCase/FetchPenaltyToBePaidUseCase.swift | 17 +++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 Features/MOITList/MOITListDomain/Interface/UseCase/FetchLeftTimeUseCase.swift create mode 100644 Features/MOITList/MOITListDomain/Interface/UseCase/FetchMoitListUseCase.swift create mode 100644 Features/MOITList/MOITListDomain/Interface/UseCase/FetchPenaltyToBePaidUseCase.swift diff --git a/Features/MOITList/MOITListDomain/Interface/UseCase/FetchLeftTimeUseCase.swift b/Features/MOITList/MOITListDomain/Interface/UseCase/FetchLeftTimeUseCase.swift new file mode 100644 index 00000000..08467e61 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Interface/UseCase/FetchLeftTimeUseCase.swift @@ -0,0 +1,19 @@ +// +// FetchLeftTimeUseCase.swift +// MOITListDomain +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +/// 오늘 진행하는 스터디 중에 가장 빨리 시작하는 moit의 이름과 남은 시간 가져온다. +public protocol FetchLeftTimeUseCase { + /// 출석 10분 전부터 + /// 이후면 지각까지 얼마나 남았는지 + /// 지각 이후면 결석까지 얼마나 남았는지 + func execute(moitList: [MOIT]) -> (moitName: String, time: Date) +} diff --git a/Features/MOITList/MOITListDomain/Interface/UseCase/FetchMoitListUseCase.swift b/Features/MOITList/MOITListDomain/Interface/UseCase/FetchMoitListUseCase.swift new file mode 100644 index 00000000..af7b68e7 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Interface/UseCase/FetchMoitListUseCase.swift @@ -0,0 +1,15 @@ +// +// FetchMoitListUseCase.swift +// MOITListDomain +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +public protocol FetchMoitListUseCase { + func execute() -> Single<[MOIT]> +} diff --git a/Features/MOITList/MOITListDomain/Interface/UseCase/FetchPenaltyToBePaidUseCase.swift b/Features/MOITList/MOITListDomain/Interface/UseCase/FetchPenaltyToBePaidUseCase.swift new file mode 100644 index 00000000..eef046b5 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Interface/UseCase/FetchPenaltyToBePaidUseCase.swift @@ -0,0 +1,17 @@ +// +// FetchPenaltyToBePaidUseCase.swift +// MOITListDomainImpl +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +/// 벌금리스트에서 아직 안 낸 벌금들 받아와서 합해서 보여주는 usecase +public protocol FetchPenaltyToBePaidUseCase { + + func execute() -> Single +} From 35d83c660e02b3a3c5b1f99729fc9bb6c805b830 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:01:19 +0900 Subject: [PATCH 071/106] =?UTF-8?q?feat:=20MOITList=20Data=20Layer=20?= =?UTF-8?q?=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 추가로 수정해야합니다..! --- .../Implement/Repository/MOITRepository.swift | 30 +++++++++++++++++++ .../Interface/DTO/MOITListDTO.swift | 28 +++++++++++++++++ .../Interface/Repository/MOITRepository.swift | 18 +++++++++++ 3 files changed, 76 insertions(+) create mode 100644 Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift create mode 100644 Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift create mode 100644 Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift diff --git a/Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift b/Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift new file mode 100644 index 00000000..4839bdf0 --- /dev/null +++ b/Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift @@ -0,0 +1,30 @@ +// +// MOITRepository.swift +// MOITListData +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +import MOITListData +import MOITListDomain + +public final class MOITRepositoryImpl: MOITRepository { + // MARK: - UI + + // MARK: - Properties + + + // MARK: - Initializers + + // MARK: - Lifecycle + + // MARK: - Methods + public func fetchMOITList() -> Single<[MOIT]> { + fatalError() + } +} diff --git a/Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift b/Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift new file mode 100644 index 00000000..c51bbace --- /dev/null +++ b/Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift @@ -0,0 +1,28 @@ +// +// MOITListDTO.swift +// MOITListData +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public struct MOITListDTO: Decodable { + let moits: [MOITDTO] +} + +public extension MOITListDTO { + + struct MOITDTO: Decodable { + let id: Int + let name: String + let profileUrl: String? + let isEnd: Bool + let repeatCycle: String + let dayOfWeeks: [String] + let startTime: String + let endTime: String + let dday: Int + } +} diff --git a/Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift b/Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift new file mode 100644 index 00000000..389a9b19 --- /dev/null +++ b/Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift @@ -0,0 +1,18 @@ +// +// MOITRepository.swift +// MOITListData +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import MOITListDomain + +import RxSwift + +public protocol MOITRepository { + + func fetchMOITList() -> Single<[MOIT]> +} From baa06b34e539e88e362d382cf4d7553bb29f7b3d Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:01:38 +0900 Subject: [PATCH 072/106] =?UTF-8?q?feat:=20FetchMoitListUseCase=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/FetchMoitListUseCaseImpl.swift | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Features/MOITList/MOITListDomain/Implement/FetchMoitListUseCaseImpl.swift diff --git a/Features/MOITList/MOITListDomain/Implement/FetchMoitListUseCaseImpl.swift b/Features/MOITList/MOITListDomain/Implement/FetchMoitListUseCaseImpl.swift new file mode 100644 index 00000000..3d0c71ff --- /dev/null +++ b/Features/MOITList/MOITListDomain/Implement/FetchMoitListUseCaseImpl.swift @@ -0,0 +1,32 @@ +// +// FetchMoitListUseCaseImpl.swift +// MOITListDomain +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +import MOITListData +import MOITListDomain + +public final class FetchMoitListUseCaseImpl: FetchMoitListUseCase { + + // MARK: - Properties + private let moitRepository: MOITRepository + + // MARK: - Initializers + public init( + moitRepository: MOITRepository + ) { + self.moitRepository = moitRepository + } + + // MARK: - Methods + public func execute() -> Single<[MOIT]> { + moitRepository.fetchMOITList() + } +} From 4abd0a058b825a2b26c9f0f9d6f34b51d7b66200 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:02:27 +0900 Subject: [PATCH 073/106] =?UTF-8?q?fix:=20MOITPreview=20=EC=8D=B8=EB=84=A4?= =?UTF-8?q?=EC=9D=BC=20=EC=97=86=EC=96=B4=EB=8F=84=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift index fb107f01..ad72809b 100644 --- a/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift +++ b/DesignSystem/Sources/StudyPreview/MOITStudyPreview.swift @@ -56,7 +56,7 @@ public final class MOITStudyPreview: UIView { public init( remainingDate: Int, - profileURLString: String, + profileURLString: String?, studyName: String, studyProgressDescription: String? ) { @@ -80,7 +80,7 @@ public final class MOITStudyPreview: UIView { // MARK: - Methods public func configure( remainingDate: Int, - profileURL: String, + profileURL: String?, studyName: String, studyProgressDescription: String? ) { @@ -156,7 +156,7 @@ public final class MOITStudyPreview: UIView { private func configureAttributes( remainingDate: Int, - profileURLString: String, + profileURLString: String?, studyName: String, studyProgressDescription: String? ) { @@ -166,7 +166,8 @@ public final class MOITStudyPreview: UIView { remainingDateLabel = MOITChip(type: .dueDate(date: remainingDate)) - if let url = URL(string: profileURLString) { + if let profileURLString = profileURLString, + let url = URL(string: profileURLString) { profileImageView.kf.setImage( with: url, options: [.processor(RoundCornerImageProcessor(cornerRadius: 20))] From f38f1494397901d3b23373e8f598f1227053f084 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:02:53 +0900 Subject: [PATCH 074/106] =?UTF-8?q?feat:=20MOITAlarmType=20hashable=20?= =?UTF-8?q?=EC=B1=84=ED=83=9D=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Modal/MOITAlarmType.swift | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/DesignSystem/Sources/Modal/MOITAlarmType.swift b/DesignSystem/Sources/Modal/MOITAlarmType.swift index e9d1d849..8f3c181c 100644 --- a/DesignSystem/Sources/Modal/MOITAlarmType.swift +++ b/DesignSystem/Sources/Modal/MOITAlarmType.swift @@ -37,3 +37,16 @@ public enum MOITAlarmType: Equatable { } } } + +extension MOITAlarmType: Hashable { + public func hash(into hasher: inout Hasher) { + switch self { + case .attendanceCheck(let remainSeconds): + hasher.combine(remainSeconds) + case .penalty(let amount): + hasher.combine(amount) + case .attendanceRating(let percent): + hasher.combine(percent) + } + } +} From a2c512fbf45671b436c6e2b55c5ff4b7786dd4f5 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:03:23 +0900 Subject: [PATCH 075/106] =?UTF-8?q?fix:=20moitButton=20width=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Button/MOITButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DesignSystem/Sources/Button/MOITButton.swift b/DesignSystem/Sources/Button/MOITButton.swift index a41228bf..a76f38b6 100644 --- a/DesignSystem/Sources/Button/MOITButton.swift +++ b/DesignSystem/Sources/Button/MOITButton.swift @@ -108,7 +108,7 @@ extension MOITButton { .marginHorizontal(12) .marginVertical(self.type.marginVertical) } - .width(self.type.width) +// .width(self.type.width) } } From 9f005ad248171193d23bbeb19f679fbbe953c467 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:03:51 +0900 Subject: [PATCH 076/106] =?UTF-8?q?fix:=20AlarmView=20size=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/Modal/MOITAlarmView.swift | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/DesignSystem/Sources/Modal/MOITAlarmView.swift b/DesignSystem/Sources/Modal/MOITAlarmView.swift index 345d0a62..0974b2d8 100644 --- a/DesignSystem/Sources/Modal/MOITAlarmView.swift +++ b/DesignSystem/Sources/Modal/MOITAlarmView.swift @@ -59,7 +59,7 @@ public final class MOITAlarmView: UIView { public override func layoutSubviews() { super.layoutSubviews() self.flexRootView.pin.all() - self.flexRootView.flex.layout() + self.flexRootView.flex.layout(mode: .fitContainer) self.configureGradient() } } @@ -73,11 +73,11 @@ extension MOITAlarmView { self.flexRootView.flex .direction(.column) + .paddingHorizontal(16) .define { flex in flex.addItem(self.titleLabel) .marginTop(20) - .marginHorizontal(16) flex.addItem() .direction(.row) @@ -95,15 +95,15 @@ extension MOITAlarmView { .shrink(1) .aspectRatio(200/130) } - .marginHorizontal(16) .height(130) flex.addItem(self.button) - .marginHorizontal(16) +// .marginHorizontal(16) .marginBottom(19) + .width(100%) } - .width(335) - .height(260) +// .width(335) +// .height(260) } private func configureGradient() { From a617abf2d59c2b304e313d890641aa2cf45ddd0f Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:04:16 +0900 Subject: [PATCH 077/106] =?UTF-8?q?feat:=20EmptyMOITView=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/StudyPreview/EmptyMOITView.swift | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 DesignSystem/Sources/StudyPreview/EmptyMOITView.swift diff --git a/DesignSystem/Sources/StudyPreview/EmptyMOITView.swift b/DesignSystem/Sources/StudyPreview/EmptyMOITView.swift new file mode 100644 index 00000000..691bafd4 --- /dev/null +++ b/DesignSystem/Sources/StudyPreview/EmptyMOITView.swift @@ -0,0 +1,79 @@ +// +// EmptyMOITView.swift +// DesignSystem +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import ResourceKit + +import FlexLayout +import Kingfisher +import RxSwift +import RxGesture + +public final class EmptyMOITView: UIView { + + // MARK: - UI + private let flexRootView = UIView() + + private let noStudyLabel: UILabel = { + let label = UILabel() + label.text = "참여한 스터디가 없어요!" + label.font = ResourceKitFontFamily.p3 + label.textColor = ResourceKitAsset.Color.gray600.color + return label + }() + + private let studySuggestionLabel: UILabel = { + let label = UILabel() + label.text = "스터디를 생성하거나 참여해보세요" + label.font = ResourceKitFontFamily.p3 + label.textColor = ResourceKitAsset.Color.gray600.color + return label + }() + + // MARK: - Properties + private let disposebag = DisposeBag() + + // MARK: - Initializers + public init() { + super.init(frame: .zero) + configure() + } + + + @available (*, unavailable) + required init?(coder: NSCoder) { + fatalError("required init called") + } + + // MARK: - Lifecycle + public override func layoutSubviews() { + super.layoutSubviews() + + self.addSubview(flexRootView) + self.flexRootView.pin.all() + self.flexRootView.flex.layout() + self.flexRootView.layer.cornerRadius = 30 + + } + + // MARK: - Methods + private func configure() { + + self.flexRootView.flex + .justifyContent(.center) + .alignItems(.center) + .backgroundColor(.white) + .define { flex in + flex.addItem(noStudyLabel) + .marginBottom(5) + flex.addItem(studySuggestionLabel) + } + + } +} From 69a21488af0ca8a848dbaa71a67ad51d8cc8c260 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:06:40 +0900 Subject: [PATCH 078/106] =?UTF-8?q?feat:=20=ED=8E=98=EC=9D=B4=EC=A7=95=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=ED=95=9C=20=EB=B7=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit designSystem으로 파일 옮겨야 할지 고민중 --- .../Implement/View/PagableView.swift | 145 ++++++++++++++++++ .../View/ThumbnailCollectionViewCell.swift | 57 +++++++ 2 files changed, 202 insertions(+) create mode 100644 Features/MOITList/MOITListUserInterface/Implement/View/PagableView.swift create mode 100644 Features/MOITList/MOITListUserInterface/Implement/View/ThumbnailCollectionViewCell.swift diff --git a/Features/MOITList/MOITListUserInterface/Implement/View/PagableView.swift b/Features/MOITList/MOITListUserInterface/Implement/View/PagableView.swift new file mode 100644 index 00000000..5f6c1b43 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/View/PagableView.swift @@ -0,0 +1,145 @@ +// +// PagableView.swift +// MOITListUserInterface +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit +import Foundation + +import DesignSystem +import ResourceKit +import Utils + +import FlexLayout +import PinLayout +import RxCocoa + +public final class PagableCollectionView: BaseView { + + // MARK: UI + + private lazy var layout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.minimumLineSpacing = 0 + layout.scrollDirection = .horizontal + return layout + }() + + private lazy var collectionView: UICollectionView = { + let view = UICollectionView(frame: .zero, collectionViewLayout: layout) + view.isScrollEnabled = true + view.isPagingEnabled = true + view.clipsToBounds = true + view.alwaysBounceHorizontal = true + view.showsHorizontalScrollIndicator = false + view.showsVerticalScrollIndicator = false + view.layer.cornerRadius = 20 + return view + }() + + private lazy var thumbnailPageControl: UIPageControl = { + let control = UIPageControl() + control.tintColor = ResourceKitAsset.Color.gray600.color + control.isUserInteractionEnabled = false + control.translatesAutoresizingMaskIntoConstraints = false + return control + }() + + // MARK: Properties + var thumbnailDidTap: ControlEvent { + return collectionView.rx.itemSelected + } + + private var dataSource: DataSource? + + // MARK: Initializers + public override init(frame: CGRect) { + super.init(frame: .zero) + } + + // MARK: Methods + + public override func configureConstraints() { + super.configureConstraints() + self.backgroundColor = .clear + flexRootView.flex + .define { flex in + flex.addItem(collectionView) + .height(272) + .width(100%) + .marginBottom(20) + + flex.addItem(thumbnailPageControl) + } + } + + public override func configureAttributes() { + super.configureAttributes() + + self.configureCollectionView() + self.dataSource = generateDataSource() + } + + func configure(alarmViewModels: [AlarmViewModel]) { + thumbnailPageControl.numberOfPages = alarmViewModels.count + + let snaphot = generateSnapshot(alarmViews: alarmViewModels) + dataSource?.apply(snaphot) + } +} + +extension PagableCollectionView: UICollectionViewDelegateFlowLayout { + + enum Section { + case main + } + + typealias DataSource = UICollectionViewDiffableDataSource + + private func configureCollectionView() { + self.collectionView.register(ThumbnailCollectionViewCell.self, forCellWithReuseIdentifier: "ThumbnailCollectionViewCell") + self.collectionView.showsHorizontalScrollIndicator = false + self.collectionView.delegate = self + } + + private func generateDataSource() -> DataSource { + return DataSource(collectionView: self.collectionView) { collectionView, indexPath, itemIdentifier in + guard let cell = collectionView.dequeueReusableCell( + withReuseIdentifier: "ThumbnailCollectionViewCell", + for: indexPath + ) as? ThumbnailCollectionViewCell + else { + return UICollectionViewCell() + } + + cell.configure( + viewType: itemIdentifier.alarmType, + studyName: itemIdentifier.studyName + ) + return cell + } + } + + private func generateSnapshot(alarmViews: [AlarmViewModel]) -> NSDiffableDataSourceSnapshot { + var snapShot = NSDiffableDataSourceSnapshot() + snapShot.appendSections([.main]) + snapShot.appendItems(alarmViews, toSection: .main) + return snapShot + } + + public func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + + let width = self.frame.width + return CGSize(width: width, height: 272) + } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + let page = scrollView.contentOffset.x / scrollView.frame.size.width + thumbnailPageControl.currentPage = Int(round(page)) + } +} + + diff --git a/Features/MOITList/MOITListUserInterface/Implement/View/ThumbnailCollectionViewCell.swift b/Features/MOITList/MOITListUserInterface/Implement/View/ThumbnailCollectionViewCell.swift new file mode 100644 index 00000000..3e712329 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/View/ThumbnailCollectionViewCell.swift @@ -0,0 +1,57 @@ +// +// ThumbnailCollectionViewCell.swift +// MOITListUserInterface +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import UIKit + +import DesignSystem +import Utils + +import PinLayout +import FlexLayout + +final class ThumbnailCollectionViewCell: BaseCollectionViewCell { + + // MARK: UI + + private var alarmView: MOITAlarmView! + + // MARK: Properties + + // MARK: Initializers + init(viewType: MOITAlarmType, studyName: String) { + super.init(frame: .zero) + configure(viewType: viewType, studyName: studyName) + } + + override init(frame: CGRect) { + super.init(frame: .zero) + } + + // MARK: Methods + + override func configureConstraints() { + super.configureConstraints() + } + + public func configure(viewType: MOITAlarmType, studyName: String) { + let alarmView = MOITAlarmView(type: viewType, studyName: studyName) + self.alarmView = alarmView + + flexRootView.flex.define { flex in + flex.addItem(self.alarmView) + .width(100%) + .height(100%) + .alignSelf(.center) + .grow(1) + .layout(mode: .fitContainer) + } + + self.alarmView.flex.layout(mode: .fitContainer) + flexRootView.flex.layout(mode: .fitContainer) + } +} From d952102e9f97540f7c3257fcf62971a3f557f266 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:07:03 +0900 Subject: [PATCH 079/106] =?UTF-8?q?feat:=20BaseCollectionViewCell=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/Utils/Base/BaseCollectionViewCell.swift | 58 ++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 Core/Utils/Base/BaseCollectionViewCell.swift diff --git a/Core/Utils/Base/BaseCollectionViewCell.swift b/Core/Utils/Base/BaseCollectionViewCell.swift new file mode 100644 index 00000000..2407da8f --- /dev/null +++ b/Core/Utils/Base/BaseCollectionViewCell.swift @@ -0,0 +1,58 @@ +// +// BaseCollectionViewCell.swift +// Utils +// +// Created by kimchansoo on 2023/07/23. +// + +import UIKit + +import RxSwift +import RxCocoa + +open class BaseCollectionViewCell: UICollectionViewCell { + + // MARK: - UI + public let flexRootView = UIView() + + // MARK: - Properties + public var disposebag = DisposeBag() + + // MARK: - Methods + public override init(frame: CGRect) { + super.init(frame: frame) + + self.backgroundColor = .white + configureAttributes() + configureHierarchy() + configureConstraints() + bind() + } + + open func configureHierarchy() { +// self.addSubview(flexRootView) + self.contentView.addSubview(flexRootView) + } + open func configureConstraints() {} + open func configureAttributes() {} + open func bind() {} + + open override func layoutSubviews() { +// self.contentView.backgroundColor = .green +// self.backgroundColor = .black +// flexRootView.backgroundColor = .blue + self.contentView.backgroundColor = .clear + self.backgroundColor = .clear + flexRootView.backgroundColor = .clear + + flexRootView.frame = contentView.bounds + flexRootView.pin.all() + flexRootView.flex.layout(mode: .fitContainer) + } + + @available(*, unavailable) + required public init?(coder: NSCoder) { + fatalError("init(coder:) is called.") + } +} + From 233f9deeea86e90804dd38bee1c790a12cbdbff6 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:07:18 +0900 Subject: [PATCH 080/106] =?UTF-8?q?feat:=20AlarmViewModel=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/ViewModel/AlarmViewModel.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Features/MOITList/MOITListUserInterface/Implement/ViewModel/AlarmViewModel.swift diff --git a/Features/MOITList/MOITListUserInterface/Implement/ViewModel/AlarmViewModel.swift b/Features/MOITList/MOITListUserInterface/Implement/ViewModel/AlarmViewModel.swift new file mode 100644 index 00000000..74370c39 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/ViewModel/AlarmViewModel.swift @@ -0,0 +1,16 @@ +// +// AlarmViewModel.swift +// MOITListUserInterfaceImpl +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import DesignSystem + +public struct AlarmViewModel: Hashable { + let alarmType: MOITAlarmType + let studyName: String +} From e6bc970134f41a716e49e677e39824aa6cda674e Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:07:32 +0900 Subject: [PATCH 081/106] =?UTF-8?q?feat:=20MOITPreviewViewModel=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ViewModel/MOITPreviewViewModel.swift | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Features/MOITList/MOITListUserInterface/Implement/ViewModel/MOITPreviewViewModel.swift diff --git a/Features/MOITList/MOITListUserInterface/Implement/ViewModel/MOITPreviewViewModel.swift b/Features/MOITList/MOITListUserInterface/Implement/ViewModel/MOITPreviewViewModel.swift new file mode 100644 index 00000000..d67ce8a3 --- /dev/null +++ b/Features/MOITList/MOITListUserInterface/Implement/ViewModel/MOITPreviewViewModel.swift @@ -0,0 +1,28 @@ +// +// MOITPreviewViewModel.swift +// MOITListUserInterface +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public struct MOITPreviewViewModel { + let remainingDate: Int + let profileUrlString: String? + let studyName: String + let studyProgressDescription: String? + + public init( + remainingDate: Int, + profileUrlString: String?, + studyName: String, + studyProgressDescription: String? + ) { + self.remainingDate = remainingDate + self.profileUrlString = profileUrlString + self.studyName = studyName + self.studyProgressDescription = studyProgressDescription + } +} From 0035181019c74289996bbd04a9e5fb5ff946c78f Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:08:15 +0900 Subject: [PATCH 082/106] =?UTF-8?q?feat:=20MOITListInteractor=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EB=B0=9B=EC=95=84=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListInteractor.swift | 110 ++++++++++++++++-- 1 file changed, 100 insertions(+), 10 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift index 7140e90d..ed1b42f6 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift @@ -6,10 +6,13 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // +import DesignSystem import MOITListUserInterface +import MOITListDomain import RIBs import RxSwift +import RxRelay protocol MOITListRouting: ViewableRouting { // TODO: Declare methods the interactor can invoke to manage sub-tree via the router. @@ -17,28 +20,115 @@ protocol MOITListRouting: ViewableRouting { protocol MOITListPresentable: Presentable { var listener: MOITListPresentableListener? { get set } - // TODO: Declare methods the interactor can invoke the presenter to present data. + + func didReceiveMOITList(moitList: [MOITPreviewViewModel]) // MOITList 받아오는 + func didReceiveAlarm(alarms: [AlarmViewModel]) } -final class MOITListInteractor: PresentableInteractor, MOITListInteractable, MOITListPresentableListener { +protocol MOITListInteractorDependency { + var fetchMOITListsUseCase: FetchMoitListUseCase { get } + var fetchLeftTimeUseCase: FetchLeftTimeUseCase { get } + var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { get } +} +final class MOITListInteractor: PresentableInteractor, MOITListInteractable { + + // MARK: - Properties + weak var router: MOITListRouting? weak var listener: MOITListListener? - - // TODO: Add additional dependencies to constructor. Do not perform any logic - // in constructor. - override init(presenter: MOITListPresentable) { + + private let dependency: MOITListInteractorDependency + + private let selectedMoitIndex = PublishRelay() + + // MARK: - Initializers + + public init( + presenter: MOITListPresentable, + dependency: MOITListInteractorDependency + ) { + self.dependency = dependency super.init(presenter: presenter) presenter.listener = self } - + + // MARK: - Methods + override func didBecomeActive() { super.didBecomeActive() - // TODO: Implement business logic here. + + bind() } - + override func willResignActive() { super.willResignActive() - // TODO: Pause any business logic. + } + + private func bind() { + let moitList = dependency.fetchMOITListsUseCase.execute() + + moitList + .subscribe(onSuccess: { [weak self] moitList in + print("fetchMOITListsUseCase list: \(moitList)") + + let moitPreviewList = moitList.compactMap { self?.makeMoitPreview(with: $0)} + self?.presenter.didReceiveMOITList(moitList: moitPreviewList) + }) + .disposeOnDeactivate(interactor: self) + + selectedMoitIndex + .subscribe(onNext: { index in + fatalError("MOITDetail 연결") + }) + .disposeOnDeactivate(interactor: self) + + let fine = dependency.fetchPaneltyToBePaiedUSeCase.execute() + .map { + AlarmViewModel( + alarmType: .penalty(amount: $0.description), + studyName: "" + ) + } + .asObservable() + + let alertMoitInfo = moitList + .compactMap { [weak self] moits in + self?.dependency.fetchLeftTimeUseCase.execute(moitList: moits) + } + .map { moitName, date in + AlarmViewModel( + alarmType: .attendanceCheck( + remainSeconds: Int(date.description) ?? 0 + ), + studyName: moitName + ) + } + .asObservable() + + // fine과 alertMoitInfo을 합쳐서 subscribe에서 didReceiveAlarm로 보낸다 + Observable.merge(fine, alertMoitInfo) + .toArray() + .subscribe(onSuccess: { [weak self] alarms in + self?.presenter.didReceiveAlarm(alarms: alarms) + }) + .disposeOnDeactivate(interactor: self) + } + + private func makeMoitPreview(with moit: MOIT) -> MOITPreviewViewModel { + let description = "\(moit.repeatCycle)마다 \(moit.dayOfWeeks) \(moit.startTime) - \( moit.endTime)" + return MOITPreviewViewModel( + remainingDate: moit.dday, + profileUrlString: moit.profileUrl, + studyName: moit.name, + studyProgressDescription: description + ) + } +} + +// MARK: - MOITListPresentableListener +extension MOITListInteractor: MOITListPresentableListener { + func didTapMOIT(index: Int) { + self.selectedMoitIndex.accept(index) } } From c3e9911141bf8dfab739497be52b511dfd8d72fe Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:08:34 +0900 Subject: [PATCH 083/106] =?UTF-8?q?feat:=20=ED=95=84=EC=9A=94=ED=95=9C=20u?= =?UTF-8?q?secase=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListBuilder.swift | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift index ace836c8..a2898d69 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift @@ -7,26 +7,35 @@ // import MOITListUserInterface +import MOITListDomain import RIBs -final class MOITListComponent: Component { - - // TODO: Declare 'fileprivate' dependencies that are only used by this RIB. +final class MOITListComponent: Component, + MOITListInteractorDependency +{ + var fetchLeftTimeUseCase: FetchLeftTimeUseCase { dependency.fetchLeftTimeUseCase } + + var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { dependency.fetchPaneltyToBePaiedUSeCase } + + var fetchMOITListsUseCase: FetchMoitListUseCase { dependency.fetchMOITListsUseCase } } // MARK: - Builder public final class MOITListBuilder: Builder, MOITListBuildable { - + public override init(dependency: MOITListDependency) { super.init(dependency: dependency) } - + public func build(withListener listener: MOITListListener) -> ViewableRouting { let component = MOITListComponent(dependency: dependency) let viewController = MOITListViewController() - let interactor = MOITListInteractor(presenter: viewController) + let interactor = MOITListInteractor( + presenter: viewController, + dependency: component + ) interactor.listener = listener return MOITListRouter(interactor: interactor, viewController: viewController) } From f302c4f7989773114e807661db2507d379d76120 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:09:04 +0900 Subject: [PATCH 084/106] =?UTF-8?q?feat:=20MOITListViewController=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=B3=B4=EC=97=AC=EC=A3=BC=EB=8A=94=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListViewController.swift | 161 +++++++++++++++++- 1 file changed, 155 insertions(+), 6 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift index 28a68325..e84cf316 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift @@ -6,26 +6,69 @@ // Copyright © 2023 chansoo.MOIT. All rights reserved. // +import DesignSystem import MOITListUserInterface +import MOITListDomain import Utils +import ResourceKit import RIBs import RxSwift import UIKit +import FlexLayout +import PinLayout protocol MOITListPresentableListener: AnyObject { - // TODO: Declare properties and methods that the view controller can invoke to perform - // business logic, such as signIn(). This protocol is implemented by the corresponding - // interactor class. + + func didTapMOIT(index: Int) -> Void // MOIT 하나 탭 시 불리는 함수 } final class MOITListViewController: BaseViewController, MOITListPresentable, MOITListViewControllable { - + // MARK: - UI + private let alarmRootView = UIView() + private let pagableAlarmView = PagableCollectionView(frame: .zero) + + private let listRootView = UIView() + + + private let moitTitleLabel: UILabel = { + let label = UILabel() + label.text = "전체 스터디" + label.textColor = ResourceKitAsset.Color.gray800.color + label.font = ResourceKitFontFamily.h6 + return label + }() + + private let moitCountLabel: UILabel = { + let label = UILabel() + label.text = "0" + label.textColor = ResourceKitAsset.Color.blue600.color + label.font = ResourceKitFontFamily.h6 + return label + }() + + private let emptyMOITView = EmptyMOITView() + + private let createButton = MOITButton( + type: .small, + title: "스터디 생성", + titleColor: ResourceKitAsset.Color.gray800.color, + backgroundColor: ResourceKitAsset.Color.gray200.color + ) + + private let participateButton = MOITButton( + type: .small, + title: "스터디 참여", + titleColor: ResourceKitAsset.Color.white.color, + backgroundColor: ResourceKitAsset.Color.blue800.color + ) // MARK: - Properties weak var listener: MOITListPresentableListener? + private lazy var moitList: [MOITList] = [] + // MARK: - Initializers public init(listener: MOITListPresentableListener? = nil) { self.listener = listener @@ -34,9 +77,115 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI // MARK: - Lifecycle override func viewDidLoad() { - self.view.backgroundColor = .cyan - self.flexRootView.backgroundColor = .systemBlue + super.viewDidLoad() + + self.view.backgroundColor = ResourceKitAsset.Color.gray100.color + self.flexRootView.backgroundColor = ResourceKitAsset.Color.gray100.color + } + + public override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + configureNavigationBar( + leftItems: [.logo], + title: "", + rightItems: [ + .alarm, + .setting + ] + ) } // MARK: - Methods + override func configureConstraints() { + super.configureConstraints() + + flexRootView.flex + .paddingHorizontal(20) + .paddingTop(20) + .define { flex in + // 알람 + flex.addItem(alarmRootView) + .marginBottom(30) + + // 모잇 몇개인지 + flex.addItem() + .direction(.row) + .define { flex in + flex.addItem(moitTitleLabel) + .marginRight(4) + flex.addItem(moitCountLabel) + } + .marginBottom(20) + + // 모잇 리스트 + flex.addItem(listRootView) + .define({ flex in + flex.addItem(emptyMOITView) + .height(108) + .width(100%) + }) + + // 참여, 생성 버튼 + flex.addItem() + .direction(.row) + .justifyContent(.spaceBetween) + .define { flex in + flex.addItem(createButton) + .width(47%) + flex.addItem(participateButton) + .width(47%) + } + } + } + + override func bind() { + super.bind() + + } + + func didReceiveMOITList(moitList: [MOITPreviewViewModel]) { + print(#function, "previewViewModel: \(moitList)") + + if moitList.isEmpty { return } + + moitCountLabel.text = moitList.count.description + moitCountLabel.flex.markDirty() + + emptyMOITView.flex.display(.none) + + listRootView.flex.define { flex in + moitList.forEach { + flex.addItem(makeStudyPreview(with: $0)) + .height(100) + .width(100%) + .marginBottom(10) + } + } + listRootView.flex.markDirty() + listRootView.flex.layout() + flexRootView.flex.layout() + } + + func didReceiveAlarm(alarms: [AlarmViewModel]) { + + self.pagableAlarmView.configure(alarmViewModels: alarms) + + alarmRootView.flex.define { flex in + flex.addItem(pagableAlarmView) + } + + pagableAlarmView.flex.layout() + alarmRootView.flex.layout() + flexRootView.flex.layout() + } + + private func makeStudyPreview(with viewModel: MOITPreviewViewModel) -> MOITStudyPreview { + MOITStudyPreview( + remainingDate: viewModel.remainingDate, + profileURLString: viewModel.profileUrlString, + studyName: viewModel.studyName, + studyProgressDescription: viewModel.studyProgressDescription + ) + } } From 1ba31dde102d48c77977a0ddb8ea779d70c3169d Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:09:24 +0900 Subject: [PATCH 085/106] =?UTF-8?q?feat:=20=20MOITListDependency=EC=97=90?= =?UTF-8?q?=20=ED=95=84=EC=9A=94=ED=95=9C=20dependency=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interface/MOITListDependency.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift b/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift index 77eb828a..c6487b14 100644 --- a/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift +++ b/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift @@ -8,7 +8,11 @@ import RIBs +import MOITListDomain + public protocol MOITListDependency: Dependency { - // TODO: Declare the set of dependencies required by this RIB, but cannot be - // created by this RIB. + + var fetchMOITListsUseCase: FetchMoitListUseCase { get } + var fetchLeftTimeUseCase: FetchLeftTimeUseCase { get } + var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { get } } From 7e2514412a818799258591dbb9620bd1488d2323 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:10:08 +0900 Subject: [PATCH 086/106] =?UTF-8?q?feat:=20=20MockUsecase=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITListUserInterfaceAppDelegate.swift | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift index 00c47f4b..f9e595fd 100644 --- a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift @@ -36,10 +36,67 @@ final class MOITListAppDelegate: UIResponder, UIApplicationDelegate { } extension MOITListAppDelegate { - - final class MockMOITListDependency: MOITListDependency { + + final class MockMoitListComponent: Component, + MOITListDependency + { + var fetchLeftTimeUseCase: FetchLeftTimeUseCase + + var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase + + var fetchMOITListsUseCase: FetchMoitListUseCase + init() { + self.fetchMOITListsUseCase = FetchMoitListUseCaseImpl(moitRepository: MockMoitRepository()) + self.fetchLeftTimeUseCase = MockFetchLeftTimeUseCase() + self.fetchPaneltyToBePaiedUSeCase = MockFetchPenaltyToBePaidUseCase() + super.init(dependency: EmptyComponent()) + } } + private final class MOCKMOITListListener: MOITListListener { } + + private final class MockMoitRepository: MOITRepository { + func fetchMOITList() -> Single<[MOIT]> { + return Single.just([ + MOIT( + id: 1, + name: "hi", + profileUrl: "hi", + isEnd: true, + repeatCycle: "hi", + dayOfWeeks: ["hi"], + startTime: "hi", + endTime: "hi", + dday: 1 + ), + MOIT( + id: 1, + name: "hi", + profileUrl: "hi", + isEnd: true, + repeatCycle: "hi", + dayOfWeeks: ["hi"], + startTime: "hi", + endTime: "hi", + dday: 1 + ) + ]) + } + } + + private final class MockFetchPenaltyToBePaidUseCase: FetchPenaltyToBePaidUseCase { + func execute() -> Single { + return Single.just(1000) + } + } + + private final class MockFetchLeftTimeUseCase: FetchLeftTimeUseCase { + func execute(moitList: [MOIT]) -> (moitName: String, time: Date) { + return ("전전자군단", Date()) + } + } + + } From 977dfb04bc2a45a700d9d8fbb813af0153498a3c Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 19:10:31 +0900 Subject: [PATCH 087/106] =?UTF-8?q?fix:=20MOITListAppDelegate=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/MOITListUserInterfaceAppDelegate.swift | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift index f9e595fd..3db048e8 100644 --- a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift @@ -10,7 +10,12 @@ import UIKit import MOITListUserInterface import MOITListUserInterfaceImpl +import MOITListDomain +import MOITListDomainImpl +import MOITListData +import MOITListDataImpl +import RxSwift import RIBs @main @@ -18,7 +23,7 @@ final class MOITListAppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? private var router: ViewableRouting? - let dependency = MockMOITListDependency() + let dependency = MockMoitListComponent() func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let window = UIWindow(frame: UIScreen.main.bounds) @@ -32,7 +37,6 @@ final class MOITListAppDelegate: UIResponder, UIApplicationDelegate { self.window = window return true } - } extension MOITListAppDelegate { From eaaae7436629dd8bfb1c911215ecb0c8c581d994 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 21:29:52 +0900 Subject: [PATCH 088/106] =?UTF-8?q?fix:=20navigationBar=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/NavigationBar/NavigationColorType.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DesignSystem/Sources/NavigationBar/NavigationColorType.swift b/DesignSystem/Sources/NavigationBar/NavigationColorType.swift index a35b2e54..1a822272 100644 --- a/DesignSystem/Sources/NavigationBar/NavigationColorType.swift +++ b/DesignSystem/Sources/NavigationBar/NavigationColorType.swift @@ -26,7 +26,7 @@ public enum NavigationColorType { var backgroundColor: UIColor { switch self { case .normal: - return ResourceKitAsset.Color.white.color + return .clear case .reverse: return ResourceKitAsset.Color.gray500.color } From da72db2e3982d2bf06d99c8162a1861da022a73b Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 21:30:31 +0900 Subject: [PATCH 089/106] =?UTF-8?q?feat:=20`MOITListViewController`=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EC=95=A1=EC=85=98=20=EB=B0=94=EC=9D=B8?= =?UTF-8?q?=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListViewController.swift | 71 ++++++++++++++++--- 1 file changed, 62 insertions(+), 9 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift index e84cf316..90396bb8 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift @@ -20,7 +20,11 @@ import PinLayout protocol MOITListPresentableListener: AnyObject { - func didTapMOIT(index: Int) -> Void // MOIT 하나 탭 시 불리는 함수 + func didTapMOIT(index: Int) // MOIT 하나 탭 시 불리는 함수 + func didTapDeleteMOIT(index: Int) // MOIT 하나 삭제 시 불리는 함수 + func didTapAlarm(index: Int) + func didTapCreateButton() + func didTapParticipateButton() } final class MOITListViewController: BaseViewController, MOITListPresentable, MOITListViewControllable { @@ -33,7 +37,7 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI private let moitTitleLabel: UILabel = { - let label = UILabel() + let label = UILabel() label.text = "전체 스터디" label.textColor = ResourceKitAsset.Color.gray800.color label.font = ResourceKitFontFamily.h6 @@ -42,14 +46,16 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI private let moitCountLabel: UILabel = { let label = UILabel() - label.text = "0" + label.text = "0" label.textColor = ResourceKitAsset.Color.blue600.color - label.font = ResourceKitFontFamily.h6 - return label - }() + label.font = ResourceKitFontFamily.h6 + return label + }() private let emptyMOITView = EmptyMOITView() + private var moitPreviewList: [MOITStudyPreview] = [] + private let createButton = MOITButton( type: .small, title: "스터디 생성", @@ -142,6 +148,45 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI override func bind() { super.bind() + pagableAlarmView.thumbnailDidTap.asObservable() + .withUnretained(self) + .subscribe(onNext: { owner, index in + owner.listener?.didTapAlarm(index: index.row) + }) + .disposed(by: disposebag) + + + createButton.rx.tap + .withUnretained(self) + .subscribe(onNext: { owner, _ in + owner.listener?.didTapCreateButton() + }) + .disposed(by: disposebag) + + participateButton.rx.tap + .withUnretained(self) + .subscribe(onNext: { owner, _ in + owner.listener?.didTapParticipateButton() + }) + .disposed(by: disposebag) + + moitPreviewList.enumerated().forEach { index, preview in + // 탭 + preview.rx.didTap + .withUnretained(self) + .subscribe(onNext: { owner, _ in + owner.listener?.didTapMOIT(index: index) + }) + .disposed(by: disposebag) + + // 삭제 + preview.rx.didConfirmDelete + .withUnretained(self) + .subscribe(onNext: { owner, _ in + owner.listener?.didTapDeleteMOIT(index: index) + }) + .disposed(by: disposebag) + } } func didReceiveMOITList(moitList: [MOITPreviewViewModel]) { @@ -154,9 +199,13 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI emptyMOITView.flex.display(.none) + // TODO: - studypreview 모아서 저장해두고 걔를 additem + let moitPreviewList = moitList.map { makeStudyPreview(with: $0) } + self.moitPreviewList = moitPreviewList + listRootView.flex.define { flex in - moitList.forEach { - flex.addItem(makeStudyPreview(with: $0)) + moitPreviewList.forEach { + flex.addItem($0) .height(100) .width(100%) .marginBottom(10) @@ -180,7 +229,10 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI flexRootView.flex.layout() } - private func makeStudyPreview(with viewModel: MOITPreviewViewModel) -> MOITStudyPreview { +} + +private extension MOITListViewController { + func makeStudyPreview(with viewModel: MOITPreviewViewModel) -> MOITStudyPreview { MOITStudyPreview( remainingDate: viewModel.remainingDate, profileURLString: viewModel.profileUrlString, @@ -188,4 +240,5 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI studyProgressDescription: viewModel.studyProgressDescription ) } + } From b01fda7207d15a96e80b554d7ed2f75ef204e15b Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 21:30:49 +0900 Subject: [PATCH 090/106] =?UTF-8?q?feat:=20`MOITListInteractor`=20?= =?UTF-8?q?=EC=9C=A0=EC=A0=80=20=EC=95=A1=EC=85=98=20=EB=B0=94=EC=9D=B8?= =?UTF-8?q?=EB=94=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListInteractor.swift | 61 ++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift index ed1b42f6..a85a6382 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift @@ -41,6 +41,10 @@ final class MOITListInteractor: PresentableInteractor, MOIT private let dependency: MOITListInteractorDependency private let selectedMoitIndex = PublishRelay() + private let deleteMoitIndex = PublishRelay() + private let selectedAlarmIndex = PublishRelay() + private let createButtonTapped = PublishRelay() + private let participateButtonTapped = PublishRelay() // MARK: - Initializers @@ -106,13 +110,45 @@ final class MOITListInteractor: PresentableInteractor, MOIT } .asObservable() + let alarmList = Observable.merge(fine, alertMoitInfo).toArray() // fine과 alertMoitInfo을 합쳐서 subscribe에서 didReceiveAlarm로 보낸다 - Observable.merge(fine, alertMoitInfo) - .toArray() + + alarmList .subscribe(onSuccess: { [weak self] alarms in self?.presenter.didReceiveAlarm(alarms: alarms) }) .disposeOnDeactivate(interactor: self) + + + deleteMoitIndex + .withLatestFrom(moitList) { index, moits in + moits[index] + } + .subscribe(onNext: { deleteMoit in + // TODO: - moit 삭제 usecase 실행 + print("deleteMoit: \(deleteMoit)") + }) + .disposeOnDeactivate(interactor: self) + + selectedMoitIndex + .withLatestFrom(moitList) { index, moits in + moits[index] + } + .subscribe(onNext: { selectedMoit in + // TODO: - MOITDetail로 보내기 + print("selectedMoit: \(selectedMoit)") + }) + .disposeOnDeactivate(interactor: self) + + selectedAlarmIndex + .withLatestFrom(alarmList) { index, alarmList in + alarmList[index] + } + .subscribe(onNext: { alarmViewModel in + // TODO: - alarm 타입에 따라서 벌금, 출첵으로 나눠서 보내기 + print("alarmViewModel: \(alarmViewModel)") + }) + .disposeOnDeactivate(interactor: self) } private func makeMoitPreview(with moit: MOIT) -> MOITPreviewViewModel { @@ -128,6 +164,27 @@ final class MOITListInteractor: PresentableInteractor, MOIT // MARK: - MOITListPresentableListener extension MOITListInteractor: MOITListPresentableListener { + + func didTapDeleteMOIT(index: Int) { + print(#function) + deleteMoitIndex.accept(index) + } + + func didTapCreateButton() { + print(#function) + createButtonTapped.accept(()) + } + + func didTapParticipateButton() { + print(#function) + participateButtonTapped.accept(()) + } + + func didTapAlarm(index: Int) { + print(#function) + selectedAlarmIndex.accept(index) + } + func didTapMOIT(index: Int) { self.selectedMoitIndex.accept(index) } From ea33a9b5699f1c4e4a808779016ee6306c80d5ba Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:06:20 +0900 Subject: [PATCH 091/106] =?UTF-8?q?chore:=20dummy=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Features/MOITList/MOITListData/Implement/dummy.swift | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 Features/MOITList/MOITListData/Implement/dummy.swift diff --git a/Features/MOITList/MOITListData/Implement/dummy.swift b/Features/MOITList/MOITListData/Implement/dummy.swift deleted file mode 100644 index 9997fb44..00000000 --- a/Features/MOITList/MOITListData/Implement/dummy.swift +++ /dev/null @@ -1,4 +0,0 @@ -// -// dummy.swift -// - From b4624a517c9cf0d23e63573bbee9dea83db55823 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:06:45 +0900 Subject: [PATCH 092/106] =?UTF-8?q?feat:=20`FetchMOITListRequestable`=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FetchMOITListRequestable.swift | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Features/MOITList/MOITListData/Implement/Requestable/FetchMOITListRequestable.swift diff --git a/Features/MOITList/MOITListData/Implement/Requestable/FetchMOITListRequestable.swift b/Features/MOITList/MOITListData/Implement/Requestable/FetchMOITListRequestable.swift new file mode 100644 index 00000000..ad5413c8 --- /dev/null +++ b/Features/MOITList/MOITListData/Implement/Requestable/FetchMOITListRequestable.swift @@ -0,0 +1,44 @@ +// +// MOITRequestable.swift +// MOITListData +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import MOITNetwork +import MOITListData + +struct FetchMOITListRequestable: Requestable { + + public typealias Response = MOITListDTO + + // MARK: - Properties + + public var baseURL: URL? { + return URL(string: "http://moit-backend-eb-env.eba-qtcnkjjy.ap-northeast-2.elasticbeanstalk.com") ?? URL(fileReferenceLiteralResourceName: "") + } + + public var path: String { + return "/api/v1/moit" + } + + public var method: HTTPMethod { + return .get + } + + public var headers: HTTPHeaders { + return [:] + } + + public var parameters: HTTPRequestParameter? { + return nil + } + + // mark: - Initializers + init() { + + } +} From 316a292cf72c859481040c562efc2d2bbfa40e5c Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:07:06 +0900 Subject: [PATCH 093/106] =?UTF-8?q?feat:=20moitlistdto=20->=20moitlist=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interface/DTO/MOITListDTO.swift | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift b/Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift index c51bbace..54c421f9 100644 --- a/Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift +++ b/Features/MOITList/MOITListData/Interface/DTO/MOITListDTO.swift @@ -8,8 +8,10 @@ import Foundation +import MOITListDomain + public struct MOITListDTO: Decodable { - let moits: [MOITDTO] + public let moits: [MOITDTO] } public extension MOITListDTO { @@ -24,5 +26,19 @@ public extension MOITListDTO { let startTime: String let endTime: String let dday: Int + + public func toMOIT() -> MOIT { + MOIT( + id: self.id, + name: self.name, + profileUrl: self.profileUrl, + isEnd: self.isEnd, + repeatCycle: self.repeatCycle, + dayOfWeeks: self.dayOfWeeks, + startTime: self.startTime, + endTime: self.endTime, + dday: self.dday + ) + } } } From ee3baa9f511ca4dbd780eb550c13436c0faa4bd4 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:07:39 +0900 Subject: [PATCH 094/106] =?UTF-8?q?feat:=20deletemoit=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/Repository/MOITRepository.swift | 30 ------------------- .../Interface/Repository/MOITRepository.swift | 1 + 2 files changed, 1 insertion(+), 30 deletions(-) delete mode 100644 Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift diff --git a/Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift b/Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift deleted file mode 100644 index 4839bdf0..00000000 --- a/Features/MOITList/MOITListData/Implement/Repository/MOITRepository.swift +++ /dev/null @@ -1,30 +0,0 @@ -// -// MOITRepository.swift -// MOITListData -// -// Created by kimchansoo on 2023/07/16. -// Copyright © 2023 chansoo.MOIT. All rights reserved. -// - -import Foundation - -import RxSwift - -import MOITListData -import MOITListDomain - -public final class MOITRepositoryImpl: MOITRepository { - // MARK: - UI - - // MARK: - Properties - - - // MARK: - Initializers - - // MARK: - Lifecycle - - // MARK: - Methods - public func fetchMOITList() -> Single<[MOIT]> { - fatalError() - } -} diff --git a/Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift b/Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift index 389a9b19..038ff164 100644 --- a/Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift +++ b/Features/MOITList/MOITListData/Interface/Repository/MOITRepository.swift @@ -15,4 +15,5 @@ import RxSwift public protocol MOITRepository { func fetchMOITList() -> Single<[MOIT]> + func deleteMoit(id: Int) -> Single } From 3c67aa1ae7382c2d340fd4424a82b3a918019a25 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:08:04 +0900 Subject: [PATCH 095/106] =?UTF-8?q?feat:=20fine=20=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=EC=9E=84=EC=8B=9C=20=EA=B0=9D=EC=B2=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/FineRepositoryImpl.swift | 33 +++++++++++ .../MOITListData/Interface/DTO/FineDTO.swift | 57 +++++++++++++++++++ .../Interface/Repository/FineRepository.swift | 18 ++++++ 3 files changed, 108 insertions(+) create mode 100644 Features/MOITList/MOITListData/Implement/Repository/FineRepositoryImpl.swift create mode 100644 Features/MOITList/MOITListData/Interface/DTO/FineDTO.swift create mode 100644 Features/MOITList/MOITListData/Interface/Repository/FineRepository.swift diff --git a/Features/MOITList/MOITListData/Implement/Repository/FineRepositoryImpl.swift b/Features/MOITList/MOITListData/Implement/Repository/FineRepositoryImpl.swift new file mode 100644 index 00000000..6c3999f4 --- /dev/null +++ b/Features/MOITList/MOITListData/Implement/Repository/FineRepositoryImpl.swift @@ -0,0 +1,33 @@ +// +// FineRepositoryImpl.swift +// MOITListDataImpl +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +import MOITListData +import MOITListDomain +import MOITNetwork + +final class FineRepositoryImpl: FineRepository { + + // MARK: - Properties + private let network: Network + + // MARK: - Initializers + public init(network: Network) { + self.network = network + } + + // MARK: - Lifecycle + + // MARK: - Methods + func fetchFine(moitId: Int) -> Single { + fatalError() + } +} diff --git a/Features/MOITList/MOITListData/Interface/DTO/FineDTO.swift b/Features/MOITList/MOITListData/Interface/DTO/FineDTO.swift new file mode 100644 index 00000000..6b437b60 --- /dev/null +++ b/Features/MOITList/MOITListData/Interface/DTO/FineDTO.swift @@ -0,0 +1,57 @@ +// +// FineDTO.swift +// MOITListData +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import MOITListDomain +// TODO: - fine 관련된 부분 나중에 이동 + +public struct FineDTO: Codable { + let id: Int + let fineAmount: Int + let userId: Int + let userNickname: String + let attendanceStatus: AttendanceStatus + let studyOrder: Int + let isApproved: Bool + let approveAt: Date + + public init( + id: Int, + fineAmount: Int, + userId: Int, + userNickname: String, + attendanceStatus: AttendanceStatus, + studyOrder: Int, + isApproved: Bool, + approveAt: Date + ) { + self.id = id + self.fineAmount = fineAmount + self.userId = userId + self.userNickname = userNickname + self.attendanceStatus = attendanceStatus + self.studyOrder = studyOrder + self.isApproved = isApproved + self.approveAt = approveAt + } + + public func toFine() -> Fine { + Fine( + id: self.id, + fineAmount: self.fineAmount, + userId: self.userId, + userNickname: self.userNickname, + attendanceStatus: self.attendanceStatus, + studyOrder: self.studyOrder, + isApproved: self.isApproved, + approveAt: self.approveAt + ) + } +} + diff --git a/Features/MOITList/MOITListData/Interface/Repository/FineRepository.swift b/Features/MOITList/MOITListData/Interface/Repository/FineRepository.swift new file mode 100644 index 00000000..d78f5ef2 --- /dev/null +++ b/Features/MOITList/MOITListData/Interface/Repository/FineRepository.swift @@ -0,0 +1,18 @@ +// +// FineRepository.swift +// MOITListData +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import MOITListDomain + +import RxSwift + +public protocol FineRepository { + + func fetchFine(moitId: Int) -> Single +} From f16d3c9d78d725920d7a55af940a8b3fd7a5ca73 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:08:17 +0900 Subject: [PATCH 096/106] =?UTF-8?q?feat:=20MOITRepositoryImpl=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Repository/MOITRepositoryImpl.swift | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 Features/MOITList/MOITListData/Implement/Repository/MOITRepositoryImpl.swift diff --git a/Features/MOITList/MOITListData/Implement/Repository/MOITRepositoryImpl.swift b/Features/MOITList/MOITListData/Implement/Repository/MOITRepositoryImpl.swift new file mode 100644 index 00000000..c444e442 --- /dev/null +++ b/Features/MOITList/MOITListData/Implement/Repository/MOITRepositoryImpl.swift @@ -0,0 +1,43 @@ +// +// MOITRepository.swift +// MOITListData +// +// Created by kimchansoo on 2023/07/16. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +import MOITListData +import MOITListDomain +import MOITNetwork + +public final class MOITRepositoryImpl: MOITRepository { + + + // MARK: - UI + + // MARK: - Properties + private let network: Network + + // MARK: - Initializers + public init(network: Network) { + self.network = network + } + + // MARK: - Lifecycle + + // MARK: - Methods + public func fetchMOITList() -> Single<[MOIT]> { + network.request( + with: FetchMOITListRequestable() + ) + .map { $0.moits.map { $0.toMOIT() } } + } + + public func deleteMoit(id: Int) -> Single { + fatalError() + } +} From 8ebac2c9fcd32015b659f2bd19f8caef1348d2bf Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:08:37 +0900 Subject: [PATCH 097/106] =?UTF-8?q?feat:=20fine=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EB=AA=A8=EB=8D=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITListDomain/Interface/Model/Fine.swift | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 Features/MOITList/MOITListDomain/Interface/Model/Fine.swift diff --git a/Features/MOITList/MOITListDomain/Interface/Model/Fine.swift b/Features/MOITList/MOITListDomain/Interface/Model/Fine.swift new file mode 100644 index 00000000..c7297580 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Interface/Model/Fine.swift @@ -0,0 +1,44 @@ +// +// Fine.swift +// MOITListDomain +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +public struct Fine { + let id: Int + let fineAmount: Int + let userId: Int + let userNickname: String + let attendanceStatus: AttendanceStatus + let studyOrder: Int + let isApproved: Bool + let approveAt: Date + + public init( + id: Int, + fineAmount: Int, + userId: Int, + userNickname: String, + attendanceStatus: AttendanceStatus, + studyOrder: Int, + isApproved: Bool, + approveAt: Date + ) { + self.id = id + self.fineAmount = fineAmount + self.userId = userId + self.userNickname = userNickname + self.attendanceStatus = attendanceStatus + self.studyOrder = studyOrder + self.isApproved = isApproved + self.approveAt = approveAt + } +} + +public enum AttendanceStatus: Codable { + case late, absence +} From 669ceebb260a6333b0b7d5ce59cb58bd25616295 Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:08:53 +0900 Subject: [PATCH 098/106] =?UTF-8?q?fix:=20dependendy=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Features/MOITList/MOITListData/Project.swift | 3 +++ Features/MOITList/MOITListDomain/Project.swift | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Features/MOITList/MOITListData/Project.swift b/Features/MOITList/MOITListData/Project.swift index 1224391c..21dff9e4 100644 --- a/Features/MOITList/MOITListData/Project.swift +++ b/Features/MOITList/MOITListData/Project.swift @@ -16,6 +16,9 @@ let project = Project.invertedDualTargetProject( iOSTargetVersion: "16.0.0", interfaceDependencies: [ .ThirdParty.RxSwift, + + .Feature.MOITList.Domain.Interface, + .MOITNetwork.Interface, ], implementDependencies: [ .ThirdParty.RxSwift, diff --git a/Features/MOITList/MOITListDomain/Project.swift b/Features/MOITList/MOITListDomain/Project.swift index e4bd2b3a..7ca34eae 100644 --- a/Features/MOITList/MOITListDomain/Project.swift +++ b/Features/MOITList/MOITListDomain/Project.swift @@ -16,9 +16,12 @@ let project = Project.invertedDualTargetProject( iOSTargetVersion: "16.0.0", interfaceDependencies: [ .ThirdParty.RxSwift, + ], implementDependencies: [ .ThirdParty.RxSwift, + + .Feature.MOITList.Data.Interface, ] ) From ed8ffb9ec9a535bd00cdcf706babba6ac2bd226c Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:09:16 +0900 Subject: [PATCH 099/106] =?UTF-8?q?feat:=20`MOITListInteractor`=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListBuilder.swift | 1 + .../Implement/MOITListInteractor.swift | 47 +++++++++++++------ 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift index a2898d69..012d34e8 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift @@ -14,6 +14,7 @@ import RIBs final class MOITListComponent: Component, MOITListInteractorDependency { + var fetchLeftTimeUseCase: FetchLeftTimeUseCase { dependency.fetchLeftTimeUseCase } var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { dependency.fetchPaneltyToBePaiedUSeCase } diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift index a85a6382..74d72d66 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListInteractor.swift @@ -29,6 +29,7 @@ protocol MOITListInteractorDependency { var fetchMOITListsUseCase: FetchMoitListUseCase { get } var fetchLeftTimeUseCase: FetchLeftTimeUseCase { get } var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { get } +// var deleteMOITUseCase: DeleteMOITUseCase { get } } final class MOITListInteractor: PresentableInteractor, MOITListInteractable { @@ -72,6 +73,7 @@ final class MOITListInteractor: PresentableInteractor, MOIT private func bind() { let moitList = dependency.fetchMOITListsUseCase.execute() + // moitlist 보내주기 moitList .subscribe(onSuccess: { [weak self] moitList in print("fetchMOITListsUseCase list: \(moitList)") @@ -81,12 +83,7 @@ final class MOITListInteractor: PresentableInteractor, MOIT }) .disposeOnDeactivate(interactor: self) - selectedMoitIndex - .subscribe(onNext: { index in - fatalError("MOITDetail 연결") - }) - .disposeOnDeactivate(interactor: self) - + // 알람 설정 let fine = dependency.fetchPaneltyToBePaiedUSeCase.execute() .map { AlarmViewModel( @@ -111,7 +108,6 @@ final class MOITListInteractor: PresentableInteractor, MOIT .asObservable() let alarmList = Observable.merge(fine, alertMoitInfo).toArray() - // fine과 alertMoitInfo을 합쳐서 subscribe에서 didReceiveAlarm로 보낸다 alarmList .subscribe(onSuccess: { [weak self] alarms in @@ -119,17 +115,25 @@ final class MOITListInteractor: PresentableInteractor, MOIT }) .disposeOnDeactivate(interactor: self) - + // moit 삭제 deleteMoitIndex .withLatestFrom(moitList) { index, moits in moits[index] } - .subscribe(onNext: { deleteMoit in - // TODO: - moit 삭제 usecase 실행 - print("deleteMoit: \(deleteMoit)") + .withUnretained(self) +// .flatMap { owner, deleteMoit in +// print("deleteMoit: \(deleteMoit)") +//// return owner.dependency.deleteMOITUseCase.execute(moitId: deleteMoit.id) +// +// } + .subscribe(onNext: { owner, deleteMoit in + print("성공") + }, onError: { _ in + print("실패") }) .disposeOnDeactivate(interactor: self) + // 선택된 moitdetail로 보내기 selectedMoitIndex .withLatestFrom(moitList) { index, moits in moits[index] @@ -140,6 +144,7 @@ final class MOITListInteractor: PresentableInteractor, MOIT }) .disposeOnDeactivate(interactor: self) + // 알람 탭 selectedAlarmIndex .withLatestFrom(alarmList) { index, alarmList in alarmList[index] @@ -149,6 +154,22 @@ final class MOITListInteractor: PresentableInteractor, MOIT print("alarmViewModel: \(alarmViewModel)") }) .disposeOnDeactivate(interactor: self) + + // 생성하기로 보내기 + createButtonTapped + .withUnretained(self) + .subscribe(onNext: { owner, _ in + // TODO: - 생성하기로 보내기 + }) + .disposeOnDeactivate(interactor: self) + + // 참여하기로 보내기 + participateButtonTapped + .withUnretained(self) + .subscribe(onNext: { owner, _ in + // TODO: - 참여하기로 보내기 + }) + .disposeOnDeactivate(interactor: self) } private func makeMoitPreview(with moit: MOIT) -> MOITPreviewViewModel { @@ -166,22 +187,18 @@ final class MOITListInteractor: PresentableInteractor, MOIT extension MOITListInteractor: MOITListPresentableListener { func didTapDeleteMOIT(index: Int) { - print(#function) deleteMoitIndex.accept(index) } func didTapCreateButton() { - print(#function) createButtonTapped.accept(()) } func didTapParticipateButton() { - print(#function) participateButtonTapped.accept(()) } func didTapAlarm(index: Int) { - print(#function) selectedAlarmIndex.accept(index) } From 2c5ba4c52868734588d7a060fb43aa6ad4b173ab Mon Sep 17 00:00:00 2001 From: chansooo Date: Sun, 23 Jul 2023 23:09:30 +0900 Subject: [PATCH 100/106] =?UTF-8?q?feat:=20DeleteMOITUseCase=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Interface/UseCase/DeleteMOITUseCase.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Features/MOITList/MOITListDomain/Interface/UseCase/DeleteMOITUseCase.swift diff --git a/Features/MOITList/MOITListDomain/Interface/UseCase/DeleteMOITUseCase.swift b/Features/MOITList/MOITListDomain/Interface/UseCase/DeleteMOITUseCase.swift new file mode 100644 index 00000000..b1d4eec5 --- /dev/null +++ b/Features/MOITList/MOITListDomain/Interface/UseCase/DeleteMOITUseCase.swift @@ -0,0 +1,16 @@ +// +// DeleteMOITUseCase.swift +// MOITListDomain +// +// Created by kimchansoo on 2023/07/23. +// Copyright © 2023 chansoo.MOIT. All rights reserved. +// + +import Foundation + +import RxSwift + +public protocol DeleteMOITUseCase { + + func execute(moitId: Int) -> Observable +} From 92df9aba3230371e5cd83f1b619606ad82bb7c39 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 27 Jul 2023 22:31:12 +0900 Subject: [PATCH 101/106] =?UTF-8?q?feat:=20clipsToBounds=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DesignSystem/Sources/StudyPreview/EmptyMOITView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DesignSystem/Sources/StudyPreview/EmptyMOITView.swift b/DesignSystem/Sources/StudyPreview/EmptyMOITView.swift index 691bafd4..20c9a050 100644 --- a/DesignSystem/Sources/StudyPreview/EmptyMOITView.swift +++ b/DesignSystem/Sources/StudyPreview/EmptyMOITView.swift @@ -59,7 +59,7 @@ public final class EmptyMOITView: UIView { self.flexRootView.pin.all() self.flexRootView.flex.layout() self.flexRootView.layer.cornerRadius = 30 - + self.flexRootView.clipsToBounds = true } // MARK: - Methods From 5b8fa0b710ab4ebbef6b8bf83ab79ff53aaa6a5d Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 27 Jul 2023 22:31:37 +0900 Subject: [PATCH 102/106] =?UTF-8?q?refactor:=20self.fetchPaneltyToBePaiedU?= =?UTF-8?q?seCase=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift index 3db048e8..21fe7d29 100644 --- a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift @@ -46,14 +46,14 @@ extension MOITListAppDelegate { { var fetchLeftTimeUseCase: FetchLeftTimeUseCase - var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase + var fetchPaneltyToBePaiedUseCase: FetchPenaltyToBePaidUseCase var fetchMOITListsUseCase: FetchMoitListUseCase init() { self.fetchMOITListsUseCase = FetchMoitListUseCaseImpl(moitRepository: MockMoitRepository()) self.fetchLeftTimeUseCase = MockFetchLeftTimeUseCase() - self.fetchPaneltyToBePaiedUSeCase = MockFetchPenaltyToBePaidUseCase() + self.fetchPaneltyToBePaiedUseCase = MockFetchPenaltyToBePaidUseCase() super.init(dependency: EmptyComponent()) } } @@ -62,6 +62,7 @@ extension MOITListAppDelegate { } private final class MockMoitRepository: MOITRepository { + func fetchMOITList() -> Single<[MOIT]> { return Single.just([ MOIT( From c9321134e3c9ae725a658485000125f6d4c511e8 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 27 Jul 2023 22:31:50 +0900 Subject: [PATCH 103/106] =?UTF-8?q?refactor:=20self.fetchPaneltyToBePaiedU?= =?UTF-8?q?seCase=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITListUserInterface/Interface/MOITListDependency.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift b/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift index c6487b14..0e402b97 100644 --- a/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift +++ b/Features/MOITList/MOITListUserInterface/Interface/MOITListDependency.swift @@ -14,5 +14,5 @@ public protocol MOITListDependency: Dependency { var fetchMOITListsUseCase: FetchMoitListUseCase { get } var fetchLeftTimeUseCase: FetchLeftTimeUseCase { get } - var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { get } + var fetchPaneltyToBePaiedUseCase: FetchPenaltyToBePaidUseCase { get } } From 59f64e1081dcae2a58dffd80658d000e0e403f44 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 27 Jul 2023 22:32:06 +0900 Subject: [PATCH 104/106] =?UTF-8?q?refactor:=20layout=20=ED=95=9C=EB=B2=88?= =?UTF-8?q?=EB=A7=8C=20=EC=9E=A1=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Implement/MOITListViewController.swift | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift index 90396bb8..573bdd19 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListViewController.swift @@ -224,8 +224,9 @@ final class MOITListViewController: BaseViewController, MOITListPresentable, MOI flex.addItem(pagableAlarmView) } - pagableAlarmView.flex.layout() - alarmRootView.flex.layout() + // TODO: - flexRootView.flex.layout만 해도 레이아웃 잡히는지 실 데이터 받을 때 확인 + pagableAlarmView.flex.markDirty() + alarmRootView.flex.markDirty() flexRootView.flex.layout() } From 49ed87c325070bc884a8480c46555e71ac911336 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 27 Jul 2023 22:32:18 +0900 Subject: [PATCH 105/106] =?UTF-8?q?refactor:=20self.fetchPaneltyToBePaiedU?= =?UTF-8?q?seCase=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../MOITListUserInterface/Implement/MOITListBuilder.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift index 012d34e8..23da36b7 100644 --- a/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift +++ b/Features/MOITList/MOITListUserInterface/Implement/MOITListBuilder.swift @@ -17,7 +17,7 @@ final class MOITListComponent: Component, var fetchLeftTimeUseCase: FetchLeftTimeUseCase { dependency.fetchLeftTimeUseCase } - var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { dependency.fetchPaneltyToBePaiedUSeCase } + var fetchPaneltyToBePaiedUSeCase: FetchPenaltyToBePaidUseCase { dependency.fetchPaneltyToBePaiedUseCase } var fetchMOITListsUseCase: FetchMoitListUseCase { dependency.fetchMOITListsUseCase } } From 0c807c6bbadb55c952b1ed4cfc0101d136aee040 Mon Sep 17 00:00:00 2001 From: chansooo Date: Thu, 27 Jul 2023 22:32:38 +0900 Subject: [PATCH 106/106] =?UTF-8?q?feat:=20=EB=A0=88=ED=8F=AC=EC=A7=80?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=ED=94=84=EB=A1=9C=ED=86=A0=EC=BD=9C=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=9E=84=EC=8B=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift index 21fe7d29..65a8b175 100644 --- a/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift +++ b/Features/MOITList/MOITListUserInterface/DemoApp/Sources/MOITListUserInterfaceAppDelegate.swift @@ -89,6 +89,10 @@ extension MOITListAppDelegate { ) ]) } + + func deleteMoit(id: Int) -> Single { + fatalError() + } } private final class MockFetchPenaltyToBePaidUseCase: FetchPenaltyToBePaidUseCase {