Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

차단하기 기능 구현 #75

Merged
merged 5 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 106 additions & 10 deletions Projects/Features/Falling/Src/Home/FallingHomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ enum FallingCellButtonAction {
case like(IndexPath)
}

enum TimerActiveAction {
case viewWillDisAppear(Bool)
case profileDoubleTap(Bool)
case reportButtonTap(Bool)
case DimViewTap(Bool)

var state: Bool {
switch self {
case .viewWillDisAppear(let flag), .profileDoubleTap(let flag), .reportButtonTap(let flag), .DimViewTap(let flag):
return flag
}
}
}

enum AnimationAction {
case scroll, delete
}

final class FallingHomeViewController: TFBaseViewController {
private let viewModel: FallingHomeViewModel
private var dataSource: DataSource!
Expand Down Expand Up @@ -49,28 +67,46 @@ final class FallingHomeViewController: TFBaseViewController {
}

override func bindViewModel() {
let timeOverSubject = PublishSubject<Void>()
let timeOverSubject = PublishSubject<AnimationAction>()

let initialTrigger = Driver<Void>.just(())
let timerOverTrigger = timeOverSubject.asDriverOnErrorJustEmpty()
let fallingCellButtonAction = PublishSubject<FallingCellButtonAction>()

let viewWillDisAppearTrigger = self.rx.viewWillDisAppear.map { _ in false }.asDriverOnErrorJustEmpty()
let timerActiveRelay = BehaviorRelay(value: true)
let profileDoubleTapTriggerObserver = PublishSubject<Void>()
let viewWillDisAppearTrigger = self.rx.viewWillDisAppear.map { _ in
return TimerActiveAction.viewWillDisAppear(false)
}.asDriverOnErrorJustEmpty()

let timerActiveRelay = BehaviorRelay<TimerActiveAction>(value: .profileDoubleTap(true))

let profileDoubleTapTriggerObserver = PublishSubject<Void>()
let profileDoubleTapTrigger = profileDoubleTapTriggerObserver
.withLatestFrom(timerActiveRelay) { !$1 }
.withLatestFrom(timerActiveRelay) {
return TimerActiveAction.profileDoubleTap(!$1.state)
}
.asDriverOnErrorJustEmpty()

let reportButtonTapTriggerObserver = PublishSubject<Void>()

let reportButtonTapTrigger = reportButtonTapTriggerObserver
.withLatestFrom(timerActiveRelay) { _, _ in
return TimerActiveAction.reportButtonTap(false)
}
.asDriverOnErrorJustEmpty()

Driver.merge(profileDoubleTapTrigger, viewWillDisAppearTrigger)
Driver.merge(reportButtonTapTrigger, profileDoubleTapTrigger, viewWillDisAppearTrigger)
.drive(timerActiveRelay)
.disposed(by: disposeBag)

let complaintsButtonTapTrigger = PublishRelay<Void>()
let blockButtonTapTrigger = PublishRelay<Void>()

let input = FallingHomeViewModel.Input(
initialTrigger: initialTrigger,
timeOverTrigger: timerOverTrigger,
cellButtonAction: fallingCellButtonAction.asDriverOnErrorJustEmpty()
cellButtonAction: fallingCellButtonAction.asDriverOnErrorJustEmpty(),
complaintsButtonTapTrigger: complaintsButtonTapTrigger.asDriverOnErrorJustEmpty(),
blockButtonTapTrigger: blockButtonTapTrigger.asDriverOnErrorJustEmpty()
)

let output = viewModel.transform(input: input)
Expand All @@ -88,7 +124,8 @@ final class FallingHomeViewController: TFBaseViewController {
timerActiveTrigger: timerActiveTrigger,
timeOverSubject: timeOverSubject,
profileDoubleTapTriggerObserver: profileDoubleTapTriggerObserver,
fallingCellButtonAction: fallingCellButtonAction
fallingCellButtonAction: fallingCellButtonAction,
reportButtonTapTriggerObserver: reportButtonTapTriggerObserver
)
}

Expand Down Expand Up @@ -124,7 +161,8 @@ final class FallingHomeViewController: TFBaseViewController {
at: indexPath,
at: .top,
animated: true
)})
)
})
.disposed(by: self.disposeBag)

output.infoButtonAction
Expand All @@ -142,10 +180,53 @@ final class FallingHomeViewController: TFBaseViewController {
cell.rejectLottieView.isHidden = false
cell.rejectLottieView.play()

DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
timeOverSubject.onNext(.scroll)
}
}
.disposed(by: disposeBag)

reportButtonTapTriggerObserver.asDriverOnErrorJustEmpty()
.do { _ in
self.showAlert(
leftActionTitle: "신고하기",
rightActionTitle: "차단하기",
leftActionCompletion: {
self.showAlert(action: .complaints)
},
rightActionCompletion: {
self.showAlert(
action: .block,
leftActionCompletion: {
blockButtonTapTrigger.accept(())
},
rightActionCompletion: {
timerActiveRelay.accept(.DimViewTap(true))
}
)
},
dimActionCompletion: {
timerActiveRelay.accept(.DimViewTap(true))
}
)
}
.drive()
.disposed(by: disposeBag)

Driver.merge(output.complaintsAction, output.blockAction)
.do { indexPath in
// timerActiveRelay.accept(.DimViewTap(true))
self.deleteItems(indexPath)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
timeOverSubject.onNext(())
timeOverSubject.onNext(.delete)
timerActiveRelay.accept(.DimViewTap(true))
}

// timerActiveRelay.accept(.DimViewTap(true))


}
.drive()
.disposed(by: disposeBag)
}
}
Expand All @@ -158,6 +239,21 @@ extension FallingHomeViewController {
typealias SectionType = FallingProfileSection
typealias DataSource = UICollectionViewDiffableDataSource<SectionType, ModelType>
typealias Snapshot = NSDiffableDataSourceSnapshot<SectionType, ModelType>

private func deleteItems(_ indexPath: IndexPath) {
guard
let item = self.dataSource.itemIdentifier(for: indexPath),
let cell = self.homeView.collectionView.cellForItem(at: indexPath) as? FallingUserCollectionViewCell else { return }
var snapshot = self.dataSource.snapshot()
snapshot.deleteItems([item])
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut) {
cell.transform = cell.transform.rotated(by: -.pi / 6).concatenating(cell.transform.translatedBy(x: cell.frame.minX - self.homeView.collectionView.frame.width, y: 37.62))
} completion: { [weak self] _ in
guard let self = self else { return }

// self.dataSource.apply(snapshot)
}
}
}

//#if DEBUG
Expand Down
32 changes: 28 additions & 4 deletions Projects/Features/Falling/Src/Home/FallingHomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@ final class FallingHomeViewModel: ViewModelType {

struct Input {
let initialTrigger: Driver<Void>
let timeOverTrigger: Driver<Void>
let timeOverTrigger: Driver<AnimationAction>
let cellButtonAction: Driver<FallingCellButtonAction>
let complaintsButtonTapTrigger: Driver<Void>
let blockButtonTapTrigger: Driver<Void>
}

struct Output {
let userList: Driver<[FallingUser]>
let nextCardIndexPath: Driver<IndexPath>
let infoButtonAction: Driver<IndexPath>
let rejectButtonAction: Driver<IndexPath>
let complaintsAction: Driver<IndexPath>
let blockAction: Driver<IndexPath>
}

init(fallingUseCase: FallingUseCaseInterface) {
Expand All @@ -57,8 +61,11 @@ final class FallingHomeViewModel: ViewModelType {
currentIndexRelay.accept(currentIndexRelay.value)
}

let updateScrollIndexTrigger = timeOverTrigger.withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0)) { _, index in
currentIndexRelay.accept(index + 1)
let updateScrollIndexTrigger = timeOverTrigger.withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0)) { action, index in
switch action {
case .scroll: currentIndexRelay.accept(index + 1)
case .delete: currentIndexRelay.accept(index + 1)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 부분은 셀 delete가 가능하도록 처리되면 리팩토링 하겠습니다.

}
}

let nextCardIndexPath = Driver.merge(
Expand All @@ -82,11 +89,28 @@ final class FallingHomeViewModel: ViewModelType {
return nil
}

let complaintsAction = input.complaintsButtonTapTrigger.withLatestFrom(currentIndexRelay.asDriver()).map { IndexPath(item: $0, section: 0) }

let blockAction = input.blockButtonTapTrigger
.withLatestFrom(currentIndexRelay.asDriver()).map { index in
let indexPath = IndexPath(item: index, section: 0)
// var mutable = snapshot.value
// if indexPath.item >= mutable.count {
// fatalError("index range")
// }
// let deleted = mutable[indexPath.item]
// mutable.remove(at: indexPath.item)
// snapshot.accept(mutable)
return indexPath
}

return Output(
userList: userList,
nextCardIndexPath: nextCardIndexPath,
infoButtonAction: infoButtonAction,
rejectButtonAction: rejectButtonAction
rejectButtonAction: rejectButtonAction,
complaintsAction: complaintsAction,
blockAction: blockAction
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,19 +121,30 @@ final class FallingUserCollectionViewCell: TFBaseCollectionViewCell {

func bind<O>(
_ viewModel: FallingUserCollectionViewCellModel,
timerActiveTrigger: Driver<Bool>,
timeOverSubject: PublishSubject<Void>,
timerActiveTrigger: Driver<TimerActiveAction>,
timeOverSubject: PublishSubject<AnimationAction>,
profileDoubleTapTriggerObserver: PublishSubject<Void>,
fallingCellButtonAction: O
fallingCellButtonAction: O,
reportButtonTapTriggerObserver: PublishSubject<Void>
) where O: ObserverType, O.Element == FallingCellButtonAction {
let rejectButtonTrigger = userInfoBoxView.rejectButton.rx.tap.mapToVoid().asDriverOnErrorJustEmpty()
let infoButtonTapTrigger = userInfoBoxView.infoButton.rx.tap.asDriver()

let likeButtonTrigger = userInfoBoxView.likeButton.rx.tap.mapToVoid().asDriverOnErrorJustEmpty()
let rejectButtonTapTrigger = userInfoBoxView.rejectButton.rx.tap.mapToVoid().asDriverOnErrorJustEmpty()

let likeButtonTapTrigger = userInfoBoxView.likeButton.rx.tap.asDriver()

let reportButtonTapTrigger = userInfoView.reportButton.rx.tap.asDriver()

let showUserInfoTrigger = Driver.merge(infoButtonTapTrigger, reportButtonTapTrigger).scan(true) { value, _ in
return !value
}

let input = FallingUserCollectionViewCellModel.Input(
timerActiveTrigger: timerActiveTrigger,
rejectButtonTrigger: rejectButtonTrigger,
likeButtonTrigger: likeButtonTrigger
showUserInfoTrigger: showUserInfoTrigger,
rejectButtonTapTrigger: rejectButtonTapTrigger,
likeButtonTapTrigger: likeButtonTapTrigger,
reportButtonTapTrigger: reportButtonTapTrigger
)

let output = viewModel
Expand All @@ -151,11 +162,8 @@ final class FallingUserCollectionViewCell: TFBaseCollectionViewCell {
.drive(timeOverSubject)
.disposed(by: disposeBag)

output.isTimerActive
.do(onNext: { _ in
self.profileCollectionView.hiddenDimView()
})
.drive(pauseView.rx.isHidden)
output.timerActiveAction
.drive(self.rx.timerActiveAction)
.disposed(by: disposeBag)

let profileDoubleTapTrigger = self.profileCollectionView.rx
Expand All @@ -179,18 +187,10 @@ final class FallingUserCollectionViewCell: TFBaseCollectionViewCell {
.drive(profileDoubleTapTriggerObserver)
.disposed(by: disposeBag)

profileCollectionView.rx.didEndDisplayingCell.asDriver()
.debug()
.drive(with: self) { owner, indexPath in
self.userInfoBoxView.pageControl.currentPage
}
.disposed(by: disposeBag)

userInfoBoxView.infoButton.rx.tap.asDriver()
.scan(true) { value, _ in return !value }
output.showUserInfoAction
.drive(userInfoView.rx.isHidden)
.disposed(by: disposeBag)

output.rejectButtonAction
.compactMap { [weak self] _ in self?.indexPath }
.map { FallingCellButtonAction.reject($0) }
Expand All @@ -202,6 +202,10 @@ final class FallingUserCollectionViewCell: TFBaseCollectionViewCell {
.map { FallingCellButtonAction.like($0) }
.drive(fallingCellButtonAction)
.disposed(by: disposeBag)

output.reportButtonAction
.drive(reportButtonTapTriggerObserver)
.disposed(by: disposeBag)
}

func bind(userProfilePhotos: [UserProfilePhoto]) {
Expand Down Expand Up @@ -276,10 +280,26 @@ extension Reactive where Base: FallingUserCollectionViewCell {
}

var user: Binder<FallingUser> {
return Binder(self.base) { (base, user) in
return Binder(self.base) { base, user in
base.bind(userProfilePhotos: user.userProfilePhotos)
base.userInfoBoxView.bind(user)
base.userInfoView.bind(user)
}
}

var timerActiveAction: Binder<TimerActiveAction> {
return Binder(self.base) { base, action in
if action.state {
base.profileCollectionView.hiddenDimView()
base.pauseView.isHidden = true
} else {
switch action {
case .reportButtonTap, .DimViewTap:
base.pauseView.isHidden = true
case .viewWillDisAppear, .profileDoubleTap:
base.pauseView.isHidden = false
}
}
}
}
}
Loading