76c9d53e179614b46ff41907d09d77817R234">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

kodo - Gogs: Go Git Service

暫無描述

huangqimin: 3d0d214667 :sparkles: Member Infos 6 年之前
..
__init__.py 3d0d214667 :sparkles: Member Infos 6 年之前
dummy_backend.py 3d0d214667 :sparkles: Member Infos 6 年之前
pillow_backend.py 3d0d214667 :sparkles: Member Infos 6 年之前
Kodo/kodo - Gogs: Go Git Service

56 Commits (f6a88c632b1d5ada036e16e92ec51ec3584401ce)

Auteur SHA1 Bericht Datum
  Brightcells f6a88c632b add group_default_avatar field for GroupInfo 10 jaren geleden
  Brightcells e50a206d29 add pagination for pai2_home_api 10 jaren geleden
  Brightcells da2a81fff1 add api pai2_home 10 jaren geleden
  Brightcells 7d85bed0b0 move errno_utils.py/response_utils.py into error file 10 jaren geleden
  Brightcells 11c6982627 return user_id for some api 10 jaren geleden
  Brightcells 0110c29272 rename api name 10 jaren geleden
  Brightcells 7a17d0fb90 add api wxpay & add redis relative 10 jaren geleden
  Brightcells 62aff0cb2f move status code into errno_utils.py to unified management 10 jaren geleden
  Brightcells a121b75ff2 add db_index=True for status field 10 jaren geleden
  Brightcells b5be31c6cd Fix Bug: Field name photo_path is not valid for model PhotosInfo 10 jaren geleden
  Brightcells 0786f22bad order_by('-pk') replace of order_by('-created_at') 10 jaren geleden
  Brightcells 62ef679981 add ret photo_url and photo_thumbnail_url 10 jaren geleden
  Brightcells d3088e1fec add ret msg_type_desc 10 jaren geleden
  Brightcells 464c31b794 support POST method for message relative api 10 jaren geleden
  Brightcells 8f83bd22be add param user_id for msg relative api 10 jaren geleden
  Brightcells 928a51477c 'UserMessageInfo' object has no attribute 'title' 10 jaren geleden
  Brightcells 8f14561134 UserMessageInfo in admin.py 10 jaren geleden
  Brightcells 89094aa77b if user exists, update user info, in api wx_authorize_api 10 jaren geleden
  Brightcells ba7bc03f03 adjust sex value 10 jaren geleden
  Brightcells 30daca135b add api message_list_api/message_type_list_api/message_read_api 10 jaren geleden
  Brightcells 03561aaa5f modify api comment_submit_api/comment_list_api 10 jaren geleden
  Brightcells c72d89f6e5 add api comment_submit_api/comment_list_api/thumbup_submit_api/thumbup_list_api/thumbup_cancel_api 10 jaren geleden
  Brightcells df1df69fe3 add api upgrade/splash 10 jaren geleden
  Brightcells 3253626936 change DOMAIN and IMG_DOMAIN to pai.ai 10 jaren geleden
  Brightcells e5721d434c add URL_CONFIG for domain pai.ai 10 jaren geleden
  Brightcells 2b831a139f CONN_MAX_AGE & cached.Loader 10 jaren geleden
  Brightcells 2fb52216da Fix Bug: wx authorize doesn't store wx_uid 10 jaren geleden
  Brightcells 48d2e93b70 return nickname for userinfo data 10 jaren geleden
  Brightcells 814ed79bfc add api group_unlock_api 10 jaren geleden
  Brightcells 1c25788dbf add group_name for group_create_api 10 jaren geleden
  Brightcells 8b5ea74192 add location /fly 10 jaren geleden
  Brightcells 4afdb94e20 add avatar for GroupUserInfo 10 jaren geleden
  Brightcells 5ef425fee7 add api wx_authorize_api 10 jaren geleden
  Brightcells d3798a39f1 update session_detail_api 10 jaren geleden
  Brightcells ce10db91f9 thumbnail_utils make_thumb 10 jaren geleden
  Brightcells f587f0a48f user can just see photo after he joined the group & zh_Hans replace zh_CN in settings.py 10 jaren geleden
  Brightcells 42df840f43 return current_id for api flyimg_upload/flyimg_list 10 jaren geleden
  Brightcells 9077a53317 return next_id for api flyimg_upload/flyimg_list 10 jaren geleden
  Brightcells f58bde298b add api flyimg_upload/flyimg_list 10 jaren geleden
  Brightcells 7fd74ed1e4 add group_join_api direct pass 10 jaren geleden
  Brightcells 7467a3e68a add api group_update/group_remove 10 jaren geleden
  Brightcells 7e305483ab add api group_detail/group_lock/group_pass/group_refuse 10 jaren geleden
  Brightcells e184e7dd5b add api group_create/group_join 10 jaren geleden
  Brightcells 6e77deb909 https://pypi.python.org/pypi/django-curtail-uuid 10 jaren geleden
  Brightcells e7d461ade5 upload photo with photo_id 10 jaren geleden
  Brightcells ca16dc830e alias .img.xfoto.com.cn/photo 10 jaren geleden
  Brightcells 7ddb9f0b5e change to use img.xfoto.com.cn as photo domain 10 jaren geleden
  Brightcells 3454610bb7 add api of user signup/login 10 jaren geleden
  Brightcells 00e8234de9 add api photo_standard_api 10 jaren geleden
  Brightcells e0ba30f506 add api session_detail_api 10 jaren geleden