diff --git a/Projects/Data/Src/Repository/Falling/FallingTarget+SampleData.swift b/Projects/Data/Src/Repository/Falling/FallingTarget+SampleData.swift index af6df267..fa24e498 100644 --- a/Projects/Data/Src/Repository/Falling/FallingTarget+SampleData.swift +++ b/Projects/Data/Src/Repository/Falling/FallingTarget+SampleData.swift @@ -59,11 +59,11 @@ extension FallingTarget { ], "userProfilePhotos": [ { - "url": "test1", + "url": "https://cdn.pixabay.com/photo/2024/01/15/21/16/dog-8510901_640.jpg", "priority": 1 }, { - "url": "https://firebasestorage.googleapis.com/v0/b/tht-falling.appspot.com/o/images%2Fprofile_example2.png?alt=media&token=e19493ed-10ba-4784-bf94-f4b99af84161", + "url": "https://firebasestorage.googleapis.com/v0/b/tht-falling.appspot.com/o/images%2Fprofile_example1.png?alt=media&token=dc28c0cd-98b2-4332-9660-35530283d77c", "priority": 2 }, { @@ -116,11 +116,11 @@ extension FallingTarget { ], "userProfilePhotos": [ { - "url": "https://firebasestorage.googleapis.com/v0/b/tht-falling.appspot.com/o/images%2Fprofile_example1 .png?alt=media&token=dc28c0cd-98b2-4332-9660-35530283d77c", + "url": "https://cdn.pixabay.com/photo/2023/05/07/11/57/surfboard-7976219_960_720.jpg", "priority": 1 }, { - "url": "https://firebasestorage.googleapis.com/v0/b/tht-falling.appspot.com/o/images%2Fprofile_example2.png?alt=media&token=e19493ed-10ba-4784-bf94-f4b99af84161", + "url": "https://cdn.pixabay.com/photo/2024/01/07/11/17/welsh-corgi-8492879_640.jpg", "priority": 2 }, { @@ -173,11 +173,11 @@ extension FallingTarget { ], "userProfilePhotos": [ { - "url": "https://firebasestorage.googleapis.com/v0/b/tht-falling.appspot.com/o/images%2Fprofile_example1.png?alt=media&token=dc28c0cd-98b2-4332-9660-35530283d77c", + "url": "https://cdn.pixabay.com/photo/2023/03/18/05/26/ferris-wheel-7859855_640.jpg", "priority": 1 }, { - "url": "https://firebasestorage.googleapis.com/v0/b/tht-falling.appspot.com/o/images%2Fprofile_example2.png?alt=media&token=e19493ed-10ba-4784-bf94-f4b99af84161", + "url": "https://cdn.pixabay.com/photo/2023/11/17/12/46/cat-8394224_640.jpg", "priority": 2 }, { diff --git a/Projects/Features/Falling/Src/Home/FallingHomeView.swift b/Projects/Features/Falling/Src/Home/FallingHomeView.swift index 22161e64..55856a85 100644 --- a/Projects/Features/Falling/Src/Home/FallingHomeView.swift +++ b/Projects/Features/Falling/Src/Home/FallingHomeView.swift @@ -12,9 +12,7 @@ import DSKit final class FallingHomeView: TFBaseView { lazy var collectionView: UICollectionView = { - let flowLayout = UICollectionViewFlowLayout() - flowLayout.minimumLineSpacing = 14 - flowLayout.scrollDirection = .vertical + let flowLayout = UICollectionViewCompositionalLayout.verticalListLayout(withEstimatedHeight: ((UIWindow.keyWindow?.frame.width ?? 0) - 32) * 1.64) let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) collectionView.isScrollEnabled = false @@ -23,11 +21,76 @@ final class FallingHomeView: TFBaseView { }() override func makeUI() { + self.backgroundColor = DSKitAsset.Color.neutral700.color + self.addSubview(collectionView) self.collectionView.snp.makeConstraints { - $0.top.equalToSuperview().inset(8) + $0.top.equalTo(self.safeAreaLayoutGuide).inset(8) $0.leading.bottom.trailing.equalToSuperview() } } } + +extension UICollectionViewCompositionalLayout { + static func verticalListLayout(withEstimatedHeight estimatedHeight: CGFloat = 110) -> UICollectionViewCompositionalLayout { + return UICollectionViewCompositionalLayout(section: .verticalListSection(withEstimatedHeight: estimatedHeight)) + } + + static func horizontalListLayout() -> UICollectionViewCompositionalLayout { + return UICollectionViewCompositionalLayout(section: .horizontalListSection()) + } +} + +extension NSCollectionLayoutSection { + static func verticalListSection(withEstimatedHeight estimatedHeight: CGFloat = 110) -> NSCollectionLayoutSection { + let itemSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1.0), + heightDimension: .fractionalHeight(1.0) + ) + let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize) + + let layoutGroupSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1.0), + heightDimension: .estimated(estimatedHeight) + ) + + let layoutGroup = NSCollectionLayoutGroup.vertical( + layoutSize: layoutGroupSize, + subitems: [layoutItem] + ) + + let section = NSCollectionLayoutSection(group: layoutGroup) + section.contentInsets = NSDirectionalEdgeInsets( + top: 0, + leading: 16, + bottom: 0, + trailing: 16 + ) + section.interGroupSpacing = 14 + return section + } + + static func horizontalListSection() -> NSCollectionLayoutSection { + let itemSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1.0), + heightDimension: .fractionalHeight(1.0) + ) + let layoutItem = NSCollectionLayoutItem(layoutSize: itemSize) + + let layoutGroupSize = NSCollectionLayoutSize( + widthDimension: .fractionalWidth(1.0), + heightDimension: .fractionalHeight(1.0) + ) + + let layoutGroup = NSCollectionLayoutGroup.horizontal( + layoutSize: layoutGroupSize, + subitems: [layoutItem] + ) + + let section = NSCollectionLayoutSection(group: layoutGroup) + section.orthogonalScrollingBehavior = .paging + + return section + } +} diff --git a/Projects/Features/Falling/Src/Home/FallingHomeViewController.swift b/Projects/Features/Falling/Src/Home/FallingHomeViewController.swift index 147327f7..464c8f89 100644 --- a/Projects/Features/Falling/Src/Home/FallingHomeViewController.swift +++ b/Projects/Features/Falling/Src/Home/FallingHomeViewController.swift @@ -13,13 +13,12 @@ import FallingInterface final class FallingHomeViewController: TFBaseViewController { private let viewModel: FallingHomeViewModel - private var dataSource: UICollectionViewDiffableDataSource! + private var dataSource: DataSource! private lazy var homeView = FallingHomeView() init(viewModel: FallingHomeViewModel) { self.viewModel = viewModel super.init(nibName: nil, bundle: nil) - setupDelegate() } required init?(coder: NSCoder) { @@ -37,15 +36,17 @@ final class FallingHomeViewController: TFBaseViewController { let mindImageView = UIImageView(image: DSKitAsset.Image.Icons.mind.image) let mindImageItem = UIBarButtonItem(customView: mindImageView) - let notificationButtonItem = UIBarButtonItem(image: DSKitAsset.Image.Icons.bell.image, style: .plain, target: nil, action: nil) + let notificationButtonItem = UIBarButtonItem.noti navigationItem.leftBarButtonItem = mindImageItem navigationItem.rightBarButtonItem = notificationButtonItem } override func bindViewModel() { + let timeOverSubject = PublishSubject() + let initialTrigger = Driver.just(()) - let timerOverTrigger = self.rx.timeOverTrigger.asDriver() + let timerOverTrigger = timeOverSubject.asDriverOnErrorJustEmpty() let viewWillAppearTrigger = self.rx.viewWillAppear.map { _ in true }.asDriverOnErrorJustEmpty() let viewWillDisAppearTrigger = self.rx.viewWillDisAppear.map { _ in false }.asDriverOnErrorJustEmpty() @@ -57,7 +58,7 @@ final class FallingHomeViewController: TFBaseViewController { .when(.recognized) .withLatestFrom(timerActiveRelay) { !$1 } .asDriverOnErrorJustEmpty() - + cardDoubleTapTrigger .drive(timerActiveRelay) .disposed(by: disposeBag) @@ -66,71 +67,61 @@ final class FallingHomeViewController: TFBaseViewController { .drive(timerActiveRelay) .disposed(by: disposeBag) - let input = FallingHomeViewModel.Input(initialTrigger: initialTrigger, - timeOverTrigger: timerOverTrigger) + let input = FallingHomeViewModel.Input( + initialTrigger: initialTrigger, + timeOverTrigger: timerOverTrigger) let output = viewModel.transform(input: input) - var usersCount = 0 - - let profileCellRegistration = UICollectionView.CellRegistration { [weak self] cell, indexPath, item in - - let observer = FallingUserCollectionViewCellObserver(userCardScrollIndex: output.userCardScrollIndex.asObservable(), - timerActiveTrigger: timerActiveRelay.asObservable()) + let profileCellRegistration = UICollectionView.CellRegistration { cell, indexPath, item in + let timerActiveTrigger = Driver.combineLatest( + output.nextCardIndexPath, + timerActiveRelay.asDriver() + ) + .filter { itemIndexPath, _ in indexPath == itemIndexPath } + .map { _, timerActiveFlag in timerActiveFlag } - cell.bind(model: item) - cell.bind(observer, - index: indexPath, - usersCount: usersCount) - cell.delegate = self + cell.bind( + FallinguserCollectionViewCellModel(userDomain: item), + timerActiveTrigger, + scrollToNextObserver: timeOverSubject + ) } - - dataSource = UICollectionViewDiffableDataSource(collectionView: homeView.collectionView, cellProvider: { collectionView, indexPath, itemIdentifier in + dataSource = DataSource(collectionView: homeView.collectionView, cellProvider: { collectionView, indexPath, itemIdentifier in return collectionView.dequeueConfiguredReusableCell(using: profileCellRegistration, for: indexPath, item: itemIdentifier) }) + var listCount = 0 + output.userList - .drive(with: self, onNext: { this, list in - usersCount = list.count - var snapshot = NSDiffableDataSourceSnapshot() + .drive(with: self, onNext: { owner, list in + listCount = list.count + var snapshot = Snapshot() snapshot.appendSections([.profile]) snapshot.appendItems(list) - this.dataSource.apply(snapshot) + owner.dataSource.apply(snapshot) }).disposed(by: disposeBag) - - output.userCardScrollIndex - .drive(with: self, onNext: { this, index in - if usersCount == 0 { return } - let index = index >= usersCount ? usersCount - 1 : index - let indexPath = IndexPath(row: index, section: 0) - this.homeView.collectionView.scrollToItem(at: indexPath, - at: .top, - animated: true) - }) + + output.nextCardIndexPath + .drive(with: self, onNext: { owner, indexPath in + guard indexPath.row < listCount else { return } + owner.homeView.collectionView.scrollToItem( + at: indexPath, + at: .top, + animated: true + )}) .disposed(by: self.disposeBag) } - - private func setupDelegate() { - homeView.collectionView.delegate = self - } } -extension FallingHomeViewController: UICollectionViewDelegateFlowLayout { - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return CGSize(width: view.frame.width - 32, - height: (view.frame.width - 32) * 1.64) - } -} +// MARK: DiffableDataSource -extension FallingHomeViewController: TimeOverDelegate { - @objc func scrollToNext() { } -} - -extension Reactive where Base: FallingHomeViewController { - var timeOverTrigger: ControlEvent { - let source = methodInvoked(#selector(Base.scrollToNext)).map { _ in } - return ControlEvent(events: source) - } +extension FallingHomeViewController { + typealias CellType = FallingUserCollectionViewCell + typealias ModelType = FallingUser + typealias SectionType = FallingProfileSection + typealias DataSource = UICollectionViewDiffableDataSource + typealias Snapshot = NSDiffableDataSourceSnapshot } //#if DEBUG @@ -141,9 +132,9 @@ extension Reactive where Base: FallingHomeViewController { // static var previews: some View { // let service = FallingAPI(isStub: true, sampleStatusCode: 200, customEndpointClosure: nil) // let navigator = MainNavigator(controller: UINavigationController(), fallingService: service) -// +// // let viewModel = MainViewModel(navigator: navigator, service: service) -// +// // return FallingHomeViewController(viewModel: viewModel) // .toPreView() // } diff --git a/Projects/Features/Falling/Src/Home/FallingHomeViewModel.swift b/Projects/Features/Falling/Src/Home/FallingHomeViewModel.swift index 7d0bd90e..ef1a0ffc 100644 --- a/Projects/Features/Falling/Src/Home/FallingHomeViewModel.swift +++ b/Projects/Features/Falling/Src/Home/FallingHomeViewModel.swift @@ -10,53 +10,59 @@ import FallingInterface import RxSwift import RxCocoa +import Foundation final class FallingHomeViewModel: ViewModelType { - + private let fallingUseCase: FallingUseCaseInterface - -// weak var delegate: FallingHomeDelegate? - + + // weak var delegate: FallingHomeDelegate? + var disposeBag: DisposeBag = DisposeBag() - + struct Input { let initialTrigger: Driver let timeOverTrigger: Driver } - + struct Output { let userList: Driver<[FallingUser]> - let userCardScrollIndex: Driver + let nextCardIndexPath: Driver } - + init(fallingUseCase: FallingUseCaseInterface) { self.fallingUseCase = fallingUseCase } - + func transform(input: Input) -> Output { let currentIndexRelay = BehaviorRelay(value: 0) let timeOverTrigger = input.timeOverTrigger - + let usersResponse = input.initialTrigger .flatMapLatest { [unowned self] _ in self.fallingUseCase.user(alreadySeenUserUUIDList: [], userDailyFallingCourserIdx: 1, size: 100) .asDriver(onErrorJustReturn: .init(selectDailyFallingIdx: 0, topicExpirationUnixTime: 0, userInfos: [])) } - + let userList = usersResponse.map { $0.userInfos }.asDriver() - - let userListObservable = userList.map { _ in + + let updateUserListTrigger = userList.map { _ in currentIndexRelay.accept(currentIndexRelay.value) } - - let nextScrollIndex = timeOverTrigger.withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0)) { _, index in + + let updateScrollIndexTrigger = timeOverTrigger.withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0)) { _, index in currentIndexRelay.accept(index + 1) } - let userCardScrollIndex = Driver.merge(userListObservable, nextScrollIndex).withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0)) - + let nextCardIndexPath = Driver.merge( + updateUserListTrigger, + updateScrollIndexTrigger + ).withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0) + .map { IndexPath(row: $0, section: 0) }) + return Output( userList: userList, - userCardScrollIndex: userCardScrollIndex) + nextCardIndexPath: nextCardIndexPath + ) } } diff --git a/Projects/Features/Falling/Src/Subviews/CardTimeView.swift b/Projects/Features/Falling/Src/Subviews/CardTimeView.swift index dc90b88b..7a7b505c 100644 --- a/Projects/Features/Falling/Src/Subviews/CardTimeView.swift +++ b/Projects/Features/Falling/Src/Subviews/CardTimeView.swift @@ -14,7 +14,7 @@ final class CardTimeView: TFBaseView { lazy var containerView: UIView = { let view = UIView() view.layer.cornerRadius = 15 - view.backgroundColor = DSKitAsset.Color.dimColor.color.withAlphaComponent(0.5) + view.backgroundColor = DSKitAsset.Color.DimColor.timerDim.color.withAlphaComponent(0.5) return view }() diff --git a/Projects/Features/Falling/Src/Subviews/Cell/FallingUserCollectionViewCell.swift b/Projects/Features/Falling/Src/Subviews/Cell/FallingUserCollectionViewCell.swift index f5aa029c..6a08f73f 100644 --- a/Projects/Features/Falling/Src/Subviews/Cell/FallingUserCollectionViewCell.swift +++ b/Projects/Features/Falling/Src/Subviews/Cell/FallingUserCollectionViewCell.swift @@ -16,86 +16,70 @@ struct FallingUserCollectionViewCellObserver { var timerActiveTrigger: Observable } -@objc protocol TimeOverDelegate: AnyObject { - @objc func scrollToNext() -} - -final class FallingUserCollectionViewCell: TFBaseCollectionViewCell { - - var viewModel: FallinguserCollectionViewCellModel! - weak var delegate: TimeOverDelegate? = nil - +final class FallingUserCollectionViewCell: UserCardViewCollectionViewCell { lazy var profileCarouselView = ProfileCarouselView() lazy var cardTimeView = CardTimeView() - override func layoutSubviews() { - self.backgroundColor = .systemGray - } - override func makeUI() { - self.contentView.addSubviews([profileCarouselView, cardTimeView]) + self.layer.cornerRadius = 20 + + self.contentView.addSubview(profileCarouselView) + self.profileCarouselView.addSubview(cardTimeView) self.profileCarouselView.snp.makeConstraints { $0.edges.equalToSuperview() } self.cardTimeView.snp.makeConstraints { - $0.top.equalTo(self.safeAreaLayoutGuide).inset(12) - $0.leading.trailing.equalToSuperview().inset(12) + $0.top.leading.trailing.equalToSuperview().inset(12) $0.height.equalTo(32) } + + self.showUserCardDimView() } override func prepareForReuse() { super.prepareForReuse() disposeBag = DisposeBag() -// profileCarouselView.tagCollectionView.isHidden = true - } - - func bind(model: FallingUser) { - viewModel = FallinguserCollectionViewCellModel(userDomain: model) - profileCarouselView.bind(viewModel.userDomain) } - - func bind(_ observer: FallingUserCollectionViewCellObserver, - index: IndexPath, - usersCount: Int) { - - let timerActiveTrigger = - observer.userCardScrollIndex - .observe(on: MainScheduler.asyncInstance) - .withLatestFrom(observer.timerActiveTrigger) { userCardScrollIndex, timerActiveTrigger in - if index.row == userCardScrollIndex { - self.profileCarouselView.hiddenDimView() - return observer.timerActiveTrigger -// return timerActiveTrigger - } -// else { return false } - else { return Observable.just(false) } - }.map { $0 } - .flatMapLatest { return $0 } - - let input = FallinguserCollectionViewCellModel.Input(timerActiveTrigger: timerActiveTrigger.asDriver(onErrorJustReturn: false)) - + + func bind( + _ viewModel: FallinguserCollectionViewCellModel, + _ timerTrigger: Driver, + scrollToNextObserver: O + ) where O: ObserverType, O.Element == Void { + let input = FallinguserCollectionViewCellModel.Input(timerActiveTrigger: timerTrigger) + let output = viewModel .transform(input: input) + output.user + .drive(with: self, onNext: { owner, user in + owner.profileCarouselView.bind(user) + }) + .disposed(by: disposeBag) + output.timeState .drive(self.rx.timeState) .disposed(by: self.disposeBag) - + + output.timeStart + .drive(with: self, onNext: { owner, _ in + owner.hiddenUserCardDimView() + }) + .disposed(by: disposeBag) + output.timeZero - .do { [weak self] _ in self?.delegate?.scrollToNext() } - .drive() - .disposed(by: self.disposeBag) - -// profileCarouselView.infoButton.rx.tap.asDriver() -// .scan(true) { lastValue, _ in -// return !lastValue -// } -// .drive(profileCarouselView.tagCollectionView.rx.isHidden) -// .disposed(by: disposeBag) + .drive(scrollToNextObserver) + .disposed(by: disposeBag) + + profileCarouselView.infoButton.rx.tap.asDriver() + .scan(true) { lastValue, _ in + return !lastValue + } + .drive(profileCarouselView.tagCollectionView.rx.isHidden) + .disposed(by: disposeBag) } func dotPosition(progress: Double, rect: CGRect) -> CGPoint { @@ -121,11 +105,11 @@ extension Reactive where Base: FallingUserCollectionViewCell { var timeState: Binder { return Binder(self.base) { (base, timeState) in base.cardTimeView.timerView.trackLayer.strokeColor = timeState.fillColor.color.cgColor - base.cardTimeView.timerView.strokeLayer.strokeColor = timeState.color.color.cgColor - base.cardTimeView.timerView.dotLayer.strokeColor = timeState.color.color.cgColor - base.cardTimeView.timerView.dotLayer.fillColor = timeState.color.color.cgColor - base.cardTimeView.timerView.timerLabel.textColor = timeState.color.color - base.cardTimeView.progressView.progressBarColor = timeState.color.color + base.cardTimeView.timerView.strokeLayer.strokeColor = timeState.timerTintColor.color.cgColor + base.cardTimeView.timerView.dotLayer.strokeColor = timeState.timerTintColor.color.cgColor + base.cardTimeView.timerView.dotLayer.fillColor = timeState.timerTintColor.color.cgColor + base.cardTimeView.timerView.timerLabel.textColor = timeState.timerTintColor.color + base.cardTimeView.progressView.progressBarColor = timeState.progressBarColor.color base.cardTimeView.timerView.dotLayer.isHidden = timeState.isDotHidden diff --git a/Projects/Features/Falling/Src/Subviews/Cell/FallinguserCollectionViewCellModel.swift b/Projects/Features/Falling/Src/Subviews/Cell/FallinguserCollectionViewCellModel.swift index e5efa7ca..1f751a6f 100644 --- a/Projects/Features/Falling/Src/Subviews/Cell/FallinguserCollectionViewCellModel.swift +++ b/Projects/Features/Falling/Src/Subviews/Cell/FallinguserCollectionViewCellModel.swift @@ -42,7 +42,7 @@ enum TimeState { } } - var color: DSKitColors { + var timerTintColor: DSKitColors { switch self { case .zero, .five: return DSKitAsset.Color.primary500 @@ -59,6 +59,23 @@ enum TimeState { } } + var progressBarColor: DSKitColors { + switch self { + case .five: + return DSKitAsset.Color.primary500 + case .four: + return DSKitAsset.Color.thtOrange100 + case .three: + return DSKitAsset.Color.thtOrange200 + case .two: + return DSKitAsset.Color.thtOrange300 + case .one: + return DSKitAsset.Color.thtRed + default: + return DSKitAsset.Color.neutral600 + } + } + var isDotHidden: Bool { switch self { case .initial, .over: @@ -111,9 +128,10 @@ final class FallinguserCollectionViewCellModel: ViewModelType { } struct Output { - let timeState: Driver - let timeZero: Driver let user: Driver + let timeState: Driver + let timeStart: Driver + let timeZero: Driver } func transform(input: Input) -> Output { @@ -135,7 +153,7 @@ final class FallinguserCollectionViewCellModel: ViewModelType { scheduler: MainScheduler.instance) .take(Int(startTime * 100) + 1) // 시간의 총 개수 .map { value in - let time = round((startTime * 100) - Double(value)) / 100 + let time = (startTime * 100 - Double(value)) / 100 currentTime = time return time } @@ -144,12 +162,14 @@ final class FallinguserCollectionViewCellModel: ViewModelType { }.asDriver(onErrorJustReturn: 8.0) let timeState = timer.map { TimeState(rawValue: $0) } - let timeZero = timer.filter { $0 == 0 } - + let timeStart = timer.filter { $0 == 8.0 }.map { _ in } + let timeZero = timer.filter { $0 == 0 }.map { _ in } + return Output( + user: user, timeState: timeState, - timeZero: timeZero, - user: user + timeStart: timeStart, + timeZero: timeZero ) } } diff --git a/Projects/Features/Falling/Src/Subviews/Cell/ProfileCollectionViewCell.swift b/Projects/Features/Falling/Src/Subviews/Cell/ProfileCollectionViewCell.swift index 84cf8709..1e57bc98 100644 --- a/Projects/Features/Falling/Src/Subviews/Cell/ProfileCollectionViewCell.swift +++ b/Projects/Features/Falling/Src/Subviews/Cell/ProfileCollectionViewCell.swift @@ -13,7 +13,7 @@ import DSKit final class ProfileCollectionViewCell: UICollectionViewCell { private lazy var imageView: UIImageView = { let imageView = UIImageView() - imageView.contentMode = .scaleAspectFit + imageView.contentMode = .scaleAspectFill imageView.layer.masksToBounds = true return imageView }() @@ -46,13 +46,7 @@ final class ProfileCollectionViewCell: UICollectionViewCell { guard let url = URL(string: imageURL) else { return } - let random: [DSKitImages] = [DSKitAsset.Image.Test.test1, DSKitAsset.Image.Test.test2] - self.imageView.image = random.randomElement()?.image - -// self.imageView.setResource(url) { [weak self] in -// self?.imageView.sizeToFit() -// self?.imageView.layoutIfNeeded() -// } + self.imageView.kf.setImage(with: url) } } diff --git a/Projects/Features/Falling/Src/Subviews/Cell/ProfileIntroduceCell.swift b/Projects/Features/Falling/Src/Subviews/Cell/ProfileIntroduceCell.swift index fca6368e..a5b37c67 100644 --- a/Projects/Features/Falling/Src/Subviews/Cell/ProfileIntroduceCell.swift +++ b/Projects/Features/Falling/Src/Subviews/Cell/ProfileIntroduceCell.swift @@ -13,8 +13,8 @@ import DSKit final class ProfileIntroduceCell: TFBaseCollectionViewCell { private lazy var textView: UITextView = { let textView = UITextView() - textView.textColor = DSKitAsset.Color.dimColor2.color - textView.font = UIFont.thtP2M +// textView.textColor = DSKitAsset.Color.DimColor.default.color + textView.font = UIFont.thtP2R textView.isScrollEnabled = false textView.isEditable = false textView.textContainerInset = .init(top: 5, left: 5, bottom: 5, right: 5) diff --git a/Projects/Features/Falling/Src/Subviews/ProfileCarouselView.swift b/Projects/Features/Falling/Src/Subviews/ProfileCarouselView.swift index 83f1365d..80b2f0ad 100644 --- a/Projects/Features/Falling/Src/Subviews/ProfileCarouselView.swift +++ b/Projects/Features/Falling/Src/Subviews/ProfileCarouselView.swift @@ -12,6 +12,8 @@ import FallingInterface import Domain final class ProfileCarouselView: TFBaseView { + private var dataSource: UICollectionViewDiffableDataSource! + var photos: [UserProfilePhoto] = [] { didSet { pageControl.currentPage = 0 @@ -24,24 +26,21 @@ final class ProfileCarouselView: TFBaseView { let tagCollection = TagCollectionView() tagCollection.layer.cornerRadius = 20 tagCollection.clipsToBounds = true - tagCollection.collectionView.backgroundColor = DSKitAsset.Color.dimColor2.color + tagCollection.collectionView.backgroundColor = DSKitAsset.Color.DimColor.default.color tagCollection.isHidden = true return tagCollection }() lazy var collectionView: UICollectionView = { - let layout = UICollectionViewFlowLayout() - layout.scrollDirection = .horizontal - layout.minimumLineSpacing = 0 + let layout = UICollectionViewCompositionalLayout.horizontalListLayout() - let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) - collectionView.showsVerticalScrollIndicator = false - collectionView.showsHorizontalScrollIndicator = false - collectionView.dataSource = self - collectionView.delegate = self - collectionView.register(cellType: ProfileCollectionViewCell.self) - collectionView.isPagingEnabled = true - collectionView.backgroundColor = DSKitAsset.Color.neutral50.color + let collectionView = UICollectionView( + frame: .zero, + collectionViewLayout: layout + ) + collectionView.isScrollEnabled = false + collectionView.backgroundColor = DSKitAsset.Color.neutral700.color + collectionView.layer.cornerRadius = 20 return collectionView }() @@ -143,12 +142,7 @@ final class ProfileCarouselView: TFBaseView { $0.bottom.equalToSuperview().offset(-30) } - self.dimView.layer.cornerRadius = 12 - - self.showDimView(frame: CGRect(x: 0, - y: 0, - width: (UIWindow.keyWindow?.frame.width ?? 0) - 32, - height: UIWindow.keyWindow?.frame.height ?? 0)) + configureDataSource() } func bind(_ viewModel: FallingUser) { @@ -160,22 +154,23 @@ final class ProfileCarouselView: TFBaseView { ProfileInfoSection(header: "흥미", items: viewModel.interestResponses), ProfileInfoSection(header: "자기소개", introduce: viewModel.introduction) ] + + var snapshot = NSDiffableDataSourceSnapshot() + snapshot.appendSections([.profile]) + snapshot.appendItems(viewModel.userProfilePhotos) + self.dataSource.apply(snapshot) } } -extension ProfileCarouselView: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { - func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { - return self.bounds.size - } - func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return photos.count - } - - func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { - let cell = collectionView.dequeueReusableCell(for: indexPath, cellType: ProfileCollectionViewCell.self) - let item = photos[indexPath.item] - cell.bind(imageURL: item.url) - return cell +extension ProfileCarouselView { + func configureDataSource() { + let profileCellRegistration = UICollectionView.CellRegistration { cell, indexPath, item in + cell.bind(imageURL: item.url) + } + + dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView, cellProvider: { collectionView, indexPath, itemIdentifier in + return collectionView.dequeueConfiguredReusableCell(using: profileCellRegistration, for: indexPath, item: itemIdentifier) + }) } } diff --git a/Projects/Features/SignUp/Src/SubView/SuccessCertificationView.swift b/Projects/Features/SignUp/Src/SubView/SuccessCertificationView.swift index f980cb05..7ed087bd 100644 --- a/Projects/Features/SignUp/Src/SubView/SuccessCertificationView.swift +++ b/Projects/Features/SignUp/Src/SubView/SuccessCertificationView.swift @@ -31,7 +31,7 @@ final class SuccessCertificationView: UIView { } func makeUI() { - self.backgroundColor = DSKitAsset.Color.dimColor.color + self.backgroundColor = DSKitAsset.Color.DimColor.signUpDim.color self.addSubview(backCardView) diff --git a/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/Contents.json b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/Contents.json new file mode 100644 index 00000000..6e965652 --- /dev/null +++ b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor2.colorset/Contents.json b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/Default.colorset/Contents.json similarity index 75% rename from Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor2.colorset/Contents.json rename to Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/Default.colorset/Contents.json index 74b61cb4..69c422e6 100644 --- a/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor2.colorset/Contents.json +++ b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/Default.colorset/Contents.json @@ -5,9 +5,9 @@ "color-space" : "srgb", "components" : { "alpha" : "0.500", - "blue" : "0x11", - "green" : "0x11", - "red" : "0x11" + "blue" : "0x00", + "green" : "0x00", + "red" : "0x00" } }, "idiom" : "universal" diff --git a/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor.colorset/Contents.json b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/SignUpDim.colorset/Contents.json similarity index 66% rename from Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor.colorset/Contents.json rename to Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/SignUpDim.colorset/Contents.json index 2879a8d0..d1dbdaa9 100644 --- a/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor.colorset/Contents.json +++ b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/SignUpDim.colorset/Contents.json @@ -4,10 +4,10 @@ "color" : { "color-space" : "srgb", "components" : { - "alpha" : "0.800", - "blue" : "0x11", - "green" : "0x11", - "red" : "0x11" + "alpha" : "0.250", + "blue" : "0x00", + "green" : "0x00", + "red" : "0x00" } }, "idiom" : "universal" diff --git a/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/TimerDim.colorset/Contents.json b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/TimerDim.colorset/Contents.json new file mode 100644 index 00000000..0361de7b --- /dev/null +++ b/Projects/Modules/DesignSystem/Resources/Color.xcassets/DimColor/TimerDim.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.500", + "blue" : "0x1A", + "green" : "0x1A", + "red" : "0x1A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Projects/Modules/DesignSystem/Src/BaseView/TFBaseCollectionVIew.swift b/Projects/Modules/DesignSystem/Src/BaseView/TFBaseCollectionViewCell.swift similarity index 100% rename from Projects/Modules/DesignSystem/Src/BaseView/TFBaseCollectionVIew.swift rename to Projects/Modules/DesignSystem/Src/BaseView/TFBaseCollectionViewCell.swift diff --git a/Projects/Modules/DesignSystem/Src/BaseView/TFBaseView.swift b/Projects/Modules/DesignSystem/Src/BaseView/TFBaseView.swift index 1ad711c7..d61502b4 100644 --- a/Projects/Modules/DesignSystem/Src/BaseView/TFBaseView.swift +++ b/Projects/Modules/DesignSystem/Src/BaseView/TFBaseView.swift @@ -10,7 +10,7 @@ import UIKit open class TFBaseView: UIView { public lazy var dimView: UIView = { let view = UIView() - view.backgroundColor = .clear + view.backgroundColor = DSKitAsset.Color.DimColor.default.color return view }() override public init(frame: CGRect) { @@ -27,10 +27,11 @@ open class TFBaseView: UIView { public func showDimView(frame: CGRect = UIWindow.keyWindow?.frame ?? .zero) { dimView.frame = frame - DispatchQueue.main.async { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } self.addSubview(self.dimView) UIView.animate(withDuration: 0.0) { - self.dimView.backgroundColor = DSKitAsset.Color.cardShadow.color.withAlphaComponent(0.7) + self.dimView.backgroundColor = DSKitAsset.Color.cardShadow.color.withAlphaComponent(0.7) } } } @@ -38,9 +39,11 @@ open class TFBaseView: UIView { public func hiddenDimView() { DispatchQueue.main.async { UIView.animate(withDuration: 0.0) { [weak self] in - self?.dimView.backgroundColor = .clear + guard let self = self else { return } + self.dimView.backgroundColor = DSKitAsset.Color.DimColor.default.color } completion: { [weak self] _ in - self?.dimView.removeFromSuperview() + guard let self = self else { return } + self.dimView.removeFromSuperview() } } } diff --git a/Projects/Modules/DesignSystem/Src/BaseView/UserCardViewCollectionViewCell.swift b/Projects/Modules/DesignSystem/Src/BaseView/UserCardViewCollectionViewCell.swift new file mode 100644 index 00000000..d09ca25a --- /dev/null +++ b/Projects/Modules/DesignSystem/Src/BaseView/UserCardViewCollectionViewCell.swift @@ -0,0 +1,48 @@ +// +// UserCardViewCollectionViewCell.swift +// DSKit +// +// Created by SeungMin on 1/31/24. +// + +import UIKit + +open class UserCardViewCollectionViewCell: TFBaseCollectionViewCell { + private let userCardDimView: UIView = { + let userCardWidth = (UIWindow.keyWindow?.bounds.width ?? .zero) - 32 + let view = UIView( + frame: CGRect( + x: 0, + y: 0, + width: userCardWidth, + height: userCardWidth * 1.64 + ) + ) + view.layer.cornerRadius = 20 + return view + }() + + public func showUserCardDimView() { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + self.addSubviews(userCardDimView) + print("DimView added!") + UIView.animate(withDuration: 0.0) { + self.userCardDimView.backgroundColor = DSKitAsset.Color.DimColor.default.color + } + } + } + + public func hiddenUserCardDimView() { + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + UIView.animate(withDuration: 0.0) { + self.userCardDimView.backgroundColor = DSKitAsset.Color.clear.color + } completion: { [weak self] _ in + guard let self = self else { return } + print("Removed DimView!") + self.userCardDimView.removeFromSuperview() + } + } + } +} diff --git a/Projects/Modules/DesignSystem/Src/UIComponent/Cell/ProfileIntroduceCell.swift b/Projects/Modules/DesignSystem/Src/UIComponent/Cell/ProfileIntroduceCell.swift index ce0dfd04..14981661 100644 --- a/Projects/Modules/DesignSystem/Src/UIComponent/Cell/ProfileIntroduceCell.swift +++ b/Projects/Modules/DesignSystem/Src/UIComponent/Cell/ProfileIntroduceCell.swift @@ -11,7 +11,7 @@ public final class ProfileIntroduceCell: TFBaseCollectionViewCell { private lazy var textView: UITextView = { let textView = UITextView() - textView.textColor = DSKitAsset.Color.dimColor2.color + textView.textColor = DSKitAsset.Color.neutral50.color textView.font = UIFont.thtP2M textView.isScrollEnabled = false textView.isEditable = false diff --git a/Projects/Modules/DesignSystem/Src/UIComponent/Cell/TagCell.swift b/Projects/Modules/DesignSystem/Src/UIComponent/Cell/TagCollectionViewCell.swift similarity index 98% rename from Projects/Modules/DesignSystem/Src/UIComponent/Cell/TagCell.swift rename to Projects/Modules/DesignSystem/Src/UIComponent/Cell/TagCollectionViewCell.swift index fca45021..474f7af7 100644 --- a/Projects/Modules/DesignSystem/Src/UIComponent/Cell/TagCell.swift +++ b/Projects/Modules/DesignSystem/Src/UIComponent/Cell/TagCollectionViewCell.swift @@ -1,5 +1,5 @@ // -// TagCell.swift +// TagCollectionViewCell.swift // Falling // // Created by Kanghos on 2023/10/02.