rel="diff-71d69b3cb361498d3fe4dc3a4924098112e86887L47">47
-    lazy var currentPhotoIndex = 0
48
-    var isHiddenEnterView = false
52
+    var listViewModel: PhotoDetailListViewModel!
53
+    
49 54
     let disposeBag = DisposeBag()
50
-    static let storyboardCtl = UIStoryboard.photoDetail.instantiateInitialViewController() as! PhotoDetailViewController
51 55
 
52 56
     // MARK: view function
53 57
     override func viewDidLoad() {
54 58
         super.viewDidLoad()
55
-//        detailPageViewModel.tipDelegate = self
56
-//        tableView.tableFooterView = UIView()
57
-        configureNotification()
58
-        
59
-        commentTextField.rx.text
60
-                        .map {!($0?.isEmpty)!}
61
-                        .bind(to: sendBtn.rx.isEnabled)
62
-                        .disposed(by: disposeBag)
59
+        binding()
60
+        setup()
61
+    }
62
+    
63
+    func setup() {
64
+        setupCommentTextField()
65
+        setupWaterMarkView()
63 66
     }
64 67
     
65 68
     func setupCommentTextField() {
66 69
         commentTextField.addLeftPadding(7)
67 70
     }
71
+    
72
+    func setupWaterMarkView() {
73
+        guard let image = UIImage.PhotoDetail.purchaseBackground else { return }
74
+        waterMarkView.backgroundColor = UIColor(patternImage: image)
75
+    }
68 76
 
69 77
     override func viewWillAppear(_ animated: Bool) {
70 78
         super.viewWillAppear(true)
71
-//        titleWithbackBar = "详情"
72
-        navigationController?.isNavigationBarHidden = false
73
-//        refreshUI(index: currentPhotoIndex)
74
-    }
75
-
76
-//    override func backToController() {
77
-//        navigationController?.popViewController(animated: true)
78
-//        if let last = navigationController?.viewControllers[(navigationController?.viewControllers.count)! - 1] as? HomeViewController {
79
-////            last.mainViewModel.models.value = datas
80
-//        }
81
-//
82
-//        if let last = navigationController?.viewControllers[(navigationController?.viewControllers.count)! - 1] as? GroupViewController {
83
-////            last.MineGroupViewModel.models.value = datas
84
-//        }
85
-//    }
86
-
87
-    func configureNotification() {
88
-        do {
89
-//            NotificationCenter.default.rx.notification(Notification.Name(rawValue: WXPayDidFinishNotification)).asObservable().subscribe { (notification) in
90
-//                FFToastView.showLoadingToast(inView: UIApplication.shared.keyWindow!, blockSuperView: true)
91
-//                self.detailPageViewModel.handleResult(errorCode: 0, success: {[weak self](PhotoItem) in
92
-//                    if let weakself = self {
93
-//                        weakself.datas[weakself.currentPhotoIndex].murl = PhotoItem.murl
94
-//                        weakself.datas[weakself.currentPhotoIndex].rurl = PhotoItem.rurl
95
-////                        weakself.showBuyView()
96
-//                        weakself.tableView.reloadRows(at: [IndexPath(item: 0, section: 1)], with: .none)
97
-//                        let fullPicCtl = UIStoryboard.detailBoard.instantiateController(ShowFullPicController.self)
98
-//                        fullPicCtl.datas = weakself.datas
99
-//                        fullPicCtl.currentPhotoIndex = weakself.currentPhotoIndex
100
-//                        fullPicCtl.showNomark = weakself.detailPageViewModel.watermarkPrice != -1
101
-//                        fullPicCtl.showHD = weakself.detailPageViewModel.hdPrice != -1
102
-//                        weakself.navigationController?.pushViewController(fullPicCtl, animated: true)
103
-//                   }
104
-//                })
105
-//                }.disposed(by: disposeBag)
106
-        }
107
-        do {
108
-//            NotificationCenter.default.rx.notification(Notification.Name.UIKeyboardWillShow)
109
-//                .asObservable()
110
-//                .subscribe({ (notification) in
111
-//                    guard let info = notification.element?.userInfo, let avalue = info[UIKeyboardFrameEndUserInfoKey] else {
112
-//                        return
113
-//                    }
114
-//
115
-//                    let height = (avalue as AnyObject).cgRectValue.size.height
116
-//                    self.returnKeyboarAction(notification.element!, height: height)
117
-//                }).disposed(by: disposeBag)
118
-        }
119
-
120
-        do {
121
-            NotificationCenter.default.rx.notification(UIResponder.keyboardWillHideNotification)
122
-                .asObservable()
123
-                .subscribe({ (notification) in
124
-                    self.returnKeyboarAction(notification.element!, height: 0)
125
-                }).disposed(by: disposeBag)
126
-        }
127
-
79
+        viewModel.viewWillAppear.accept(())
128 80
     }
81
+}
129 82
 
130
-    // MARK: refresh interface
131
-    func refreshUI(index: Int) {
132
-        currentPhotoIndex = index
133
-//        detailPageViewModel.currentPhoto = datas[index]
134
-
135
-//        detailPageViewModel.fetchThumbup(success: {[weak self] in
136
-//            if let weakself = self {
137
-//                var model = weakself.datas[index]
138
-//                model.thumbup_num =  weakself.detailPageViewModel.thumbups.count
139
-//                weakself.datas[index] = model
140
-////                PhotoLocalStorage.instance.updateLocalData(PhotoItem: model)
141
-//                weakself.reloadSection(inter: 3)
142
-//            }
143
-//        })
144
-//        detailPageViewModel.fetchComment(success: {[weak self] in
145
-//            if let weakself = self {
146
-//
147
-//                var model = weakself.datas[index]
148
-//                model.comment_num =  weakself.detailPageViewModel.comments.count
149
-//                weakself.datas[index] = model
150
-////                PhotoLocalStorage.instance.updateLocalData(PhotoItem: model)
151
-//                weakself.reloadSection(inter: 4)
152
-//            }
153
-//        })
83
+//MARK textField delegate
84
+extension PhotoDetailViewController: UIGestureRecognizerDelegate {
85
+    // MARK: textField
154 86
 
155
-//        reloadSection(inter: 0)
156
-//        reloadSection(inter: 2)
157
-        showBuyView()
87
+    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
88
+        return commentTextField.isFirstResponder
158 89
     }
90
+    
91
+}
159 92
 
160
-    func showBuyView() {
161
-//        if detailPageViewModel.currentPhoto.photo_from == kPhotographerMark && detailPageViewModel.currentPhoto.display_payment_btn == 1 {
162
-//            buyView.isHidden = false
163
-//            detailPageViewModel.hdPrice = -0.01
164
-//            detailPageViewModel.watermarkPrice = -0.01
165
-//            shuiyinLabel.text = !detailPageViewModel.currentPhoto.murl.isEmpty ? "查看无水印图" : "去除水印"
166
-//            shuiyinImage.isHidden = false
167
-//        } else {
168
-//            buyView.isHidden = true
169
-//        }
170
-    }
171 93
 
172
-    // MARK: Storyboard  button function
173
-    @IBAction func HDPay(_ sender: UIButton) {
174
-//        detailPageViewModel.getHD (getPriceSuccess: { [weak self] (isExist) in
175
-//            if let weakself = self {
176
-//                if isExist {
177
-//                    let fullPicCtl = UIStoryboard(name: "Detail", bundle: nil).instantiateController(ShowFullPicController.self)
178
-//                    fullPicCtl.datas = [weakself.datas[weakself.currentPhotoIndex]]
179
-//                    fullPicCtl.showNomark = true
180
-//                    fullPicCtl.currentPhotoIndex = weakself.currentPhotoIndex
181
-//                    weakself.navigationController?.pushViewController(fullPicCtl, animated: true)
182
-//                } else {
183
-//                }
184
-//            }
185
-//        })
94
+/// bind storyboard gesture action
95
+extension PhotoDetailViewController {
96
+    @IBAction func purchase(_ sender: UITapGestureRecognizer) {
97
+        
186 98
     }
187
-
188
-    @IBAction func waterMarkPay(_ sender: UIButton) {
189
-
190
-//        detailPageViewModel.getWatermark (getPriceSuccess: { [weak self] (isExist) in
191
-//            if let weakself = self {
192
-//                if isExist {
193
-//                    let fullPicCtl = UIStoryboard(name: "Detail", bundle: nil).instantiateController(ShowFullPicController.self)
194
-//                    fullPicCtl.datas = weakself.datas
195
-//                    fullPicCtl.showNomark = true
196
-//                    fullPicCtl.currentPhotoIndex = weakself.currentPhotoIndex
197
-//                    weakself.navigationController?.pushViewController(fullPicCtl, animated: true)
198
-//                } else {
199
-//                    weakself.shuiyinImage.isHidden = true
200
-//                    weakself.shuiyinLabel.text = "¥\((weakself.detailPageViewModel.watermarkPrice/100))"
201
-//                }
202
-//            }
203
-//        })
99
+    
100
+    @IBAction func enterGroup(_ sender: UITapGestureRecognizer) {
101
+        self.viewModel.navigateToGroup()
204 102
     }
103
+}
205 104
 
105
+/// bind storyboard button action
106
+extension PhotoDetailViewController {
206 107
     @IBAction func share() {
207 108
         let ctl = UIStoryboard.photoDetail.instantiateController(ShareController.self)
208 109
         ctl.shareContent = "我使用拍爱分享了一张美图,你也快来试试吧"
209
-        ctl.shareImgUrlThumb = datas[currentPhotoIndex].photo_thumbnail_url
210
-        ctl.shareUrl = datas[currentPhotoIndex].photo_share_url
110
+        //        ctl.shareImgUrlThumb = datas[currentPhotoIndex].photo_thumbnail_url
111
+        //        ctl.shareUrl = datas[currentPhotoIndex].photo_share_url
211 112
         presentController(ctl)
212 113
     }
213
-
114
+    
214 115
     @IBAction func comment() {
215
-        commentView.isHidden = false
216 116
         commentTextField.becomeFirstResponder()
117
+        
217 118
     }
218
-
119
+    
219 120
     @IBAction func sendComment() {
220
-        guard let text = commentTextField.text else {
221
-            return
222
-        }
223
-//        detailPageViewModel.sendComment(content: text, success: { [weak self] in
224
-//            if let weakself = self {
225
-//                weakself.commentTextField.text = ""
226
-//                weakself.commentTextField.resignFirstResponder()
227
-//                weakself.commentView.isHidden = true
228
-//                weakself.refreshUI(index: weakself.currentPhotoIndex)
229
-//            }
230
-//        })
121
+        guard let text = commentTextField.text else { return }
122
+        
123
+        viewModel.submitComment(text: text)
124
+        commentTextField.resignFirstResponder()
231 125
     }
232
-
126
+    
233 127
     @IBAction func thumbup() {
234
-//        detailPageViewModel.sendThumbup(success: {[weak self]  in
235
-//            if let weakself = self {
236
-//                weakself.refreshUI(index: weakself.currentPhotoIndex)
237
-//            }
238
-//
239
-//        })
128
+        viewModel.submitThumbup()
240 129
     }
130
+}
241 131
 
242
-    // MARK: custom function
243
-    func reloadSection(inter: Int) {
244
-        tableView.beginUpdates()
245
-        let indexSet = IndexSet(integer: inter)
246
-        tableView.reloadSections(indexSet, with: .none)
247
-        tableView.endUpdates()
132
+/// bind rx
133
+extension PhotoDetailViewController {
134
+    
135
+    var commentTableViewDataSource: RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoCommentItem>> {
136
+        return RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoCommentItem>>(configureCell: { (dataSource, tableView, indexPath, item) in
137
+            let cell = tableView.dequeueReusableCell(withIdentifier: "photoDetailCommentCell", for: indexPath) as! PhotoDetailCommentCell
138
+            cell.setInfo(item)
139
+            return cell
140
+        })
248 141
     }
249
-
250
-    @objc func showThumps() {
251
-//        if detailPageViewModel.thumbupsCount > 0 {
252
-//            detailPageViewModel.thumbupsCount = 0
253
-//        } else {
254
-//            detailPageViewModel.thumbupsCount = detailPageViewModel.thumbups.count
255
-//        }
256
-        reloadSection(inter: 3)
257
-    }
258
-    @objc func showComments() {
259
-//        if detailPageViewModel.commentsCount > 0 {
260
-//            detailPageViewModel.commentsCount = 0
261
-//        } else {
262
-//            detailPageViewModel.commentsCount = detailPageViewModel.comments.count
263
-//        }
264
-        reloadSection(inter: 4)
142
+    
143
+    var photoCollectionViewDataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>> {
144
+        return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>>(configureCell: { (dataSource, collectionView, indexPath, item) in
145
+            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoDetailImageCell", for: indexPath) as! PhotoDetailImageCell
146
+            cell.imageView.setImage(item.photo_thumbnail2_url, placeholder: UIImage.photoPlaceholder)
147
+            return cell
148
+        })
265 149
     }
266
-
267
-    @objc func loadReportController() {
268
-//        let ctl = UIStoryboard.photoDetail.instantiateController(ReportController.self)
269
-//        presentController(ctl)
150
+    
151
+    func binding() {
152
+        bindEnterGroupViewHiddenState()
153
+        bindViewModelToGroupName()
154
+        bindViewModelToGroupAvatar()
155
+        
156
+        bindViewModelToUserName()
157
+        bindgingViewModelToUserAvatar()
158
+        
159
+        bindViewModelToThumbupCount()
160
+        bindViewModelToThumbupView()
161
+        
162
+        bindViewModelToCommentCount()
163
+        bindViewModelToCommentTableView()
164
+        
165
+        bindBuyViewIsVisiable()
166
+        
167
+        bindCommentTextFieldToSendBtn()
168
+        
169
+        bindCollectionViewDelegate()
170
+        bindCollectionViewSelected()
171
+        bindCollectionViewToListViewModel()
172
+        bindListViewModelToCollectionView()
173
+        
174
+        bindViewWillAppear()
175
+        
176
+        monitorKeyboardWillShow()
177
+        monitorKeyboardWillHide()
270 178
     }
271
-
272
-    func returnKeyboarAction(_ notification: Notification, height: CGFloat) {
273
-        guard let info = (notification as NSNotification).userInfo, let duration = info[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval else {
274
-            return
275
-        }
276
-
277
-        UIView.animate(withDuration: duration, animations: {() -> Void in
278
-                self.commentHeight.constant = height
279
-                self.commentView.superview!.layoutIfNeeded()
280
-        })
179
+    
180
+    func bindEnterGroupViewHiddenState() {
181
+        viewModel.isHiddenEnterGroupBtn.bind(to: enterGroupView.rx.isHidden).disposed(by: disposeBag)
281 182
     }
282
-
283
-    // MARK: deinit
284
-    deinit {
285
-        NotificationCenter.default.removeObserver(self)
183
+    
184
+    func bindViewModelToGroupName() {
185
+        viewModel.groupName.bind(to: groupName.rx.text).disposed(by: disposeBag)
286 186
     }
287
-
288
-}
289
-
290
-// MARK: custom delegate function
291
-extension PhotoDetailViewController: CellDelegate {
292
-    func selectIndex(indexpath: IndexPath) {
293
-        let ctl = UIStoryboard.photoDetail.instantiateController(ShowFullPicController.self)
294
-        ctl.datas = datas
295
-        ctl.currentPhotoIndex = currentPhotoIndex
296
-        show(ctl, sender: nil)
187
+    
188
+    func bindViewModelToGroupAvatar() {
189
+        viewModel.groupAvatar
190
+            .subscribe(onNext: {[weak self] (avatar) in
191
+            guard let `self` = self else { return }
192
+            self.groupAvatar.setImage(avatar)
193
+        }).disposed(by: disposeBag)
297 194
     }
298
-
299
-    func returnCurrentIndex(index: Int) {
300
-        refreshUI(index: index)
195
+    
196
+    func bindgingViewModelToUserAvatar() {
197
+        viewModel.userAvatar
198
+            .subscribe(onNext: {[weak self] (avatar) in
199
+                guard let `self` = self else { return }
200
+                self.userAvatar.setImage(avatar)
201
+            }).disposed(by: disposeBag)
301 202
     }
302
-
303
-    func pushNext() {
304
-        let ctl = UIStoryboard.main.instantiateController(GroupViewController.self)
305
-
306
-//        ctl.groupModel = GroupModel(map: Map(mappingType: .fromJSON, JSON: datas[currentPhotoIndex].toJSON()))
307
-        show(ctl, sender: nil)
203
+    
204
+    func bindViewModelToUserName() {
205
+        viewModel.groupName.bind(to: userName.rx.text).disposed(by: disposeBag)
308 206
     }
309
-}
310
-
311
-//MARK textField delegate
312
-extension PhotoDetailViewController: UIGestureRecognizerDelegate {
313
-    // MARK: textField
314
-
315
-    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
316
-        return commentTextField.isFirstResponder
207
+    
208
+    func bindViewModelToPhotoTime() {
209
+        viewModel.photoTime.bind(to: photoTime.rx.text).disposed(by: disposeBag)
317 210
     }
318
-
319
-    @IBAction func ReturnKeyboard(_ sender: UITapGestureRecognizer) {
320
-        if !commentView.isHidden {
321
-            commentTextField.resignFirstResponder()
322
-            commentView.isHidden = true
323
-        }
211
+    
212
+    func bindViewModelToThumbupCount() {
213
+        viewModel.thumbupCount.bind(to: thumbupCount.rx.text).disposed(by: disposeBag)
324 214
     }
325
-
326
-}
327
-
328
-// MARK: UITableView delegate
329
-extension PhotoDetailViewController: UITableViewDataSource, UITableViewDelegate {
330
-
331
-    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
332
-        if section == 3 {
333
-            let cell = tableView.dequeueReusableCell(withIdentifier: "thumbupHeadCell")
334
-            if let label = cell?.viewWithTag(1001) as? UILabel {
335
-//                label.text = "(\(detailPageViewModel.thumbups.count))"
336
-            }
337
-            if let button = cell?.viewWithTag(1011) as? UIButton {
338
-                button.addTarget(self, action: #selector(showThumps), for: .touchUpInside)
339
-            }
340
-            if let imageView = cell?.viewWithTag(1008) as? UIImageView {
341
-//                let imageName = detailPageViewModel.thumbupsCount <= 0 ? "收起" : "list-arrow"
342
-//                imageView.image = UIImage(named : imageName)
343
-            }
344
-            return cell?.contentView
345
-        } else if section == 4 {
346
-            let cell = tableView.dequeueReusableCell(withIdentifier: "comentHeadCell")
347
-            if let label = cell?.viewWithTag(1002) as? UILabel {
348
-//                label.text = "(\(detailPageViewModel.comments.count))"
349
-            }
350
-            if let button = cell?.viewWithTag(1012) as? UIButton {
351
-                button.addTarget(self, action: #selector(showComments), for: .touchUpInside)
352
-            }
353
-            if let imageView = cell?.viewWithTag(1009) as? UIImageView {
354
-//                let imageName = detailPageViewModel.commentsCount <= 0 ? "收起" : "list-arrow"
355
-//                imageView.image = UIImage(named : imageName)
356
-            }
357
-            return cell?.contentView
358
-        }
359
-        return nil
215
+    
216
+    func bindViewModelToThumbupView() {
217
+        viewModel.thumbupItems
218
+            .asDriver(onErrorJustReturn: [])
219
+            .drive(onNext: { [weak self] (items) in
220
+                self?.setupThumbupView(items: items)
221
+            }).disposed(by: disposeBag)
360 222
     }
361
-
362
-    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
363
-        if section == 3 || section == 4 {
364
-            return 44
365
-        }
366
-        return 0
223
+    
224
+    func bindViewModelToCommentCount() {
225
+        viewModel.commentCount.bind(to: commentCount.rx.text).disposed(by: disposeBag)
367 226
     }
368
-
369
-    func numberOfSections(in tableView: UITableView) -> Int {
370
-        return 0
227
+    
228
+    func bindViewModelToCommentTableView() {
229
+        viewModel.commentItems
230
+            .bind(to: commentTableView.rx.items(dataSource: commentTableViewDataSource))
231
+            .disposed(by: disposeBag)
371 232
     }
372
-
373
-    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
374
-//        if section == 3 {
375
-//            return detailPageViewModel.thumbupsCount > 0 ? 1 : 0
376
-//        } else if section == 4 {
377
-//            return detailPageViewModel.commentsCount
378
-//        }
379
-        return 0
233
+    
234
+    func bindBuyViewIsVisiable() {
235
+        viewModel.canBuy.map { !$0 }.bind(to: buyView.rx.isHidden).disposed(by: disposeBag)
380 236
     }
381
-
382
-    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
383
-        if indexPath.section == 0 {
384
-            let cell = tableView.dequeueReusableCell(withIdentifier: "headCell", for: indexPath) as! DetailPageHeadCell
385
-            cell.enterView.isHidden = isHiddenEnterView
386
-//            cell.setInfo(datas[currentPhotoIndex])
387
-            cell.delegate = self
388
-            if let reportBtn = cell.viewWithTag(40001) as? UIButton {
389
-
390
-                reportBtn.addTarget(self, action: #selector(loadReportController), for: .touchUpInside)
391
-//                reportBtn.isHidden = !(UserDefaults.Account.bool(forKey: .isAudit))
392
-            }
393
-            return cell
394
-        } else if indexPath.section == 1 {
395
-            let cell = tableView.dequeueReusableCell(withIdentifier: "detailPagePhotoCell", for: indexPath) as! DetailPagePhotoCell
396
-//            cell.datas = datas
397
-//            cell.currentPhotoIndex = currentPhotoIndex
398
-            cell.delegate = self
399
-            cell.first = true
400
-            cell.collectionView.reloadData()
401
-            return cell
402
-        } else if indexPath.section == 2 {
403
-            let cell = tableView.dequeueReusableCell(withIdentifier: "nameCell", for: indexPath) as! DetailPageNameCell
404
-//            cell.setInfo(datas[currentPhotoIndex])
405
-            return cell
406
-        } else if indexPath.section == 3 {
407
-            let cell = tableView.dequeueReusableCell(withIdentifier: "thumbupCell", for: indexPath) as! DetailthumbupImagesCell
408
-//            if detailPageViewModel.thumbups.count > 0 {
409
-//                let headers = detailPageViewModel.thumbups.map {$0.avatar}
410
-//                cell.setInfo(content: headers)
411
-//            }
412
-            return cell
413
-        } else {
414
-            let cell = tableView.dequeueReusableCell(withIdentifier: "comentCell", for: indexPath) as! DetailCommentCell
415
-//            cell.setInfo(detailPageViewModel.comments[indexPath.row])
416
-            return cell
417
-        }
237
+    
238
+    func bindCommentTextFieldToSendBtn() {
239
+        commentTextField.rx.text
240
+            .map { !($0?.isEmpty)! }
241
+            .bind(to: sendBtn.rx.isEnabled)
242
+            .disposed(by: disposeBag)
243
+    }
244
+    
245
+    func bindCollectionViewDelegate() {
246
+        photoCollectionView.rx.setDelegate(self).disposed(by: disposeBag)
247
+        
248
+    }
249
+    
250
+    func bindListViewModelToCollectionView() {
251
+        listViewModel.content
252
+            .bind(to: photoCollectionView.rx.items(dataSource: photoCollectionViewDataSource))
253
+            .disposed(by: disposeBag)
254
+    }
255
+    
256
+    func bindCollectionViewToListViewModel() {
257
+        photoCollectionView.rx.willDisplayCell
258
+            .asDriver()
259
+            .drive(onNext: { [unowned self] in
260
+                self.listViewModel.willShow(index: $0.at.row)
261
+            })
262
+            .disposed(by: disposeBag)
263
+    }
264
+    
265
+    func bindCollectionViewSelected() {
266
+        photoCollectionView.rx.itemSelected
267
+            .asDriver(onErrorJustReturn: IndexPath(item: 0, section: 0))
268
+            .drive(onNext: { [unowned self] _ in self.listViewModel.didSelected() })
269
+            .disposed(by: disposeBag)
270
+    }
271
+    
272
+    func bindViewWillAppear() {
273
+        viewModel.viewWillAppear
274
+            .asDriver()
275
+            .drive(onNext: { [unowned self] _ in
276
+                self.photoCollectionView.scrollToItem(at: IndexPath(item: self.listViewModel.currIndex, section: 0), at: .right, animated: false)
277
+            })
278
+            .disposed(by: disposeBag)
418 279
     }
280
+    
281
+    func monitorKeyboardWillShow() {
282
+        NotificationCenter.default.rx
283
+            .notification(UIResponder.keyboardWillShowNotification)
284
+            .takeUntil(self.rx.deallocated)
285
+            .subscribe { [unowned self] notification in
286
+                guard let userInfo = notification.element?.userInfo,
287
+                    let keyboardFrame = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect,
288
+                    let timeInterval = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval,
289
+                    let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int
290
+                    else { return }
291
+                UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: curve) ?? .linear)
292
+                UIView.animate(withDuration: timeInterval, animations: {
293
+                    self.commentEditYConstraint.constant = keyboardFrame.height
294
+                    self.view.layoutIfNeeded()
295
+                })
296
+        }.disposed(by: disposeBag)
297
+    }
298
+    
299
+    func monitorKeyboardWillHide() {
300
+        NotificationCenter.default.rx
301
+            .notification(UIResponder.keyboardWillHideNotification)
302
+            .takeUntil(self.rx.deallocated)
303
+            .subscribe { [unowned self] notification in
304
+                guard let userInfo = notification.element?.userInfo,
305
+                    let timeInterval = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval,
306
+                    let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? Int
307
+                    else { return }
308
+                UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: curve) ?? .linear)
309
+                UIView.animate(withDuration: timeInterval, animations: {
310
+                    self.commentEditYConstraint.constant = -56
311
+                    self.view.layoutIfNeeded()
312
+                })
313
+                self.commentTextField.clear()
314
+        }.disposed(by: disposeBag)
315
+    }
316
+}
419 317
 
420
-    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
421
-        if indexPath.section == 0 {
422
-            return 48
423
-        } else if indexPath.section == 1 {
424
-            return 360
425
-        } else if indexPath.section == 2 {
426
-            return 36
427
-        } else if indexPath.section == 3 {
428
-            return 40
429
-        } else {
430
-//            return 40 + detailPageViewModel.comments[indexPath.row].cellHeigth
431
-            return 40
318
+extension PhotoDetailViewController {
319
+    func setupThumbupView(items: [PhotoThumbupUserItem]) {
320
+        thumbupView.subviews.forEach { $0.removeFromSuperview() }
321
+        
322
+        let row = (Int(kScreenWidth) - 6) / 34
323
+        var topConstraint: CGFloat = 6
324
+        var last: UIImageView?
325
+        
326
+        for (index, item) in items.enumerated() {
327
+            let imageView = UIImageView()
328
+            imageView.cornerRadius = 5
329
+            imageView.translatesAutoresizingMaskIntoConstraints = false
330
+            imageView.setImage(item.avatar, placeholder: UIImage.defaultAvatar)
331
+            thumbupView.addSubview(imageView)
332
+            
333
+            if index % row == 0 && index != 0 {
334
+                topConstraint += 28 + 6
335
+                last = nil
336
+            }
337
+            
338
+            NSLayoutConstraint.activate([
339
+                imageView.widthAnchor.constraint(equalToConstant: 28),
340
+                imageView.heightAnchor.constraint(equalToConstant: 28),
341
+                imageView.topAnchor.constraint(equalTo: thumbupView.topAnchor, constant: topConstraint),
342
+                imageView.leadingAnchor.constraint(equalTo: last?.trailingAnchor ?? thumbupView.leadingAnchor, constant: 6)
343
+                ])
344
+            
345
+            last = imageView
432 346
         }
347
+        thumbupViewHeightConstraint.constant = items.isEmpty ? 1 : topConstraint + 34
348
+        commentTableView.tableHeaderView?.height = 532 + thumbupViewHeightConstraint.constant
433 349
     }
434 350
 }
435 351
 
436
-extension PhotoDetailViewController {
352
+extension PhotoDetailViewController: UICollectionViewDelegateFlowLayout {
353
+    func collectionView(_ collectionView: UICollectionView,
354
+                        layout collectionViewLayout: UICollectionViewLayout,
355
+                        sizeForItemAt indexPath: IndexPath) -> CGSize {
356
+        return CGSize(width: kScreenWidth, height: 359)
357
+    }
437 358
     
359
+    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
360
+        return 0
361
+    }
438 362
 }
363
+
364
+extension PhotoDetailViewController: NavigationBackViewController {}

+ 90 - 75
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoPreviewViewController.swift

@@ -1,5 +1,5 @@
1 1
 //
2
-//  ShowFullPicController.swift
2
+//  PhotoPreviewViewController.swift
3 3
 //  PaiAi
4 4
 //
5 5
 //  Created by zhengjianfei on 16/4/9.
@@ -9,49 +9,104 @@
9 9
 import UIKit
10 10
 import PaiaiDataKit
11 11
 import PaiaiUIKit
12
+import RxCocoa
13
+import RxSwift
14
+import RxDataSources
12 15
 
13
-final class ShowFullPicController: UIViewController {
16
+final class PhotoPreviewViewController: UIViewController {
14 17
 
15
-    // MARK: Storyboard property
18
+    /// MARK: Storyboard property
16 19
     @IBOutlet weak var collectionView: UICollectionView!
17
-//    @IBOutlet weak var progressView: FFProgress!
18
-   // MARK: parameter property
19
-    lazy var datas = [PhotoItem]()
20
-    lazy var currentPhotoIndex = 0
21
-    lazy var firstLayout = true
22
-    lazy var currentPageIndex = 0
23
-    lazy var showNomark = false
24
-    lazy var showHD = false
25
-
26
-    var shufflingImage = [String]()
27
-
28
-    // MARK: Controller fucntion
20
+    var viewModel: PhotoDetailListViewModel!
21
+    var disposeBag = DisposeBag()
22
+    
23
+    override var prefersStatusBarHidden: Bool {
24
+        return true
25
+    }
26
+    
29 27
     override func viewDidLoad() {
30 28
         super.viewDidLoad()
31
-        navigationController?.isNavigationBarHidden = true
32
-//        titleWithbackBar = ""
33
-
34
-     }
35
-
36
-    override func viewDidLayoutSubviews() {
37
-        if firstLayout {
38
-            collectionView.contentOffset = CGPoint(x: (CGFloat(currentPhotoIndex) * (collectionView.width)), y: 0)
39
-            firstLayout = false
29
+        binding()
30
+        scrollToSpecifiedImage()
31
+        navigationController?.setNavigationBarHidden(true, animated: true)
32
+        
33
+    }
34
+    
35
+    func scrollToSpecifiedImage() {
36
+        collectionView.layoutIfNeeded()
37
+        collectionView.scrollToItem(at: IndexPath(item: viewModel.currIndex, section: 0), at: .right, animated: false)
38
+    }
39
+    
40
+    override func viewDidAppear(_ animated: Bool) {
41
+        super.viewWillAppear(animated)
42
+        bindCollectionViewToViewModel()
43
+    }
44
+    
45
+    override func viewWillDisappear(_ animated: Bool) {
46
+        super.viewWillDisappear(animated)
47
+        navigationController?.setNavigationBarHidden(false, animated: true)
48
+    }
49
+    
50
+    @IBAction func download(_ sender: UIButton) {
51
+        guard let cell = collectionView.cellForItem(at: IndexPath(item: viewModel.currIndex, section: 0)) as? ImageCell,
52
+            let image = cell.photoImage.image else {
53
+                //            FFToastView.showToast(inView: view, withText: "未检测到图片")
54
+                return
40 55
         }
41
-        super.viewDidLayoutSubviews()
56
+        
57
+        UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
42 58
     }
59
+    
60
+    @objc func image(_ image: UIImage?, didFinishSavingWithError error: NSError?, contextInfo info: UnsafeMutableRawPointer) {
61
+        if error != nil {
62
+            //            FFToastView.showToast(inView: view, withText: "保存图片失败")
63
+        } else {
64
+            //            FFToastView.showImageToast(inView: view, withText: "已保存图片到相册", withImage: "提示弹窗-勾")
65
+        }
66
+    }
67
+}
68
+
69
+/// binding
70
+extension PhotoPreviewViewController {
71
+    
72
+    var dataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>> {
73
+        return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>>(configureCell: { (dataSource, collectionView, indexPath, item) in
74
+            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCell
75
+            cell.setModel(url: item.murl.isEmpty ? item.photo_url : item.murl)
76
+            return cell
77
+        })
78
+    }
79
+    
80
+    func binding() {
81
+        bindViewModelToCollectionView()
82
+        bindCollectionViewDelegate()
83
+    }
84
+    
85
+    func bindViewModelToCollectionView() {
86
+        viewModel.content
87
+            .bind(to: collectionView.rx.items(dataSource: dataSource))
88
+            .disposed(by: disposeBag)
89
+    }
90
+    
91
+    func bindCollectionViewDelegate() {
92
+        collectionView.rx.setDelegate(self).disposed(by: disposeBag)
93
+    }
94
+    
95
+    func bindCollectionViewToViewModel() {
96
+        collectionView.rx.willDisplayCell
97
+            .asDriver()
98
+            .drive(onNext: { [unowned self] in self.viewModel.willShow(index: $0.at.row) })
99
+            .disposed(by: disposeBag)
100
+    }
101
+}
43 102
 
44
-    // MARK: Storyboard  button function
103
+/// storyboard button action
104
+extension PhotoPreviewViewController {
45 105
     @IBAction  func back() {
46
-         _ = navigationController?.popViewController(animated: true)
47
-        guard let ctl = navigationController?.viewControllers.last as? PhotoDetailViewController else {
48
-            return
49
-        }
50
-//        ctl.currentPhotoIndex = currentPageIndex
51
-//        ctl.tableView.reloadData()
106
+        navigationController?.popViewController(animated: true)
52 107
     }
53 108
     @IBAction func rotateTheImage(_ sender: UIButton) {
54
-        guard let cell = collectionView.cellForItem(at: IndexPath(item: currentPageIndex, section: 0)) as? ImageCell else {
109
+        guard let cell = collectionView.cellForItem(at: IndexPath(item: viewModel.currIndex, section: 0)) as? ImageCell else {
55 110
             return
56 111
         }
57 112
         UIView.beginAnimations("image.rotate", context: nil)
@@ -71,54 +126,14 @@ final class ShowFullPicController: UIViewController {
71 126
             }
72 127
         }
73 128
     }
129
+    
74 130
 
75
-    @IBAction func load() {
76
-        guard let cell = collectionView.cellForItem(at: IndexPath(item: currentPageIndex, section: 0)) as? ImageCell else {
77
-//            FFToastView.showToast(inView: view, withText: "未检测到图片")
78
-            return
79
-        }
80
-        guard let image = cell.photoImage.image else {
81
-//            FFToastView.showToast(inView: view, withText: "未检测到图片")
82
-            return
83
-        }
84
-        UIImageWriteToSavedPhotosAlbum(image, self, #selector(image(_:didFinishSavingWithError:contextInfo:)), nil)
85
-    }
86
-
87
-    @objc func image(_ image: UIImage?, didFinishSavingWithError error: NSError?, contextInfo info: UnsafeMutableRawPointer) {
88
-        if error != nil {
89
-//            FFToastView.showToast(inView: view, withText: "保存图片失败")
90
-        } else {
91
-//            FFToastView.showImageToast(inView: view, withText: "已保存图片到相册", withImage: "提示弹窗-勾")
92
-        }
93
-
94
-    }
95 131
 }
96 132
 
97 133
 // MARK: UICollectionView delegate
98
-extension ShowFullPicController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
99
-
100
-    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
101
-        return shufflingImage.count > datas.count ? shufflingImage.count : datas.count
102
-    }
103
-
104
-    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
105
-        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! ImageCell
106
-        if shufflingImage.count <= 0 {
107
-            let data = datas[indexPath.item]
108
-            let urlStr = data.murl.isEmpty ? data.photo_url : data.murl
109
-            cell.setModel(url: urlStr)
110
-        } else {
111
-            cell.setModel(url: shufflingImage[indexPath.row])
112
-        }
113
-        return cell
114
-    }
134
+extension PhotoPreviewViewController: UICollectionViewDelegateFlowLayout {
115 135
 
116 136
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
117 137
         return CGSize(width: collectionView.width, height: collectionView.height - 20)
118 138
     }
119
-
120
-    func scrollViewDidScroll(_ scrollView: UIScrollView) {
121
-        let page = Int(scrollView.contentOffset.x / (collectionView.width))
122
-        currentPageIndex = page
123
-    }
124 139
 }

+ 15 - 7
PaiAi/Paiai_iOS/App/PhotoDetail/ShareView.swift

@@ -9,13 +9,21 @@
9 9
 import UIKit
10 10
 
11 11
 class ShareView: UIView {
12
+    
13
+}
14
+
12 15
 
13
-    /*
14
-    // Only override draw() if you perform custom drawing.
15
-    // An empty implementation adversely affects performance during animation.
16
-    override func draw(_ rect: CGRect) {
17
-        // Drawing code
18
-    }
19
-    */
20 16
 
17
+extension ShareView {
18
+    
19
+    func activateConstraints() {
20
+        
21
+    }
22
+    
23
+    func activateConstraintsShareView() {
24
+        guard let superView = superview else { return }
25
+        
26
+        self.translatesAutoresizingMaskIntoConstraints = false
27
+        
28
+    }
21 29
 }

+ 0 - 15
PaiAi/launch_multiple_simulators.sh

@@ -1,15 +0,0 @@
1
-#!/bin/bash
2
-
3
-xcrun simctl shutdown all
4
-
5
-path=$(find ~/Library/Developer/Xcode/DerivedData/Paiai-*/Build/Products/Debug-iphonesimulator -name "Paiai.app" | head -n 1)
6
-echo "${path}"
7
-
8
-filename=MultiSimConfig.txt
9
-grep -v '^#' $filename | while read -r line
10
-do
11
-  echo $line
12
-  xcrun instruments -w "$line"
13
-  xcrun simctl install booted $path
14
-  xcrun simctl launch booted com.Paiai.Paiai
15
-done

Kodo/kodo - Gogs: Go Git Service

2 Commits (96f6c2557f5cd3d16611bea8ce4fdf03bb04c232)

Autor SHA1 Mensaje Fecha
  Brightcells fabef63211 set line_length=200 for isort %!s(int64=9) %!d(string=hace) años
  Brightcells 4defb80fdc gogs first init %!s(int64=10) %!d(string=hace) años
Kodo/kodo - Gogs: Go Git Service

2 Commits (3b6d93a51e3fde8398c4d01cafd6bbd26dd8f3b5)

Autor SHA1 Mensaje Fecha
  huangqimin 3bbfc60c06 :art: Support del_clerk_sale_submit_api %!s(int64=5) %!d(string=hace) años
  huangqimin 6d06194a0c SubscribeUserInfo %!s(int64=5) %!d(string=hace) años