Skip to content

Commit dd5adce

Browse files
committed
[#74]Feat: report 버튼 클릭 시, 타이머를 멈추고 info view를 hidden하고 alert를 표시
- 현재는 차단하기를 했을 떄, 데이터 또는 dataSource에서 item을 삭제하지 않고, 0.5초 후에 scroll하는 방식으로 구현 - dimview를 클릭하면 타이머가 다시 시작되도록 이벤트 전달 - reject 버튼 이벤트는 애니메이션 1초여서 1초후에 다음 유저로 넘어가도록 구현
1 parent 4d4c330 commit dd5adce

File tree

2 files changed

+134
-14
lines changed

2 files changed

+134
-14
lines changed

Projects/Features/Falling/Src/Home/FallingHomeViewController.swift

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@ enum FallingCellButtonAction {
1717
case like(IndexPath)
1818
}
1919

20+
enum TimerActiveAction {
21+
case viewWillDisAppear(Bool)
22+
case profileDoubleTap(Bool)
23+
case reportButtonTap(Bool)
24+
case DimViewTap(Bool)
25+
26+
var state: Bool {
27+
switch self {
28+
case .viewWillDisAppear(let flag), .profileDoubleTap(let flag), .reportButtonTap(let flag), .DimViewTap(let flag):
29+
return flag
30+
}
31+
}
32+
}
33+
34+
enum AnimationAction {
35+
case scroll, delete
36+
}
37+
2038
final class FallingHomeViewController: TFBaseViewController {
2139
private let viewModel: FallingHomeViewModel
2240
private var dataSource: DataSource!
@@ -49,28 +67,46 @@ final class FallingHomeViewController: TFBaseViewController {
4967
}
5068

5169
override func bindViewModel() {
52-
let timeOverSubject = PublishSubject<Void>()
70+
let timeOverSubject = PublishSubject<AnimationAction>()
5371

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

58-
let viewWillDisAppearTrigger = self.rx.viewWillDisAppear.map { _ in false }.asDriverOnErrorJustEmpty()
59-
let timerActiveRelay = BehaviorRelay(value: true)
60-
let profileDoubleTapTriggerObserver = PublishSubject<Void>()
76+
let viewWillDisAppearTrigger = self.rx.viewWillDisAppear.map { _ in
77+
return TimerActiveAction.viewWillDisAppear(false)
78+
}.asDriverOnErrorJustEmpty()
6179

80+
let timerActiveRelay = BehaviorRelay<TimerActiveAction>(value: .profileDoubleTap(true))
81+
82+
let profileDoubleTapTriggerObserver = PublishSubject<Void>()
6283
let profileDoubleTapTrigger = profileDoubleTapTriggerObserver
63-
.withLatestFrom(timerActiveRelay) { !$1 }
84+
.withLatestFrom(timerActiveRelay) {
85+
return TimerActiveAction.profileDoubleTap(!$1.state)
86+
}
87+
.asDriverOnErrorJustEmpty()
88+
89+
let reportButtonTapTriggerObserver = PublishSubject<Void>()
90+
91+
let reportButtonTapTrigger = reportButtonTapTriggerObserver
92+
.withLatestFrom(timerActiveRelay) { _, _ in
93+
return TimerActiveAction.reportButtonTap(false)
94+
}
6495
.asDriverOnErrorJustEmpty()
6596

66-
Driver.merge(profileDoubleTapTrigger, viewWillDisAppearTrigger)
97+
Driver.merge(reportButtonTapTrigger, profileDoubleTapTrigger, viewWillDisAppearTrigger)
6798
.drive(timerActiveRelay)
6899
.disposed(by: disposeBag)
69100

101+
let complaintsButtonTapTrigger = PublishRelay<Void>()
102+
let blockButtonTapTrigger = PublishRelay<Void>()
103+
70104
let input = FallingHomeViewModel.Input(
71105
initialTrigger: initialTrigger,
72106
timeOverTrigger: timerOverTrigger,
73-
cellButtonAction: fallingCellButtonAction.asDriverOnErrorJustEmpty()
107+
cellButtonAction: fallingCellButtonAction.asDriverOnErrorJustEmpty(),
108+
complaintsButtonTapTrigger: complaintsButtonTapTrigger.asDriverOnErrorJustEmpty(),
109+
blockButtonTapTrigger: blockButtonTapTrigger.asDriverOnErrorJustEmpty()
74110
)
75111

76112
let output = viewModel.transform(input: input)
@@ -88,7 +124,8 @@ final class FallingHomeViewController: TFBaseViewController {
88124
timerActiveTrigger: timerActiveTrigger,
89125
timeOverSubject: timeOverSubject,
90126
profileDoubleTapTriggerObserver: profileDoubleTapTriggerObserver,
91-
fallingCellButtonAction: fallingCellButtonAction
127+
fallingCellButtonAction: fallingCellButtonAction,
128+
reportButtonTapTriggerObserver: reportButtonTapTriggerObserver
92129
)
93130
}
94131

@@ -124,7 +161,8 @@ final class FallingHomeViewController: TFBaseViewController {
124161
at: indexPath,
125162
at: .top,
126163
animated: true
127-
)})
164+
)
165+
})
128166
.disposed(by: self.disposeBag)
129167

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

183+
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
184+
timeOverSubject.onNext(.scroll)
185+
}
186+
}
187+
.disposed(by: disposeBag)
188+
189+
reportButtonTapTriggerObserver.asDriverOnErrorJustEmpty()
190+
.do { _ in
191+
self.showAlert(
192+
leftActionTitle: "신고하기",
193+
rightActionTitle: "차단하기",
194+
leftActionCompletion: {
195+
self.showAlert(action: .complaints)
196+
},
197+
rightActionCompletion: {
198+
self.showAlert(
199+
action: .block,
200+
leftActionCompletion: {
201+
blockButtonTapTrigger.accept(())
202+
},
203+
rightActionCompletion: {
204+
timerActiveRelay.accept(.DimViewTap(true))
205+
}
206+
)
207+
},
208+
dimActionCompletion: {
209+
timerActiveRelay.accept(.DimViewTap(true))
210+
}
211+
)
212+
}
213+
.drive()
214+
.disposed(by: disposeBag)
215+
216+
Driver.merge(output.complaintsAction, output.blockAction)
217+
.do { indexPath in
218+
// timerActiveRelay.accept(.DimViewTap(true))
219+
self.deleteItems(indexPath)
145220
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
146-
timeOverSubject.onNext(())
221+
timeOverSubject.onNext(.delete)
222+
timerActiveRelay.accept(.DimViewTap(true))
147223
}
224+
225+
// timerActiveRelay.accept(.DimViewTap(true))
226+
227+
148228
}
229+
.drive()
149230
.disposed(by: disposeBag)
150231
}
151232
}
@@ -158,6 +239,21 @@ extension FallingHomeViewController {
158239
typealias SectionType = FallingProfileSection
159240
typealias DataSource = UICollectionViewDiffableDataSource<SectionType, ModelType>
160241
typealias Snapshot = NSDiffableDataSourceSnapshot<SectionType, ModelType>
242+
243+
private func deleteItems(_ indexPath: IndexPath) {
244+
guard
245+
let item = self.dataSource.itemIdentifier(for: indexPath),
246+
let cell = self.homeView.collectionView.cellForItem(at: indexPath) as? FallingUserCollectionViewCell else { return }
247+
var snapshot = self.dataSource.snapshot()
248+
snapshot.deleteItems([item])
249+
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut) {
250+
cell.transform = cell.transform.rotated(by: -.pi / 6).concatenating(cell.transform.translatedBy(x: cell.frame.minX - self.homeView.collectionView.frame.width, y: 37.62))
251+
} completion: { [weak self] _ in
252+
guard let self = self else { return }
253+
254+
// self.dataSource.apply(snapshot)
255+
}
256+
}
161257
}
162258

163259
//#if DEBUG

Projects/Features/Falling/Src/Home/FallingHomeViewModel.swift

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,19 @@ final class FallingHomeViewModel: ViewModelType {
2222

2323
struct Input {
2424
let initialTrigger: Driver<Void>
25-
let timeOverTrigger: Driver<Void>
25+
let timeOverTrigger: Driver<AnimationAction>
2626
let cellButtonAction: Driver<FallingCellButtonAction>
27+
let complaintsButtonTapTrigger: Driver<Void>
28+
let blockButtonTapTrigger: Driver<Void>
2729
}
2830

2931
struct Output {
3032
let userList: Driver<[FallingUser]>
3133
let nextCardIndexPath: Driver<IndexPath>
3234
let infoButtonAction: Driver<IndexPath>
3335
let rejectButtonAction: Driver<IndexPath>
36+
let complaintsAction: Driver<IndexPath>
37+
let blockAction: Driver<IndexPath>
3438
}
3539

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

60-
let updateScrollIndexTrigger = timeOverTrigger.withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0)) { _, index in
61-
currentIndexRelay.accept(index + 1)
64+
let updateScrollIndexTrigger = timeOverTrigger.withLatestFrom(currentIndexRelay.asDriver(onErrorJustReturn: 0)) { action, index in
65+
switch action {
66+
case .scroll: currentIndexRelay.accept(index + 1)
67+
case .delete: currentIndexRelay.accept(index + 1)
68+
}
6269
}
6370

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

92+
let complaintsAction = input.complaintsButtonTapTrigger.withLatestFrom(currentIndexRelay.asDriver()).map { IndexPath(item: $0, section: 0) }
93+
94+
let blockAction = input.blockButtonTapTrigger
95+
.withLatestFrom(currentIndexRelay.asDriver()).map { index in
96+
let indexPath = IndexPath(item: index, section: 0)
97+
// var mutable = snapshot.value
98+
// if indexPath.item >= mutable.count {
99+
// fatalError("index range")
100+
// }
101+
// let deleted = mutable[indexPath.item]
102+
// mutable.remove(at: indexPath.item)
103+
// snapshot.accept(mutable)
104+
return indexPath
105+
}
106+
85107
return Output(
86108
userList: userList,
87109
nextCardIndexPath: nextCardIndexPath,
88110
infoButtonAction: infoButtonAction,
89-
rejectButtonAction: rejectButtonAction
111+
rejectButtonAction: rejectButtonAction,
112+
complaintsAction: complaintsAction,
113+
blockAction: blockAction
90114
)
91115
}
92116
}

0 commit comments

Comments
 (0)