="lines-code">
                     </connections>
337 301
                 </viewController>
338 302
                 <placeholder placeholderIdentifier="IBFirstResponder" id="3Gk-LZ-t7S" sceneMemberID="firstResponder"/>
303
+                <tapGestureRecognizer id="QhO-Be-7C1" userLabel="GroupNameGesture">
304
+                    <connections>
305
+                        <action selector="navigationToGroupNameModification:" destination="s9X-RR-Rat" id="R9K-8v-b14"/>
306
+                    </connections>
307
+                </tapGestureRecognizer>
308
+                <tapGestureRecognizer id="PAc-yU-TO1" userLabel="GroupMemeberGesture">
309
+                    <connections>
310
+                        <action selector="navigationToGroupMember:" destination="s9X-RR-Rat" id="V81-eM-vdl"/>
311
+                    </connections>
312
+                </tapGestureRecognizer>
313
+                <tapGestureRecognizer id="CLv-er-MwX" userLabel="GroupQRGesture">
314
+                    <connections>
315
+                        <action selector="presentGroupQR:" destination="s9X-RR-Rat" id="RHF-fz-Emo"/>
316
+                    </connections>
317
+                </tapGestureRecognizer>
339 318
             </objects>
340 319
             <point key="canvasLocation" x="-983.20000000000005" y="926.08695652173924"/>
341 320
         </scene>
342
-        <!--ChangeGroupNameController-->
321
+        <!--GroupNameModificationViewController-->
343 322
         <scene sceneID="LCo-hF-TXa">
344 323
             <objects>
345
-                <viewController storyboardIdentifier="ChangeGroupNameController" id="xy6-fJ-25c" userLabel="ChangeGroupNameController" customClass="ChangeGroupNameController" customModule="PaiAi" sceneMemberID="viewController">
346
-                    <layoutGuides>
347
-                        <viewControllerLayoutGuide type="top" id="js2-YR-fZ8"/>
348
-                        <viewControllerLayoutGuide type="bottom" id="UR6-vz-0Cc"/>
349
-                    </layoutGuides>
324
+                <viewController storyboardIdentifier="GroupNameModificationViewController" id="xy6-fJ-25c" userLabel="GroupNameModificationViewController" customClass="GroupNameModificationViewController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController">
350 325
                     <view key="view" contentMode="scaleToFill" id="k0W-jb-XQ1">
351 326
                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
352 327
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
353 328
                         <subviews>
354 329
                             <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="群名称" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8A1-xH-nsg">
355
-                                <rect key="frame" x="0.0" y="64" width="375" height="44"/>
330
+                                <rect key="frame" x="0.0" y="20" width="375" height="44"/>
356 331
                                 <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
357 332
                                 <constraints>
358 333
                                     <constraint firstAttribute="height" constant="44" id="K1B-yr-x1W"/>
@@ -361,12 +336,12 @@
361 336
                                 <textInputTraits key="textInputTraits"/>
362 337
                             </textField>
363 338
                             <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6ys-SB-QLv">
364
-                                <rect key="frame" x="0.0" y="138" width="375" height="48"/>
339
+                                <rect key="frame" x="0.0" y="94" width="375" height="48"/>
365 340
                                 <constraints>
366 341
                                     <constraint firstAttribute="height" constant="48" id="VPL-IJ-M2Y"/>
367 342
                                 </constraints>
368 343
                                 <fontDescription key="fontDescription" type="system" pointSize="18"/>
369
-                                <state key="normal" title="保存" backgroundImage="标题栏 copy 2">
344
+                                <state key="normal" title="保存" backgroundImage="navigation-background">
370 345
                                     <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
371 346
                                 </state>
372 347
                                 <connections>
@@ -378,12 +353,13 @@
378 353
                         <gestureRecognizers/>
379 354
                         <constraints>
380 355
                             <constraint firstItem="6ys-SB-QLv" firstAttribute="top" secondItem="8A1-xH-nsg" secondAttribute="bottom" constant="30" id="4qN-11-vnF"/>
381
-                            <constraint firstItem="6ys-SB-QLv" firstAttribute="leading" secondItem="k0W-jb-XQ1" secondAttribute="leading" id="Fen-r1-swQ"/>
382
-                            <constraint firstAttribute="trailing" secondItem="6ys-SB-QLv" secondAttribute="trailing" id="KeF-22-9xs"/>
383
-                            <constraint firstItem="8A1-xH-nsg" firstAttribute="top" secondItem="js2-YR-fZ8" secondAttribute="bottom" id="O3J-RE-wko"/>
384
-                            <constraint firstItem="8A1-xH-nsg" firstAttribute="leading" secondItem="k0W-jb-XQ1" secondAttribute="leading" id="a8E-Fz-s5Z"/>
385
-                            <constraint firstAttribute="trailing" secondItem="8A1-xH-nsg" secondAttribute="trailing" id="cAq-3V-p2y"/>
356
+                            <constraint firstItem="6ys-SB-QLv" firstAttribute="leading" secondItem="Xk6-cx-bQU" secondAttribute="leading" id="Fen-r1-swQ"/>
357
+                            <constraint firstItem="Xk6-cx-bQU" firstAttribute="trailing" secondItem="6ys-SB-QLv" secondAttribute="trailing" id="KeF-22-9xs"/>
358
+                            <constraint firstItem="8A1-xH-nsg" firstAttribute="top" secondItem="Xk6-cx-bQU" secondAttribute="top" id="O3J-RE-wko"/>
359
+                            <constraint firstItem="8A1-xH-nsg" firstAttribute="leading" secondItem="Xk6-cx-bQU" secondAttribute="leading" id="a8E-Fz-s5Z"/>
360
+                            <constraint firstItem="Xk6-cx-bQU" firstAttribute="trailing" secondItem="8A1-xH-nsg" secondAttribute="trailing" id="cAq-3V-p2y"/>
386 361
                         </constraints>
362
+                        <viewLayoutGuide key="safeArea" id="Xk6-cx-bQU"/>
387 363
                         <connections>
388 364
                             <outletCollection property="gestureRecognizers" destination="TeB-xY-v1V" appends="YES" id="o89-cE-p8S"/>
389 365
                         </connections>
@@ -403,24 +379,20 @@
403 379
             </objects>
404 380
             <point key="canvasLocation" x="665.60000000000002" y="277.06146926536735"/>
405 381
         </scene>
406
-        <!--GroupUserController-->
382
+        <!--GroupMemberViewController-->
407 383
         <scene sceneID="LEa-gB-9eo">
408 384
             <objects>
409
-                <viewController storyboardIdentifier="GroupUserController" id="DUe-lx-JN1" userLabel="GroupUserController" customClass="GroupUserController" customModule="PaiAi" sceneMemberID="viewController">
410
-                    <layoutGuides>
411
-                        <viewControllerLayoutGuide type="top" id="akD-at-rrg"/>
412
-                        <viewControllerLayoutGuide type="bottom" id="Yii-Z2-rvQ"/>
413
-                    </layoutGuides>
385
+                <viewController storyboardIdentifier="GroupMemberViewController" id="DUe-lx-JN1" userLabel="GroupMemberViewController" customClass="GroupMemberViewController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController">
414 386
                     <view key="view" contentMode="scaleToFill" id="wjV-Cy-YkZ">
415 387
                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
416 388
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
417 389
                         <subviews>
418 390
                             <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="cas-Ep-jsP">
419
-                                <rect key="frame" x="0.0" y="6" width="375" height="661"/>
391
+                                <rect key="frame" x="0.0" y="20" width="375" height="647"/>
420 392
                                 <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
421 393
                                 <color key="separatorColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
422 394
                                 <prototypes>
423
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="MemberCell" rowHeight="50" id="DJ1-Ig-ZYH" customClass="MemberCell" customModule="Paiai_iOS" customModuleProvider="target">
395
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="groupMemberCell" rowHeight="50" id="DJ1-Ig-ZYH" customClass="GroupMemberCell" customModule="Paiai_iOS" customModuleProvider="target">
424 396
                                         <rect key="frame" x="0.0" y="28" width="375" height="50"/>
425 397
                                         <autoresizingMask key="autoresizingMask"/>
426 398
                                         <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="DJ1-Ig-ZYH" id="IJX-qw-roh">
@@ -500,11 +472,12 @@
500 472
                         </subviews>
501 473
                         <color key="backgroundColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
502 474
                         <constraints>
503
-                            <constraint firstItem="Yii-Z2-rvQ" firstAttribute="top" secondItem="cas-Ep-jsP" secondAttribute="bottom" id="A2j-Na-7en"/>
504
-                            <constraint firstItem="cas-Ep-jsP" firstAttribute="leading" secondItem="wjV-Cy-YkZ" secondAttribute="leading" id="NW3-AC-Ax4"/>
505
-                            <constraint firstItem="cas-Ep-jsP" firstAttribute="top" secondItem="akD-at-rrg" secondAttribute="bottom" constant="-64" id="NvE-Ok-Rur"/>
506
-                            <constraint firstAttribute="trailing" secondItem="cas-Ep-jsP" secondAttribute="trailing" id="PPv-Ze-mtL"/>
475
+                            <constraint firstItem="D3F-7B-V4M" firstAttribute="bottom" secondItem="cas-Ep-jsP" secondAttribute="bottom" id="A2j-Na-7en"/>
476
+                            <constraint firstItem="cas-Ep-jsP" firstAttribute="leading" secondItem="D3F-7B-V4M" secondAttribute="leading" id="NW3-AC-Ax4"/>
477
+                            <constraint firstItem="cas-Ep-jsP" firstAttribute="top" secondItem="D3F-7B-V4M" secondAttribute="top" id="NvE-Ok-Rur"/>
478
+                            <constraint firstItem="D3F-7B-V4M" firstAttribute="trailing" secondItem="cas-Ep-jsP" secondAttribute="trailing" id="PPv-Ze-mtL"/>
507 479
                         </constraints>
480
+                        <viewLayoutGuide key="safeArea" id="D3F-7B-V4M"/>
508 481
                     </view>
509 482
                     <navigationItem key="navigationItem" id="7KI-2g-oIA"/>
510 483
                     <connections>
@@ -515,48 +488,12 @@
515 488
             </objects>
516 489
             <point key="canvasLocation" x="665.60000000000002" y="1461.7691154422789"/>
517 490
         </scene>
518
-        <!--Navigation Controller-->
519
-        <scene sceneID="ov2-RO-i1Z">
520
-            <objects>
521
-                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="ahh-gm-C2t" sceneMemberID="viewController">
522
-                    <toolbarItems/>
523
-                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="6Xa-cD-JBm">
524
-                        <rect key="frame" x="0.0" y="20" width="375" height="44"/>
525
-                        <autoresizingMask key="autoresizingMask"/>
526
-                    </navigationBar>
527
-                    <nil name="viewControllers"/>
528
-                    <connections>
529
-                        <segue destination="xy6-fJ-25c" kind="relationship" relationship="rootViewController" id="cOL-rO-K5H"/>
530
-                    </connections>
531
-                </navigationController>
532
-                <placeholder placeholderIdentifier="IBFirstResponder" id="KNI-l3-BnW" userLabel="First Responder" sceneMemberID="firstResponder"/>
533
-            </objects>
534
-            <point key="canvasLocation" x="-228.80000000000001" y="277.06146926536735"/>
535
-        </scene>
536
-        <!--Navigation Controller-->
537
-        <scene sceneID="5Kq-iV-cq7">
538
-            <objects>
539
-                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="bLF-bf-ZTt" sceneMemberID="viewController">
540
-                    <toolbarItems/>
541
-                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="XDR-Gh-5JG">
542
-                        <rect key="frame" x="0.0" y="20" width="375" height="44"/>
543
-                        <autoresizingMask key="autoresizingMask"/>
544
-                    </navigationBar>
545
-                    <nil name="viewControllers"/>
546
-                    <connections>
547
-                        <segue destination="DUe-lx-JN1" kind="relationship" relationship="rootViewController" id="eVW-yF-vp0"/>
548
-                    </connections>
549
-                </navigationController>
550
-                <placeholder placeholderIdentifier="IBFirstResponder" id="ewD-Hk-TCe" userLabel="First Responder" sceneMemberID="firstResponder"/>
551
-            </objects>
552
-            <point key="canvasLocation" x="-230.40000000000001" y="1461.7691154422789"/>
553
-        </scene>
554 491
     </scenes>
555 492
     <resources>
556 493
         <image name="delete" width="66" height="66"/>
557
-        <image name="二维码" width="80" height="80"/>
558
-        <image name="列表箭头" width="24" height="36"/>
559
-        <image name="标题栏 copy 2" width="6" height="66"/>
494
+        <image name="list-QR" width="36" height="36"/>
495
+        <image name="list-arrow" width="24" height="36"/>
496
+        <image name="navigation-background" width="12" height="132"/>
560 497
         <image name="默认头像" width="240" height="240"/>
561 498
     </resources>
562 499
 </document>

+ 31 - 2
PaiAi/Paiai_iOS/App/Group/GroupDetail/GroupDetailCoordinator.swift

@@ -6,7 +6,8 @@
6 6
 //  Copyright © 2018 yb. All rights reserved.
7 7
 //
8 8
 
9
-import Foundation
9
+import UIKit
10
+import PaiaiDataKit
10 11
 
11 12
 class GroupDetailCoordinator: Coordinator {
12 13
     let navigationController: UINavigationController
@@ -16,7 +17,35 @@ class GroupDetailCoordinator: Coordinator {
16 17
         self.groupDetailViewController = groupDetailVC
17 18
         self.navigationController = navigationController
18 19
         
19
-//        groupViewController.viewModel.delegate = self
20
+        groupDetailViewController.viewModel.delegate = self
21
+    }
22
+}
23
+
24
+extension GroupDetailCoordinator: GroupDetailViewModelDelegate {
25
+    func navigationToRootViewController() {
26
+        navigationController.popToRootViewController(animated: true)
27
+    }
28
+    
29
+    func navigationToGroupMember(_ item: GroupDetailItem) {
30
+        navigationController.pushViewController(makeGroupMemberViewController(item))
31
+    }
32
+    
33
+    func navigationToGroupNameModification(_ item: GroupDetailItem) {
34
+        navigationController.pushViewController(makeGroupNameModificationViewController(item))
35
+    }
36
+}
37
+
38
+extension GroupDetailCoordinator {
39
+    func makeGroupMemberViewController(_ item: GroupDetailItem) -> GroupMemberViewController {
40
+        let vc = UIStoryboard.groupDetail.instantiateController(GroupMemberViewController.self)
41
+        vc.viewModel = GroupMemberViewModel(item: item)
42
+        return vc
43
+    }
44
+    
45
+    func makeGroupNameModificationViewController(_ item: GroupDetailItem) -> GroupNameModificationViewController {
46
+        let vc = UIStoryboard.groupDetail.instantiateController(GroupNameModificationViewController.self)
47
+        vc.item = item
48
+        return vc
20 49
     }
21 50
 }
22 51
 

+ 47 - 8
PaiAi/Paiai_iOS/App/Group/GroupDetail/GroupDetailMemeberView.swift

@@ -9,13 +9,52 @@
9 9
 import UIKit
10 10
 
11 11
 class GroupDetailMemeberView: UIView {
12
-
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
12
+    var avatars = [String]() {
13
+        didSet {
14
+            constructViewHierarchy()
15
+            activateConstraints()
16
+        }
17
+    }
18
+    
19
+    private var imageViews = [UIImageView]()
20
+    private var visiableMembersCount = 0
21
+    private var space: CGFloat = 0
22
+    
23
+    override func didMoveToWindow() {
24
+        visiableMembersCount = Int((width - 6) / 46)
25
+        space = (width - CGFloat(40 * visiableMembersCount)) / CGFloat(visiableMembersCount + 1)
26
+    }
27
+    
28
+    func constructViewHierarchy() {
29
+        imageViews.forEach { $0.removeFromSuperview() }
30
+        imageViews.removeAll()
31
+        
32
+        
33
+        for avatar in avatars {
34
+            let imageView = UIImageView()
35
+            
36
+            imageView.cornerRadius = 5
37
+            imageView.setImage(avatar, placeholder: UIImage.defaultAvatar)
38
+            
39
+            addSubview(imageView)
40
+            imageViews.append(imageView)
41
+        }
42
+    }
43
+    
44
+    func activateConstraints() {
45
+        var last: UIImageView?
46
+        for imageView in imageViews {
47
+            imageView.translatesAutoresizingMaskIntoConstraints = false
48
+            
49
+            NSLayoutConstraint.activate([
50
+                imageView.widthAnchor.constraint(equalToConstant: 40),
51
+                imageView.heightAnchor.constraint(equalToConstant: 40),
52
+                imageView.centerYAnchor.constraint(equalTo: centerYAnchor),
53
+                imageView.leadingAnchor.constraint(equalTo: last?.trailingAnchor ?? leadingAnchor, constant: space)
54
+            ])
55
+            
56
+            last = imageView
57
+        }
18 58
     }
19
-    */
20
-
21 59
 }
60
+

+ 83 - 99
PaiAi/Paiai_iOS/App/Group/GroupDetail/GroupDetailViewController.swift

@@ -14,120 +14,104 @@ import PaiaiDataKit
14 14
 
15 15
 final class GroupDetailViewController: UIViewController {
16 16
 
17
+    @IBOutlet weak var groupNameLabel: UILabel!
17 18
     // MARK: Storyboard property
18
-    @IBOutlet weak var scrollViewConstraint: NSLayoutConstraint!
19
-    @IBOutlet weak var groupLockConstraint: NSLayoutConstraint!
20
-    @IBOutlet var titleLabel: UILabel!
21
-    @IBOutlet var groupNameLabel: UILabel!
22
-    @IBOutlet var groupUserCountLabel: UILabel!
23
-    @IBOutlet var groupUserHeaderScrollView: UIScrollView!
24
-    @IBOutlet var groupLockSwitch: UISwitch!
25
-    @IBOutlet var groupLockTip: UILabel!
19
+    @IBOutlet weak var groupMemberCountLabel: UILabel!
20
+    @IBOutlet weak var groupMemeberView: GroupDetailMemeberView!
21
+    @IBOutlet weak var groupLockSwitch: UISwitch!
22
+    @IBOutlet weak var groupLockTip: UILabel!
26 23
 
27 24
     var viewModel: GroupDetailViewModel!
28
-  // MARK: parameter property
29 25
     let disposeBag = DisposeBag()
30
-    // MARK: view function
26
+
31 27
     override func viewDidLoad() {
32 28
         super.viewDidLoad()
33
-//        rightBarAction = #selector(quit)
34
-        configureInterface()
29
+        binding()
30
+        viewModel.reload()
31
+        title = "群资料"
32
+        setRightBarButtonItems()
35 33
     }
36
-
37
-    override func viewWillAppear(_ animated: Bool) {
38
-        super.viewWillAppear(true)
39
-//        titleWithbackBar = "群资料"
34
+    
35
+    func setRightBarButtonItems() {
36
+        let item = UIBarButtonItem(image: UIImage(named: "navigation-right"), target: self, action: #selector(quit))
37
+        navigationItem.rightBarButtonItem = item
40 38
     }
41
-
42
-    // MARK: init interface
43
-    func configureInterface() {
44
-        
45
-//        groupDetailViewModel.groupDetailData.asObservable().bind {[unowned self] (model) in
46
-//            if let adminID = model.group?.admin_id {
47
-//                self.groupLockSwitch.isHidden = adminID != SharedUserInfo.userId
48
-//            } else {
49
-//                self.groupLockSwitch.isHidden = true
50
-//            }
51
-//
52
-//            self.groupNameLabel.text = model.group?.group_name
53
-//            if let count = model.users?.passed_count {
54
-//                self.groupUserCountLabel.text = "\(count)名"
55
-//            } else {
56
-//                self.groupUserCountLabel.text = "0名"
57
-//            }
58
-//
59
-//            guard let passUsers = model.users?.passed else {
60
-//                return
61
-//            }
62
-//            //锁定
63
-//            if let lock = model.group?.group_lock {
64
-//                self.groupLockSwitch.isOn = lock
65
-//                self.groupLockTip.text = lock ? "群已锁定,不再允许新成员加入" : "群未锁定,可以邀请新成员加入"
66
-//            }
67
-//            let userHead = passUsers.flatMap {[$0.avatar]}
68
-//            self.configureScrollView(userHead: userHead)
69
-//        }.disposed(by: disposeBag)
70
-
39
+    
40
+    @objc func quit() {
41
+        let alert = AlertController(title: "退出群", message: "退出后将不再能看到群内照片")
42
+        alert.addAlertAction(AlertAction(title: "取消", style: .cancel))
43
+        alert.addAlertAction(AlertAction(title: "确定", handler: { _ in
44
+            self.viewModel.quit()
45
+        }))
46
+        presentController(alert)
71 47
     }
48
+}
72 49
 
73
-    func configureScrollView(userHead: [String]) {
74
-        var count = -1
75
-        let headerUrl = userHead.filter { (_) -> Bool in
76
-            count += 1
77
-            return count < 6
78
-        }
79
-        let userSize = (view.width - 70) / 6
80
-        self.scrollViewConstraint.constant = userSize + 12
81
-//        self.groupUserHeaderScrollView.buildImageViews(headerUrl, width: userSize, height: (view.width - 70) / 6, spacing: 10, topSpcing: 0) { (_) in
82
-
83
-//        }
84
-
50
+/// binding UI
51
+fileprivate extension GroupDetailViewController {
52
+    func binding() {
53
+        bindViewModelToGroupName()
54
+        bindViewModelToGroupMemberCount()
55
+        bindViewModelToGroupMemeber()
56
+        bindViewModelToGroupLock()
57
+        bindViewModelToGroupLockSwitch()
58
+        bindGroupLockSwitchToGroupLockTip()
85 59
     }
86
-
87
-    // MARK: Storyboard  button
88
-
89
-    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
90
-//        let navigationController = segue.destination as! UINavigationController
91
-//        if let ctl = navigationController.topViewController as? ChangeGroupNameController {
92
-//            ctl.detailData = groupDetailViewModel.groupDetailData.value
93
-//        }
94
-//        if let ctl = navigationController.topViewController as? GroupUserController {
95
-//            guard let passed = groupDetailViewModel.groupDetailData.value.users?.passed else {
96
-//                return
97
-//            }
98
-//            ctl.meberData = Variable<[UserModel]>(passed)
99
-//            ctl.groupId = groupDetailViewModel.groupDetailData.value.group_id
100
-//        }
60
+    
61
+    func bindViewModelToGroupName() {
62
+        viewModel.groupName.bind(to: groupNameLabel.rx.text).disposed(by: disposeBag)
101 63
     }
102
-
103
-    @IBAction func showEWM() {
104
-        let ctl = UIStoryboard.groupDetail.instantiateController(ShowGroupQRController.self)
105
-//        ctl.data = groupDetailViewModel.groupDetailData.value.group
106
-        presentController(ctl)
64
+    
65
+    func bindViewModelToGroupMemberCount() {
66
+        viewModel.groupMemberCount.bind(to: groupMemberCountLabel.rx.text).disposed(by: disposeBag)
107 67
     }
108
-
109
-    @objc func quit() {
110
-//        let alert = FFAlertController(title: "", message: "", alertStyle: .actionSheet)
111
-//        alert.addAlertAction(alertAction: DestructiveAlertAction(title: "退出该群", handler: { (alertAction) in
112
-//            let subAlert = FFAlertController(title: "退出群", message: "退出后将不再能看到群内照片", alertStyle: .alert)
113
-//            subAlert.addAlertAction(alertAction: CancelAlertAction())
114
-//            subAlert.addAlertAction(alertAction: ConfirmAlertAction(handler: { (alertAction) in
115
-//                self.groupDetailViewModel.quitQroup(success: {[weak self] in
116
-//                    if let weakself = self {
117
-//                        PhotoLocalStorage.instance.removeLocalData(group_id: weakself.groupId)
118
-//                        subAlert.dismissController()
119
-//                        _ = weakself.navigationController?.popToRootViewController(animated: true)
120
-//                        FFToastView.showToast(inView: UIApplication.shared.keyWindow ?? weakself.view, withText: "退出群成功")
121
-//                    }
122
-//                })
123
-//            }))
124
-//            self.presentController(subAlert)
125
-//        }))
126
-//        alert.addAlertAction(alertAction: FFAlertAction(title: "取消", handler: nil))
127
-//        presentController(alert)
68
+    
69
+    func bindViewModelToGroupMemeber() {
70
+        viewModel.groupMembers.subscribe(onNext: { self.setupGroupMember(groupMemebers: $0) }).disposed(by: disposeBag)
71
+    }
72
+    
73
+    func bindViewModelToGroupLock() {
74
+        viewModel.groupLock.bind(to: groupLockSwitch.rx.value).disposed(by: disposeBag)
75
+    }
76
+    
77
+    func bindViewModelToGroupLockSwitch() {
78
+        viewModel.isAdmin.map { !$0 }.bind(to: groupLockSwitch.rx.isHidden).disposed(by: disposeBag)
79
+    }
80
+    
81
+    func bindGroupLockSwitchToGroupLockTip() {
82
+        groupLockSwitch.rx.value.subscribe(onNext: {[weak self] (v) in
83
+            guard let `self` = self else { return }
84
+            self.groupLockTip.text = v ? "群已锁定,不再允许新成员加入" : "群未锁定,可以邀请新成员加入"
85
+        }).disposed(by: disposeBag)
128 86
     }
87
+    
88
+    private func setupGroupMember(groupMemebers: [GroupMemberItem]) {
89
+        groupMemeberView.avatars = groupMemebers.compactMap { $0.avatar }
90
+    }
91
+}
129 92
 
93
+/// storyboard action
94
+extension GroupDetailViewController {
95
+    @IBAction func navigationToGroupMember(_ sender: UITapGestureRecognizer) {
96
+        viewModel.navigationToGroupMember()
97
+    }
98
+    
99
+    @IBAction func navigationToGroupNameModification(_ sender: UITapGestureRecognizer) {
100
+        viewModel.navigationToGroupNameModification()
101
+    }
102
+    
103
+    @IBAction func presentGroupQR(_ sender: UITapGestureRecognizer) {
104
+        let groupItem = viewModel.item.value.group
105
+        let alert = AlertViewController(style: .custom(GroupQRView(groupName: groupItem.group_name,
106
+                                                                   groupAvatar: "Group\(groupItem.group_default_avatar)",
107
+            groupQR: "https:pai.ai/g/\(groupItem.group_id)"),
108
+                                                       AlertAnimator()) )
109
+        presentController(alert)
110
+    }
111
+    
130 112
     @IBAction func changeSwitch() {
131
-//        groupDetailViewModel.postLock(isLock: groupLockSwitch.isOn)
113
+        viewModel.toggle(isLock: groupLockSwitch.isOn)
132 114
     }
133 115
 }
116
+
117
+extension GroupDetailViewController: NavigationBackViewController {}

+ 11 - 22
PaiAi/Paiai_iOS/App/Group/GroupDetail/GroupMemberCell.swift

@@ -1,5 +1,5 @@
1 1
 //
2
-//  MemberCell.swift
2
+//  GroupMemberCell.swift
3 3
 //  PaiAi
4 4
 //
5 5
 //  Created by mac on 16/5/20.
@@ -10,11 +10,11 @@ import UIKit
10 10
 import PaiaiDataKit
11 11
 import PaiaiUIKit
12 12
 
13
-protocol ReturnIndexPathDelegate: class {
14
-    func renturnIndexPath(_ indexpath: IndexPath)
13
+protocol GroupMemberCellDelegate: class {
14
+    func remove(_ item: GroupMemberItem)
15 15
 }
16 16
 
17
-final class MemberCell: UITableViewCell {
17
+final class GroupMemberCell: UITableViewCell {
18 18
 
19 19
     // MARK: Storyboard property
20 20
     @IBOutlet weak var isManager: UILabel!
@@ -24,32 +24,21 @@ final class MemberCell: UITableViewCell {
24 24
     @IBOutlet weak var uerImage: UIImageView!
25 25
 
26 26
     // MARK: delete property
27
-    weak var delegate: ReturnIndexPathDelegate?
28
-
29
-  // MARK: parameter property
30
-    fileprivate var index: IndexPath!
31
-
32
-    // MARK: view function
33
-    override func awakeFromNib() {
34
-        super.awakeFromNib()
35
-    }
36
-
37
-    override func setSelected(_ selected: Bool, animated: Bool) {
38
-        super.setSelected(selected, animated: animated)
39
-    }
27
+    weak var delegate: GroupMemberCellDelegate?
28
+    var item = GroupMemberItem(json: [:])
40 29
 
41 30
     // MARK: init interface
42
-    func setInfo(_ model: GroupMemberItem, isManage: Bool, indexPath: IndexPath) {
43
-        index = indexPath
31
+    func setInfo(_ model: GroupMemberItem, isAdmin: Bool) {
32
+        item = model
44 33
         meberName.text = model.nickname
45
-//        uerImage.setImageWithNullableURL(model.avatar, placeholderImage: defaultAvatar)
34
+        uerImage.setImage(model.avatar, placeholder: UIImage.defaultAvatar)
46 35
         isManager.isHidden = !model.admin
47
-        deleteConstraint.constant = !isManage || model.admin ? -32 : 12
36
+        deleteConstraint.constant = !isAdmin || model.admin ? -32 : 12
48 37
     }
49 38
 
50 39
     // MARK: Storyboard  button
51 40
     @IBAction func deleteMemberAction(_ sender: UIButton) {
52
-        delegate?.renturnIndexPath(index)
41
+        delegate?.remove(item)
53 42
     }
54 43
 
55 44
 }

+ 40 - 44
PaiAi/Paiai_iOS/App/Group/GroupDetail/GroupMemberViewController.swift

@@ -1,5 +1,5 @@
1 1
 //
2
-//  GroupMemberController.swift
2
+//  GroupMemberViewController.swift
3 3
 //  PaiAi
4 4
 //
5 5
 //  Created by zhengjianfei on 16/4/6.
@@ -9,62 +9,58 @@
9 9
 import UIKit
10 10
 import RxCocoa
11 11
 import RxSwift
12
+import RxDataSources
12 13
 import PaiaiUIKit
13 14
 import PaiaiDataKit
14 15
 
15
-final class GroupMemberController: UIViewController {
16
+final class GroupMemberViewController: UIViewController {
16 17
 
17
-    // MARK: Storyboard property
18
-    @IBOutlet var tableView: UITableView!
18
+    @IBOutlet weak var tableView: UITableView!
19 19
 
20
-    // MARK: data property
21
-    lazy var meberData = Variable<[GroupMemberItem]>([])
22
-    var groupMebersViewModel = GroupMemberViewModel()
23
-
24
-  // MARK: parameter property
25
-    lazy var groupId = ""
26
-    lazy var isManage = false
20
+    var viewModel: GroupMemberViewModel!
27 21
     let disposeBag = DisposeBag()
22
+    
28 23
     // MARK: view function
29 24
     override func viewDidLoad() {
30 25
         super.viewDidLoad()
31
-        tableView?.rowHeight = 44.0
32
-//        isManage = meberData.value.filter({ (userModel) -> Bool in
33
-//            return userModel.user_id == SharedUserInfo.userId && userModel.admin
34
-//        }).count > 0
35
-        meberData.asObservable().bind(to: tableView.rx.items(cellIdentifier: "MemberCell", cellType: MemberCell.self)) { (row, model, cell) in
36
-            cell.setInfo(model, isManage: self.isManage, indexPath :IndexPath(row: row, section: 0))
37
-            cell.delegate = self
38
-        }.disposed(by: disposeBag)
26
+        title = "群成员"
27
+        binding()
39 28
     }
29
+}
40 30
 
41
-//    override func backToController() {
42
-//        dismissController()
43
-//    }
44
-
45
-    override func viewWillAppear(_ animated: Bool) {
46
-        super.viewWillAppear(true)
47
-//        titleWithbackBar = "群成员"
31
+fileprivate extension GroupMemberViewController {
32
+    
33
+    var dataSource: RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, GroupMemberItem>> {
34
+        return RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, GroupMemberItem>>(
35
+            configureCell: { (dataSource, tableView, indexPath, item) in
36
+                let cell = tableView.dequeueReusableCell(withIdentifier: "groupMemberCell", for: indexPath) as! GroupMemberCell
37
+                cell.setInfo(item, isAdmin: self.viewModel.isAdmin)
38
+                cell.delegate = self
39
+                return cell
40
+        })
41
+    }
42
+    
43
+    func binding() {
44
+        bindViewModelToTableView()
45
+    }
46
+    
47
+    func bindViewModelToTableView() {
48
+        viewModel.contents
49
+            .bind(to: tableView.rx.items(dataSource: dataSource))
50
+            .disposed(by: disposeBag)
48 51
     }
49 52
 }
50 53
 
51
-// MARK: custom delegate
52
-extension GroupMemberController: ReturnIndexPathDelegate {
53
-
54
-    func renturnIndexPath(_ indexpath: IndexPath) {
55
-
56
-//        let alert = FFAlertController(title: "删除群成员", message: "删除后将不再看见群内照片", alertStyle: .alert)
57
-//        alert.addAlertAction(alertAction: CancelAlertAction())
58
-//        alert.addAlertAction(alertAction: ConfirmAlertAction(handler: { (alertAction) in
59
-//            let params: [String: AnyObject] = ["group_id": self.groupId as AnyObject, "admin_id": SharedUserInfo.userId as AnyObject, "user_id": self.meberData.value[indexpath.row].user_id as AnyObject]
60
-//            self.groupMebersViewModel.deleteMeber(params: params, success: {
61
-//                self.meberData.value.remove(at: indexpath.row)
62
-//                self.tableView.beginUpdates()
63
-//                self.tableView.deleteRows(at: [indexpath], with: UITableViewRowAnimation.left)
64
-//                self.tableView.endUpdates()
65
-//            })
66
-//        }))
67
-//        presentController(alert)
54
+extension GroupMemberViewController: GroupMemberCellDelegate {
55
+    func remove(_ item: GroupMemberItem) {
56
+        let alert = AlertController(title: "删除群成员", message: "删除后将不再看见群内照片")
57
+        alert.addAlertAction(AlertAction(title: "取消", style: .cancel))
58
+        alert.addAlertAction(AlertAction(title: "确定", handler: {(_) in
59
+            self.viewModel.removeMember(item)
60
+        }))
61
+        
62
+        presentController(alert)
68 63
     }
69
-
70 64
 }
65
+
66
+extension GroupMemberViewController: NavigationBackViewController {}

+ 54 - 54
PaiAi/Paiai_iOS/App/Group/GroupDetail/GroupNameModificationViewController.swift

@@ -1,5 +1,5 @@
1 1
 //
2
-//  ChangeGroupNameController.swift
2
+//  GroupNameModificationViewController.swift
3 3
 //  PaiAi
4 4
 //
5 5
 //  Created by zhengjianfei on 16/4/6.
@@ -12,79 +12,79 @@ import RxCocoa
12 12
 import PaiaiUIKit
13 13
 import PaiaiDataKit
14 14
 
15
-final class ChangeGroupNameController: UIViewController {
15
+final class GroupNameModificationViewController: UIViewController {
16 16
 
17 17
     // MARK: Storyboard property
18
-    @IBOutlet var textField: UITextField!
18
+    @IBOutlet weak var textField: UITextField!
19 19
     @IBOutlet weak var saveButton: UIButton!
20
-
21
-    // MARK: data property
22
-//    var detailData: GroupDetailModel?
20
+    
21
+    var item = GroupDetailItem(json: [:])
22
+    
23 23
     let disposeBag = DisposeBag()
24 24
     // MARK: view function
25 25
     override func viewDidLoad() {
26 26
         super.viewDidLoad()
27
-        configureTextField()
27
+        title = "群名称"
28
+        setupTextFieldLeftView()
29
+        bindTextFieldToSaveButton()
28 30
     }
29
-
30
-    override func viewWillAppear(_ animated: Bool) {
31
-        super.viewWillAppear(true)
32
-//        titleWithbackBar = "群名称"
31
+    
32
+    func setupTextFieldLeftView() {
33
+        let leftView = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: textField.width))
34
+        textField.leftView = leftView
35
+        textField.leftViewMode = .always
36
+        textField.placeholder = item.group.group_name
33 37
     }
34 38
 
35
-//    override func backToController() {
36
-//        dismissController()
37
-//    }
38
-
39
-    func configureTextField() {
40
-        do {
41
-            let view = UIView(frame: CGRect(x: 0, y: 0, width: 12, height: textField.width))
42
-            textField.leftView = view
43
-            textField.leftViewMode = .always
44
-//            textField.placeholder = detailData?.group?.group_name
45
-        }
46
-
47
-        do {
48
-            textField.rx.text
49
-                        .map {!($0?.isEmpty)!}
50
-                        .bind(to: saveButton.rx.isEnabled)
51
-                        .disposed(by: disposeBag)
52
-        }
39
+    func bindTextFieldToSaveButton() {
40
+        textField.rx.text
41
+                    .map {!($0?.isEmpty)!}
42
+                    .bind(to: saveButton.rx.isEnabled)
43
+                    .disposed(by: disposeBag)
53 44
     }
45
+}
54 46
 
55
-    // MARK: Storyboard  button
47
+extension GroupNameModificationViewController {
48
+    
56 49
     @IBAction func saveName() {
57
-        guard NSString(string: textField.text ?? "").length < 20 else {
58
-            jumpToSaveFailController()
50
+        if (textField.text ?? "").count > 20 {
51
+            saveFailed()
59 52
             return
60 53
         }
61
-//        guard let info = detailData else {
62
-//            return
63
-//        }
64
-//        guard let group = detailData?.group else {
65
-//            return
66
-//        }
67
-//        let params = ["group_id": info.group_id,
68
-//        "admin_id": group.admin_id, "group_name": textField.text ?? ""] as [String: AnyObject]
69
-//        let request = StatusNetworkRequest(param: params, path: .groupUpdate)
70
-//        NetworkApi.share.post(request: request) { (res) in
71
-//            guard res.status == 200 else {
72
-//                return
73
-//            }
74
-//            addGroupInfoToRecent(group)
75
-//            FFToastView.showToast(inView: self.view, withText: "保存成功")
76
-//            self.textField.resignFirstResponder()
77
-//        }
54
+        
55
+        
56
+        
57
+        //        guard let info = detailData else {
58
+        //            return
59
+        //        }
60
+        //        guard let group = detailData?.group else {
61
+        //            return
62
+        //        }
63
+        //        let params = ["group_id": info.group_id,
64
+        //        "admin_id": group.admin_id, "group_name": textField.text ?? ""] as [String: AnyObject]
65
+        //        let request = StatusNetworkRequest(param: params, path: .groupUpdate)
66
+        //        NetworkApi.share.post(request: request) { (res) in
67
+        //            guard res.status == 200 else {
68
+        //                return
69
+        //            }
70
+        //            addGroupInfoToRecent(group)
71
+        //            FFToastView.showToast(inView: self.view, withText: "保存成功")
72
+        //            self.textField.resignFirstResponder()
73
+        //        }
78 74
     }
79
-
80
-    func jumpToSaveFailController() {
75
+    
76
+    func saveFailed() {
81 77
         textField.resignFirstResponder()
82
-//        let alert = FFAlertController(title: "保存失败", message: "群名称不能超过20个字", alertStyle: .alert)
83
-//        alert.addAlertAction(alertAction: ConfirmAlertAction(handler: nil))
84
-//        presentController(alert)
78
+        let alert = AlertController(title: "保存失败", message: "群名称不能超过20个字")
79
+        alert.addAlertAction(AlertAction(title: "确定"))
80
+        presentController(alert)
85 81
     }
86 82
 
83
+    
87 84
     @IBAction func tapView() {
88 85
         textField.resignFirstResponder()
89 86
     }
90 87
 }
88
+
89
+
90
+extension GroupNameModificationViewController: NavigationBackViewController {}

+ 12 - 11
PaiAi/Paiai_iOS/App/Group/GroupViewController.swift

@@ -17,7 +17,7 @@ import PullToRefresh
17 17
 final class GroupViewController: UIViewController {
18 18
 
19 19
     // MARK: Storyboard property
20
-    @IBOutlet var collectionView: UICollectionView!
20
+    @IBOutlet weak var collectionView: UICollectionView!
21 21
     @IBOutlet weak var photographBtn: UIButton!
22 22
 
23 23
     // MARK: custom UI property
@@ -43,7 +43,6 @@ final class GroupViewController: UIViewController {
43 43
     
44 44
     // MARK: data property
45 45
     var viewModel: GroupViewModel!
46
-    var groupItem: GroupItem!
47 46
     
48 47
     fileprivate var navigationViewNotReady = true
49 48
     fileprivate let disposeBag = DisposeBag()
@@ -113,19 +112,23 @@ fileprivate extension GroupViewController {
113 112
     }
114 113
     
115 114
     func bindCollectionViewToViewModel() {
116
-        collectionView.rx.modelSelected(PhotoItem.self)
115
+        collectionView.rx.itemSelected
117 116
             .asDriver()
118
-            .drive(onNext: { [unowned self] in self.viewModel.didSelect($0) })
117
+            .drive(onNext: { [unowned self] in self.viewModel.didSelect($0.item) })
119 118
             .disposed(by: disposeBag)
120 119
     }
121 120
     
122 121
     func bindViewModelToNavigationBarTitle() {
123
-        navigationBarViewTitle.text = groupItem.group_name
122
+        viewModel.groupName.bind(to: navigationBarViewTitle.rx.text).disposed(by: disposeBag)
124 123
     }
125 124
     
126 125
     func bindViewModelToNavigationBarImage() {
127
-        navigationBarViewImage.setImage(groupItem.group_avatar,
128
-                                        placeholder: UIImage(named: "Group\(groupItem.group_default_avatar)"))
126
+        viewModel.groupAvatar
127
+            .subscribe(onNext: {[weak self] (avatar) in
128
+                guard let `self` = self else { return }
129
+                self.navigationBarViewImage.image = UIImage(named: avatar)
130
+        }).disposed(by: disposeBag)
131
+        
129 132
     }
130 133
 }
131 134
 
@@ -160,6 +163,8 @@ extension GroupViewController: NavigationBarInteractiveViewController {
160 163
     }
161 164
     
162 165
     @objc func presentGroupQR() {
166
+        
167
+        let groupItem = viewModel.groupItem.value
163 168
         let alert = AlertViewController(style: .custom(GroupQRView(groupName: groupItem.group_name,
164 169
                                                                    groupAvatar: "Group\(groupItem.group_default_avatar)",
165 170
                                                                    groupQR: "https:pai.ai/g/\(groupItem.group_id)"),
@@ -211,10 +216,6 @@ fileprivate extension GroupViewController {
211 216
     }
212 217
 }
213 218
 
214
-extension GroupViewController {
215
-    
216
-}
217
-
218 219
 extension GroupViewController: UICollectionViewDelegateFlowLayout {
219 220
     func collectionView(_ collectionView: UICollectionView,
220 221
                         layout collectionViewLayout: UICollectionViewLayout,

+ 31 - 46
PaiAi/Paiai_iOS/App/Home/CreateGroupConfirmViewController.swift

@@ -7,67 +7,52 @@
7 7
 //
8 8
 
9 9
 import UIKit
10
-import RxSwift
11 10
 import PaiaiDataKit
12 11
 import PaiaiUIKit
13 12
 
14 13
 
15 14
 final class CreateGroupConfirmViewController: AlertViewController {
15
+    
16
+    override var animationView: UIView? {
17
+        return tipView
18
+    }
19
+    
16 20
     // MARK: Storyboard property
17
-    @IBOutlet var tipView: UIView!
18
-    @IBOutlet var nameLabel: UILabel!
19
-    @IBOutlet var imageView: UIImageView!
21
+    @IBOutlet weak var tipView: UIView!
22
+    @IBOutlet weak var nameLabel: UILabel!
23
+    @IBOutlet weak var imageView: UIImageView!
20 24
     
21
-    var viewModel = CreateGroupConfirmViewModel()
22
-    var disposeBag = DisposeBag()
25
+    var viewModel: CreateGroupViewModel!
23 26
 
24 27
     override func viewDidLoad() {
25 28
         super.viewDidLoad()
26
-        configurationRx()
27
-    }
28
-    
29
-    func configurationRx() {
30
-        viewModel.name.bind(to: nameLabel.rx.text).disposed(by: disposeBag)
29
+        binding()
31 30
     }
32
-    
33
-    // MARK: Storyboard  button function
31
+}
32
+
33
+/// storyboard button action
34
+extension CreateGroupConfirmViewController {
34 35
     @IBAction func confirmAction() {
35
-        self.viewModel.createGroup()
36
+        viewModel.createGroup()
36 37
     }
37 38
     
38
-    override var animationView: UIView? {
39
-        return tipView
40
-    }
41
-
42
-//    func createGroup(_ name: String, avatar: Int) {
43
-//        let params = ["user_id": SharedUserInfo.userId, "group_name": name, "group_default_avatar": avatar] as [String: AnyObject]
44
-//        FFToastView.showLoadingToast(inView: view, blockSuperView: true)
45
-////        let request = CommonNetworkRequest<GroupModel>(param: params, path: .groupCreate)
46
-////        NetworkApi.share.post(request: request) {[weak self] (res) in
47
-////            guard let weakself = self else {
48
-////                return
49
-////            }
50
-////            weakself.group = res.first ?? GroupModel()
51
-////            weakself.confirmAndJump()
52
-////
53
-////        }
54
-//    }
55
-
56
-//    func confirmAndJump() {
57
-//        let ctl = UIStoryboard.main.instantiateController(GroupViewController.self)
58
-//        ctl.groupModel = group
59
-//        ctl.isCreate = true
60
-//        guard let parentController = presentingViewController as? UINavigationController else {
61
-//            return
62
-//        }
63
-//        guard let rootController = parentController.viewControllers.first as? HomeViewController else {
64
-//            return
65
-//        }
66
-//        dismissController()
67
-//        rootController.navigationController?.pushViewController(ctl, animated: true)
68
-//    }
69
-
70 39
     @IBAction func cancelAction() {
71 40
         dismissController()
72 41
     }
73 42
 }
43
+
44
+/// binding UI
45
+extension CreateGroupConfirmViewController {
46
+    func binding() {
47
+        bindGroupName()
48
+        bindGroupAvatar()
49
+    }
50
+    
51
+    func bindGroupName() {
52
+        nameLabel.text = viewModel.name
53
+    }
54
+    
55
+    func bindGroupAvatar() {
56
+        imageView.image = UIImage(named: viewModel.avatar)
57
+    }
58
+}

+ 6 - 6
PaiAi/Paiai_iOS/App/Home/CreateGroupViewController.swift

@@ -35,7 +35,7 @@ final class CreateGroupViewController: AlertViewController {
35 35
     // MARK: view function
36 36
     override func viewDidLoad() {
37 37
         super.viewDidLoad()
38
-        contentHeightConstraint.constant = 48 + 44 * CGFloat(RecentGroupInfo.share.count + 1)
38
+        contentHeightConstraint.constant = 48 + 44 * CGFloat(ShareRecentGroupInfo.count + 1)
39 39
     }
40 40
 
41 41
     // MARK: Storyboard  button function
@@ -50,7 +50,7 @@ extension CreateGroupViewController: UITableViewDataSource, UITableViewDelegate
50 50
     }
51 51
 
52 52
     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
53
-        return RecentGroupInfo.share.count + 1
53
+        return ShareRecentGroupInfo.count + 1
54 54
     }
55 55
 
56 56
     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
@@ -59,7 +59,7 @@ extension CreateGroupViewController: UITableViewDataSource, UITableViewDelegate
59 59
         case 0:
60 60
             self.delegate?.navigateToCreateGroupConfirm()
61 61
         default:
62
-            self.delegate?.didSelect(RecentGroupInfo.share[indexPath.row - 1])
62
+            self.delegate?.didSelect(ShareRecentGroupInfo[indexPath.row - 1])
63 63
         }
64 64
     }
65 65
 
@@ -70,9 +70,9 @@ extension CreateGroupViewController: UITableViewDataSource, UITableViewDelegate
70 70
             return cell
71 71
         default:
72 72
             let cell = tableView.dequeueReusableCell(withIdentifier: "RecentCell", for: indexPath)
73
-//            let group =
74
-//            (cell.viewWithTag(90) as? UILabel).flatMap {$0}?.text = group.group_name
75
-//            (cell.viewWithTag(90) as? UIImageView).flatMap {$0}?.setImageWithNullableURL(group.group_avatar, placeholderImage: UIImage(named: "Group\(group.group_default_avatar)"))
73
+            let group = ShareRecentGroupInfo[indexPath.row - 1]
74
+            cell.textLabel?.text = group.group_name
75
+            cell.imageView?.setImage(group.group_avatar, placeholder: UIImage(named: "Group\(group.group_default_avatar)"))
76 76
 
77 77
             return cell
78 78
         }

+ 44 - 7
PaiAi/Paiai_iOS/App/Home/HomeCoordinator.swift

@@ -11,12 +11,24 @@ import PaiaiDataKit
11 11
 import PaiaiUIKit
12 12
 
13 13
 class HomeCoordinator: Coordinator {
14
+    fileprivate enum CoordinatorKey: String {
15
+        case home = "home"
16
+        case message = "message"
17
+        case mine = "mine"
18
+        case photoDetail = "photoDetail"
19
+        case group = "group"
20
+    }
21
+    fileprivate var coordinators = [CoordinatorKey: Coordinator]()
14 22
     
15 23
     var homeViewController: HomeViewController
24
+    var navigationController: UINavigationController
16 25
     var shareUserInfoViewModel: UserInfoViewModel
17 26
     
18
-    init(_ homeVC: HomeViewController, userInfoViewModel: UserInfoViewModel) {
27
+    init(_ homeVC: HomeViewController,
28
+         navigationController: UINavigationController,
29
+         userInfoViewModel: UserInfoViewModel) {
19 30
         homeViewController = homeVC
31
+        self.navigationController = navigationController
20 32
         shareUserInfoViewModel = userInfoViewModel
21 33
         homeViewController.viewModel.delegate = self
22 34
     }
@@ -27,9 +39,14 @@ class HomeCoordinator: Coordinator {
27 39
 }
28 40
 
29 41
 extension HomeCoordinator: HomeViewModelDelegate {
30
-    func didSelect(_ item: PhotoItem) {
31
-        let ctl = UIStoryboard.photoDetail.instantiateController(DetailPageController.self)
32
-        homeViewController.pushController(ctl)
42
+    func didSelect(_ items: [PhotoItem], currIndex: Int) {
43
+        let ctl = UIStoryboard.photoDetail.instantiateController(PhotoDetailViewController.self)
44
+        let coordinator = PhotoDetailCoordinator(ctl, nav: navigationController,
45
+                                                 viewModel: PhotoDetailViewModel(item: items[currIndex]),
46
+                                                 listViewModel: PhotoDetailListViewModel(items: items, currIndex: currIndex))
47
+        coordinators[.photoDetail] = coordinator
48
+        coordinator.start()
49
+        navigationController.pushViewController(coordinator.photoDetailViewController)
33 50
     }
34 51
     
35 52
     func createGroup() {
@@ -46,16 +63,36 @@ extension HomeCoordinator: HomeViewModelDelegate {
46 63
 
47 64
 extension HomeCoordinator: CreateGroupViewControllerDelegate {
48 65
     func didSelect(_ item: GroupItem) {
49
-//        let ctl = UIStoryboard.
66
+        let ctl = UIStoryboard.group.instantiateController(GroupViewController.self)
67
+        ctl.viewModel = GroupViewModel(groupItem: item)
68
+        let coordinator = GroupCoordinator(ctl,
69
+                                           navigationController: navigationController)
70
+        coordinators[.group] = coordinator
71
+        navigationController.pushViewController(ctl)
50 72
     }
51
-    
73
+
52 74
     func navigateToCreateGroupConfirm() {
53 75
         let ctl = UIStoryboard.main.instantiateCreateGroupConfirmViewController()
54
-        
76
+        ctl.viewModel = CreateGroupViewModel(userInfoViewModel: shareUserInfoViewModel)
77
+        ctl.viewModel.delegate = self
55 78
         homeViewController.presentController(ctl)
56 79
     }
57 80
 }
58 81
 
82
+extension HomeCoordinator: CreateGroupViewModelDelegate {
83
+    func navigationToGroup(_ item: GroupItem) {
84
+        guard let vc = homeViewController.presentedViewController, vc.isMember(of: CreateGroupConfirmViewController.self) else { return }
85
+        vc.dismissController()
86
+        
87
+        let ctl = UIStoryboard.group.instantiateController(GroupViewController.self)
88
+        let coordinator = GroupCoordinator(ctl,
89
+                                           navigationController: navigationController)
90
+        coordinators[.group] = coordinator
91
+        ctl.viewModel = GroupViewModel(groupItem: item)
92
+        navigationController.pushViewController(ctl)
93
+    }
94
+}
95
+
59 96
 extension UIStoryboard {
60 97
     fileprivate func instantiateCreateGroupViewController() -> CreateGroupViewController {
61 98
         let createGroupVC = instantiateController(CreateGroupViewController.self)

+ 3 - 3
PaiAi/Paiai_iOS/App/Home/HomeViewController.swift

@@ -120,9 +120,9 @@ fileprivate extension HomeViewController {
120 120
             .drive(onNext: { [unowned self] in self.preload(indexPath: $0.at) })
121 121
             .disposed(by: disposeBag)
122 122
         
123
-        collectionView.rx.modelSelected(PhotoItem.self)
124
-            .asDriver()
125
-            .drive(onNext: { [unowned self] in self.viewModel.didSelect($0) })
123
+        collectionView.rx.itemSelected
124
+            .asDriver(onErrorJustReturn: IndexPath(item: 0, section: 0))
125
+            .drive(onNext: { [unowned self] in self.viewModel.didSelect($0.row) } )
126 126
             .disposed(by: disposeBag)
127 127
     }
128 128
     

+ 2 - 2
PaiAi/Paiai_iOS/App/Home/ScanQRViewController.swift

@@ -14,8 +14,8 @@ import PaiaiUIKit
14 14
 final class ScanQRViewController: UIViewController {
15 15
 
16 16
     // MARK: Storyboard property
17
-    @IBOutlet var scanView: QRCodeScanView!
18
-    @IBOutlet var lightLabel: UILabel!
17
+    @IBOutlet weak var scanView: QRCodeScanView!
18
+    @IBOutlet weak var lightLabel: UILabel!
19 19
 
20 20
    // MARK: parameter property
21 21
     var viewModel = ScanQRViewModel()

+ 4 - 4
PaiAi/Paiai_iOS/App/LoginViewController.swift

@@ -14,10 +14,10 @@ import RxSwift
14 14
 
15 15
 final class LoginViewController: UIViewController {
16 16
 
17
-    @IBOutlet var pageControl: UIPageControl!
18
-    @IBOutlet var scrollView: UIScrollView!
19
-    @IBOutlet var guestLoginBtn: UIButton!
20
-    @IBOutlet var weixinLoginBtn: UIButton!
17
+    @IBOutlet weak var pageControl: UIPageControl!
18
+    @IBOutlet weak var scrollView: UIScrollView!
19
+    @IBOutlet weak var guestLoginBtn: UIButton!
20
+    @IBOutlet weak var weixinLoginBtn: UIButton!
21 21
     
22 22
     public var userInfoViewModel: UserInfoViewModel!
23 23
     

+ 10 - 14
PaiAi/Paiai_iOS/App/Message/Message.storyboard

@@ -1,10 +1,6 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2 2
 <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
3
-    <device id="retina4_7" orientation="portrait">
4
-        <adaptation id="fullscreen"/>
5
-    </device>
6 3
     <dependencies>
7
-        <deployment identifier="iOS"/>
8 4
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
9 5
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
10 6
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -213,8 +209,8 @@
213 209
                                         <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
214 210
                                         <nil key="highlightedColor"/>
215 211
                                     </label>
216
-                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="列表箭头" translatesAutoresizingMaskIntoConstraints="NO" id="mre-Tt-F0S">
217
-                                        <rect key="frame" x="341" y="14" width="24" height="36"/>
212
+                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="mre-Tt-F0S">
213
+                                        <rect key="frame" x="349" y="24" width="16" height="16"/>
218 214
                                     </imageView>
219 215
                                     <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="T9q-a4-Ugc">
220 216
                                         <rect key="frame" x="0.0" y="64" width="375" height="64"/>
@@ -230,8 +226,8 @@
230 226
                                             <constraint firstAttribute="width" secondItem="NEm-bF-yno" secondAttribute="height" id="snW-w9-7b3"/>
231 227
                                         </constraints>
232 228
                                     </imageView>
233
-                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="列表箭头" translatesAutoresizingMaskIntoConstraints="NO" id="8VZ-dR-b6z">
234
-                                        <rect key="frame" x="341" y="78" width="24" height="36"/>
229
+                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="8VZ-dR-b6z">
230
+                                        <rect key="frame" x="349" y="88" width="16" height="16"/>
235 231
                                     </imageView>
236 232
                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="赞" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J3p-B7-gMi">
237 233
                                         <rect key="frame" x="70" y="86" width="17" height="20"/>
@@ -253,8 +249,8 @@
253 249
                                             <constraint firstAttribute="width" constant="48" id="Kmf-oj-nfI"/>
254 250
                                         </constraints>
255 251
                                     </imageView>
256
-                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="列表箭头" translatesAutoresizingMaskIntoConstraints="NO" id="hJe-J2-RpF">
257
-                                        <rect key="frame" x="341" y="142" width="24" height="36"/>
252
+                                    <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="hJe-J2-RpF">
253
+                                        <rect key="frame" x="349" y="152" width="16" height="16"/>
258 254
                                     </imageView>
259 255
                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="评论" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6fy-0a-WYd">
260 256
                                         <rect key="frame" x="70" y="150" width="33" height="20"/>
@@ -263,7 +259,7 @@
263 259
                                         <nil key="highlightedColor"/>
264 260
                                     </label>
265 261
                                     <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oLf-Xb-QSv">
266
-                                        <rect key="frame" x="325" y="28" width="8" height="8"/>
262
+                                        <rect key="frame" x="333" y="28" width="8" height="8"/>
267 263
                                         <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
268 264
                                         <constraints>
269 265
                                             <constraint firstAttribute="height" constant="8" id="8PB-CF-AvI"/>
@@ -276,7 +272,7 @@
276 272
                                         </userDefinedRuntimeAttributes>
277 273
                                     </view>
278 274
                                     <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="R8U-gK-x5D">
279
-                                        <rect key="frame" x="325" y="92" width="8" height="8"/>
275
+                                        <rect key="frame" x="333" y="92" width="8" height="8"/>
280 276
                                         <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
281 277
                                         <constraints>
282 278
                                             <constraint firstAttribute="height" constant="8" id="pvk-DY-af3"/>
@@ -289,7 +285,7 @@
289 285
                                         </userDefinedRuntimeAttributes>
290 286
                                     </view>
291 287
                                     <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Qi9-c7-GCt">
292
-                                        <rect key="frame" x="325" y="156" width="8" height="8"/>
288
+                                        <rect key="frame" x="333" y="156" width="8" height="8"/>
293 289
                                         <color key="backgroundColor" red="1" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
294 290
                                         <constraints>
295 291
                                             <constraint firstAttribute="height" constant="8" id="d1V-XC-UJk"/>
@@ -390,10 +386,10 @@
390 386
         </scene>
391 387
     </scenes>
392 388
     <resources>
389
+        <image name="list-arrow" width="16" height="16"/>
393 390
         <image name="message-comment" width="144" height="144"/>
394 391
         <image name="message-system" width="144" height="144"/>
395 392
         <image name="message-thumpub" width="144" height="144"/>
396
-        <image name="列表箭头" width="24" height="36"/>
397 393
         <image name="默认头像" width="240" height="240"/>
398 394
     </resources>
399 395
 </document>

+ 5 - 5
PaiAi/Paiai_iOS/App/Message/MessageCommentAndThumbupCell.swift

@@ -13,11 +13,11 @@ final class MessageCommentAndThumbupCell: UITableViewCell {
13 13
 
14 14
     // MARK: Storyboard property
15 15
     @IBOutlet weak var thumbupOrComment: UILabel!
16
-    @IBOutlet var userImage: UIImageView!
17
-    @IBOutlet var username: UILabel!
18
-    @IBOutlet var content: UILabel!
19
-    @IBOutlet var time: UILabel!
20
-    @IBOutlet var myPhoto: UIImageView!
16
+    @IBOutlet weak var userImage: UIImageView!
17
+    @IBOutlet weak var username: UILabel!
18
+    @IBOutlet weak var content: UILabel!
19
+    @IBOutlet weak var time: UILabel!
20
+    @IBOutlet weak var myPhoto: UIImageView!
21 21
 
22 22
     // MARK: view function
23 23
     override func awakeFromNib() {

+ 1 - 1
PaiAi/Paiai_iOS/App/Message/MessageListViewController.swift

@@ -20,7 +20,7 @@ protocol MessageViewControllerDelegate: class {
20 20
 
21 21
 final class MessageListViewController: UIViewController {
22 22
 
23
-    @IBOutlet var tableView: UITableView!
23
+    @IBOutlet weak var tableView: UITableView!
24 24
     
25 25
     var emptyView : UILabel = {
26 26
         let empty = UILabel(frame: CGRect(x: kScreenWidth / 2 - 50, y: 74, width: 50, height: 50))

+ 1 - 1
PaiAi/Paiai_iOS/App/Message/MessageSystemCell.swift

@@ -19,7 +19,7 @@ final class MessageSystemCell: UITableViewCell {
19 19
     
20 20
     func setInfo(_ info: MessageListItem) {
21 21
 //        userImage.setImageWithNullableURL(info.url, placeholderImage: defaultAvatar)
22
-        name.text = info.title
22
+        name.text = info.msg_title
23 23
         content.text = info.content
24 24
     }
25 25
 }

+ 3 - 3
PaiAi/Paiai_iOS/App/Message/MessageViewController.swift

@@ -12,9 +12,9 @@ import PaiaiDataKit
12 12
 
13 13
 class MessageViewController: UIViewController {
14 14
 
15
-    @IBOutlet var sysUnreadTip: UIView!
16
-    @IBOutlet var thumbupUnreadTip: UIView!
17
-    @IBOutlet var commentUnreadTip: UIView!
15
+    @IBOutlet weak var sysUnreadTip: UIView!
16
+    @IBOutlet weak var thumbupUnreadTip: UIView!
17
+    @IBOutlet weak var commentUnreadTip: UIView!
18 18
     
19 19
     @IBOutlet weak var sysBtn: UIButton!
20 20
     @IBOutlet weak var thumbupBtn: UIButton!

+ 3 - 3
PaiAi/Paiai_iOS/App/Mine/GroupCell.swift

@@ -13,9 +13,9 @@ import PaiaiUIKit
13 13
 final class GroupCell: UITableViewCell {
14 14
 
15 15
     // MARK: Storyboard property
16
-    @IBOutlet var groupImageView: UIImageView!
17
-    @IBOutlet var groupNameLabel: UILabel!
18
-    @IBOutlet var createTimeLabel: UILabel!
16
+    @IBOutlet weak var groupImageView: UIImageView!
17
+    @IBOutlet weak var groupNameLabel: UILabel!
18
+    @IBOutlet weak var createTimeLabel: UILabel!
19 19
     @IBOutlet weak var photoNumLabel: UILabel!
20 20
 
21 21
     // MARK: init interface

+ 8 - 15
PaiAi/Paiai_iOS/App/Mine/Mine.storyboard

@@ -42,7 +42,7 @@
42 42
                                                         </userDefinedRuntimeAttribute>
43 43
                                                     </userDefinedRuntimeAttributes>
44 44
                                                 </imageView>
45
-                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="列表箭头" translatesAutoresizingMaskIntoConstraints="NO" id="GAH-5d-ArA">
45
+                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="GAH-5d-ArA">
46 46
                                                     <rect key="frame" x="339" y="12" width="24" height="36"/>
47 47
                                                 </imageView>
48 48
                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bx9-cB-B0U">
@@ -127,23 +127,15 @@
127 127
                                 <fontDescription key="fontDescription" type="system" pointSize="14"/>
128 128
                                 <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
129 129
                             </textView>
130
-                            <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kyg-hG-JSP">
130
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kyg-hG-JSP">
131 131
                                 <rect key="frame" x="0.0" y="190" width="375" height="45"/>
132 132
                                 <constraints>
133 133
                                     <constraint firstAttribute="height" constant="45" id="x3X-y4-kmZ"/>
134 134
                                 </constraints>
135 135
                                 <fontDescription key="fontDescription" type="system" pointSize="20"/>
136
-                                <state key="normal" title="发送">
136
+                                <state key="normal" title="发送" backgroundImage="BTN-send">
137 137
                                     <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
138 138
                                 </state>
139
-                                <userDefinedRuntimeAttributes>
140
-                                    <userDefinedRuntimeAttribute type="color" keyPath="normalStatusBackgroundColor">
141
-                                        <color key="value" red="0.98431372549999996" green="0.31372549020000001" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
142
-                                    </userDefinedRuntimeAttribute>
143
-                                    <userDefinedRuntimeAttribute type="color" keyPath="pressedStatusBackgroundColor">
144
-                                        <color key="value" red="0.98431372549999996" green="0.31372549020000001" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
145
-                                    </userDefinedRuntimeAttribute>
146
-                                </userDefinedRuntimeAttributes>
147 139
                                 <connections>
148 140
                                     <action selector="sendFeedBack" destination="iwu-HG-AWF" eventType="touchUpInside" id="hQt-ku-2nH"/>
149 141
                                 </connections>
@@ -228,7 +220,7 @@
228 220
                                                 <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
229 221
                                                 <nil key="highlightedColor"/>
230 222
                                             </label>
231
-                                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="列表箭头" translatesAutoresizingMaskIntoConstraints="NO" id="MgR-ta-3jg">
223
+                                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="MgR-ta-3jg">
232 224
                                                 <rect key="frame" x="349" y="6" width="24" height="36"/>
233 225
                                             </imageView>
234 226
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="L1g-sb-a5F">
@@ -263,7 +255,7 @@
263 255
                                                 <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
264 256
                                                 <nil key="highlightedColor"/>
265 257
                                             </label>
266
-                                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="列表箭头" translatesAutoresizingMaskIntoConstraints="NO" id="vLw-Zd-Mis">
258
+                                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="vLw-Zd-Mis">
267 259
                                                 <rect key="frame" x="349" y="6" width="24" height="36"/>
268 260
                                             </imageView>
269 261
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FIE-jb-ZGu">
@@ -298,7 +290,7 @@
298 290
                                                 <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
299 291
                                                 <nil key="highlightedColor"/>
300 292
                                             </label>
301
-                                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="列表箭头" translatesAutoresizingMaskIntoConstraints="NO" id="mhJ-Uj-tdj">
293
+                                            <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="mhJ-Uj-tdj">
302 294
                                                 <rect key="frame" x="349" y="6" width="24" height="36"/>
303 295
                                             </imageView>
304 296
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VGv-oO-leT">
@@ -623,12 +615,13 @@
623 615
         </scene>
624 616
     </scenes>
625 617
     <resources>
618
+        <image name="BTN-send" width="608" height="304"/>
626 619
         <image name="Logo" width="140" height="140"/>
627 620
         <image name="about-contactUs" width="32" height="32"/>
628 621
         <image name="about-score" width="32" height="32"/>
629 622
         <image name="about-userAgreement" width="32" height="32"/>
623
+        <image name="list-arrow" width="24" height="36"/>
630 624
         <image name="navigation-background" width="12" height="132"/>
631
-        <image name="列表箭头" width="24" height="36"/>
632 625
         <image name="注销切图" width="32" height="32"/>
633 626
         <image name="默认头像" width="240" height="240"/>
634 627
     </resources>

+ 1 - 1
PaiAi/Paiai_iOS/App/Mine/MineAboutViewController.swift

@@ -17,7 +17,7 @@ final class MineAboutViewController: UIViewController {
17 17
     @IBOutlet weak var contactUsBtn: UIButton!
18 18
     @IBOutlet weak var scoreBtn: UIButton!
19 19
     @IBOutlet weak var userAgreementBtn: UIButton!
20
-    @IBOutlet var versionLabel: UILabel!
20
+    @IBOutlet weak var versionLabel: UILabel!
21 21
     
22 22
     private var disposeBag = DisposeBag()
23 23
     

+ 0 - 1
PaiAi/Paiai_iOS/App/Mine/MineCoordinator.swift

@@ -100,7 +100,6 @@ fileprivate extension MineCoordinator {
100 100
     func makeGroupViewController(item: GroupItem) -> GroupViewController {
101 101
         let vc = GroupViewController.instantiate()
102 102
         vc.viewModel = GroupViewModel(groupItem: item)
103
-        vc.groupItem = item
104 103
         return vc
105 104
     }
106 105
 }

+ 2 - 2
PaiAi/Paiai_iOS/App/Mine/MineFeedbackViewController.swift

@@ -15,8 +15,8 @@ import PaiaiUIKit
15 15
 final class MineFeedbackViewController: UIViewController {
16 16
 
17 17
     // MARK: Storyboard property
18
-    @IBOutlet var textView: UITextView!
19
-    @IBOutlet var sendBtn: UIButton!
18
+    @IBOutlet weak var textView: UITextView!
19
+    @IBOutlet weak var sendBtn: UIButton!
20 20
     fileprivate let disposeBag = DisposeBag()
21 21
     
22 22
     var feedbackAPI: FeedbackRemoteAPI!

+ 1 - 1
PaiAi/Paiai_iOS/App/Mine/MineGroupViewController.swift

@@ -17,7 +17,7 @@ import PullToRefresh
17 17
 final class MineGroupViewController: UIViewController {
18 18
 
19 19
     // MARK: Storyboard property
20
-    @IBOutlet var tableView: UITableView!
20
+    @IBOutlet weak var tableView: UITableView!
21 21
 
22 22
     // MARK: data property
23 23
     fileprivate let disposeBag = DisposeBag()

+ 1 - 1
PaiAi/Paiai_iOS/App/Mine/MineOrderViewController.swift

@@ -17,7 +17,7 @@ import PullToRefresh
17 17
 final class MineOrderViewController: UIViewController {
18 18
 
19 19
     // MARK: Storyboard property
20
-    @IBOutlet var tableView: UITableView!
20
+    @IBOutlet weak var tableView: UITableView!
21 21
     
22 22
     // MARK: data property
23 23
     fileprivate let disposeBag = DisposeBag()

+ 4 - 4
PaiAi/Paiai_iOS/App/Mine/OrderCell.swift

@@ -13,10 +13,10 @@ import PaiaiUIKit
13 13
 final class OrderCell: UITableViewCell {
14 14
 
15 15
     // MARK: Storyboard property
16
-    @IBOutlet var photo: UIImageView!
17
-    @IBOutlet var time: UILabel!
18
-    @IBOutlet var price: UILabel!
19
-    @IBOutlet var orderNumber: UILabel!
16
+    @IBOutlet weak var photo: UIImageView!
17
+    @IBOutlet weak var time: UILabel!
18
+    @IBOutlet weak var price: UILabel!
19
+    @IBOutlet weak var orderNumber: UILabel!
20 20
 
21 21
     // MARK: init interface
22 22
     func setInfo(_ info: OrderItem) {

+ 4 - 11
PaiAi/Paiai_iOS/App/PhotoDetail/ImageCell.swift

@@ -11,26 +11,20 @@ import PaiaiDataKit
11 11
 import PaiaiUIKit
12 12
 
13 13
 final class ImageCell: UICollectionViewCell, UIScrollViewDelegate {
14
-    @IBOutlet var scrollView: UIScrollView!
14
+    @IBOutlet weak var scrollView: UIScrollView!
15 15
     var photoImage = UIImageView()
16 16
 
17 17
     func setModel(url: String) {
18
-        photoImage.frame = CGRect.init(x: 0, y: 0, width: width, height: height)
18
+        photoImage.frame = CGRect(x: 0, y: 0, width: width, height: height)
19 19
         photoImage.contentMode = .scaleAspectFit
20 20
         scrollView.contentSize = size
21 21
         scrollView.addSubview(photoImage)
22
-//        photoImage.image = UIImage.imageWithColor(UIColor.black)
23
-        if !url.isEmpty {
24
-//            photoImage.setImageWithNullableURL(url, placeholderImage: UIImage(named: "详情页占位图"))
25
-        } else {
26
-            photoImage.image =  UIImage(named: url)
27
-        }
22
+        
23
+        photoImage.setImage(url, placeholder: UIImage.photoPlaceholder)
28 24
 
29 25
         let tapGr = UITapGestureRecognizer(target: self, action: #selector(ImageCell.doubleTap(_:)))
30 26
         tapGr.numberOfTapsRequired = 2
31 27
         scrollView.addGestureRecognizer(tapGr)
32
-
33
-//        printLog(scrollView)
34 28
     }
35 29
 
36 30
     func viewForZooming(in scrollView: UIScrollView) -> UIView? {
@@ -43,7 +37,6 @@ final class ImageCell: UICollectionViewCell, UIScrollViewDelegate {
43 37
         } else {
44 38
             //Zoom to rect
45 39
             let tapPt = gr.location(in: scrollView)
46
-//            printLog(tapPt)
47 40
             var zoomRect = CGRect.zero
48 41
             zoomRect.size.width = frame.width / scrollView.maximumZoomScale
49 42
             zoomRect.size.height = frame.height / scrollView.maximumZoomScale

+ 349 - 494
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoDetail.storyboard

@@ -1,445 +1,300 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="qsT-Pc-Bhh">
2
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
3
+    <device id="retina4_7" orientation="portrait">
4
+        <adaptation id="fullscreen"/>
5
+    </device>
3 6
     <dependencies>
7
+        <deployment identifier="iOS"/>
4 8
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
9
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
5 10
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
6 11
     </dependencies>
7 12
     <scenes>
8
-        <!--ReportController-->
9
-        <scene sceneID="wUV-hi-YAV">
10
-            <objects>
11
-                <viewController storyboardIdentifier="ReportController" automaticallyAdjustsScrollViewInsets="NO" id="DkF-mX-lIk" userLabel="ReportController" customClass="ReportController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController">
12
-                    <layoutGuides>
13
-                        <viewControllerLayoutGuide type="top" id="4jJ-Gj-1F2"/>
14
-                        <viewControllerLayoutGuide type="bottom" id="ZhS-9D-uxH"/>
15
-                    </layoutGuides>
16
-                    <view key="view" contentMode="scaleToFill" id="VKJ-Rl-cDh">
17
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
18
-                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
19
-                        <subviews>
20
-                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dKK-5n-7NI">
21
-                                <rect key="frame" x="0.0" y="467" width="375" height="200"/>
22
-                                <subviews>
23
-                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="r4F-Uk-4U9">
24
-                                        <rect key="frame" x="0.0" y="152" width="375" height="48"/>
25
-                                        <constraints>
26
-                                            <constraint firstAttribute="height" constant="48" id="PNZ-IF-PSp"/>
27
-                                        </constraints>
28
-                                        <fontDescription key="fontDescription" type="system" pointSize="20"/>
29
-                                        <state key="normal" title="取消">
30
-                                            <color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
31
-                                        </state>
32
-                                        <connections>
33
-                                            <action selector="cancelAction:" destination="DkF-mX-lIk" eventType="touchUpInside" id="bXf-2r-PWF"/>
34
-                                        </connections>
35
-                                    </button>
36
-                                    <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="hrt-tA-trR">
37
-                                        <rect key="frame" x="0.0" y="0.0" width="375" height="152"/>
38
-                                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
39
-                                        <prototypes>
40
-                                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="reportCell" id="mem-R8-etc">
41
-                                                <rect key="frame" x="0.0" y="28" width="375" height="44"/>
42
-                                                <autoresizingMask key="autoresizingMask"/>
43
-                                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="mem-R8-etc" id="tpv-xM-lZp">
44
-                                                    <rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
45
-                                                    <autoresizingMask key="autoresizingMask"/>
46
-                                                </tableViewCellContentView>
47
-                                            </tableViewCell>
48
-                                        </prototypes>
49
-                                        <connections>
50
-                                            <outlet property="dataSource" destination="DkF-mX-lIk" id="NNr-XE-WFH"/>
51
-                                            <outlet property="delegate" destination="DkF-mX-lIk" id="Ar9-vT-UJr"/>
52
-                                        </connections>
53
-                                    </tableView>
54
-                                </subviews>
55
-                                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
56
-                                <constraints>
57
-                                    <constraint firstAttribute="trailing" secondItem="r4F-Uk-4U9" secondAttribute="trailing" id="QiQ-0q-XK9"/>
58
-                                    <constraint firstAttribute="bottom" secondItem="r4F-Uk-4U9" secondAttribute="bottom" id="TWR-hL-NWZ"/>
59
-                                    <constraint firstItem="r4F-Uk-4U9" firstAttribute="leading" secondItem="dKK-5n-7NI" secondAttribute="leading" id="XkS-7p-opA"/>
60
-                                    <constraint firstItem="r4F-Uk-4U9" firstAttribute="top" secondItem="hrt-tA-trR" secondAttribute="bottom" id="haU-qN-JV2"/>
61
-                                    <constraint firstItem="hrt-tA-trR" firstAttribute="leading" secondItem="dKK-5n-7NI" secondAttribute="leading" id="loV-jI-jzd"/>
62
-                                    <constraint firstAttribute="height" constant="200" id="m2O-Lg-r1R"/>
63
-                                    <constraint firstItem="hrt-tA-trR" firstAttribute="top" secondItem="dKK-5n-7NI" secondAttribute="top" id="rtt-WL-c3Z"/>
64
-                                    <constraint firstAttribute="trailing" secondItem="hrt-tA-trR" secondAttribute="trailing" id="wVv-Cc-7Ox"/>
65
-                                </constraints>
66
-                            </view>
67
-                        </subviews>
68
-                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
69
-                        <constraints>
70
-                            <constraint firstItem="ZhS-9D-uxH" firstAttribute="top" secondItem="dKK-5n-7NI" secondAttribute="bottom" id="8px-JV-5Rs"/>
71
-                            <constraint firstItem="dKK-5n-7NI" firstAttribute="leading" secondItem="VKJ-Rl-cDh" secondAttribute="leading" id="Vsd-a3-Kp9"/>
72
-                            <constraint firstAttribute="trailing" secondItem="dKK-5n-7NI" secondAttribute="trailing" id="pCe-x1-6IP"/>
73
-                        </constraints>
74
-                    </view>
75
-                    <connections>
76
-                        <outlet property="contentView" destination="dKK-5n-7NI" id="I15-oP-aR3"/>
77
-                        <outlet property="reportTableView" destination="hrt-tA-trR" id="gkP-cc-Emj"/>
78
-                    </connections>
79
-                </viewController>
80
-                <placeholder placeholderIdentifier="IBFirstResponder" id="FMr-bp-t1r" userLabel="First Responder" sceneMemberID="firstResponder"/>
81
-            </objects>
82
-            <point key="canvasLocation" x="-953.60000000000002" y="1390.704647676162"/>
83
-        </scene>
84 13
         <!--PhotoDetailViewController-->
85 14
         <scene sceneID="OIh-Ut-mfb">
86 15
             <objects>
87
-                <viewController storyboardIdentifier="PhotoDetailViewController" automaticallyAdjustsScrollViewInsets="NO" id="qsT-Pc-Bhh" userLabel="PhotoDetailViewController" customClass="PhotoDetailViewController" customModule="PaiAi" sceneMemberID="viewController">
88
-                    <layoutGuides>
89
-                        <viewControllerLayoutGuide type="top" id="aUY-hC-XIK"/>
90
-                        <viewControllerLayoutGuide type="bottom" id="9RM-c8-CL6"/>
91
-                    </layoutGuides>
16
+                <viewController storyboardIdentifier="PhotoDetailViewController" automaticallyAdjustsScrollViewInsets="NO" id="qsT-Pc-Bhh" userLabel="PhotoDetailViewController" customClass="PhotoDetailViewController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController">
92 17
                     <view key="view" contentMode="scaleToFill" id="DXj-L8-o9b">
93
-                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
18
+                        <rect key="frame" x="0.0" y="0.0" width="375" height="1000"/>
94 19
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
95 20
                         <subviews>
96
-                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" style="plain" allowsSelection="NO" rowHeight="409" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="BJb-h6-o9s">
97
-                                <rect key="frame" x="0.0" y="20" width="375" height="647"/>
98
-                                <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
99
-                                <color key="separatorColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
100
-                                <prototypes>
101
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="headCell" rowHeight="48" id="i3U-Ls-3d4" customClass="DetailPageHeadCell" customModule="Paiai_iOS" customModuleProvider="target">
102
-                                        <rect key="frame" x="0.0" y="28" width="375" height="48"/>
103
-                                        <autoresizingMask key="autoresizingMask"/>
104
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="i3U-Ls-3d4" id="wrX-0i-fve">
105
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="47.5"/>
106
-                                            <autoresizingMask key="autoresizingMask"/>
21
+                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="fD2-Ow-gtt">
22
+                                <rect key="frame" x="0.0" y="20" width="375" height="980"/>
23
+                                <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
24
+                                <view key="tableHeaderView" contentMode="scaleToFill" id="kJj-s4-SK1" userLabel="header view">
25
+                                    <rect key="frame" x="0.0" y="0.0" width="375" height="533"/>
26
+                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
27
+                                    <subviews>
28
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rL2-VZ-0O7" userLabel="Group Info View">
29
+                                            <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
107 30
                                             <subviews>
108
-                                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mcz-eC-zz1">
109
-                                                    <rect key="frame" x="0.0" y="0.0" width="375" height="47.5"/>
31
+                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="nng-M9-7cj">
32
+                                                    <rect key="frame" x="10" y="10" width="28" height="28"/>
33
+                                                    <constraints>
34
+                                                        <constraint firstAttribute="width" secondItem="nng-M9-7cj" secondAttribute="height" id="69G-dm-HcL"/>
35
+                                                        <constraint firstAttribute="width" constant="28" id="Pq9-h7-Ls2"/>
36
+                                                    </constraints>
37
+                                                    <userDefinedRuntimeAttributes>
38
+                                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
39
+                                                            <real key="value" value="14"/>
40
+                                                        </userDefinedRuntimeAttribute>
41
+                                                        <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
42
+                                                            <real key="value" value="0.5"/>
43
+                                                        </userDefinedRuntimeAttribute>
44
+                                                        <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
45
+                                                            <color key="value" white="0.66666666669999997" alpha="1" colorSpace="calibratedWhite"/>
46
+                                                        </userDefinedRuntimeAttribute>
47
+                                                    </userDefinedRuntimeAttributes>
48
+                                                </imageView>
49
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XM7-FX-tOk">
50
+                                                    <rect key="frame" x="48" y="15.5" width="43" height="17"/>
51
+                                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
52
+                                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
53
+                                                    <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
54
+                                                    <nil key="highlightedColor"/>
55
+                                                </label>
56
+                                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gSr-Cm-y1W">
57
+                                                    <rect key="frame" x="300" y="0.0" width="75" height="48"/>
110 58
                                                     <subviews>
111
-                                                        <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Qun-83-nZU">
112
-                                                            <rect key="frame" x="10" y="10" width="28" height="28"/>
113
-                                                            <constraints>
114
-                                                                <constraint firstAttribute="width" secondItem="Qun-83-nZU" secondAttribute="height" id="faj-ic-igd"/>
115
-                                                                <constraint firstAttribute="width" constant="28" id="lVF-LX-TCT"/>
116
-                                                            </constraints>
117
-                                                            <userDefinedRuntimeAttributes>
118
-                                                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
119
-                                                                    <real key="value" value="14"/>
120
-                                                                </userDefinedRuntimeAttribute>
121
-                                                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
122
-                                                                    <real key="value" value="0.5"/>
123
-                                                                </userDefinedRuntimeAttribute>
124
-                                                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
125
-                                                                    <color key="value" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
126
-                                                                </userDefinedRuntimeAttribute>
127
-                                                            </userDefinedRuntimeAttributes>
128
-                                                        </imageView>
129
-                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PYj-cS-z4N">
130
-                                                            <rect key="frame" x="48" y="15.5" width="43" height="17"/>
59
+                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="进入群" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VBE-46-KXK">
60
+                                                            <rect key="frame" x="19" y="18" width="31" height="12"/>
131 61
                                                             <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
132
-                                                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
133
-                                                            <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
62
+                                                            <fontDescription key="fontDescription" type="system" pointSize="10"/>
63
+                                                            <color key="textColor" red="0.98431372549999996" green="0.31372549020000001" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
134 64
                                                             <nil key="highlightedColor"/>
135 65
                                                         </label>
136
-                                                        <button opaque="NO" tag="40001" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="1wY-9u-hwn">
137
-                                                            <rect key="frame" x="243" y="11" width="60" height="25"/>
138
-                                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
139
-                                                            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="calibratedRGB"/>
140
-                                                            <state key="normal" title="举报"/>
141
-                                                        </button>
142
-                                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vNs-t5-E73">
143
-                                                            <rect key="frame" x="300" y="0.0" width="75" height="47.5"/>
144
-                                                            <subviews>
145
-                                                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="E7A-3b-Oup">
146
-                                                                    <rect key="frame" x="0.0" y="0.0" width="75" height="47.5"/>
147
-                                                                    <connections>
148
-                                                                        <action selector="enterGroup" destination="i3U-Ls-3d4" eventType="touchUpInside" id="u7N-vm-SPZ"/>
149
-                                                                    </connections>
150
-                                                                </button>
151
-                                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="进入群" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="KGW-c8-vqa">
152
-                                                                    <rect key="frame" x="19" y="18" width="31" height="12"/>
153
-                                                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
154
-                                                                    <fontDescription key="fontDescription" type="system" pointSize="10"/>
155
-                                                                    <color key="textColor" red="0.98431372549999996" green="0.31372549020000001" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
156
-                                                                    <nil key="highlightedColor"/>
157
-                                                                </label>
158
-                                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="进入群" translatesAutoresizingMaskIntoConstraints="NO" id="dhi-7u-NYu">
159
-                                                                    <rect key="frame" x="9" y="11.5" width="60" height="25"/>
160
-                                                                    <constraints>
161
-                                                                        <constraint firstAttribute="height" constant="25" id="dTO-tb-zE5"/>
162
-                                                                        <constraint firstAttribute="width" constant="60" id="mIF-dz-pKG"/>
163
-                                                                    </constraints>
164
-                                                                </imageView>
165
-                                                            </subviews>
166
-                                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
66
+                                                        <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="进入群" translatesAutoresizingMaskIntoConstraints="NO" id="70o-zv-I0l">
67
+                                                            <rect key="frame" x="9" y="11.5" width="60" height="25"/>
167 68
                                                             <constraints>
168
-                                                                <constraint firstAttribute="trailing" secondItem="KGW-c8-vqa" secondAttribute="trailing" constant="25" id="0dn-xR-eOs"/>
169
-                                                                <constraint firstAttribute="trailing" secondItem="dhi-7u-NYu" secondAttribute="trailing" constant="6" id="36c-1S-xFf"/>
170
-                                                                <constraint firstItem="E7A-3b-Oup" firstAttribute="top" secondItem="vNs-t5-E73" secondAttribute="top" id="GK3-PV-8bY"/>
171
-                                                                <constraint firstAttribute="trailing" secondItem="E7A-3b-Oup" secondAttribute="trailing" id="KSp-sT-kJX"/>
172
-                                                                <constraint firstAttribute="width" constant="75" id="TRt-Gp-4pZ"/>
173
-                                                                <constraint firstAttribute="bottom" secondItem="E7A-3b-Oup" secondAttribute="bottom" id="XJv-kC-HNg"/>
174
-                                                                <constraint firstItem="KGW-c8-vqa" firstAttribute="centerY" secondItem="vNs-t5-E73" secondAttribute="centerY" id="gzf-lb-UQR"/>
175
-                                                                <constraint firstItem="dhi-7u-NYu" firstAttribute="centerY" secondItem="vNs-t5-E73" secondAttribute="centerY" id="oVV-L7-SwG"/>
176
-                                                                <constraint firstItem="E7A-3b-Oup" firstAttribute="leading" secondItem="vNs-t5-E73" secondAttribute="leading" id="z56-tc-xs8"/>
69
+                                                                <constraint firstAttribute="height" constant="25" id="X8l-P5-3Rd"/>
70
+                                                                <constraint firstAttribute="width" constant="60" id="hNf-F0-tvW"/>
177 71
                                                             </constraints>
178
-                                                        </view>
72
+                                                        </imageView>
179 73
                                                     </subviews>
180
-                                                    <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
74
+                                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
181 75
                                                     <constraints>
182
-                                                        <constraint firstItem="Qun-83-nZU" firstAttribute="leading" secondItem="mcz-eC-zz1" secondAttribute="leading" constant="10" id="4Uk-DP-TXV"/>
183
-                                                        <constraint firstItem="PYj-cS-z4N" firstAttribute="leading" secondItem="Qun-83-nZU" secondAttribute="trailing" constant="10" id="4iY-yd-PZA"/>
184
-                                                        <constraint firstAttribute="trailing" secondItem="vNs-t5-E73" secondAttribute="trailing" id="VSQ-UO-9pM"/>
185
-                                                        <constraint firstItem="vNs-t5-E73" firstAttribute="top" secondItem="mcz-eC-zz1" secondAttribute="top" id="lDC-67-VeA"/>
186
-                                                        <constraint firstAttribute="bottom" secondItem="vNs-t5-E73" secondAttribute="bottom" id="m3i-3L-tTn"/>
187
-                                                        <constraint firstItem="Qun-83-nZU" firstAttribute="centerY" secondItem="mcz-eC-zz1" secondAttribute="centerY" id="vUx-nv-jbb"/>
188
-                                                        <constraint firstItem="PYj-cS-z4N" firstAttribute="centerY" secondItem="Qun-83-nZU" secondAttribute="centerY" id="vco-EW-1A0"/>
76
+                                                        <constraint firstAttribute="width" constant="75" id="BPB-Pz-Ugv"/>
77
+                                                        <constraint firstItem="70o-zv-I0l" firstAttribute="centerY" secondItem="gSr-Cm-y1W" secondAttribute="centerY" id="ByJ-1c-nyQ"/>
78
+                                                        <constraint firstItem="VBE-46-KXK" firstAttribute="centerY" secondItem="gSr-Cm-y1W" secondAttribute="centerY" id="bzl-Og-LB3"/>
79
+                                                        <constraint firstAttribute="trailing" secondItem="70o-zv-I0l" secondAttribute="trailing" constant="6" id="cio-Sc-fn0"/>
80
+                                                        <constraint firstAttribute="trailing" secondItem="VBE-46-KXK" secondAttribute="trailing" constant="25" id="weN-fs-GNd"/>
189 81
                                                     </constraints>
82
+                                                    <connections>
83
+                                                        <outletCollection property="gestureRecognizers" destination="EHE-XX-kIE" appends="YES" id="80J-8y-IJs"/>
84
+                                                    </connections>
190 85
                                                 </view>
191 86
                                             </subviews>
87
+                                            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
192 88
                                             <constraints>
193
-                                                <constraint firstItem="mcz-eC-zz1" firstAttribute="leading" secondItem="wrX-0i-fve" secondAttribute="leading" id="6eI-bf-ijz"/>
194
-                                                <constraint firstAttribute="trailing" secondItem="mcz-eC-zz1" secondAttribute="trailing" id="FHX-FY-vOl"/>
195
-                                                <constraint firstAttribute="bottom" secondItem="mcz-eC-zz1" secondAttribute="bottom" id="kkV-lT-uZs"/>
196
-                                                <constraint firstItem="mcz-eC-zz1" firstAttribute="top" secondItem="wrX-0i-fve" secondAttribute="top" id="tWa-Ve-Mgf"/>
89
+                                                <constraint firstAttribute="trailing" secondItem="gSr-Cm-y1W" secondAttribute="trailing" id="5tR-Qu-wtQ"/>
90
+                                                <constraint firstAttribute="bottom" secondItem="gSr-Cm-y1W" secondAttribute="bottom" id="NCO-KD-pVQ"/>
91
+                                                <constraint firstItem="XM7-FX-tOk" firstAttribute="leading" secondItem="nng-M9-7cj" secondAttribute="trailing" constant="10" id="Wig-8j-STm"/>
92
+                                                <constraint firstItem="nng-M9-7cj" firstAttribute="leading" secondItem="rL2-VZ-0O7" secondAttribute="leading" constant="10" id="ZHc-Mw-2tJ"/>
93
+                                                <constraint firstItem="gSr-Cm-y1W" firstAttribute="top" secondItem="rL2-VZ-0O7" secondAttribute="top" id="b1T-Xy-yZs"/>
94
+                                                <constraint firstItem="XM7-FX-tOk" firstAttribute="centerY" secondItem="nng-M9-7cj" secondAttribute="centerY" id="dVs-1n-mqL"/>
95
+                                                <constraint firstAttribute="height" constant="48" id="v42-oR-6qs"/>
96
+                                                <constraint firstItem="nng-M9-7cj" firstAttribute="centerY" secondItem="rL2-VZ-0O7" secondAttribute="centerY" id="zGd-66-ngX"/>
197 97
                                             </constraints>
198
-                                        </tableViewCellContentView>
199
-                                        <connections>
200
-                                            <outlet property="enterView" destination="vNs-t5-E73" id="wuj-yg-uj8"/>
201
-                                            <outlet property="groupImage" destination="Qun-83-nZU" id="vVq-cH-ZgN"/>
202
-                                            <outlet property="groupName" destination="PYj-cS-z4N" id="RdJ-r6-Jqw"/>
203
-                                        </connections>
204
-                                    </tableViewCell>
205
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="detailPagePhotoCell" rowHeight="360" id="5X4-7Q-chL" customClass="DetailPagePhotoCell" customModule="Paiai_iOS" customModuleProvider="target">
206
-                                        <rect key="frame" x="0.0" y="76" width="375" height="360"/>
207
-                                        <autoresizingMask key="autoresizingMask"/>
208
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="5X4-7Q-chL" id="yVY-TK-vg7">
209
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="359.5"/>
210
-                                            <autoresizingMask key="autoresizingMask"/>
211
-                                            <subviews>
212
-                                                <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="lAD-oZ-Zgp">
213
-                                                    <rect key="frame" x="0.0" y="0.0" width="375" height="359.5"/>
214
-                                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
215
-                                                    <collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="A4Q-fW-D0V">
216
-                                                        <size key="itemSize" width="375" height="319"/>
217
-                                                        <size key="headerReferenceSize" width="0.0" height="0.0"/>
218
-                                                        <size key="footerReferenceSize" width="0.0" height="0.0"/>
219
-                                                        <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
220
-                                                    </collectionViewFlowLayout>
221
-                                                    <cells>
222
-                                                        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="photoDetailCell" id="UJ2-Hm-obI">
223
-                                                            <rect key="frame" x="0.0" y="0.0" width="375" height="319"/>
224
-                                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
225
-                                                            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
98
+                                        </view>
99
+                                        <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" bounces="NO" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" bouncesZoom="NO" dataMode="prototypes" prefetchingEnabled="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dtf-M8-otl">
100
+                                            <rect key="frame" x="0.0" y="48" width="375" height="360"/>
101
+                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
102
+                                            <constraints>
103
+                                                <constraint firstAttribute="height" constant="360" id="4L8-84-zDa"/>
104
+                                            </constraints>
105
+                                            <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="xaD-fO-dLy">
106
+                                                <size key="itemSize" width="375" height="319"/>
107
+                                                <size key="headerReferenceSize" width="0.0" height="0.0"/>
108
+                                                <size key="footerReferenceSize" width="0.0" height="0.0"/>
109
+                                                <inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
110
+                                            </collectionViewFlowLayout>
111
+                                            <cells>
112
+                                                <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="photoDetailImageCell" id="odI-PO-hV5" customClass="PhotoDetailImageCell" customModule="Paiai_iOS" customModuleProvider="target">
113
+                                                    <rect key="frame" x="0.0" y="20.5" width="375" height="319"/>
114
+                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
115
+                                                    <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
116
+                                                        <rect key="frame" x="0.0" y="0.0" width="375" height="319"/>
117
+                                                        <autoresizingMask key="autoresizingMask"/>
118
+                                                        <subviews>
119
+                                                            <imageView userInteractionEnabled="NO" tag="1010" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="9v7-Ky-ukt">
226 120
                                                                 <rect key="frame" x="0.0" y="0.0" width="375" height="319"/>
227
-                                                                <autoresizingMask key="autoresizingMask"/>
228
-                                                                <subviews>
229
-                                                                    <imageView userInteractionEnabled="NO" tag="1010" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="ld5-dn-2RB">
230
-                                                                        <rect key="frame" x="0.0" y="0.0" width="375" height="319"/>
231
-                                                                    </imageView>
232
-                                                                </subviews>
233
-                                                            </view>
234
-                                                            <constraints>
235
-                                                                <constraint firstAttribute="trailing" secondItem="ld5-dn-2RB" secondAttribute="trailing" id="GLQ-xO-RUy"/>
236
-                                                                <constraint firstAttribute="bottom" secondItem="ld5-dn-2RB" secondAttribute="bottom" id="Ttz-Zt-E6n"/>
237
-                                                                <constraint firstItem="ld5-dn-2RB" firstAttribute="top" secondItem="UJ2-Hm-obI" secondAttribute="top" id="cSU-ct-Cep"/>
238
-                                                                <constraint firstItem="ld5-dn-2RB" firstAttribute="leading" secondItem="UJ2-Hm-obI" secondAttribute="leading" id="veK-zA-dfx"/>
239
-                                                            </constraints>
240
-                                                        </collectionViewCell>
241
-                                                    </cells>
121
+                                                            </imageView>
122
+                                                        </subviews>
123
+                                                    </view>
124
+                                                    <constraints>
125
+                                                        <constraint firstItem="9v7-Ky-ukt" firstAttribute="top" secondItem="odI-PO-hV5" secondAttribute="top" id="PCk-i0-Rwg"/>
126
+                                                        <constraint firstAttribute="bottom" secondItem="9v7-Ky-ukt" secondAttribute="bottom" id="R3n-1a-d5C"/>
127
+                                                        <constraint firstItem="9v7-Ky-ukt" firstAttribute="leading" secondItem="odI-PO-hV5" secondAttribute="leading" id="YBl-MG-BWY"/>
128
+                                                        <constraint firstAttribute="trailing" secondItem="9v7-Ky-ukt" secondAttribute="trailing" id="xxx-f9-RZf"/>
129
+                                                    </constraints>
242 130
                                                     <connections>
243
-                                                        <outlet property="dataSource" destination="5X4-7Q-chL" id="gmm-ci-u2l"/>
244
-                                                        <outlet property="delegate" destination="5X4-7Q-chL" id="RHM-y7-e7G"/>
131
+                                                        <outlet property="imageView" destination="9v7-Ky-ukt" id="wbu-di-9Ls"/>
245 132
                                                     </connections>
246
-                                                </collectionView>
247
-                                            </subviews>
248
-                                            <constraints>
249
-                                                <constraint firstAttribute="trailing" secondItem="lAD-oZ-Zgp" secondAttribute="trailing" id="0fy-qh-Y4r"/>
250
-                                                <constraint firstItem="lAD-oZ-Zgp" firstAttribute="leading" secondItem="yVY-TK-vg7" secondAttribute="leading" id="Fcg-rJ-o3p"/>
251
-                                                <constraint firstAttribute="bottom" secondItem="lAD-oZ-Zgp" secondAttribute="bottom" id="JiM-Rf-C9H"/>
252
-                                                <constraint firstItem="lAD-oZ-Zgp" firstAttribute="top" secondItem="yVY-TK-vg7" secondAttribute="top" id="Vdg-DU-USU"/>
253
-                                            </constraints>
254
-                                        </tableViewCellContentView>
255
-                                        <connections>
256
-                                            <outlet property="collectionView" destination="lAD-oZ-Zgp" id="DhH-TY-4el"/>
257
-                                        </connections>
258
-                                    </tableViewCell>
259
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="nameCell" rowHeight="47" id="4vg-z0-coW" customClass="DetailPageNameCell" customModule="Paiai_iOS" customModuleProvider="target">
260
-                                        <rect key="frame" x="0.0" y="436" width="375" height="47"/>
261
-                                        <autoresizingMask key="autoresizingMask"/>
262
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4vg-z0-coW" id="cco-VM-Dnu">
263
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="46.5"/>
264
-                                            <autoresizingMask key="autoresizingMask"/>
133
+                                                </collectionViewCell>
134
+                                            </cells>
135
+                                        </collectionView>
136
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rr6-c2-Nmb" userLabel="Photo Info View">
137
+                                            <rect key="frame" x="0.0" y="408" width="375" height="36"/>
265 138
                                             <subviews>
266
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="名字" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="waZ-4s-ioU">
267
-                                                    <rect key="frame" x="41" y="17.5" width="21" height="12"/>
139
+                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="defaultAvatar" translatesAutoresizingMaskIntoConstraints="NO" id="Zj6-ve-uzJ">
140
+                                                    <rect key="frame" x="15" y="8" width="20" height="20"/>
141
+                                                    <constraints>
142
+                                                        <constraint firstAttribute="width" constant="20" id="dui-uv-HdI"/>
143
+                                                        <constraint firstAttribute="width" secondItem="Zj6-ve-uzJ" secondAttribute="height" multiplier="1:1" id="mya-LW-5NJ"/>
144
+                                                    </constraints>
145
+                                                    <userDefinedRuntimeAttributes>
146
+                                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
147
+                                                            <real key="value" value="4"/>
148
+                                                        </userDefinedRuntimeAttribute>
149
+                                                    </userDefinedRuntimeAttributes>
150
+                                                </imageView>
151
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="名字" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jmc-9F-Uzr">
152
+                                                    <rect key="frame" x="41" y="12" width="21" height="12"/>
268 153
                                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
269 154
                                                     <fontDescription key="fontDescription" type="system" pointSize="10"/>
270 155
                                                     <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
271 156
                                                     <nil key="highlightedColor"/>
272 157
                                                 </label>
273
-                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon-记录" translatesAutoresizingMaskIntoConstraints="NO" id="jOJ-N0-rYP">
274
-                                                    <rect key="frame" x="286" y="5.5" width="36" height="36"/>
158
+                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon-time" translatesAutoresizingMaskIntoConstraints="NO" id="xXQ-Hj-wzP">
159
+                                                    <rect key="frame" x="286" y="0.0" width="36" height="36"/>
275 160
                                                 </imageView>
276
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="5分钟前" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d9Q-3T-h1t">
277
-                                                    <rect key="frame" x="328" y="17.5" width="37" height="12"/>
161
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="5分钟前" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QpI-Mp-URP">
162
+                                                    <rect key="frame" x="332" y="12" width="37" height="12"/>
278 163
                                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
279 164
                                                     <fontDescription key="fontDescription" type="system" pointSize="10"/>
280 165
                                                     <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
281 166
                                                     <nil key="highlightedColor"/>
282 167
                                                 </label>
283
-                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="默认头像" translatesAutoresizingMaskIntoConstraints="NO" id="ngb-KR-cA6">
284
-                                                    <rect key="frame" x="15" y="13.5" width="20" height="20"/>
285
-                                                    <constraints>
286
-                                                        <constraint firstAttribute="width" constant="20" id="cSl-og-Uae"/>
287
-                                                        <constraint firstAttribute="width" secondItem="ngb-KR-cA6" secondAttribute="height" id="fbg-yA-QyN"/>
288
-                                                    </constraints>
289
-                                                    <userDefinedRuntimeAttributes>
290
-                                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
291
-                                                            <real key="value" value="4"/>
292
-                                                        </userDefinedRuntimeAttribute>
293
-                                                    </userDefinedRuntimeAttributes>
294
-                                                </imageView>
295 168
                                             </subviews>
169
+                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
296 170
                                             <constraints>
297
-                                                <constraint firstItem="d9Q-3T-h1t" firstAttribute="leading" secondItem="jOJ-N0-rYP" secondAttribute="trailing" constant="6" id="DFx-VY-iOc"/>
298
-                                                <constraint firstItem="waZ-4s-ioU" firstAttribute="leading" secondItem="ngb-KR-cA6" secondAttribute="trailing" constant="6" id="Yai-Qc-Kxw"/>
299
-                                                <constraint firstItem="waZ-4s-ioU" firstAttribute="centerY" secondItem="cco-VM-Dnu" secondAttribute="centerY" id="aUY-C4-Hbb"/>
300
-                                                <constraint firstItem="ngb-KR-cA6" firstAttribute="width" secondItem="ngb-KR-cA6" secondAttribute="height" id="ery-Ch-bGL"/>
301
-                                                <constraint firstItem="jOJ-N0-rYP" firstAttribute="centerY" secondItem="waZ-4s-ioU" secondAttribute="centerY" id="m0E-Mf-ee0"/>
302
-                                                <constraint firstItem="waZ-4s-ioU" firstAttribute="centerY" secondItem="ngb-KR-cA6" secondAttribute="centerY" id="nUJ-pU-dXK"/>
303
-                                                <constraint firstItem="ngb-KR-cA6" firstAttribute="leading" secondItem="cco-VM-Dnu" secondAttribute="leading" constant="15" id="vfD-Pc-Dfp"/>
304
-                                                <constraint firstAttribute="trailing" secondItem="d9Q-3T-h1t" secondAttribute="trailing" constant="10" id="w69-ZT-64v"/>
305
-                                                <constraint firstItem="d9Q-3T-h1t" firstAttribute="centerY" secondItem="jOJ-N0-rYP" secondAttribute="centerY" id="zau-ES-xhb"/>
171
+                                                <constraint firstAttribute="trailing" secondItem="QpI-Mp-URP" secondAttribute="trailing" constant="6" id="GDW-SR-ql9"/>
172
+                                                <constraint firstItem="QpI-Mp-URP" firstAttribute="leading" secondItem="xXQ-Hj-wzP" secondAttribute="trailing" constant="10" id="NNQ-Rx-3ip"/>
173
+                                                <constraint firstItem="Zj6-ve-uzJ" firstAttribute="leading" secondItem="rr6-c2-Nmb" secondAttribute="leading" constant="15" id="NWK-xB-He1"/>
174
+                                                <constraint firstItem="jmc-9F-Uzr" firstAttribute="centerY" secondItem="rr6-c2-Nmb" secondAttribute="centerY" id="PsY-nq-8ao"/>
175
+                                                <constraint firstAttribute="height" constant="36" id="SUQ-5X-XLy"/>
176
+                                                <constraint firstItem="jmc-9F-Uzr" firstAttribute="leading" secondItem="Zj6-ve-uzJ" secondAttribute="trailing" constant="6" id="cr3-c0-hhq"/>
177
+                                                <constraint firstItem="QpI-Mp-URP" firstAttribute="centerY" secondItem="rr6-c2-Nmb" secondAttribute="centerY" id="eBQ-qI-A8r"/>
178
+                                                <constraint firstItem="Zj6-ve-uzJ" firstAttribute="centerY" secondItem="rr6-c2-Nmb" secondAttribute="centerY" id="t6b-zO-3rf"/>
179
+                                                <constraint firstItem="xXQ-Hj-wzP" firstAttribute="centerY" secondItem="rr6-c2-Nmb" secondAttribute="centerY" id="x1T-b0-thB"/>
306 180
                                             </constraints>
307
-                                        </tableViewCellContentView>
308
-                                        <connections>
309
-                                            <outlet property="personImage" destination="ngb-KR-cA6" id="UKC-bx-df1"/>
310
-                                            <outlet property="personName" destination="waZ-4s-ioU" id="7kC-Jy-joK"/>
311
-                                            <outlet property="time" destination="d9Q-3T-h1t" id="8ku-p3-pIy"/>
312
-                                        </connections>
313
-                                    </tableViewCell>
314
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="thumbupHeadCell" rowHeight="45" id="drb-Ur-Tep">
315
-                                        <rect key="frame" x="0.0" y="483" width="375" height="45"/>
316
-                                        <autoresizingMask key="autoresizingMask"/>
317
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="drb-Ur-Tep" id="BWN-JQ-YDl">
318
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="44.5"/>
319
-                                            <autoresizingMask key="autoresizingMask"/>
181
+                                        </view>
182
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="q4A-0r-b7Z" userLabel="Thumbup Head View">
183
+                                            <rect key="frame" x="0.0" y="444" width="375" height="44"/>
320 184
                                             <subviews>
321
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="赞" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="G5n-Xf-7Hy">
322
-                                                    <rect key="frame" x="57" y="14" width="15" height="17"/>
185
+                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon-thumbup" translatesAutoresizingMaskIntoConstraints="NO" id="haH-1L-wfF">
186
+                                                    <rect key="frame" x="15" y="4" width="36" height="36"/>
187
+                                                </imageView>
188
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="赞" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vrx-vV-ymg">
189
+                                                    <rect key="frame" x="57" y="13.5" width="14.5" height="17"/>
323 190
                                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
324 191
                                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
325 192
                                                     <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
326 193
                                                     <nil key="highlightedColor"/>
327 194
                                                 </label>
328
-                                                <imageView userInteractionEnabled="NO" tag="1008" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="pC6-7A-WSm">
329
-                                                    <rect key="frame" x="349" y="14.5" width="16" height="16"/>
330
-                                                </imageView>
331
-                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon-赞" translatesAutoresizingMaskIntoConstraints="NO" id="jXa-8T-THD">
332
-                                                    <rect key="frame" x="15" y="4.5" width="36" height="36"/>
333
-                                                </imageView>
334
-                                                <label opaque="NO" userInteractionEnabled="NO" tag="1001" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(0)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="60x-jR-ECW">
335
-                                                    <rect key="frame" x="72" y="15" width="17" height="15"/>
195
+                                                <label opaque="NO" userInteractionEnabled="NO" tag="1002" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(0)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h88-PP-cvG">
196
+                                                    <rect key="frame" x="77.5" y="14.5" width="17" height="15"/>
336 197
                                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
337 198
                                                     <fontDescription key="fontDescription" type="system" pointSize="12"/>
338 199
                                                     <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
339 200
                                                     <nil key="highlightedColor"/>
340 201
                                                 </label>
341
-                                                <button opaque="NO" tag="1011" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LBo-30-wNB">
342
-                                                    <rect key="frame" x="0.0" y="0.0" width="375" height="44.5"/>
343
-                                                </button>
202
+                                                <imageView userInteractionEnabled="NO" tag="1008" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="sg5-Nx-u2C">
203
+                                                    <rect key="frame" x="341" y="4" width="24" height="36"/>
204
+                                                </imageView>
344 205
                                             </subviews>
345
-                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
206
+                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
346 207
                                             <constraints>
347
-                                                <constraint firstItem="60x-jR-ECW" firstAttribute="leading" secondItem="G5n-Xf-7Hy" secondAttribute="trailing" id="9q1-CU-lc7"/>
348
-                                                <constraint firstItem="pC6-7A-WSm" firstAttribute="centerY" secondItem="BWN-JQ-YDl" secondAttribute="centerY" id="GBf-JN-0V2"/>
349
-                                                <constraint firstItem="jXa-8T-THD" firstAttribute="leading" secondItem="BWN-JQ-YDl" secondAttribute="leading" constant="15" id="GLF-x3-OKn"/>
350
-                                                <constraint firstItem="LBo-30-wNB" firstAttribute="leading" secondItem="BWN-JQ-YDl" secondAttribute="leading" id="JoW-OJ-4RR"/>
351
-                                                <constraint firstItem="60x-jR-ECW" firstAttribute="centerY" secondItem="G5n-Xf-7Hy" secondAttribute="centerY" id="KDe-lJ-k9I"/>
352
-                                                <constraint firstAttribute="trailing" secondItem="pC6-7A-WSm" secondAttribute="trailing" constant="10" id="TIX-Ap-qwt"/>
353
-                                                <constraint firstItem="G5n-Xf-7Hy" firstAttribute="centerY" secondItem="jXa-8T-THD" secondAttribute="centerY" id="aY4-8A-f3G"/>
354
-                                                <constraint firstAttribute="trailing" secondItem="LBo-30-wNB" secondAttribute="trailing" id="mO4-S9-lSy"/>
355
-                                                <constraint firstItem="jXa-8T-THD" firstAttribute="centerY" secondItem="BWN-JQ-YDl" secondAttribute="centerY" id="nGe-eB-vLt"/>
356
-                                                <constraint firstAttribute="bottom" secondItem="LBo-30-wNB" secondAttribute="bottom" id="rzW-nS-eo8"/>
357
-                                                <constraint firstItem="G5n-Xf-7Hy" firstAttribute="leading" secondItem="jXa-8T-THD" secondAttribute="trailing" constant="6" id="vMx-nk-gUB"/>
358
-                                                <constraint firstItem="LBo-30-wNB" firstAttribute="top" secondItem="BWN-JQ-YDl" secondAttribute="top" id="xOJ-uY-wdZ"/>
208
+                                                <constraint firstItem="vrx-vV-ymg" firstAttribute="centerY" secondItem="q4A-0r-b7Z" secondAttribute="centerY" id="2aB-mH-SX5"/>
209
+                                                <constraint firstAttribute="trailing" secondItem="sg5-Nx-u2C" secondAttribute="trailing" constant="10" id="Xcf-rE-5in"/>
210
+                                                <constraint firstItem="haH-1L-wfF" firstAttribute="leading" secondItem="q4A-0r-b7Z" secondAttribute="leading" constant="15" id="coB-Ko-wkQ"/>
211
+                                                <constraint firstAttribute="height" constant="44" id="iuu-F3-RtX"/>
212
+                                                <constraint firstItem="haH-1L-wfF" firstAttribute="centerY" secondItem="q4A-0r-b7Z" secondAttribute="centerY" id="j94-Un-Fr7"/>
213
+                                                <constraint firstItem="h88-PP-cvG" firstAttribute="centerY" secondItem="q4A-0r-b7Z" secondAttribute="centerY" id="miO-hD-cUC"/>
214
+                                                <constraint firstItem="h88-PP-cvG" firstAttribute="leading" secondItem="vrx-vV-ymg" secondAttribute="trailing" constant="6" id="okS-hS-zFj"/>
215
+                                                <constraint firstItem="vrx-vV-ymg" firstAttribute="leading" secondItem="haH-1L-wfF" secondAttribute="trailing" constant="6" id="rQM-ic-NS0"/>
216
+                                                <constraint firstItem="sg5-Nx-u2C" firstAttribute="centerY" secondItem="q4A-0r-b7Z" secondAttribute="centerY" id="yjO-bc-Du8"/>
359 217
                                             </constraints>
360
-                                        </tableViewCellContentView>
361
-                                    </tableViewCell>
362
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="thumbupCell" rowHeight="40" id="53z-YY-Hrb" customClass="DetailthumbupImagesCell" customModule="Paiai_iOS" customModuleProvider="target">
363
-                                        <rect key="frame" x="0.0" y="528" width="375" height="40"/>
364
-                                        <autoresizingMask key="autoresizingMask"/>
365
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="53z-YY-Hrb" id="L28-C6-ile">
366
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="39.5"/>
367
-                                            <autoresizingMask key="autoresizingMask"/>
368
-                                            <subviews>
369
-                                                <scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MCX-77-Qga">
370
-                                                    <rect key="frame" x="0.0" y="0.0" width="375" height="39.5"/>
371
-                                                </scrollView>
372
-                                            </subviews>
218
+                                        </view>
219
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Zde-8U-5Bl" userLabel="Thumbup View">
220
+                                            <rect key="frame" x="0.0" y="488" width="375" height="1"/>
221
+                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
373 222
                                             <constraints>
374
-                                                <constraint firstAttribute="trailing" secondItem="MCX-77-Qga" secondAttribute="trailing" id="2pY-hr-G4z"/>
375
-                                                <constraint firstItem="MCX-77-Qga" firstAttribute="leading" secondItem="L28-C6-ile" secondAttribute="leading" id="YJo-K5-cWs"/>
376
-                                                <constraint firstAttribute="bottom" secondItem="MCX-77-Qga" secondAttribute="bottom" id="nby-bv-mI5"/>
377
-                                                <constraint firstItem="MCX-77-Qga" firstAttribute="top" secondItem="L28-C6-ile" secondAttribute="top" id="wbM-of-emg"/>
223
+                                                <constraint firstAttribute="height" constant="1" id="fc8-6l-lEC"/>
378 224
                                             </constraints>
379
-                                        </tableViewCellContentView>
380
-                                        <connections>
381
-                                            <outlet property="imagesScrollView" destination="MCX-77-Qga" id="qdA-ux-1Op"/>
382
-                                        </connections>
383
-                                    </tableViewCell>
384
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="comentHeadCell" rowHeight="45" id="avB-IM-8sZ">
385
-                                        <rect key="frame" x="0.0" y="568" width="375" height="45"/>
386
-                                        <autoresizingMask key="autoresizingMask"/>
387
-                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="avB-IM-8sZ" id="B2U-lF-5Lm">
388
-                                            <rect key="frame" x="0.0" y="0.0" width="375" height="44.5"/>
389
-                                            <autoresizingMask key="autoresizingMask"/>
225
+                                        </view>
226
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IOw-Xw-2vP" userLabel="Comment Head View">
227
+                                            <rect key="frame" x="0.0" y="489" width="375" height="44"/>
390 228
                                             <subviews>
391
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="评论" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sbI-Yk-yw3">
392
-                                                    <rect key="frame" x="57" y="14" width="29" height="17"/>
229
+                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon-comment" translatesAutoresizingMaskIntoConstraints="NO" id="zTQ-T2-IMt">
230
+                                                    <rect key="frame" x="15" y="4" width="36" height="36"/>
231
+                                                </imageView>
232
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="评论" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vLK-B7-FQc">
233
+                                                    <rect key="frame" x="57" y="13.5" width="29" height="17"/>
393 234
                                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
394 235
                                                     <fontDescription key="fontDescription" type="system" pointSize="14"/>
395 236
                                                     <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
396 237
                                                     <nil key="highlightedColor"/>
397 238
                                                 </label>
398
-                                                <imageView userInteractionEnabled="NO" tag="1009" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="GOS-Xt-kBa">
399
-                                                    <rect key="frame" x="349" y="14.5" width="16" height="16"/>
400
-                                                </imageView>
401
-                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon-评论" translatesAutoresizingMaskIntoConstraints="NO" id="7bL-8L-k4P">
402
-                                                    <rect key="frame" x="15" y="4.5" width="36" height="36"/>
403
-                                                </imageView>
404
-                                                <label opaque="NO" userInteractionEnabled="NO" tag="1002" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(0)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vvS-oJ-TqJ">
405
-                                                    <rect key="frame" x="86" y="15" width="17" height="15"/>
239
+                                                <label opaque="NO" userInteractionEnabled="NO" tag="1002" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="(0)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cuT-s1-NnA">
240
+                                                    <rect key="frame" x="92" y="14.5" width="17" height="15"/>
406 241
                                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
407 242
                                                     <fontDescription key="fontDescription" type="system" pointSize="12"/>
408 243
                                                     <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
409 244
                                                     <nil key="highlightedColor"/>
410 245
                                                 </label>
411
-                                                <button opaque="NO" tag="1012" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qe6-le-PxN">
412
-                                                    <rect key="frame" x="0.0" y="0.0" width="375" height="44.5"/>
413
-                                                </button>
246
+                                                <imageView userInteractionEnabled="NO" tag="1009" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="ns5-B1-ilP">
247
+                                                    <rect key="frame" x="341" y="4" width="24" height="36"/>
248
+                                                </imageView>
414 249
                                             </subviews>
415
-                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
250
+                                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
416 251
                                             <constraints>
417
-                                                <constraint firstAttribute="trailing" secondItem="GOS-Xt-kBa" secondAttribute="trailing" constant="10" id="44I-Im-laR"/>
418
-                                                <constraint firstItem="7bL-8L-k4P" firstAttribute="centerY" secondItem="B2U-lF-5Lm" secondAttribute="centerY" id="DvT-0Q-xhb"/>
419
-                                                <constraint firstItem="sbI-Yk-yw3" firstAttribute="centerY" secondItem="7bL-8L-k4P" secondAttribute="centerY" id="Ee0-la-oHg"/>
420
-                                                <constraint firstAttribute="bottom" secondItem="qe6-le-PxN" secondAttribute="bottom" id="HHp-89-beY"/>
421
-                                                <constraint firstItem="7bL-8L-k4P" firstAttribute="leading" secondItem="B2U-lF-5Lm" secondAttribute="leading" constant="15" id="LAr-Q4-Zfc"/>
422
-                                                <constraint firstAttribute="trailing" secondItem="qe6-le-PxN" secondAttribute="trailing" id="MzB-GI-zPj"/>
423
-                                                <constraint firstItem="qe6-le-PxN" firstAttribute="top" secondItem="B2U-lF-5Lm" secondAttribute="top" id="OK4-7y-Ty6"/>
424
-                                                <constraint firstItem="sbI-Yk-yw3" firstAttribute="leading" secondItem="7bL-8L-k4P" secondAttribute="trailing" constant="6" id="VUL-1O-eDc"/>
425
-                                                <constraint firstItem="vvS-oJ-TqJ" firstAttribute="leading" secondItem="sbI-Yk-yw3" secondAttribute="trailing" id="ekQ-rb-Mq7"/>
426
-                                                <constraint firstItem="vvS-oJ-TqJ" firstAttribute="centerY" secondItem="sbI-Yk-yw3" secondAttribute="centerY" id="fed-Gs-JKg"/>
427
-                                                <constraint firstItem="GOS-Xt-kBa" firstAttribute="centerY" secondItem="B2U-lF-5Lm" secondAttribute="centerY" id="gap-OK-zCS"/>
428
-                                                <constraint firstItem="qe6-le-PxN" firstAttribute="leading" secondItem="B2U-lF-5Lm" secondAttribute="leading" id="iNa-2Q-Opq"/>
252
+                                                <constraint firstAttribute="height" constant="44" id="3Tu-zh-sgQ"/>
253
+                                                <constraint firstItem="vLK-B7-FQc" firstAttribute="leading" secondItem="zTQ-T2-IMt" secondAttribute="trailing" constant="6" id="DSt-2x-Aqs"/>
254
+                                                <constraint firstItem="zTQ-T2-IMt" firstAttribute="centerY" secondItem="IOw-Xw-2vP" secondAttribute="centerY" id="MFO-T3-4Bi"/>
255
+                                                <constraint firstItem="cuT-s1-NnA" firstAttribute="centerY" secondItem="IOw-Xw-2vP" secondAttribute="centerY" id="N92-Fg-wmf"/>
256
+                                                <constraint firstAttribute="trailing" secondItem="ns5-B1-ilP" secondAttribute="trailing" constant="10" id="Q1P-ZJ-bnb"/>
257
+                                                <constraint firstItem="vLK-B7-FQc" firstAttribute="centerY" secondItem="IOw-Xw-2vP" secondAttribute="centerY" id="fcK-Ns-e87"/>
258
+                                                <constraint firstItem="cuT-s1-NnA" firstAttribute="leading" secondItem="vLK-B7-FQc" secondAttribute="trailing" constant="6" id="kub-1K-GZD"/>
259
+                                                <constraint firstItem="zTQ-T2-IMt" firstAttribute="leading" secondItem="IOw-Xw-2vP" secondAttribute="leading" constant="15" id="qjz-mA-ueh"/>
260
+                                                <constraint firstItem="ns5-B1-ilP" firstAttribute="centerY" secondItem="IOw-Xw-2vP" secondAttribute="centerY" id="zaJ-pH-gPl"/>
429 261
                                             </constraints>
430
-                                        </tableViewCellContentView>
431
-                                    </tableViewCell>
432
-                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="comentCell" rowHeight="95" id="DCX-Km-bjG" customClass="DetailCommentCell" customModule="Paiai_iOS" customModuleProvider="target">
433
-                                        <rect key="frame" x="0.0" y="613" width="375" height="95"/>
262
+                                        </view>
263
+                                    </subviews>
264
+                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
265
+                                    <constraints>
266
+                                        <constraint firstItem="rr6-c2-Nmb" firstAttribute="leading" secondItem="kJj-s4-SK1" secondAttribute="leading" id="0SQ-nj-VPb"/>
267
+                                        <constraint firstItem="dtf-M8-otl" firstAttribute="top" secondItem="rL2-VZ-0O7" secondAttribute="bottom" id="5yA-SJ-n2O"/>
268
+                                        <constraint firstAttribute="trailing" secondItem="rL2-VZ-0O7" secondAttribute="trailing" id="9Fd-m1-g5N"/>
269
+                                        <constraint firstAttribute="trailing" secondItem="IOw-Xw-2vP" secondAttribute="trailing" id="HO5-eq-e4w"/>
270
+                                        <constraint firstItem="dtf-M8-otl" firstAttribute="leading" secondItem="kJj-s4-SK1" secondAttribute="leading" id="HaR-NE-PdQ"/>
271
+                                        <constraint firstItem="q4A-0r-b7Z" firstAttribute="leading" secondItem="kJj-s4-SK1" secondAttribute="leading" id="LbP-SU-Mc1"/>
272
+                                        <constraint firstItem="IOw-Xw-2vP" firstAttribute="top" secondItem="Zde-8U-5Bl" secondAttribute="bottom" id="QU5-ve-FU8"/>
273
+                                        <constraint firstAttribute="trailing" secondItem="Zde-8U-5Bl" secondAttribute="trailing" id="QiZ-Na-0ZD"/>
274
+                                        <constraint firstItem="q4A-0r-b7Z" firstAttribute="top" secondItem="rr6-c2-Nmb" secondAttribute="bottom" id="Rdi-IX-jRd"/>
275
+                                        <constraint firstItem="rL2-VZ-0O7" firstAttribute="top" secondItem="kJj-s4-SK1" secondAttribute="top" id="ePm-7e-WNF"/>
276
+                                        <constraint firstAttribute="trailing" secondItem="dtf-M8-otl" secondAttribute="trailing" id="eRL-0a-k9R"/>
277
+                                        <constraint firstItem="IOw-Xw-2vP" firstAttribute="leading" secondItem="kJj-s4-SK1" secondAttribute="leading" id="fXq-hn-nah"/>
278
+                                        <constraint firstAttribute="bottom" secondItem="IOw-Xw-2vP" secondAttribute="bottom" id="gyd-SZ-DKX"/>
279
+                                        <constraint firstAttribute="trailing" secondItem="rr6-c2-Nmb" secondAttribute="trailing" id="jux-w6-IPv"/>
280
+                                        <constraint firstItem="rr6-c2-Nmb" firstAttribute="top" secondItem="dtf-M8-otl" secondAttribute="bottom" id="oGA-xB-bcp"/>
281
+                                        <constraint firstItem="Zde-8U-5Bl" firstAttribute="top" secondItem="q4A-0r-b7Z" secondAttribute="bottom" id="sGh-IF-x0B"/>
282
+                                        <constraint firstItem="rL2-VZ-0O7" firstAttribute="leading" secondItem="kJj-s4-SK1" secondAttribute="leading" id="w0b-Fi-mSe"/>
283
+                                        <constraint firstItem="Zde-8U-5Bl" firstAttribute="leading" secondItem="kJj-s4-SK1" secondAttribute="leading" id="wXy-sO-XoE"/>
284
+                                        <constraint firstAttribute="trailing" secondItem="q4A-0r-b7Z" secondAttribute="trailing" id="wuV-6N-4YD"/>
285
+                                    </constraints>
286
+                                </view>
287
+                                <prototypes>
288
+                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="none" indentationWidth="10" reuseIdentifier="photoDetailCommentCell" rowHeight="95" id="DCX-Km-bjG" customClass="PhotoDetailCommentCell" customModule="Paiai_iOS" customModuleProvider="target">
289
+                                        <rect key="frame" x="0.0" y="561" width="375" height="95"/>
434 290
                                         <autoresizingMask key="autoresizingMask"/>
435 291
                                         <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="DCX-Km-bjG" id="ncE-AG-MIP">
436 292
                                             <rect key="frame" x="0.0" y="0.0" width="375" height="94.5"/>
437 293
                                             <autoresizingMask key="autoresizingMask"/>
438 294
                                             <subviews>
439
-                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="默认头像" translatesAutoresizingMaskIntoConstraints="NO" id="str-tM-QWN">
295
+                                                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="defaultAvatar" translatesAutoresizingMaskIntoConstraints="NO" id="str-tM-QWN">
440 296
                                                     <rect key="frame" x="15" y="10" width="28" height="28"/>
441 297
                                                     <constraints>
442
-                                                        <constraint firstAttribute="width" secondItem="str-tM-QWN" secondAttribute="height" id="PB6-88-f0G"/>
443 298
                                                         <constraint firstAttribute="width" constant="28" id="VSg-1T-4Hy"/>
444 299
                                                     </constraints>
445 300
                                                     <userDefinedRuntimeAttributes>
@@ -455,13 +310,6 @@
455 310
                                                     <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
456 311
                                                     <nil key="highlightedColor"/>
457 312
                                                 </label>
458
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iwc-4j-TRS">
459
-                                                    <rect key="frame" x="53" y="34" width="312" height="29"/>
460
-                                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
461
-                                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
462
-                                                    <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
463
-                                                    <nil key="highlightedColor"/>
464
-                                                </label>
465 313
                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0分钟前" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MsN-4R-lt2">
466 314
                                                     <rect key="frame" x="327" y="12" width="38" height="12"/>
467 315
                                                     <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@@ -469,17 +317,24 @@
469 317
                                                     <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
470 318
                                                     <nil key="highlightedColor"/>
471 319
                                                 </label>
320
+                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="iwc-4j-TRS">
321
+                                                    <rect key="frame" x="15" y="44" width="350" height="50.5"/>
322
+                                                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
323
+                                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
324
+                                                    <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
325
+                                                    <nil key="highlightedColor"/>
326
+                                                </label>
472 327
                                             </subviews>
473 328
                                             <constraints>
474
-                                                <constraint firstItem="iwc-4j-TRS" firstAttribute="top" secondItem="u6l-UB-FoK" secondAttribute="bottom" constant="8" id="5LY-xA-5ML"/>
329
+                                                <constraint firstItem="iwc-4j-TRS" firstAttribute="top" secondItem="str-tM-QWN" secondAttribute="bottom" constant="6" id="2qq-j5-mKw"/>
475 330
                                                 <constraint firstItem="MsN-4R-lt2" firstAttribute="centerY" secondItem="u6l-UB-FoK" secondAttribute="centerY" id="9qq-6O-Vhb"/>
476
-                                                <constraint firstAttribute="trailing" secondItem="iwc-4j-TRS" secondAttribute="trailing" constant="10" id="TMI-os-LvC"/>
477
-                                                <constraint firstItem="str-tM-QWN" firstAttribute="width" secondItem="str-tM-QWN" secondAttribute="height" id="c0x-MP-hUB"/>
331
+                                                <constraint firstAttribute="trailing" secondItem="iwc-4j-TRS" secondAttribute="trailing" constant="10" id="VFy-cP-ts4"/>
332
+                                                <constraint firstItem="iwc-4j-TRS" firstAttribute="leading" secondItem="ncE-AG-MIP" secondAttribute="leading" constant="15" id="bmd-Ve-5aG"/>
478 333
                                                 <constraint firstItem="str-tM-QWN" firstAttribute="width" secondItem="str-tM-QWN" secondAttribute="height" id="d0r-sR-lUW"/>
479
-                                                <constraint firstItem="MsN-4R-lt2" firstAttribute="trailing" secondItem="iwc-4j-TRS" secondAttribute="trailing" id="gas-t9-dV6"/>
334
+                                                <constraint firstAttribute="bottom" secondItem="iwc-4j-TRS" secondAttribute="bottom" id="ggt-ZE-bzP"/>
480 335
                                                 <constraint firstItem="u6l-UB-FoK" firstAttribute="leading" secondItem="str-tM-QWN" secondAttribute="trailing" constant="10" id="hIT-CX-JbS"/>
481 336
                                                 <constraint firstItem="u6l-UB-FoK" firstAttribute="top" secondItem="str-tM-QWN" secondAttribute="top" id="pca-XM-Z1U"/>
482
-                                                <constraint firstItem="iwc-4j-TRS" firstAttribute="leading" secondItem="u6l-UB-FoK" secondAttribute="leading" id="rlX-um-t0a"/>
337
+                                                <constraint firstAttribute="trailing" secondItem="MsN-4R-lt2" secondAttribute="trailing" constant="10" id="rmu-5a-Rld"/>
483 338
                                                 <constraint firstItem="str-tM-QWN" firstAttribute="leading" secondItem="ncE-AG-MIP" secondAttribute="leading" constant="15" id="ucZ-2U-sZg"/>
484 339
                                                 <constraint firstItem="str-tM-QWN" firstAttribute="top" secondItem="ncE-AG-MIP" secondAttribute="top" constant="10" id="xc5-Fo-t4y"/>
485 340
                                             </constraints>
@@ -492,34 +347,42 @@
492 347
                                         </connections>
493 348
                                     </tableViewCell>
494 349
                                 </prototypes>
495
-                                <connections>
496
-                                    <outlet property="dataSource" destination="qsT-Pc-Bhh" id="Ftm-VU-vAa"/>
497
-                                    <outlet property="delegate" destination="qsT-Pc-Bhh" id="Aej-45-W3l"/>
498
-                                </connections>
499 350
                             </tableView>
500
-                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lID-7p-0oW">
501
-                                <rect key="frame" x="-70.5" y="430" width="516" height="192"/>
351
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lID-7p-0oW" userLabel="button group">
352
+                                <rect key="frame" x="46.5" y="859" width="282" height="96"/>
502 353
                                 <subviews>
503
-                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Tvg-6N-vtJ" userLabel="thumbup">
504
-                                        <rect key="frame" x="162" y="0.0" width="192" height="192"/>
354
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0wu-p1-ehU" userLabel="mes">
355
+                                        <rect key="frame" x="0.0" y="13.5" width="69" height="69"/>
505 356
                                         <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
506
-                                        <state key="normal" image="Oval 491"/>
357
+                                        <constraints>
358
+                                            <constraint firstAttribute="width" constant="69" id="Kl9-19-ofx"/>
359
+                                            <constraint firstAttribute="height" constant="69" id="NE5-HG-g9l"/>
360
+                                        </constraints>
361
+                                        <state key="normal" image="BTN-comment"/>
507 362
                                         <connections>
508
-                                            <action selector="zan" destination="qsT-Pc-Bhh" eventType="touchUpInside" id="m0i-Im-CcG"/>
363
+                                            <action selector="comment" destination="qsT-Pc-Bhh" eventType="touchUpInside" id="CAa-E8-57D"/>
509 364
                                         </connections>
510 365
                                     </button>
511
-                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0wu-p1-ehU" userLabel="mes">
512
-                                        <rect key="frame" x="0.0" y="27" width="138" height="138"/>
366
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Tvg-6N-vtJ" userLabel="thumbup">
367
+                                        <rect key="frame" x="93" y="0.0" width="96" height="96"/>
513 368
                                         <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
514
-                                        <state key="normal" image="BTN-评论"/>
369
+                                        <constraints>
370
+                                            <constraint firstAttribute="height" constant="96" id="pQ4-9p-4wb"/>
371
+                                            <constraint firstAttribute="width" constant="96" id="uaf-UW-oXr"/>
372
+                                        </constraints>
373
+                                        <state key="normal" image="BTN-thumbup"/>
515 374
                                         <connections>
516
-                                            <action selector="comment" destination="qsT-Pc-Bhh" eventType="touchUpInside" id="CAa-E8-57D"/>
375
+                                            <action selector="thumbup" destination="qsT-Pc-Bhh" eventType="touchUpInside" id="yGL-Ix-DyZ"/>
517 376
                                         </connections>
518 377
                                     </button>
519 378
                                     <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="BWu-RT-ZEQ" userLabel="share">
520
-                                        <rect key="frame" x="378" y="27" width="138" height="138"/>
379
+                                        <rect key="frame" x="213" y="13.5" width="69" height="69"/>
521 380
                                         <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
522
-                                        <state key="normal" image="BTN-分享"/>
381
+                                        <constraints>
382
+                                            <constraint firstAttribute="width" constant="69" id="EcS-81-GGx"/>
383
+                                            <constraint firstAttribute="height" constant="69" id="Mpf-VI-Pej"/>
384
+                                        </constraints>
385
+                                        <state key="normal" image="BTN-share"/>
523 386
                                         <connections>
524 387
                                             <action selector="share" destination="qsT-Pc-Bhh" eventType="touchUpInside" id="ai8-KT-pxy"/>
525 388
                                         </connections>
@@ -538,8 +401,8 @@
538 401
                                     <constraint firstItem="BWu-RT-ZEQ" firstAttribute="centerY" secondItem="Tvg-6N-vtJ" secondAttribute="centerY" id="yEr-l3-Y6R"/>
539 402
                                 </constraints>
540 403
                             </view>
541
-                            <view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="M7B-fx-M7f">
542
-                                <rect key="frame" x="0.0" y="611" width="375" height="56"/>
404
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="M7B-fx-M7f">
405
+                                <rect key="frame" x="0.0" y="1000" width="375" height="56"/>
543 406
                                 <subviews>
544 407
                                     <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" placeholder="我也说一句..." textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="1va-ae-Juh">
545 408
                                         <rect key="frame" x="12" y="10" width="285" height="36"/>
@@ -558,25 +421,15 @@
558 421
                                             </userDefinedRuntimeAttribute>
559 422
                                         </userDefinedRuntimeAttributes>
560 423
                                     </textField>
561
-                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oef-gW-sEK">
424
+                                    <button opaque="NO" contentMode="scaleToFill" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="oef-gW-sEK">
562 425
                                         <rect key="frame" x="303" y="10" width="60" height="36"/>
426
+                                        <color key="backgroundColor" red="0.9995151162147522" green="0.16799759864807129" blue="0.24112263321876526" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
563 427
                                         <constraints>
564 428
                                             <constraint firstAttribute="width" constant="60" id="lDb-Za-vrb"/>
565 429
                                         </constraints>
566 430
                                         <state key="normal" title="发表">
567 431
                                             <color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
568 432
                                         </state>
569
-                                        <userDefinedRuntimeAttributes>
570
-                                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
571
-                                                <real key="value" value="4"/>
572
-                                            </userDefinedRuntimeAttribute>
573
-                                            <userDefinedRuntimeAttribute type="color" keyPath="normalStatusBackgroundColor">
574
-                                                <color key="value" red="0.98431372549999996" green="0.31372549020000001" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
575
-                                            </userDefinedRuntimeAttribute>
576
-                                            <userDefinedRuntimeAttribute type="color" keyPath="pressedStatusBackgroundColor">
577
-                                                <color key="value" red="0.98431372549999996" green="0.31372549020000001" blue="0.31372549020000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
578
-                                            </userDefinedRuntimeAttribute>
579
-                                        </userDefinedRuntimeAttributes>
580 433
                                         <connections>
581 434
                                             <action selector="sendComment" destination="qsT-Pc-Bhh" eventType="touchUpInside" id="utb-Y9-GCy"/>
582 435
                                         </connections>
@@ -602,38 +455,37 @@
602 455
                                 </userDefinedRuntimeAttributes>
603 456
                             </view>
604 457
                             <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="n3n-4c-ZrJ">
605
-                                <rect key="frame" x="0.0" y="619" width="375" height="48"/>
458
+                                <rect key="frame" x="0.0" y="952" width="375" height="48"/>
606 459
                                 <subviews>
607 460
                                     <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lCw-zE-NnH">
608 461
                                         <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
609 462
                                         <subviews>
610
-                                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IpC-PG-FTb">
611
-                                                <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
612
-                                                <state key="normal" backgroundImage="去除水印"/>
613
-                                                <connections>
614
-                                                    <action selector="waterMarkPay:" destination="qsT-Pc-Bhh" eventType="touchUpInside" id="Jms-KW-CI9"/>
615
-                                                </connections>
616
-                                            </button>
617 463
                                             <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="购买-去水印" translatesAutoresizingMaskIntoConstraints="NO" id="pvN-rn-4Jn">
618
-                                                <rect key="frame" x="99.5" y="-24" width="96" height="96"/>
464
+                                                <rect key="frame" x="123.5" y="0.0" width="48" height="48"/>
465
+                                                <constraints>
466
+                                                    <constraint firstAttribute="height" constant="48" id="2VC-Nk-MXl"/>
467
+                                                    <constraint firstAttribute="width" constant="48" id="RbZ-dr-qL8"/>
468
+                                                </constraints>
619 469
                                             </imageView>
620 470
                                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="去除水印" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Xot-0B-lcT">
621
-                                                <rect key="frame" x="200.5" y="15" width="62" height="18"/>
471
+                                                <rect key="frame" x="176.5" y="15" width="62" height="18"/>
622 472
                                                 <fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
623 473
                                                 <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
624 474
                                                 <nil key="highlightedColor"/>
625 475
                                             </label>
626 476
                                         </subviews>
477
+                                        <accessibility key="accessibilityConfiguration">
478
+                                            <accessibilityTraits key="traits" image="YES"/>
479
+                                        </accessibility>
627 480
                                         <constraints>
628
-                                            <constraint firstItem="IpC-PG-FTb" firstAttribute="leading" secondItem="lCw-zE-NnH" secondAttribute="leading" id="AI8-0A-5NM"/>
629 481
                                             <constraint firstItem="pvN-rn-4Jn" firstAttribute="centerY" secondItem="lCw-zE-NnH" secondAttribute="centerY" id="IiE-3R-qra"/>
630
-                                            <constraint firstAttribute="trailing" secondItem="IpC-PG-FTb" secondAttribute="trailing" id="JXk-xw-Ijl"/>
631 482
                                             <constraint firstItem="Xot-0B-lcT" firstAttribute="leading" secondItem="pvN-rn-4Jn" secondAttribute="trailing" constant="5" id="iEp-95-h2T"/>
632 483
                                             <constraint firstItem="pvN-rn-4Jn" firstAttribute="centerX" secondItem="lCw-zE-NnH" secondAttribute="centerX" constant="-40" id="ldO-mF-P0P"/>
633
-                                            <constraint firstAttribute="bottom" secondItem="IpC-PG-FTb" secondAttribute="bottom" id="w9Z-mh-Lbw"/>
634
-                                            <constraint firstItem="IpC-PG-FTb" firstAttribute="top" secondItem="lCw-zE-NnH" secondAttribute="top" id="wZx-uT-kRL"/>
635 484
                                             <constraint firstItem="Xot-0B-lcT" firstAttribute="centerY" secondItem="pvN-rn-4Jn" secondAttribute="centerY" id="z6Y-h0-ffK"/>
636 485
                                         </constraints>
486
+                                        <connections>
487
+                                            <outletCollection property="gestureRecognizers" destination="thN-TP-atT" appends="YES" id="gKW-D0-5pd"/>
488
+                                        </connections>
637 489
                                     </view>
638 490
                                 </subviews>
639 491
                                 <constraints>
@@ -648,54 +500,64 @@
648 500
                         <color key="backgroundColor" red="0.94117647059999998" green="0.94117647059999998" blue="0.94117647059999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
649 501
                         <gestureRecognizers/>
650 502
                         <constraints>
651
-                            <constraint firstItem="9RM-c8-CL6" firstAttribute="top" secondItem="BJb-h6-o9s" secondAttribute="bottom" id="73f-0Y-3Vq"/>
652
-                            <constraint firstItem="9RM-c8-CL6" firstAttribute="top" secondItem="lID-7p-0oW" secondAttribute="bottom" constant="45" id="8XF-qX-tug"/>
653
-                            <constraint firstAttribute="trailing" secondItem="BJb-h6-o9s" secondAttribute="trailing" id="FVI-fa-ovF"/>
654
-                            <constraint firstAttribute="bottom" secondItem="M7B-fx-M7f" secondAttribute="bottom" id="HPO-e8-4k2"/>
655
-                            <constraint firstItem="BJb-h6-o9s" firstAttribute="leading" secondItem="DXj-L8-o9b" secondAttribute="leading" id="LUw-LA-s32"/>
656
-                            <constraint firstAttribute="trailing" secondItem="M7B-fx-M7f" secondAttribute="trailing" id="N1J-SK-PaC"/>
657
-                            <constraint firstItem="9RM-c8-CL6" firstAttribute="top" secondItem="n3n-4c-ZrJ" secondAttribute="bottom" id="WmR-iX-rxE"/>
658
-                            <constraint firstItem="lID-7p-0oW" firstAttribute="centerX" secondItem="DXj-L8-o9b" secondAttribute="centerX" id="X50-n0-wZy"/>
659
-                            <constraint firstItem="BJb-h6-o9s" firstAttribute="top" secondItem="aUY-hC-XIK" secondAttribute="bottom" id="YxH-gE-R4v"/>
660
-                            <constraint firstAttribute="trailing" secondItem="n3n-4c-ZrJ" secondAttribute="trailing" id="c7G-xk-PsT"/>
661
-                            <constraint firstItem="n3n-4c-ZrJ" firstAttribute="leading" secondItem="DXj-L8-o9b" secondAttribute="leading" id="cYR-vc-dTi"/>
662
-                            <constraint firstItem="M7B-fx-M7f" firstAttribute="leading" secondItem="DXj-L8-o9b" secondAttribute="leading" id="svX-zh-yc8"/>
503
+                            <constraint firstItem="fD2-Ow-gtt" firstAttribute="leading" secondItem="9gv-8b-ehH" secondAttribute="leading" id="05m-kg-yB6"/>
504
+                            <constraint firstItem="9gv-8b-ehH" firstAttribute="bottom" secondItem="lID-7p-0oW" secondAttribute="bottom" constant="45" id="8XF-qX-tug"/>
505
+                            <constraint firstAttribute="bottom" secondItem="M7B-fx-M7f" secondAttribute="bottom" constant="-56" id="HPO-e8-4k2"/>
506
+                            <constraint firstItem="fD2-Ow-gtt" firstAttribute="top" secondItem="9gv-8b-ehH" secondAttribute="top" id="IeE-A7-ZV9"/>
507
+                            <constraint firstItem="9gv-8b-ehH" firstAttribute="trailing" secondItem="M7B-fx-M7f" secondAttribute="trailing" id="N1J-SK-PaC"/>
508
+                            <constraint firstAttribute="bottom" secondItem="n3n-4c-ZrJ" secondAttribute="bottom" id="WmR-iX-rxE"/>
509
+                            <constraint firstItem="lID-7p-0oW" firstAttribute="centerX" secondItem="9gv-8b-ehH" secondAttribute="centerX" id="X50-n0-wZy"/>
510
+                            <constraint firstAttribute="bottom" secondItem="fD2-Ow-gtt" secondAttribute="bottom" id="XB5-IP-h70"/>
511
+                            <constraint firstItem="9gv-8b-ehH" firstAttribute="trailing" secondItem="n3n-4c-ZrJ" secondAttribute="trailing" id="c7G-xk-PsT"/>
512
+                            <constraint firstItem="n3n-4c-ZrJ" firstAttribute="leading" secondItem="9gv-8b-ehH" secondAttribute="leading" id="cYR-vc-dTi"/>
513
+                            <constraint firstItem="9gv-8b-ehH" firstAttribute="trailing" secondItem="fD2-Ow-gtt" secondAttribute="trailing" id="riO-3O-KZ0"/>
514
+                            <constraint firstItem="M7B-fx-M7f" firstAttribute="leading" secondItem="9gv-8b-ehH" secondAttribute="leading" id="svX-zh-yc8"/>
663 515
                         </constraints>
664
-                        <connections>
665
-                            <outletCollection property="gestureRecognizers" destination="thN-TP-atT" appends="YES" id="fm4-zR-Gbm"/>
666
-                        </connections>
516
+                        <viewLayoutGuide key="safeArea" id="9gv-8b-ehH"/>
667 517
                     </view>
518
+                    <size key="freeformSize" width="375" height="1000"/>
668 519
                     <connections>
669 520
                         <outlet property="buyView" destination="n3n-4c-ZrJ" id="SXL-nK-eIX"/>
521
+                        <outlet property="commentCount" destination="cuT-s1-NnA" id="m50-cn-Kcn"/>
522
+                        <outlet property="commentEditYConstraint" destination="HPO-e8-4k2" id="tfy-Rg-aiz"/>
523
+                        <outlet property="commentEditingView" destination="M7B-fx-M7f" id="ZRf-mw-WVD"/>
670 524
                         <outlet property="commentHeight" destination="HPO-e8-4k2" id="gpG-te-dKf"/>
525
+                        <outlet property="commentTableView" destination="fD2-Ow-gtt" id="jog-WM-p44"/>
671 526
                         <outlet property="commentTextField" destination="1va-ae-Juh" id="TpO-kE-PhT"/>
672
-                        <outlet property="commentView" destination="M7B-fx-M7f" id="c0Q-vg-7C9"/>
527
+                        <outlet property="enterGroupView" destination="gSr-Cm-y1W" id="bNT-Z4-eOG"/>
528
+                        <outlet property="groupAvatar" destination="nng-M9-7cj" id="Y42-Tc-QnV"/>
529
+                        <outlet property="groupName" destination="XM7-FX-tOk" id="ifP-h1-72j"/>
530
+                        <outlet property="photoCollectionView" destination="dtf-M8-otl" id="VlY-wa-ekc"/>
531
+                        <outlet property="photoTime" destination="QpI-Mp-URP" id="rJM-TG-fZW"/>
673 532
                         <outlet property="sendBtn" destination="oef-gW-sEK" id="3RV-uD-3q1"/>
674
-                        <outlet property="shuiyinImage" destination="pvN-rn-4Jn" id="SOk-vE-uCT"/>
675
-                        <outlet property="shuiyinLabel" destination="Xot-0B-lcT" id="eWR-Rv-Fzl"/>
676
-                        <outlet property="tableView" destination="BJb-h6-o9s" id="XS2-bS-jiH"/>
677
-                        <outlet property="thumbupView" destination="lID-7p-0oW" id="nBh-5u-Utm"/>
678
-                        <outlet property="waterMarkView" destination="lCw-zE-NnH" id="CPm-lw-FQT"/>
533
+                        <outlet property="thumbupCount" destination="h88-PP-cvG" id="hwu-eb-a1J"/>
534
+                        <outlet property="thumbupView" destination="Zde-8U-5Bl" id="ceB-lf-AhY"/>
535
+                        <outlet property="thumbupViewHeightConstraint" destination="fc8-6l-lEC" id="E8M-of-NHC"/>
536
+                        <outlet property="userAvatar" destination="Zj6-ve-uzJ" id="3Un-We-QLK"/>
537
+                        <outlet property="userName" destination="jmc-9F-Uzr" id="1Z5-wc-83i"/>
538
+                        <outlet property="waterMarkImage" destination="pvN-rn-4Jn" id="TaO-CX-590"/>
539
+                        <outlet property="waterMarkLabel" destination="Xot-0B-lcT" id="Jok-hr-Eeb"/>
540
+                        <outlet property="waterMarkView" destination="lCw-zE-NnH" id="z8i-gh-ZRG"/>
679 541
                     </connections>
680 542
                 </viewController>
681 543
                 <placeholder placeholderIdentifier="IBFirstResponder" id="MFn-pn-5Jb" userLabel="First Responder" sceneMemberID="firstResponder"/>
682
-                <tapGestureRecognizer id="thN-TP-atT">
544
+                <tapGestureRecognizer id="thN-TP-atT" userLabel="purchaseGestureRecognizer">
683 545
                     <connections>
684
-                        <action selector="ReturnKeyboard:" destination="qsT-Pc-Bhh" id="uVf-UL-SuP"/>
685
-                        <outlet property="delegate" destination="qsT-Pc-Bhh" id="vFS-jJ-MlO"/>
546
+                        <action selector="purchase:" destination="qsT-Pc-Bhh" id="qjs-Ot-XwA"/>
547
+                    </connections>
548
+                </tapGestureRecognizer>
549
+                <tapGestureRecognizer id="EHE-XX-kIE" userLabel="enterGroupGestureRecognizer">
550
+                    <connections>
551
+                        <action selector="enterGroup:" destination="qsT-Pc-Bhh" id="dZE-ok-iUM"/>
686 552
                     </connections>
687 553
                 </tapGestureRecognizer>
688 554
             </objects>
689
-            <point key="canvasLocation" x="-1927.2" y="1267.0164917541231"/>
555
+            <point key="canvasLocation" x="-1452" y="1137.9310344827586"/>
690 556
         </scene>
691 557
         <!--ShareController-->
692 558
         <scene sceneID="UTe-rv-qoO">
693 559
             <objects>
694 560
                 <viewController storyboardIdentifier="ShareController" automaticallyAdjustsScrollViewInsets="NO" id="KnW-jg-4H5" userLabel="ShareController" customClass="ShareController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController">
695
-                    <layoutGuides>
696
-                        <viewControllerLayoutGuide type="top" id="hPQ-yS-v0d"/>
697
-                        <viewControllerLayoutGuide type="bottom" id="xwf-Eg-SuC"/>
698
-                    </layoutGuides>
699 561
                     <view key="view" contentMode="scaleToFill" id="rN5-Zb-vwm">
700 562
                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
701 563
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@@ -795,10 +657,11 @@
795 657
                         </subviews>
796 658
                         <gestureRecognizers/>
797 659
                         <constraints>
798
-                            <constraint firstItem="xUW-ue-yp5" firstAttribute="leading" secondItem="rN5-Zb-vwm" secondAttribute="leading" id="Afy-jR-Jec"/>
799
-                            <constraint firstItem="xwf-Eg-SuC" firstAttribute="top" secondItem="xUW-ue-yp5" secondAttribute="bottom" constant="127" id="hco-RD-Kle"/>
800
-                            <constraint firstAttribute="trailing" secondItem="xUW-ue-yp5" secondAttribute="trailing" id="lAd-Wf-RcE"/>
660
+                            <constraint firstItem="xUW-ue-yp5" firstAttribute="leading" secondItem="C6P-7J-fWs" secondAttribute="leading" id="Afy-jR-Jec"/>
661
+                            <constraint firstItem="C6P-7J-fWs" firstAttribute="bottom" secondItem="xUW-ue-yp5" secondAttribute="bottom" constant="127" id="hco-RD-Kle"/>
662
+                            <constraint firstItem="C6P-7J-fWs" firstAttribute="trailing" secondItem="xUW-ue-yp5" secondAttribute="trailing" id="lAd-Wf-RcE"/>
801 663
                         </constraints>
664
+                        <viewLayoutGuide key="safeArea" id="C6P-7J-fWs"/>
802 665
                     </view>
803 666
                     <connections>
804 667
                         <outlet property="shareView" destination="xUW-ue-yp5" id="I5g-Zk-9uW"/>
@@ -806,22 +669,18 @@
806 669
                 </viewController>
807 670
                 <placeholder placeholderIdentifier="IBFirstResponder" id="9LO-35-FRH" userLabel="First Responder" sceneMemberID="firstResponder"/>
808 671
             </objects>
809
-            <point key="canvasLocation" x="649.60000000000002" y="1430.2848575712146"/>
672
+            <point key="canvasLocation" x="-513" y="1287"/>
810 673
         </scene>
811
-        <!--ShowFullPicController-->
674
+        <!--PhotoPreviewViewController-->
812 675
         <scene sceneID="yhk-2u-fiu">
813 676
             <objects>
814
-                <viewController storyboardIdentifier="ShowFullPicController" automaticallyAdjustsScrollViewInsets="NO" id="p3y-A2-QU1" userLabel="ShowFullPicController" customClass="ShowFullPicController" customModule="PaiAi" sceneMemberID="viewController">
815
-                    <layoutGuides>
816
-                        <viewControllerLayoutGuide type="top" id="LdU-do-COB"/>
817
-                        <viewControllerLayoutGuide type="bottom" id="uHN-Ad-PoZ"/>
818
-                    </layoutGuides>
677
+                <viewController storyboardIdentifier="PhotoPreviewViewController" automaticallyAdjustsScrollViewInsets="NO" id="p3y-A2-QU1" userLabel="PhotoPreviewViewController" customClass="PhotoPreviewViewController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController">
819 678
                     <view key="view" contentMode="scaleToFill" id="MdC-Fu-zFL">
820 679
                         <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
821 680
                         <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
822 681
                         <subviews>
823
-                            <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" indicatorStyle="white" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="cvI-jg-TrD">
824
-                                <rect key="frame" x="0.0" y="20" width="395" height="647"/>
682
+                            <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" indicatorStyle="white" dataMode="prototypes" prefetchingEnabled="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cvI-jg-TrD">
683
+                                <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
825 684
                                 <collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="0.0" minimumInteritemSpacing="0.0" id="nE7-Ce-1KB">
826 685
                                     <size key="itemSize" width="237.5" height="357"/>
827 686
                                     <size key="headerReferenceSize" width="0.0" height="0.0"/>
@@ -830,7 +689,7 @@
830 689
                                 </collectionViewFlowLayout>
831 690
                                 <cells>
832 691
                                     <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="imageCell" id="PAU-eQ-c9k" customClass="ImageCell" customModule="Paiai_iOS" customModuleProvider="target">
833
-                                        <rect key="frame" x="0.0" y="145" width="237.5" height="357"/>
692
+                                        <rect key="frame" x="0.0" y="155" width="237.5" height="357"/>
834 693
                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
835 694
                                         <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
836 695
                                             <rect key="frame" x="0.0" y="0.0" width="237.5" height="357"/>
@@ -856,35 +715,31 @@
856 715
                                         </connections>
857 716
                                     </collectionViewCell>
858 717
                                 </cells>
859
-                                <connections>
860
-                                    <outlet property="dataSource" destination="p3y-A2-QU1" id="gOQ-91-JoU"/>
861
-                                    <outlet property="delegate" destination="p3y-A2-QU1" id="Woc-UQ-V73"/>
862
-                                </connections>
863 718
                             </collectionView>
864
-                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BRP-J0-WGF">
719
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BRP-J0-WGF" userLabel="button group">
865 720
                                 <rect key="frame" x="0.0" y="623" width="375" height="44"/>
866 721
                                 <subviews>
867
-                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Q90-2h-mGx">
868
-                                        <rect key="frame" x="231" y="-26" width="96" height="96"/>
869
-                                        <state key="normal" image="大图模式-下载"/>
870
-                                        <connections>
871
-                                            <action selector="load" destination="p3y-A2-QU1" eventType="touchUpInside" id="tC2-9R-1be"/>
872
-                                        </connections>
873
-                                    </button>
874
-                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2r6-s1-9be">
722
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="2r6-s1-9be" userLabel="back">
875 723
                                         <rect key="frame" x="43.5" y="-26" width="96" height="96"/>
876
-                                        <state key="normal" image="back"/>
724
+                                        <state key="normal" image="navigation-back"/>
877 725
                                         <connections>
878 726
                                             <action selector="back" destination="p3y-A2-QU1" eventType="touchUpInside" id="xKk-c3-Iub"/>
879 727
                                         </connections>
880 728
                                     </button>
881
-                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aOC-mu-785">
729
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="aOC-mu-785" userLabel="rotate">
882 730
                                         <rect key="frame" x="139.5" y="-26" width="96" height="96"/>
883
-                                        <state key="normal" image="旋转"/>
731
+                                        <state key="normal" image="BTN-rotate"/>
884 732
                                         <connections>
885 733
                                             <action selector="rotateTheImage:" destination="p3y-A2-QU1" eventType="touchUpInside" id="LiB-TG-UYL"/>
886 734
                                         </connections>
887 735
                                     </button>
736
+                                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Q90-2h-mGx" userLabel="download">
737
+                                        <rect key="frame" x="231" y="-26" width="96" height="96"/>
738
+                                        <state key="normal" image="BTN-download"/>
739
+                                        <connections>
740
+                                            <action selector="download:" destination="p3y-A2-QU1" eventType="touchUpInside" id="cEE-Yt-FWf"/>
741
+                                        </connections>
742
+                                    </button>
888 743
                                 </subviews>
889 744
                                 <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
890 745
                                 <constraints>
@@ -902,14 +757,15 @@
902 757
                         </subviews>
903 758
                         <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
904 759
                         <constraints>
905
-                            <constraint firstItem="uHN-Ad-PoZ" firstAttribute="top" secondItem="cvI-jg-TrD" secondAttribute="bottom" id="F0H-Mg-CBe"/>
906
-                            <constraint firstItem="uHN-Ad-PoZ" firstAttribute="top" secondItem="BRP-J0-WGF" secondAttribute="bottom" id="HMX-tH-TKt"/>
907
-                            <constraint firstItem="cvI-jg-TrD" firstAttribute="top" secondItem="MdC-Fu-zFL" secondAttribute="topMargin" id="bET-rg-QJH"/>
908
-                            <constraint firstItem="cvI-jg-TrD" firstAttribute="leading" secondItem="MdC-Fu-zFL" secondAttribute="leading" id="bxo-Ri-B7l"/>
909
-                            <constraint firstAttribute="trailing" secondItem="BRP-J0-WGF" secondAttribute="trailing" id="es7-Qg-qLl"/>
910
-                            <constraint firstItem="BRP-J0-WGF" firstAttribute="leading" secondItem="MdC-Fu-zFL" secondAttribute="leading" id="nES-ms-zxG"/>
911
-                            <constraint firstAttribute="trailing" secondItem="cvI-jg-TrD" secondAttribute="trailing" constant="-20" id="y4O-SP-QE3"/>
760
+                            <constraint firstAttribute="bottom" secondItem="cvI-jg-TrD" secondAttribute="bottom" id="F0H-Mg-CBe"/>
761
+                            <constraint firstItem="pxb-BY-KAJ" firstAttribute="bottom" secondItem="BRP-J0-WGF" secondAttribute="bottom" id="HMX-tH-TKt"/>
762
+                            <constraint firstItem="cvI-jg-TrD" firstAttribute="top" secondItem="MdC-Fu-zFL" secondAttribute="top" id="bET-rg-QJH"/>
763
+                            <constraint firstItem="cvI-jg-TrD" firstAttribute="leading" secondItem="pxb-BY-KAJ" secondAttribute="leading" id="bxo-Ri-B7l"/>
764
+                            <constraint firstItem="pxb-BY-KAJ" firstAttribute="trailing" secondItem="BRP-J0-WGF" secondAttribute="trailing" id="es7-Qg-qLl"/>
765
+                            <constraint firstItem="BRP-J0-WGF" firstAttribute="leading" secondItem="pxb-BY-KAJ" secondAttribute="leading" id="nES-ms-zxG"/>
766
+                            <constraint firstItem="pxb-BY-KAJ" firstAttribute="trailing" secondItem="cvI-jg-TrD" secondAttribute="trailing" id="y4O-SP-QE3"/>
912 767
                         </constraints>
768
+                        <viewLayoutGuide key="safeArea" id="pxb-BY-KAJ"/>
913 769
                     </view>
914 770
                     <connections>
915 771
                         <outlet property="collectionView" destination="cvI-jg-TrD" id="1eT-ax-Cma"/>
@@ -921,23 +777,22 @@
921 777
         </scene>
922 778
     </scenes>
923 779
     <resources>
924
-        <image name="BTN-分享" width="138" height="138"/>
925
-        <image name="BTN-评论" width="138" height="138"/>
926
-        <image name="Oval 491" width="192" height="192"/>
927
-        <image name="back" width="36" height="72"/>
928
-        <image name="icon-记录" width="36" height="36"/>
929
-        <image name="icon-评论" width="36" height="36"/>
930
-        <image name="icon-赞" width="36" height="36"/>
931
-        <image name="list-arrow" width="16" height="16"/>
780
+        <image name="BTN-comment" width="138" height="138"/>
781
+        <image name="BTN-download" width="96" height="96"/>
782
+        <image name="BTN-rotate" width="96" height="96"/>
783
+        <image name="BTN-share" width="138" height="138"/>
784
+        <image name="BTN-thumbup" width="192" height="192"/>
785
+        <image name="defaultAvatar" width="240" height="240"/>
786
+        <image name="icon-comment" width="36" height="36"/>
787
+        <image name="icon-thumbup" width="36" height="36"/>
788
+        <image name="icon-time" width="36" height="36"/>
789
+        <image name="list-arrow" width="24" height="36"/>
790
+        <image name="navigation-back" width="36" height="72"/>
932 791
         <image name="分享-QQ" width="162" height="162"/>
933 792
         <image name="分享-微信好友" width="162" height="162"/>
934 793
         <image name="分享-微博" width="162" height="162"/>
935 794
         <image name="分享-朋友圈" width="162" height="162"/>
936
-        <image name="去除水印" width="8" height="144"/>
937
-        <image name="大图模式-下载" width="96" height="96"/>
938
-        <image name="旋转" width="96" height="96"/>
939 795
         <image name="购买-去水印" width="96" height="96"/>
940 796
         <image name="进入群" width="114" height="60"/>
941
-        <image name="默认头像" width="80" height="80"/>
942 797
     </resources>
943 798
 </document>

+ 2 - 2
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoDetailCommentCell.swift

@@ -1,5 +1,5 @@
1 1
 //
2
-//  DetailCommentCell.swift
2
+//  PhotoDetailCommentCell.swift
3 3
 //  PaiAi
4 4
 //
5 5
 //  Created by zhengjianfei on 16/4/8.
@@ -10,7 +10,7 @@ import UIKit
10 10
 import PaiaiDataKit
11 11
 import PaiaiUIKit
12 12
 
13
-class DetailCommentCell: UITableViewCell {
13
+class PhotoDetailCommentCell: UITableViewCell {
14 14
 
15 15
     // MARK: Storyboard property
16 16
     @IBOutlet weak var headImage: UIImageView!

+ 49 - 1
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoDetailCoordinator.swift

@@ -7,9 +7,57 @@
7 7
 //
8 8
 
9 9
 import Foundation
10
+import PaiaiDataKit
11
+
12
+final class PhotoDetailCoordinator: Coordinator {
13
+    let navigationController: UINavigationController
14
+    let photoDetailViewController: PhotoDetailViewController
15
+    let shareListViewModel: PhotoDetailListViewModel
16
+    
17
+    fileprivate var coordinators = [String: Coordinator]()
18
+    
19
+    init(_ photoDetailVC: PhotoDetailViewController,
20
+         nav: UINavigationController,
21
+         viewModel: PhotoDetailViewModel,
22
+         listViewModel: PhotoDetailListViewModel) {
23
+        photoDetailViewController = photoDetailVC
24
+        shareListViewModel = listViewModel
25
+        navigationController = nav
26
+        photoDetailViewController.listViewModel = shareListViewModel
27
+        photoDetailViewController.viewModel = viewModel
28
+        
29
+        viewModel.delegate = self
30
+        shareListViewModel.synchronization = viewModel
31
+        shareListViewModel.delegate = self
32
+    }
33
+    
34
+    func start() {
35
+        
36
+    }
37
+}
38
+
39
+extension PhotoDetailCoordinator: PhotoDetailViewModelDelegate {
40
+    func navigateToGroup(_ item: GroupItem) {
41
+        let vc = GroupViewController.instantiate()
42
+        vc.viewModel = GroupViewModel(groupItem: item)
43
+        let coordinator = GroupCoordinator(vc,
44
+                                           navigationController: navigationController)
45
+        coordinators["group"] = coordinator
46
+        
47
+        navigationController.pushViewController(vc)
48
+    }
49
+}
50
+
51
+extension PhotoDetailCoordinator: PhotoDetailListViewModelDelegate {
52
+    func didSelected() {
53
+        let vc = UIStoryboard.photoDetail.instantiateController(PhotoPreviewViewController.self)
54
+        vc.viewModel = shareListViewModel
55
+        navigationController.pushViewController(vc, animated: true)
56
+    }
57
+}
10 58
 
11 59
 extension UIStoryboard {
12 60
     static var photoDetail: UIStoryboard {
13
-        return UIStoryboard(name: "Detail", bundle: Bundle(identifier: "com.Paiai-iOS"))
61
+        return UIStoryboard(name: "PhotoDetail", bundle: Bundle(identifier: "com.Paiai-iOS"))
14 62
     }
15 63
 }

+ 1 - 1
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoDetailImageCell.swift

@@ -9,5 +9,5 @@
9 9
 import UIKit
10 10
 
11 11
 class PhotoDetailImageCell: UICollectionViewCell {
12
-    
12
+    @IBOutlet weak var imageView: UIImageView!
13 13
 }

+ 265 - 339
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoDetailViewController.swift

@@ -9,6 +9,7 @@
9 9
 import UIKit
10 10
 import RxSwift
11 11
 import RxCocoa
12
+import RxDataSources
12 13
 import PaiaiDataKit
13 14
 import PaiaiUIKit
14 15
 
@@ -17,6 +18,7 @@ let kPhotographerMark = 1
17 18
 
18 19
 final class PhotoDetailViewController: UIViewController {
19 20
 
21
+    @IBOutlet weak var enterGroupView: UIView!
20 22
     @IBOutlet weak var groupAvatar: UIImageView!
21 23
     @IBOutlet weak var groupName: UILabel!
22 24
     
@@ -30,409 +32,333 @@ final class PhotoDetailViewController: UIViewController {
30 32
     @IBOutlet weak var thumbupView: UIView!
31 33
     
32 34
     @IBOutlet weak var commentCount: UILabel!
33
-    @IBOutlet weak var tableView: UITableView!
35
+    @IBOutlet weak var commentTableView: UITableView!
34 36
     
35
-    @IBOutlet weak var commentView: UIView!
37
+    @IBOutlet weak var commentEditingView: UIView!
36 38
     @IBOutlet weak var commentHeight: NSLayoutConstraint!
37 39
     @IBOutlet weak var commentTextField: UITextField!
38 40
     @IBOutlet weak var sendBtn: UIButton!
39 41
     
40 42
     @IBOutlet weak var buyView: UIView!
43
+    @IBOutlet weak var waterMarkView: UIView!
41 44
     @IBOutlet weak var waterMarkImage: UIImageView!
42 45
     @IBOutlet weak var waterMarkLabel: UILabel!
43
-
46
+    
47
+    @IBOutlet weak var thumbupViewHeightConstraint: NSLayoutConstraint!
48
+    @IBOutlet weak var commentEditYConstraint: NSLayoutConstraint!
49
+    
44 50
     // MARK: data property
45 51
     var viewModel: PhotoDetailViewModel!
46
-    lazy var datas = [PhotoItem]()
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

set line_length=200 for isort · fabef63211 - Gogs: Go Git Service

set line_length=200 for isort

Brightcells 9 年之前
父节点
当前提交
fabef63211

+ 5 - 1
.isort.cfg

@@ -1,4 +1,8 @@
1
+# See the menu of settings available here:
2
+#   https://github.com/timothycrosley/isort/wiki/isort-Settings
3
+
1 4
 [settings]
2 5
 indent='    '
3
-line_length=120
6
+line_length=200
7
+lines_after_imports=2
4 8
 skip=migrations

+ 1 - 2
account/admin.py

@@ -4,8 +4,7 @@ from curtail_uuid import CurtailUUID
4 4
 from django.contrib import admin
5 5
 from django.contrib.auth.hashers import make_password
6 6
 
7
-from account.models import (LensmanInfo, LensmanLoginLogInfo, UserInfo,
8
-                            UserLoginLogInfo)
7
+from account.models import LensmanInfo, LensmanLoginLogInfo, UserInfo, UserLoginLogInfo
9 8
 
10 9
 
11 10
 class LensmanInfoAdmin(admin.ModelAdmin):

+ 1 - 0
account/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 1 - 2
account/views.py

@@ -8,8 +8,7 @@ from rest_framework import viewsets
8 8
 from TimeConvert import TimeConvert as tc
9 9
 
10 10
 from account.models import LensmanInfo, UserInfo, UserLoginLogInfo
11
-from account.serializers import (GroupSerializer, LensmanInfoSerializer,
12
-                                 UserInfoSerializer, UserSerializer)
11
+from account.serializers import GroupSerializer, LensmanInfoSerializer, UserInfoSerializer, UserSerializer
13 12
 from utils.error.errno_utils import LensmanStatusCode, UserStatusCode
14 13
 from utils.error.response_utils import response
15 14
 from utils.ip_utils import ip_addr

+ 1 - 0
api/admin.py

@@ -1,3 +1,4 @@
1 1
 from django.contrib import admin
2 2
 
3
+
3 4
 # Register your models here.

+ 1 - 0
api/models.py

@@ -1,3 +1,4 @@
1 1
 from django.db import models
2 2
 
3
+
3 4
 # Create your models here.

+ 1 - 0
api/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 1 - 0
api/urls.py

@@ -9,6 +9,7 @@ from operation import views as op_views
9 9
 from pay import views as pay_views
10 10
 from photo import views as photo_views
11 11
 
12
+
12 13
 # 帐户相关
13 14
 urlpatterns = [
14 15
     url(r'^login$', account_views.lensman_login_api, name='lensman_login_api'),  # 摄影师登录

+ 1 - 0
api/views.py

@@ -1,3 +1,4 @@
1 1
 from django.shortcuts import render
2 2
 
3
+
3 4
 # Create your views here.

+ 1 - 2
group/admin.py

@@ -2,8 +2,7 @@
2 2
 
3 3
 from django.contrib import admin
4 4
 
5
-from group.models import (GroupInfo, GroupPhotoInfo, GroupPhotoOrderInfo,
6
-                          GroupUserInfo, PhotoCommentInfo, PhotoThumbUpInfo)
5
+from group.models import GroupInfo, GroupPhotoInfo, GroupPhotoOrderInfo, GroupUserInfo, PhotoCommentInfo, PhotoThumbUpInfo
7 6
 
8 7
 
9 8
 class GroupInfoAdmin(admin.ModelAdmin):

+ 1 - 0
group/models.py

@@ -9,6 +9,7 @@ from utils.redis.rgroup import get_group_photo_thumbup_flag
9 9
 from utils.redis.rorder import get_lensman_order_record
10 10
 from utils.url_utils import img_url
11 11
 
12
+
12 13
 r = settings.REDIS_CACHE
13 14
 
14 15
 

+ 1 - 0
group/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 6 - 14
group/views.py

@@ -14,29 +14,21 @@ from rest_framework import viewsets
14 14
 from TimeConvert import TimeConvert as tc
15 15
 
16 16
 from account.models import UserInfo
17
-from group.models import (GroupInfo, GroupPhotoInfo, GroupUserInfo,
18
-                          PhotoCommentInfo, PhotoThumbUpInfo)
19
-from group.serializers import (GroupInfoSerializer, GroupPhotoInfoSerializer,
20
-                               GroupUserInfoSerializer)
17
+from group.models import GroupInfo, GroupPhotoInfo, GroupUserInfo, PhotoCommentInfo, PhotoThumbUpInfo
18
+from group.serializers import GroupInfoSerializer, GroupPhotoInfoSerializer, GroupUserInfoSerializer
21 19
 from message.models import UserMessageInfo
22
-from utils.error.errno_utils import (GroupPhotoStatusCode, GroupStatusCode,
23
-                                     GroupUserStatusCode, UserStatusCode)
20
+from utils.error.errno_utils import GroupPhotoStatusCode, GroupStatusCode, GroupUserStatusCode, UserStatusCode
24 21
 from utils.error.response_utils import response
25 22
 from utils.page_utils import pagination
26
-from utils.redis.rgroup import (del_group_photo_thumbup_flag, get_group_info,
27
-                                get_group_photo_thumbup_flag,
28
-                                get_group_users_info, set_group_info,
29
-                                set_group_photo_thumbup_flag,
30
-                                set_group_users_info)
31
-from utils.redis.rkeys import (GROUP_LAST_PHOTO_PK, GROUP_USERS_APPLYING_SET,
32
-                               GROUP_USERS_DELETED_SET, GROUP_USERS_PASSED_SET,
33
-                               GROUP_USERS_QUIT_SET, GROUP_USERS_REFUSED_SET,
23
+from utils.redis.rgroup import del_group_photo_thumbup_flag, get_group_info, get_group_photo_thumbup_flag, get_group_users_info, set_group_info, set_group_photo_thumbup_flag, set_group_users_info
24
+from utils.redis.rkeys import (GROUP_LAST_PHOTO_PK, GROUP_USERS_APPLYING_SET, GROUP_USERS_DELETED_SET, GROUP_USERS_PASSED_SET, GROUP_USERS_QUIT_SET, GROUP_USERS_REFUSED_SET,
34 25
                                LENSMAN_PHOTO_HAGGLE_TIMES, LENSMAN_PHOTO_PRICE)
35 26
 from utils.redis.rorder import get_lensman_order_record
36 27
 from utils.sql.raw import PAI2_HOME_API
37 28
 from utils.thumbnail_utils import make_thumbnail
38 29
 from utils.url_utils import img_url
39 30
 
31
+
40 32
 r = settings.REDIS_CACHE
41 33
 
42 34
 

+ 1 - 1
isort.sh

@@ -1,3 +1,3 @@
1 1
 #!/bin/bash
2 2
 
3
-isort -rc --settings-path .isort.cfg .
3
+isort -rc -sp .isort.cfg .

+ 1 - 0
manage.py

@@ -2,6 +2,7 @@
2 2
 import os
3 3
 import sys
4 4
 
5
+
5 6
 if __name__ == "__main__":
6 7
     os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pai2.settings")
7 8
 

+ 1 - 2
message/admin.py

@@ -2,8 +2,7 @@
2 2
 
3 3
 from django.contrib import admin
4 4
 
5
-from message.models import (SystemMessageDeleteInfo, SystemMessageInfo,
6
-                            SystemMessageReadInfo, UserMessageInfo)
5
+from message.models import SystemMessageDeleteInfo, SystemMessageInfo, SystemMessageReadInfo, UserMessageInfo
7 6
 
8 7
 
9 8
 class UserMessageInfoAdmin(admin.ModelAdmin):

+ 1 - 0
message/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 2 - 6
message/views.py

@@ -4,15 +4,11 @@ from django.conf import settings
4 4
 from django.http import JsonResponse
5 5
 
6 6
 from account.models import UserInfo
7
-from message.models import (SystemMessageDeleteInfo, SystemMessageInfo,
8
-                            SystemMessageReadInfo, UserMessageInfo)
7
+from message.models import SystemMessageDeleteInfo, SystemMessageInfo, SystemMessageReadInfo, UserMessageInfo
9 8
 from utils.error.errno_utils import MessageStatusCode, UserStatusCode
10 9
 from utils.error.response_utils import response
11 10
 from utils.page_utils import pagination
12
-from utils.redis.rmessage import (get_system_message_delete_info,
13
-                                  get_system_message_read_info,
14
-                                  set_system_message_delete_info,
15
-                                  set_system_message_read_info)
11
+from utils.redis.rmessage import get_system_message_delete_info, get_system_message_read_info, set_system_message_delete_info, set_system_message_read_info
16 12
 
17 13
 
18 14
 def message_list_api(request):

+ 1 - 0
operation/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 1 - 0
page/admin.py

@@ -1,3 +1,4 @@
1 1
 from django.contrib import admin
2 2
 
3
+
3 4
 # Register your models here.

+ 1 - 0
page/models.py

@@ -1,3 +1,4 @@
1 1
 from django.db import models
2 2
 
3
+
3 4
 # Create your models here.

+ 1 - 0
page/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 1 - 0
pai2/settings.py

@@ -15,6 +15,7 @@ https://docs.djangoproject.com/en/1.8/ref/settings/
15 15
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16 16
 import os
17 17
 
18
+
18 19
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19 20
 PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
20 21
 

+ 1 - 0
pai2/urls.py

@@ -27,6 +27,7 @@ from page import views as page_views
27 27
 from photo import views as photo_views
28 28
 from website import views as website_views
29 29
 
30
+
30 31
 router = routers.DefaultRouter()
31 32
 # router.register(r'users', account_views.UserViewSet)
32 33
 # router.register(r'groups', account_views.GroupViewSet)

+ 1 - 0
pai2/urls_api.py

@@ -3,6 +3,7 @@
3 3
 from django.conf import settings
4 4
 from django.conf.urls import include, url
5 5
 
6
+
6 7
 urlpatterns = [
7 8
     url(r'^', include('api.urls', namespace='api')),
8 9
 ]

+ 1 - 0
pai2/views.py

@@ -1,3 +1,4 @@
1 1
 from django.shortcuts import render
2 2
 
3
+
3 4
 # Create your views here.

+ 1 - 0
pai2/wsgi.py

@@ -11,6 +11,7 @@ import os
11 11
 
12 12
 from django.core.wsgi import get_wsgi_application
13 13
 
14
+
14 15
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pai2.settings")
15 16
 
16 17
 application = get_wsgi_application()

+ 1 - 0
pay/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 1 - 0
pay/views.py

@@ -18,6 +18,7 @@ from utils.page_utils import pagination
18 18
 from utils.redis.rkeys import LENSMAN_PHOTO_PRICE
19 19
 from utils.redis.rorder import set_lensman_order_record
20 20
 
21
+
21 22
 r = settings.REDIS_CACHE
22 23
 WECHAT = settings.WECHAT
23 24
 

+ 1 - 0
photo/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.

+ 2 - 2
photo/views.py

@@ -19,12 +19,12 @@ from photo.serializers import PhotosInfoSerializer
19 19
 from utils.error.errno_utils import PhotoStatusCode
20 20
 from utils.error.response_utils import response
21 21
 from utils.ip_utils import ip_addr
22
-from utils.redis.rgroup import (get_group_info, get_group_users_info,
23
-                                set_group_info, set_group_users_info)
22
+from utils.redis.rgroup import get_group_info, get_group_users_info, set_group_info, set_group_users_info
24 23
 from utils.redis.rkeys import GROUP_LAST_PHOTO_PK
25 24
 from utils.thumbnail_utils import make_thumbnail
26 25
 from utils.watermark_utils import watermark_wrap
27 26
 
27
+
28 28
 r = settings.REDIS_CACHE
29 29
 
30 30
 

+ 2 - 3
utils/redis/retrieve.py

@@ -3,9 +3,8 @@
3 3
 from django.conf import settings
4 4
 
5 5
 from group.models import GroupInfo, GroupPhotoInfo, GroupUserInfo
6
-from utils.redis.rkeys import (GROUP_LAST_PHOTO_PK, GROUP_USERS_APPLYING_SET,
7
-                               GROUP_USERS_DELETED_SET, GROUP_USERS_PASSED_SET,
8
-                               GROUP_USERS_REFUSED_SET)
6
+from utils.redis.rkeys import GROUP_LAST_PHOTO_PK, GROUP_USERS_APPLYING_SET, GROUP_USERS_DELETED_SET, GROUP_USERS_PASSED_SET, GROUP_USERS_REFUSED_SET
7
+
9 8
 
10 9
 r = settings.REDIS_CACHE
11 10
 

+ 2 - 2
utils/redis/rgroup.py

@@ -5,8 +5,8 @@ import json
5 5
 from django.conf import settings
6 6
 from django.core.serializers.json import DjangoJSONEncoder
7 7
 
8
-from utils.redis.rkeys import (GROUP_INFO, GROUP_PHOTO_THUMB_UP,
9
-                               GROUP_USERS_INFO)
8
+from utils.redis.rkeys import GROUP_INFO, GROUP_PHOTO_THUMB_UP, GROUP_USERS_INFO
9
+
10 10
 
11 11
 r = settings.REDIS_CACHE
12 12
 

+ 2 - 2
utils/redis/rmessage.py

@@ -5,8 +5,8 @@ import json
5 5
 from django.conf import settings
6 6
 
7 7
 from message.models import SystemMessageDeleteInfo, SystemMessageReadInfo
8
-from utils.redis.rkeys import (SYSTEM_MESSAGE_DELETED_INFO,
9
-                               SYSTEM_MESSAGE_READ_INFO)
8
+from utils.redis.rkeys import SYSTEM_MESSAGE_DELETED_INFO, SYSTEM_MESSAGE_READ_INFO
9
+
10 10
 
11 11
 r = settings.REDIS_CACHE
12 12
 

+ 1 - 0
utils/redis/rorder.py

@@ -7,6 +7,7 @@ from django.core.serializers.json import DjangoJSONEncoder
7 7
 
8 8
 from utils.redis.rkeys import LENSMAN_PHOTO_ORDER_RECORD
9 9
 
10
+
10 11
 r = settings.REDIS_CACHE
11 12
 
12 13
 

+ 1 - 0
utils/thumbnail_utils.py

@@ -2,6 +2,7 @@
2 2
 
3 3
 from __future__ import division
4 4
 
5
+
5 6
 try:
6 7
     from PIL import Image
7 8
 except ImportError:

+ 1 - 0
website/admin.py

@@ -1,3 +1,4 @@
1 1
 from django.contrib import admin
2 2
 
3
+
3 4
 # Register your models here.

+ 1 - 0
website/models.py

@@ -1,3 +1,4 @@
1 1
 from django.db import models
2 2
 
3
+
3 4
 # Create your models here.

+ 1 - 0
website/tests.py

@@ -1,3 +1,4 @@
1 1
 from django.test import TestCase
2 2
 
3
+
3 4
 # Create your tests here.