@@ -110,7 +110,7 @@  | 
            ||
| 110 | 110 | 
                 		0513103C21CA1B67004EF1BE /* GroupMemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42CF50491EC0536000D23E9F /* GroupMemberViewModel.swift */; };
               | 
            
| 111 | 111 | 
                 		0513103D21CA1B67004EF1BE /* MineGroupViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42CF50451EC0526C00D23E9F /* MineGroupViewModel.swift */; };
               | 
            
| 112 | 112 | 
                 		0513103E21CA1B67004EF1BE /* MineOrderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42CF50471EC052B200D23E9F /* MineOrderViewModel.swift */; };
               | 
            
| 113 | 
                -		0513103F21CA1B67004EF1BE /* PhotoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69FFAA41E7004700006FEE0 /* PhotoDetailViewModel.swift */; };
               | 
            |
| 113 | 
                +		0513103F21CA1B67004EF1BE /* PhotoDetailItemViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69FFAA41E7004700006FEE0 /* PhotoDetailItemViewModel.swift */; };
               | 
            |
| 114 | 114 | 
                 		0513104021CA1B67004EF1BE /* MessageListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = A69FFADE1E70047E0006FEE0 /* MessageListViewModel.swift */; };
               | 
            
| 115 | 115 | 
                 		0513104121CA1B67004EF1BE /* MessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 059AA62A21BA85B000485188 /* MessageViewModel.swift */; };
               | 
            
| 116 | 116 | 
                 		0513104221CA1B67004EF1BE /* CreateGroupViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05A0E8A821C782D700EAB9A2 /* CreateGroupViewModel.swift */; };
               | 
            
                @@ -177,7 +177,7 @@  | 
            ||
| 177 | 177 | 
                 		0546D9852242460700742939 /* OriginData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0546D9842242460700742939 /* OriginData.swift */; };
               | 
            
| 178 | 178 | 
                 		054B6C45223F884600939FE6 /* PhotoDetailRemoteAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 054B6C44223F884600939FE6 /* PhotoDetailRemoteAPI.swift */; };
               | 
            
| 179 | 179 | 
                 		054B6C46223F966A00939FE6 /* RxDataSources.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05130FC421CA1997004EF1BE /* RxDataSources.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
               | 
            
| 180 | 
                -		05594BFF2240BEDE002D4910 /* PhotoDetailListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05594BFE2240BEDE002D4910 /* PhotoDetailListViewModel.swift */; };
               | 
            |
| 180 | 
                +		05594BFF2240BEDE002D4910 /* PhotoDetailViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05594BFE2240BEDE002D4910 /* PhotoDetailViewModel.swift */; };
               | 
            |
| 181 | 181 | 
                 		05594C012240BF9C002D4910 /* PhotoPurchaseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05594C002240BF9C002D4910 /* PhotoPurchaseViewModel.swift */; };
               | 
            
| 182 | 182 | 
                 		05594C032240E94E002D4910 /* PhotoDetailImageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05594C022240E94E002D4910 /* PhotoDetailImageCell.swift */; };
               | 
            
| 183 | 183 | 
                 		055BB53E220AEA3B009548AA /* NiblessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 055BB53D220AEA3B009548AA /* NiblessViewController.swift */; };
               | 
            
                @@ -251,6 +251,8 @@  | 
            ||
| 251 | 251 | 
                 		05D3A3CD22000C3A00A29A20 /* GroupCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05D3A3CC22000C3900A29A20 /* GroupCoordinator.swift */; };
               | 
            
| 252 | 252 | 
                 		05D3A3D02200288400A29A20 /* Storyboarded.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05D3A3CF2200288400A29A20 /* Storyboarded.swift */; };
               | 
            
| 253 | 253 | 
                 		05E80E3021DF65D5006368C4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 05E80E2F21DF65D4006368C4 /* Assets.xcassets */; };
               | 
            
| 254 | 
                +		05ED11C52251A90000FF3758 /* PhotoPurchaseRemoteAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05ED11C42251A90000FF3758 /* PhotoPurchaseRemoteAPI.swift */; };
               | 
            |
| 255 | 
                +		05ED11C72252165700FF3758 /* Notification+wxPay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 05ED11C62252165700FF3758 /* Notification+wxPay.swift */; };
               | 
            |
| 254 | 256 | 
                /* End PBXBuildFile section */  | 
            
| 255 | 257 | 
                 | 
            
| 256 | 258 | 
                /* Begin PBXContainerItemProxy section */  | 
            
                @@ -420,7 +422,7 @@  | 
            ||
| 420 | 422 | 
                 		054863661FA326CB00A39DA0 /* PhotoCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoCell.swift; sourceTree = "<group>"; };
               | 
            
| 421 | 423 | 
                 		054863671FA326CB00A39DA0 /* PhotoCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PhotoCell.xib; sourceTree = "<group>"; };
               | 
            
| 422 | 424 | 
                 		054B6C44223F884600939FE6 /* PhotoDetailRemoteAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoDetailRemoteAPI.swift; sourceTree = "<group>"; };
               | 
            
| 423 | 
                -		05594BFE2240BEDE002D4910 /* PhotoDetailListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoDetailListViewModel.swift; sourceTree = "<group>"; };
               | 
            |
| 425 | 
                +		05594BFE2240BEDE002D4910 /* PhotoDetailViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoDetailViewModel.swift; sourceTree = "<group>"; };
               | 
            |
| 424 | 426 | 
                 		05594C002240BF9C002D4910 /* PhotoPurchaseViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPurchaseViewModel.swift; sourceTree = "<group>"; };
               | 
            
| 425 | 427 | 
                 		05594C022240E94E002D4910 /* PhotoDetailImageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoDetailImageCell.swift; sourceTree = "<group>"; };
               | 
            
| 426 | 428 | 
                 		055BB53D220AEA3B009548AA /* NiblessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NiblessViewController.swift; sourceTree = "<group>"; };
               | 
            
                @@ -493,6 +495,8 @@  | 
            ||
| 493 | 495 | 
                 		05D3A3CC22000C3900A29A20 /* GroupCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupCoordinator.swift; sourceTree = "<group>"; };
               | 
            
| 494 | 496 | 
                 		05D3A3CF2200288400A29A20 /* Storyboarded.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboarded.swift; sourceTree = "<group>"; };
               | 
            
| 495 | 497 | 
                 		05E80E2F21DF65D4006368C4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
               | 
            
| 498 | 
                +		05ED11C42251A90000FF3758 /* PhotoPurchaseRemoteAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPurchaseRemoteAPI.swift; sourceTree = "<group>"; };
               | 
            |
| 499 | 
                +		05ED11C62252165700FF3758 /* Notification+wxPay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Notification+wxPay.swift"; sourceTree = "<group>"; };
               | 
            |
| 496 | 500 | 
                 		3864C06C1CAD27EC0048ADAD /* Swift-bridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Swift-bridge.h"; sourceTree = "<group>"; };
               | 
            
| 497 | 501 | 
                 		42CF50451EC0526C00D23E9F /* MineGroupViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineGroupViewModel.swift; sourceTree = "<group>"; };
               | 
            
| 498 | 502 | 
                 		42CF50471EC052B200D23E9F /* MineOrderViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MineOrderViewModel.swift; sourceTree = "<group>"; };
               | 
            
                @@ -506,7 +510,7 @@  | 
            ||
| 506 | 510 | 
                 		A69FFA841E7002B50006FEE0 /* UserInfoRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserInfoRepository.swift; sourceTree = "<group>"; };
               | 
            
| 507 | 511 | 
                 		A69FFA9E1E7004700006FEE0 /* PhotoDetailCommentCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoDetailCommentCell.swift; sourceTree = "<group>"; };
               | 
            
| 508 | 512 | 
                 		A69FFAA31E7004700006FEE0 /* PhotoDetailViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoDetailViewController.swift; sourceTree = "<group>"; };
               | 
            
| 509 | 
                -		A69FFAA41E7004700006FEE0 /* PhotoDetailViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoDetailViewModel.swift; sourceTree = "<group>"; };
               | 
            |
| 513 | 
                +		A69FFAA41E7004700006FEE0 /* PhotoDetailItemViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoDetailItemViewModel.swift; sourceTree = "<group>"; };
               | 
            |
| 510 | 514 | 
                 		A69FFAA61E7004700006FEE0 /* ImageCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCell.swift; sourceTree = "<group>"; usesTabs = 0; wrapsLines = 1; };
               | 
            
| 511 | 515 | 
                 		A69FFAA81E7004700006FEE0 /* ShareController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShareController.swift; sourceTree = "<group>"; };
               | 
            
| 512 | 516 | 
                 		A69FFAA91E7004700006FEE0 /* PhotoPreviewViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PhotoPreviewViewController.swift; sourceTree = "<group>"; };
               | 
            
                @@ -877,6 +881,7 @@  | 
            ||
| 877 | 881 | 
                0543274121C68C1900C6388D /* StringExt.swift */,  | 
            
| 878 | 882 | 
                0543274721C68C1900C6388D /* DateExt.swift */,  | 
            
| 879 | 883 | 
                05B2C60521D60E97008063B3 /* DictionaryExt.swift */,  | 
            
| 884 | 
                + 05ED11C62252165700FF3758 /* Notification+wxPay.swift */,  | 
            |
| 880 | 885 | 
                );  | 
            
| 881 | 886 | 
                path = Extension;  | 
            
| 882 | 887 | 
                sourceTree = "<group>";  | 
            
                @@ -971,8 +976,8 @@  | 
            ||
| 971 | 976 | 
                 		0543E80521D0CDDA00A42807 /* PhotoDetail */ = {
               | 
            
| 972 | 977 | 
                isa = PBXGroup;  | 
            
| 973 | 978 | 
                children = (  | 
            
| 974 | 
                - A69FFAA41E7004700006FEE0 /* PhotoDetailViewModel.swift */,  | 
            |
| 975 | 
                - 05594BFE2240BEDE002D4910 /* PhotoDetailListViewModel.swift */,  | 
            |
| 979 | 
                + 05594BFE2240BEDE002D4910 /* PhotoDetailViewModel.swift */,  | 
            |
| 980 | 
                + A69FFAA41E7004700006FEE0 /* PhotoDetailItemViewModel.swift */,  | 
            |
| 976 | 981 | 
                05594C002240BF9C002D4910 /* PhotoPurchaseViewModel.swift */,  | 
            
| 977 | 982 | 
                );  | 
            
| 978 | 983 | 
                path = PhotoDetail;  | 
            
                @@ -1078,6 +1083,7 @@  | 
            ||
| 1078 | 1083 | 
                05B2C62821D74F27008063B3 /* MessageRemoteAPI.swift */,  | 
            
| 1079 | 1084 | 
                05B2C62A21D750F1008063B3 /* FeedbackRemoteAPI.swift */,  | 
            
| 1080 | 1085 | 
                054B6C44223F884600939FE6 /* PhotoDetailRemoteAPI.swift */,  | 
            
| 1086 | 
                + 05ED11C42251A90000FF3758 /* PhotoPurchaseRemoteAPI.swift */,  | 
            |
| 1081 | 1087 | 
                );  | 
            
| 1082 | 1088 | 
                path = Remote;  | 
            
| 1083 | 1089 | 
                sourceTree = "<group>";  | 
            
                @@ -1722,8 +1728,9 @@  | 
            ||
| 1722 | 1728 | 
                0513103E21CA1B67004EF1BE /* MineOrderViewModel.swift in Sources */,  | 
            
| 1723 | 1729 | 
                05B2C62721D74E92008063B3 /* OrderRemoteAPI.swift in Sources */,  | 
            
| 1724 | 1730 | 
                05B2C62921D74F27008063B3 /* MessageRemoteAPI.swift in Sources */,  | 
            
| 1725 | 
                - 0513103F21CA1B67004EF1BE /* PhotoDetailViewModel.swift in Sources */,  | 
            |
| 1731 | 
                + 0513103F21CA1B67004EF1BE /* PhotoDetailItemViewModel.swift in Sources */,  | 
            |
| 1726 | 1732 | 
                054B6C45223F884600939FE6 /* PhotoDetailRemoteAPI.swift in Sources */,  | 
            
| 1733 | 
                + 05ED11C72252165700FF3758 /* Notification+wxPay.swift in Sources */,  | 
            |
| 1727 | 1734 | 
                0513104021CA1B67004EF1BE /* MessageListViewModel.swift in Sources */,  | 
            
| 1728 | 1735 | 
                053E127521F5A72000A64893 /* Error.swift in Sources */,  | 
            
| 1729 | 1736 | 
                05B2C61D21D710C5008063B3 /* GroupRemoteAPI.swift in Sources */,  | 
            
                @@ -1733,11 +1740,12 @@  | 
            ||
| 1733 | 1740 | 
                05130FB721C9E80F004EF1BE /* MessageListItem.swift in Sources */,  | 
            
| 1734 | 1741 | 
                05B2C62121D727AA008063B3 /* StatusResource.swift in Sources */,  | 
            
| 1735 | 1742 | 
                051310C021CB6EF4004EF1BE /* UserInfo.swift in Sources */,  | 
            
| 1736 | 
                - 05594BFF2240BEDE002D4910 /* PhotoDetailListViewModel.swift in Sources */,  | 
            |
| 1743 | 
                + 05594BFF2240BEDE002D4910 /* PhotoDetailViewModel.swift in Sources */,  | 
            |
| 1737 | 1744 | 
                05130FB521C9E7CE004EF1BE /* MessageItem.swift in Sources */,  | 
            
| 1738 | 1745 | 
                057CA9C621DCA2C900FB7D03 /* PhotoRepository.swift in Sources */,  | 
            
| 1739 | 1746 | 
                0546D9852242460700742939 /* OriginData.swift in Sources */,  | 
            
| 1740 | 1747 | 
                05B2C62F21D754BD008063B3 /* GroupDetailRemoteAPI.swift in Sources */,  | 
            
| 1748 | 
                + 05ED11C52251A90000FF3758 /* PhotoPurchaseRemoteAPI.swift in Sources */,  | 
            |
| 1741 | 1749 | 
                05130FB321C9E76A004EF1BE /* GroupItem.swift in Sources */,  | 
            
| 1742 | 1750 | 
                05130FB021C9E6CD004EF1BE /* OrderItem.swift in Sources */,  | 
            
| 1743 | 1751 | 
                );  | 
            
                @@ -2,32 +2,4 @@  | 
            ||
| 2 | 2 | 
                <Bucket  | 
            
| 3 | 3 | 
                type = "1"  | 
            
| 4 | 4 | 
                version = "2.0">  | 
            
| 5 | 
                - <Breakpoints>  | 
            |
| 6 | 
                - <BreakpointProxy  | 
            |
| 7 | 
                - BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">  | 
            |
| 8 | 
                - <BreakpointContent  | 
            |
| 9 | 
                - shouldBeEnabled = "Yes"  | 
            |
| 10 | 
                - ignoreCount = "0"  | 
            |
| 11 | 
                - continueAfterRunningActions = "No"  | 
            |
| 12 | 
                - scope = "0"  | 
            |
| 13 | 
                - stopOnStyle = "0">  | 
            |
| 14 | 
                - </BreakpointContent>  | 
            |
| 15 | 
                - </BreakpointProxy>  | 
            |
| 16 | 
                - <BreakpointProxy  | 
            |
| 17 | 
                - BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">  | 
            |
| 18 | 
                - <BreakpointContent  | 
            |
| 19 | 
                - shouldBeEnabled = "Yes"  | 
            |
| 20 | 
                - ignoreCount = "0"  | 
            |
| 21 | 
                - continueAfterRunningActions = "No"  | 
            |
| 22 | 
                - filePath = "PaiaiDataKit/DataLayer/Repositories/Remote/Reusable/NetWork/NetworkApi.swift"  | 
            |
| 23 | 
                - timestampString = "575541384.462981"  | 
            |
| 24 | 
                - startingColumnNumber = "9223372036854775807"  | 
            |
| 25 | 
                - endingColumnNumber = "9223372036854775807"  | 
            |
| 26 | 
                - startingLineNumber = "146"  | 
            |
| 27 | 
                - endingLineNumber = "146"  | 
            |
| 28 | 
                - landmarkName = "upload(resource:)"  | 
            |
| 29 | 
                - landmarkType = "7">  | 
            |
| 30 | 
                - </BreakpointContent>  | 
            |
| 31 | 
                - </BreakpointProxy>  | 
            |
| 32 | 
                - </Breakpoints>  | 
            |
| 33 | 5 | 
                </Bucket>  | 
            
                @@ -11,10 +11,6 @@ import Paiai_iOS  | 
            ||
| 11 | 11 | 
                import PaiaiUIKit  | 
            
| 12 | 12 | 
                import PaiaiDataKit  | 
            
| 13 | 13 | 
                 | 
            
| 14 | 
                -let WXPayDidFinishNotification = "WXPayDidFinishNotification"  | 
            |
| 15 | 
                -let WXPayErrorCode = "WXPayErrorCode"  | 
            |
| 16 | 
                -let WXPayErrorStr = "WXPayErrorStr"  | 
            |
| 17 | 
                -  | 
            |
| 18 | 14 | 
                let WXAppid = "wx4e22a0c8ae6d766d"  | 
            
| 19 | 15 | 
                let WXSecret = "636ac848016c593575d11143c55c8333"  | 
            
| 20 | 16 | 
                 | 
            
                @@ -24,9 +20,6 @@ private let QQSecret = "OFQ2J1RBMJyHPW8G"  | 
            ||
| 24 | 20 | 
                private let WBAppid = "2730190333"  | 
            
| 25 | 21 | 
                private let WBSecret = "ff16591583c7bcf4a0d781eae316635a"  | 
            
| 26 | 22 | 
                 | 
            
| 27 | 
                -private let WIFIUploadOriginal = "WIFIUploadOriginal"  | 
            |
| 28 | 
                -private let ReceivePush = "ReceivePush"  | 
            |
| 29 | 
                -  | 
            |
| 30 | 23 | 
                @UIApplicationMain  | 
            
| 31 | 24 | 
                 | 
            
| 32 | 25 | 
                 class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
               | 
            
                @@ -94,20 +87,20 @@ class AppDelegate: UIResponder, UIApplicationDelegate, WXApiDelegate {
               | 
            ||
| 94 | 87 | 
                #if !((arch(i386) || arch(x86_64)))  | 
            
| 95 | 88 | 
                     func onResp(_ resp: BaseResp!) {
               | 
            
| 96 | 89 | 
                         if let resp = resp as? PayResp {
               | 
            
| 97 | 
                - var userInfo: [String: AnyObject] = [(WXPayErrorCode as NSObject) as! String: Int(resp.errCode) as AnyObject]  | 
            |
| 98 | 
                -            if resp.errStr != nil {
               | 
            |
| 99 | 
                - userInfo[WXPayErrorStr] = resp.errStr as AnyObject?  | 
            |
| 100 | 
                - }  | 
            |
| 101 | 
                - NotificationCenter.default.post(name: NSNotification.Name(rawValue: WXPayDidFinishNotification), object: nil, userInfo: userInfo)  | 
            |
| 102 | 
                -        } else if let resp = resp as? SendAuthResp, let code = resp.code {
               | 
            |
| 103 | 
                - NotificationCenter.default.post(name: NSNotification.Name(rawValue: WXPayDidFinishNotification), object: nil, userInfo: userInfo)  | 
            |
| 104 | 
                - wxLoginJumpFinishCallback?(["code": code as AnyObject], nil)  | 
            |
| 105 | 
                - wxLoginJumpFinishCallback = nil  | 
            |
| 90 | 
                + var userInfo: [String: Int] = ["code": resp.errCode]  | 
            |
| 91 | 
                + NotificationCenter.default.post(name: Notification.wxNotification.payDidFinish, object: nil, userInfo: userInfo)  | 
            |
| 92 | 
                +//        } else if let resp = resp as? SendAuthResp, let code = resp.code {
               | 
            |
| 93 | 
                +// NotificationCenter.default.post(name: , object: nil, userInfo: userInfo)  | 
            |
| 94 | 
                +//// wxLoginJumpFinishCallback?(["code": code as AnyObject], nil)  | 
            |
| 95 | 
                +//// wxLoginJumpFinishCallback = nil  | 
            |
| 106 | 96 | 
                }  | 
            
| 107 | 97 | 
                }  | 
            
| 108 | 98 | 
                #endif  | 
            
| 109 | 99 | 
                }  | 
            
| 110 | 100 | 
                 | 
            
| 101 | 
                +private let WIFIUploadOriginal = "WIFIUploadOriginal"  | 
            |
| 102 | 
                +private let ReceivePush = "ReceivePush"  | 
            |
| 103 | 
                +  | 
            |
| 111 | 104 | 
                 extension AppDelegate {
               | 
            
| 112 | 105 | 
                     func registerAppConfiguration() {
               | 
            
| 113 | 106 | 
                WXApi.registerApp(WXAppid)  | 
            
                @@ -43,6 +43,7 @@ public struct PhotoItem: JSONCode {
               | 
            ||
| 43 | 43 | 
                public var thumbup = false  | 
            
| 44 | 44 | 
                public var murl = ""  | 
            
| 45 | 45 | 
                public var rurl = ""  | 
            
| 46 | 
                + public var nomark = 0  | 
            |
| 46 | 47 | 
                 | 
            
| 47 | 48 | 
                public var create_at = ""  | 
            
| 48 | 49 | 
                public var create_at_time_interval = ""  | 
            
                @@ -89,7 +90,7 @@ extension PhotoItem: Mappable {
               | 
            ||
| 89 | 90 | 
                     mutating public func mapping(map: Map) {
               | 
            
| 90 | 91 | 
                let dateFormatter = DateFormatter()  | 
            
| 91 | 92 | 
                dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"  | 
            
| 92 | 
                - created_at <- (map["created_at"], DateFormatterTransform(dateFormatter:dateFormatter))  | 
            |
| 93 | 
                + created_at <- (map["created_at"], DateFormatterTransform(dateFormatter:dateFormatter))  | 
            |
| 93 | 94 | 
                avatar <- map["avatar"]  | 
            
| 94 | 95 | 
                comment_num <- map["comment_num"]  | 
            
| 95 | 96 | 
                group_avatar <- map["group_avatar"]  | 
            
                @@ -115,6 +116,7 @@ extension PhotoItem: Mappable {
               | 
            ||
| 115 | 116 | 
                user_id <- map["user_id"]  | 
            
| 116 | 117 | 
                porder <- map["porder"]  | 
            
| 117 | 118 | 
                display_payment_btn <- map["display_payment_btn"]  | 
            
| 119 | 
                + nomark <- map["nomark"]  | 
            |
| 118 | 120 | 
                rurl = porder["r_photo_url"] ?? ""  | 
            
| 119 | 121 | 
                murl = porder["m_photo_url"] ?? ""  | 
            
| 120 | 122 | 
                 | 
            
                @@ -0,0 +1,131 @@  | 
            ||
| 1 | 
                +//  | 
            |
| 2 | 
                +// PhotoPurchaseRemoteAPI.swift  | 
            |
| 3 | 
                +// PaiaiDataKit  | 
            |
| 4 | 
                +//  | 
            |
| 5 | 
                +// Created by ffib on 2019/4/1.  | 
            |
| 6 | 
                +// Copyright © 2019 yb. All rights reserved.  | 
            |
| 7 | 
                +//  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                +import Foundation  | 
            |
| 10 | 
                +import RxSwift  | 
            |
| 11 | 
                +import ObjectMapper  | 
            |
| 12 | 
                +  | 
            |
| 13 | 
                +struct PurchaseModel {
               | 
            |
| 14 | 
                + var wxpay_params: [String: AnyObject] = [:]  | 
            |
| 15 | 
                +  | 
            |
| 16 | 
                + var appid: String = ""  | 
            |
| 17 | 
                + var noncestr: String = ""  | 
            |
| 18 | 
                + var package: String = ""  | 
            |
| 19 | 
                + var sign: String = ""  | 
            |
| 20 | 
                + var partnerid: String = ""  | 
            |
| 21 | 
                + var timestamp: Int = 0  | 
            |
| 22 | 
                +  | 
            |
| 23 | 
                + var order_id: String = ""  | 
            |
| 24 | 
                + var prepay_id: String = ""  | 
            |
| 25 | 
                +  | 
            |
| 26 | 
                +    init(_ json: JSON) {
               | 
            |
| 27 | 
                + self.init(map: Map(mappingType: .fromJSON, JSON: json))  | 
            |
| 28 | 
                + }  | 
            |
| 29 | 
                +}  | 
            |
| 30 | 
                +  | 
            |
| 31 | 
                +extension PurchaseModel: Mappable {
               | 
            |
| 32 | 
                +    init(map: Map) {
               | 
            |
| 33 | 
                + mapping(map: map)  | 
            |
| 34 | 
                + }  | 
            |
| 35 | 
                +  | 
            |
| 36 | 
                +    mutating func mapping(map: Map) {
               | 
            |
| 37 | 
                + wxpay_params <- map["wxpay_params"]  | 
            |
| 38 | 
                + order_id <- map["order_id"]  | 
            |
| 39 | 
                + prepay_id <- map["prepay_id"]  | 
            |
| 40 | 
                +  | 
            |
| 41 | 
                + let params = Map(mappingType: .fromJSON, JSON: wxpay_params)  | 
            |
| 42 | 
                +  | 
            |
| 43 | 
                + appid <- params["appid"]  | 
            |
| 44 | 
                + noncestr <- params["noncestr"]  | 
            |
| 45 | 
                + package <- params["package"]  | 
            |
| 46 | 
                + sign <- params["sign"]  | 
            |
| 47 | 
                + partnerid <- params["partnerid"]  | 
            |
| 48 | 
                + timestamp <- params["timestamp"]  | 
            |
| 49 | 
                + }  | 
            |
| 50 | 
                +}  | 
            |
| 51 | 
                +  | 
            |
| 52 | 
                +struct PhotoPurchaseRemoteAPI {
               | 
            |
| 53 | 
                + private var item: PhotoItem  | 
            |
| 54 | 
                + private var disposeBag = DisposeBag()  | 
            |
| 55 | 
                +  | 
            |
| 56 | 
                +    init(item: PhotoItem) {
               | 
            |
| 57 | 
                + self.item = item  | 
            |
| 58 | 
                + }  | 
            |
| 59 | 
                +  | 
            |
| 60 | 
                +    func parse(json: JSON) -> Int? {
               | 
            |
| 61 | 
                + guard let data = json["data"] as? [String: AnyObject],  | 
            |
| 62 | 
                +            let price = data["price"] as? Int else { return nil }
               | 
            |
| 63 | 
                +  | 
            |
| 64 | 
                + return price  | 
            |
| 65 | 
                + }  | 
            |
| 66 | 
                +  | 
            |
| 67 | 
                +    func parseOrder(json: JSON) -> PurchaseModel? {
               | 
            |
| 68 | 
                +        guard let data = json["data"] as? [String: AnyObject] else { return nil }
               | 
            |
| 69 | 
                + return PurchaseModel(data)  | 
            |
| 70 | 
                + }  | 
            |
| 71 | 
                +  | 
            |
| 72 | 
                +    func parseOrderDetail(json: JSON) -> PhotoItem? {
               | 
            |
| 73 | 
                + guard let data = json["data"] as? [String: AnyObject],  | 
            |
| 74 | 
                + let order = data["order"] as? [String: AnyObject],  | 
            |
| 75 | 
                +            let photoInfo = order["group_photo_info"] as? [String: AnyObject] else { return nil }
               | 
            |
| 76 | 
                +  | 
            |
| 77 | 
                + return PhotoItem(json: photoInfo)  | 
            |
| 78 | 
                + }  | 
            |
| 79 | 
                +  | 
            |
| 80 | 
                +    func getPrice() -> Single<Int> {
               | 
            |
| 81 | 
                + let contentResource = ContentResource(path: .picPrice,  | 
            |
| 82 | 
                + parameter: ["user_id": ShareUserId,  | 
            |
| 83 | 
                + "photo_id": item.photo_id, "photo_type": "nomark"],  | 
            |
| 84 | 
                + parseJSON: parse)  | 
            |
| 85 | 
                + return contentResource.loadContent()  | 
            |
| 86 | 
                + }  | 
            |
| 87 | 
                +  | 
            |
| 88 | 
                +    mutating func purchase() -> Single<String> {
               | 
            |
| 89 | 
                + let resource = ContentResource(path: .wxorderCreat, parameter: ["user_id": ShareUserId,  | 
            |
| 90 | 
                + "body": "获取去水印照片",  | 
            |
| 91 | 
                + "total_fee": item.nomark / 100,  | 
            |
| 92 | 
                + "trade_type": "APP",  | 
            |
| 93 | 
                + "group_id": item.group_id,  | 
            |
| 94 | 
                + "photo_id": item.photo_id,  | 
            |
| 95 | 
                + "photo_type": "nomark"],  | 
            |
| 96 | 
                + parseJSON: parseOrder)  | 
            |
| 97 | 
                +        return resource.loadContent().do(onSuccess: { model in
               | 
            |
| 98 | 
                + #if !((arch(i386) || arch(x86_64)))  | 
            |
| 99 | 
                +                    guard WXApi.isWXAppInstalled() else {
               | 
            |
| 100 | 
                + Toast.show(message: "尚未安装微信")  | 
            |
| 101 | 
                + return  | 
            |
| 102 | 
                + }  | 
            |
| 103 | 
                +  | 
            |
| 104 | 
                + WXApi.registerApp(model.appid)  | 
            |
| 105 | 
                + let payRequest = PayReq()  | 
            |
| 106 | 
                + payRequest.openID = model.appid  | 
            |
| 107 | 
                + payRequest.partnerId = model.partnerid  | 
            |
| 108 | 
                + payRequest.prepayId = model.prepay_id  | 
            |
| 109 | 
                + payRequest.package = model.package  | 
            |
| 110 | 
                + payRequest.nonceStr = model.noncestr  | 
            |
| 111 | 
                + payRequest.timeStamp = UInt32(model.timestamp)  | 
            |
| 112 | 
                +  | 
            |
| 113 | 
                + WXApi.send(payRequest)  | 
            |
| 114 | 
                + #endif  | 
            |
| 115 | 
                +            }).map { $0.order_id }
               | 
            |
| 116 | 
                + }  | 
            |
| 117 | 
                +  | 
            |
| 118 | 
                +    func getOrderStatus(orderId: String) -> Completable {
               | 
            |
| 119 | 
                + let resource = StatusResource(path: .orderDetail, parameter: ["user_id": ShareUserId])  | 
            |
| 120 | 
                +  | 
            |
| 121 | 
                + return resource.getStatus()  | 
            |
| 122 | 
                + }  | 
            |
| 123 | 
                +  | 
            |
| 124 | 
                +    func getOrderDetail(orderId: String) -> Single<PhotoItem> {
               | 
            |
| 125 | 
                + let resource = ContentResource(path: .orderDetail, parameter: ["order_id": orderId,  | 
            |
| 126 | 
                + "user_id": ShareUserId],  | 
            |
| 127 | 
                + parseJSON: parseOrderDetail)  | 
            |
| 128 | 
                +  | 
            |
| 129 | 
                + return resource.loadContent()  | 
            |
| 130 | 
                + }  | 
            |
| 131 | 
                +}  | 
            
                @@ -39,7 +39,6 @@ public enum Interfaces: String {
               | 
            ||
| 39 | 39 | 
                case groupLock = "/g/lock"  | 
            
| 40 | 40 | 
                case groupUnlock = "/g/unlock"  | 
            
| 41 | 41 | 
                case groupQuit = "/g/quit"  | 
            
| 42 | 
                -  | 
            |
| 43 | 42 | 
                 | 
            
| 44 | 43 | 
                //照片  | 
            
| 45 | 44 | 
                case groupPhotoList = "/f/list"  | 
            
                @@ -0,0 +1,58 @@  | 
            ||
| 1 | 
                +//  | 
            |
| 2 | 
                +// PhotoDetailViewModel.swift  | 
            |
| 3 | 
                +// PaiAi  | 
            |
| 4 | 
                +//  | 
            |
| 5 | 
                +// Created by zhengjianfei on 2017/1/4.  | 
            |
| 6 | 
                +// Copyright © 2017年 FFIB. All rights reserved.  | 
            |
| 7 | 
                +//  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                +import Foundation  | 
            |
| 10 | 
                +import RxSwift  | 
            |
| 11 | 
                +import RxCocoa  | 
            |
| 12 | 
                +import RxDataSources  | 
            |
| 13 | 
                +  | 
            |
| 14 | 
                +public final class PhotoDetailItemViewModel {
               | 
            |
| 15 | 
                +  | 
            |
| 16 | 
                + var item: BehaviorRelay<PhotoItem>  | 
            |
| 17 | 
                + var thumbupItems = BehaviorRelay<[PhotoThumbupUserItem]>(value: [])  | 
            |
| 18 | 
                + var commentItems = BehaviorRelay<[PhotoCommentItem]>(value: [])  | 
            |
| 19 | 
                +  | 
            |
| 20 | 
                + private var repository: PhotoDetailRepository  | 
            |
| 21 | 
                +  | 
            |
| 22 | 
                + private var disposeBag = DisposeBag()  | 
            |
| 23 | 
                +  | 
            |
| 24 | 
                +    public init(item: PhotoItem) {
               | 
            |
| 25 | 
                + self.item = BehaviorRelay<PhotoItem>(value: item)  | 
            |
| 26 | 
                + self.repository = PhotoDetailRepository(photoId: item.photo_id, groupId: item.group_id)  | 
            |
| 27 | 
                +  | 
            |
| 28 | 
                +        self.item.subscribe(onNext: {[unowned self] (photoItem) in
               | 
            |
| 29 | 
                + self.repository = PhotoDetailRepository(photoId: photoItem.photo_id, groupId: photoItem.group_id)  | 
            |
| 30 | 
                + self.loadCommentItems()  | 
            |
| 31 | 
                + self.loadThumbupUserItems()  | 
            |
| 32 | 
                + }).disposed(by: disposeBag)  | 
            |
| 33 | 
                + }  | 
            |
| 34 | 
                +  | 
            |
| 35 | 
                +    private func loadThumbupUserItems() {
               | 
            |
| 36 | 
                +        repository.loadThumbups().subscribe(onSuccess: { (items) in
               | 
            |
| 37 | 
                + self.thumbupItems.accept(items)  | 
            |
| 38 | 
                + }).disposed(by: disposeBag)  | 
            |
| 39 | 
                + }  | 
            |
| 40 | 
                +  | 
            |
| 41 | 
                +    private func loadCommentItems() {
               | 
            |
| 42 | 
                +        repository.loadComments().subscribe(onSuccess: { (items) in
               | 
            |
| 43 | 
                + self.commentItems.accept(items)  | 
            |
| 44 | 
                + }).disposed(by: disposeBag)  | 
            |
| 45 | 
                + }  | 
            |
| 46 | 
                +  | 
            |
| 47 | 
                +    public func submitThumbup() {
               | 
            |
| 48 | 
                +        repository.submitThumbup().subscribe(onSuccess: { items in
               | 
            |
| 49 | 
                + self.thumbupItems.accept(items)  | 
            |
| 50 | 
                + }).disposed(by: disposeBag)  | 
            |
| 51 | 
                + }  | 
            |
| 52 | 
                +  | 
            |
| 53 | 
                +    public func submitComment(text: String) {
               | 
            |
| 54 | 
                +        repository.submitComment(text: text).subscribe(onSuccess: { (items) in
               | 
            |
| 55 | 
                + self.commentItems.accept(items)  | 
            |
| 56 | 
                + }).disposed(by: disposeBag)  | 
            |
| 57 | 
                + }  | 
            |
| 58 | 
                +}  | 
            
                @@ -1,49 +0,0 @@  | 
            ||
| 1 | 
                -//  | 
            |
| 2 | 
                -// PhotoDetailListViewModel.swift  | 
            |
| 3 | 
                -// PaiaiDataKit  | 
            |
| 4 | 
                -//  | 
            |
| 5 | 
                -// Created by ffib on 2019/3/19.  | 
            |
| 6 | 
                -// Copyright © 2019 yb. All rights reserved.  | 
            |
| 7 | 
                -//  | 
            |
| 8 | 
                -  | 
            |
| 9 | 
                -import Foundation  | 
            |
| 10 | 
                -import RxSwift  | 
            |
| 11 | 
                -import RxCocoa  | 
            |
| 12 | 
                -import RxDataSources  | 
            |
| 13 | 
                -  | 
            |
| 14 | 
                -public protocol PhotoDetailListViewModelSynchronization: class {
               | 
            |
| 15 | 
                - func willShow(_ item: PhotoItem)  | 
            |
| 16 | 
                -}  | 
            |
| 17 | 
                -  | 
            |
| 18 | 
                -public protocol PhotoDetailListViewModelDelegate: class {
               | 
            |
| 19 | 
                - func didSelected()  | 
            |
| 20 | 
                -}  | 
            |
| 21 | 
                -  | 
            |
| 22 | 
                -  | 
            |
| 23 | 
                -public final class PhotoDetailListViewModel {
               | 
            |
| 24 | 
                - private var items: BehaviorRelay<[PhotoItem]>  | 
            |
| 25 | 
                - public var currIndex: Int  | 
            |
| 26 | 
                -  | 
            |
| 27 | 
                - public weak var delegate: PhotoDetailListViewModelDelegate?  | 
            |
| 28 | 
                - public weak var synchronization: PhotoDetailListViewModelSynchronization?  | 
            |
| 29 | 
                -  | 
            |
| 30 | 
                -    public var content: Observable<[AnimatableSectionModel<Int, PhotoItem>]> {
               | 
            |
| 31 | 
                -        return items.map({ model in
               | 
            |
| 32 | 
                - return [AnimatableSectionModel(model: 0, items: model)]  | 
            |
| 33 | 
                - })  | 
            |
| 34 | 
                - }  | 
            |
| 35 | 
                -  | 
            |
| 36 | 
                -    public init(items: [PhotoItem], currIndex: Int) {
               | 
            |
| 37 | 
                - self.items = BehaviorRelay<[PhotoItem]>(value: items)  | 
            |
| 38 | 
                - self.currIndex = currIndex  | 
            |
| 39 | 
                - }  | 
            |
| 40 | 
                -  | 
            |
| 41 | 
                -    public func willShow(index: Int) {
               | 
            |
| 42 | 
                - currIndex = index  | 
            |
| 43 | 
                - synchronization?.willShow(items.value[currIndex])  | 
            |
| 44 | 
                - }  | 
            |
| 45 | 
                -  | 
            |
| 46 | 
                -    public func didSelected() {
               | 
            |
| 47 | 
                - delegate?.didSelected()  | 
            |
| 48 | 
                - }  | 
            |
| 49 | 
                -}  | 
            
                @@ -1,9 +1,9 @@  | 
            ||
| 1 | 1 | 
                //  | 
            
| 2 | 
                -// PhotoDetailViewModel.swift  | 
            |
| 3 | 
                -// PaiAi  | 
            |
| 2 | 
                +// PhotoDetailListViewModel.swift  | 
            |
| 3 | 
                +// PaiaiDataKit  | 
            |
| 4 | 4 | 
                //  | 
            
| 5 | 
                -// Created by zhengjianfei on 2017/1/4.  | 
            |
| 6 | 
                -// Copyright © 2017年 FFIB. All rights reserved.  | 
            |
| 5 | 
                +// Created by ffib on 2019/3/19.  | 
            |
| 6 | 
                +// Copyright © 2019 yb. All rights reserved.  | 
            |
| 7 | 7 | 
                //  | 
            
| 8 | 8 | 
                 | 
            
| 9 | 9 | 
                import Foundation  | 
            
                @@ -12,124 +12,161 @@ import RxCocoa  | 
            ||
| 12 | 12 | 
                import RxDataSources  | 
            
| 13 | 13 | 
                 | 
            
| 14 | 14 | 
                 public protocol PhotoDetailViewModelDelegate: class {
               | 
            
| 15 | 
                + func didSelected()  | 
            |
| 15 | 16 | 
                func navigateToGroup(_ item: GroupItem)  | 
            
| 16 | 17 | 
                }  | 
            
| 17 | 18 | 
                 | 
            
| 19 | 
                +  | 
            |
| 18 | 20 | 
                 public final class PhotoDetailViewModel {
               | 
            
| 21 | 
                + private var items: BehaviorRelay<[PhotoItem]>  | 
            |
| 22 | 
                + private var itemViewModel: PhotoDetailItemViewModel  | 
            |
| 23 | 
                + private var purchaseViewModel: PhotoPurchaseViewModel  | 
            |
| 24 | 
                + private var _hasGetPrice = BehaviorRelay<Bool>(value: false)  | 
            |
| 25 | 
                +  | 
            |
| 26 | 
                + private var disposeBag = DisposeBag()  | 
            |
| 27 | 
                +  | 
            |
| 28 | 
                + public var currIndex: Int  | 
            |
| 19 | 29 | 
                 | 
            
| 20 | 30 | 
                     public var thumbupItems: Observable<[PhotoThumbupUserItem]> {
               | 
            
| 21 | 
                - return _thumbupItems.asObservable()  | 
            |
| 31 | 
                + return itemViewModel.thumbupItems.asObservable()  | 
            |
| 22 | 32 | 
                }  | 
            
| 23 | 33 | 
                 | 
            
| 24 | 34 | 
                     public var commentItems: Observable<[AnimatableSectionModel<Int, PhotoCommentItem>]> {
               | 
            
| 25 | 
                -        return _commentItems.map ({ model in
               | 
            |
| 35 | 
                +        return itemViewModel.commentItems.map ({ model in
               | 
            |
| 26 | 36 | 
                return [AnimatableSectionModel(model: 0, items: model)]  | 
            
| 27 | 37 | 
                })  | 
            
| 28 | 38 | 
                }  | 
            
| 29 | 39 | 
                 | 
            
| 30 | 40 | 
                     public var groupName: Observable<String> {
               | 
            
| 31 | 
                -        return item.map({ v in
               | 
            |
| 41 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 32 | 42 | 
                return v.group_name  | 
            
| 33 | 43 | 
                })  | 
            
| 34 | 44 | 
                }  | 
            
| 35 | 45 | 
                 | 
            
| 36 | 46 | 
                     public var groupAvatar: Observable<Int> {
               | 
            
| 37 | 
                -        return item.map({ v in
               | 
            |
| 47 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 38 | 48 | 
                return v.group_default_avatar  | 
            
| 39 | 49 | 
                })  | 
            
| 40 | 50 | 
                }  | 
            
| 41 | 51 | 
                 | 
            
| 42 | 52 | 
                     public var userName: Observable<String> {
               | 
            
| 43 | 
                -        return item.map({ v in
               | 
            |
| 53 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 44 | 54 | 
                return v.nickname  | 
            
| 45 | 55 | 
                })  | 
            
| 46 | 56 | 
                }  | 
            
| 47 | 57 | 
                 | 
            
| 48 | 58 | 
                     public var userAvatar: Observable<String> {
               | 
            
| 49 | 
                -        return item.map({ v in
               | 
            |
| 59 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 50 | 60 | 
                return v.avatar  | 
            
| 51 | 61 | 
                })  | 
            
| 52 | 62 | 
                }  | 
            
| 53 | 63 | 
                 | 
            
| 54 | 64 | 
                     public var photoTime: Observable<String> {
               | 
            
| 55 | 
                -        return item.map({ v in
               | 
            |
| 65 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 56 | 66 | 
                return v.create_at_time_interval  | 
            
| 57 | 67 | 
                })  | 
            
| 58 | 68 | 
                }  | 
            
| 59 | 69 | 
                 | 
            
| 60 | 70 | 
                     public var thumbupCount: Observable<String> {
               | 
            
| 61 | 
                -        return _thumbupItems.map({ v in
               | 
            |
| 71 | 
                +        return itemViewModel.thumbupItems.map({ v in
               | 
            |
| 62 | 72 | 
                return "(\(v.count))"  | 
            
| 63 | 73 | 
                })  | 
            
| 64 | 74 | 
                }  | 
            
| 65 | 75 | 
                 | 
            
| 66 | 76 | 
                     public var commentCount: Observable<String> {
               | 
            
| 67 | 
                -        return _commentItems.map({ v in
               | 
            |
| 68 | 
                - return "(\(v.count))"  | 
            |
| 77 | 
                +        return itemViewModel.commentItems.map({ v in
               | 
            |
| 78 | 
                + return "(\(v.count))"  | 
            |
| 69 | 79 | 
                })  | 
            
| 70 | 80 | 
                }  | 
            
| 71 | 81 | 
                 | 
            
| 72 | 82 | 
                     public var canBuy: Observable<Bool> {
               | 
            
| 73 | 
                -        return item.map({ v in
               | 
            |
| 83 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 74 | 84 | 
                return v.display_payment_btn > 0  | 
            
| 75 | 85 | 
                })  | 
            
| 76 | 86 | 
                }  | 
            
| 77 | 87 | 
                 | 
            
| 88 | 
                +    public var watermarkImage: Observable<Bool> {
               | 
            |
| 89 | 
                + return _hasGetPrice.asObservable()  | 
            |
| 90 | 
                + }  | 
            |
| 91 | 
                +  | 
            |
| 92 | 
                +    public var watermarkText: Observable<String> {
               | 
            |
| 93 | 
                +        return _hasGetPrice.map ({ hasGetPrice in
               | 
            |
| 94 | 
                + return hasGetPrice ? "¥\(CGFloat(self.itemViewModel.item.value.nomark) / 100)" : "去除水印"  | 
            |
| 95 | 
                + })  | 
            |
| 96 | 
                + }  | 
            |
| 97 | 
                +  | 
            |
| 98 | 
                +    public var watermarkTextWithBought: Observable<String> {
               | 
            |
| 99 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 100 | 
                + return v.murl.isEmpty ? "去除水印" : "查看无水印照片"  | 
            |
| 101 | 
                + })  | 
            |
| 102 | 
                + }  | 
            |
| 103 | 
                +  | 
            |
| 104 | 
                +    public var watermarkImageWithBought: Observable<Bool> {
               | 
            |
| 105 | 
                +        return itemViewModel.item.map({ v in
               | 
            |
| 106 | 
                + return !v.murl.isEmpty  | 
            |
| 107 | 
                + })  | 
            |
| 108 | 
                + }  | 
            |
| 109 | 
                +  | 
            |
| 78 | 110 | 
                public var isHiddenEnterGroupBtn = BehaviorRelay<Bool>(value: false)  | 
            
| 79 | 111 | 
                 | 
            
| 80 | 112 | 
                public var viewWillAppear = BehaviorRelay<Void>(value: ())  | 
            
| 81 | 113 | 
                public weak var delegate: PhotoDetailViewModelDelegate?  | 
            
| 82 | 114 | 
                 | 
            
| 83 | 
                - private var item: BehaviorRelay<PhotoItem>  | 
            |
| 84 | 
                - private var _thumbupItems = BehaviorRelay<[PhotoThumbupUserItem]>(value: [])  | 
            |
| 85 | 
                - private var _commentItems = BehaviorRelay<[PhotoCommentItem]>(value: [])  | 
            |
| 86 | 
                -  | 
            |
| 87 | 
                - var repository: PhotoDetailRepository  | 
            |
| 115 | 
                +    public var content: Observable<[AnimatableSectionModel<Int, PhotoItem>]> {
               | 
            |
| 116 | 
                +        return items.map({ model in
               | 
            |
| 117 | 
                + return [AnimatableSectionModel(model: 0, items: model)]  | 
            |
| 118 | 
                + })  | 
            |
| 119 | 
                + }  | 
            |
| 120 | 
                +  | 
            |
| 121 | 
                +    public init(items: [PhotoItem], currIndex: Int) {
               | 
            |
| 122 | 
                + self.items = BehaviorRelay<[PhotoItem]>(value: items)  | 
            |
| 123 | 
                + self.currIndex = currIndex  | 
            |
| 124 | 
                + self.itemViewModel = PhotoDetailItemViewModel(item: items[currIndex])  | 
            |
| 125 | 
                + self.purchaseViewModel = PhotoPurchaseViewModel(item: items[currIndex])  | 
            |
| 126 | 
                + }  | 
            |
| 88 | 127 | 
                 | 
            
| 89 | 
                - var disposeBag = DisposeBag()  | 
            |
| 90 | 
                -  | 
            |
| 91 | 
                -    public init(item: PhotoItem) {
               | 
            |
| 92 | 
                - self.item = BehaviorRelay<PhotoItem>(value: item)  | 
            |
| 93 | 
                - repository = PhotoDetailRepository(photoId: item.photo_id, groupId: item.group_id)  | 
            |
| 128 | 
                +    public func willShow(index: Int) {
               | 
            |
| 129 | 
                + currIndex = index  | 
            |
| 130 | 
                + _hasGetPrice.accept(false)  | 
            |
| 131 | 
                + itemViewModel.item.accept(items.value[index])  | 
            |
| 132 | 
                + purchaseViewModel.switchItem(item: items.value[index])  | 
            |
| 94 | 133 | 
                 | 
            
| 95 | 
                -        self.item.subscribe(onNext: {[unowned self] (photoItem) in
               | 
            |
| 96 | 
                - self.repository = PhotoDetailRepository(photoId: photoItem.photo_id, groupId: photoItem.group_id)  | 
            |
| 97 | 
                - self.loadCommentItems()  | 
            |
| 98 | 
                - self.loadThumbupUserItems()  | 
            |
| 99 | 
                - }).disposed(by: disposeBag)  | 
            |
| 134 | 
                + purchaseViewModel.notifyPhotoChanged.subscribe(onNext: payDidFinish(item:)).disposed(by: disposeBag)  | 
            |
| 100 | 135 | 
                }  | 
            
| 101 | 136 | 
                 | 
            
| 102 | 
                -    private func loadThumbupUserItems() {
               | 
            |
| 103 | 
                -        repository.loadThumbups().subscribe(onSuccess: { (items) in
               | 
            |
| 104 | 
                - self._thumbupItems.accept(items)  | 
            |
| 105 | 
                - }).disposed(by: disposeBag)  | 
            |
| 137 | 
                +    public func submitThumbup() {
               | 
            |
| 138 | 
                + itemViewModel.submitThumbup()  | 
            |
| 106 | 139 | 
                }  | 
            
| 107 | 140 | 
                 | 
            
| 108 | 
                -    private func loadCommentItems() {
               | 
            |
| 109 | 
                -        repository.loadComments().subscribe(onSuccess: { (items) in
               | 
            |
| 110 | 
                - self._commentItems.accept(items)  | 
            |
| 111 | 
                - }).disposed(by: disposeBag)  | 
            |
| 141 | 
                +    public func submitComment(text: String) {
               | 
            |
| 142 | 
                + itemViewModel.submitComment(text: text)  | 
            |
| 112 | 143 | 
                }  | 
            
| 113 | 
                -  | 
            |
| 114 | 
                -    public final func submitThumbup() {
               | 
            |
| 115 | 
                -        repository.submitThumbup().subscribe(onSuccess: { items in
               | 
            |
| 116 | 
                - self._thumbupItems.accept(items)  | 
            |
| 117 | 
                - }).disposed(by: disposeBag)  | 
            |
| 144 | 
                +  | 
            |
| 145 | 
                +    public func purchase() {
               | 
            |
| 146 | 
                +        if !itemViewModel.item.value.murl.isEmpty {
               | 
            |
| 147 | 
                + delegate?.didSelected()  | 
            |
| 148 | 
                + return  | 
            |
| 149 | 
                + }  | 
            |
| 150 | 
                +        if !_hasGetPrice.value {
               | 
            |
| 151 | 
                + _hasGetPrice.accept(true)  | 
            |
| 152 | 
                +        } else {
               | 
            |
| 153 | 
                + Toast.showActivity(message: "正在支付")  | 
            |
| 154 | 
                + purchaseViewModel.purchase()  | 
            |
| 155 | 
                + }  | 
            |
| 118 | 156 | 
                }  | 
            
| 119 | 
                -  | 
            |
| 120 | 
                -    public final func submitComment(text: String) {
               | 
            |
| 121 | 
                -        repository.submitComment(text: text).subscribe(onSuccess: { (items) in
               | 
            |
| 122 | 
                - self._commentItems.accept(items)  | 
            |
| 123 | 
                - }).disposed(by: disposeBag)  | 
            |
| 157 | 
                +  | 
            |
| 158 | 
                +    public func payDidFinish(item: PhotoItem) {
               | 
            |
| 159 | 
                + var originItems = items.value  | 
            |
| 160 | 
                + originItems[currIndex] = item  | 
            |
| 161 | 
                + items.accept(originItems)  | 
            |
| 162 | 
                + itemViewModel.item.accept(item)  | 
            |
| 124 | 163 | 
                }  | 
            
| 125 | 164 | 
                 | 
            
| 126 | 165 | 
                     public func navigateToGroup() {
               | 
            
| 127 | 
                - delegate?.navigateToGroup(GroupItem(json: item.value.toJSON() as [String : AnyObject]))  | 
            |
| 166 | 
                + delegate?.navigateToGroup(GroupItem(json: items.value[currIndex].toJSON() as [String : AnyObject]))  | 
            |
| 128 | 167 | 
                }  | 
            
| 129 | 
                -}  | 
            |
| 130 | 
                -  | 
            |
| 131 | 
                -extension PhotoDetailViewModel: PhotoDetailListViewModelSynchronization {
               | 
            |
| 132 | 
                -    public func willShow(_ item: PhotoItem) {
               | 
            |
| 133 | 
                - self.item.accept(item)  | 
            |
| 168 | 
                +  | 
            |
| 169 | 
                +    public func didSelected() {
               | 
            |
| 170 | 
                + delegate?.didSelected()  | 
            |
| 134 | 171 | 
                }  | 
            
| 135 | 172 | 
                }  | 
            
                @@ -7,116 +7,58 @@  | 
            ||
| 7 | 7 | 
                //  | 
            
| 8 | 8 | 
                 | 
            
| 9 | 9 | 
                import Foundation  | 
            
| 10 | 
                +import RxSwift  | 
            |
| 11 | 
                +import RxCocoa  | 
            |
| 10 | 12 | 
                 | 
            
| 11 | 13 | 
                //wechat pay  | 
            
| 12 | 
                -extension PhotoDetailViewModel {
               | 
            |
| 13 | 
                -    public final func handleResult(errorCode: Int, success: @escaping ((_ item: PhotoItem) -> Void)) {
               | 
            |
| 14 | 
                -        //        func fetchOrderDetail() {
               | 
            |
| 15 | 
                -        //            detailPageApi.post(param: ["order_id": orderId, "user_id": SharedUserInfo.userId] as [String: AnyObject], url: .orderDetail) { (result) in
               | 
            |
| 16 | 
                -        //                guard let status = result["status"] as? Int, let data = result["data"] as? [String: AnyObject], let photoInfo = data["group_photo_info"] as? [String: AnyObject], status == 200 else {
               | 
            |
| 17 | 
                - //// FFToastView.hideLoadingToast()  | 
            |
| 18 | 
                - //// FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "")  | 
            |
| 19 | 
                - // return  | 
            |
| 20 | 
                - // }  | 
            |
| 21 | 
                - // let PhotoItem = PhotoItem(map: Map(mappingType: .fromJSON, JSON: photoInfo))  | 
            |
| 22 | 
                - // self.currentPhoto.murl = PhotoItem.murl  | 
            |
| 23 | 
                - // self.currentPhoto.rurl = PhotoItem.rurl  | 
            |
| 24 | 
                - // success(PhotoItem)  | 
            |
| 25 | 
                - //// FFToastView.hideLoadingToast()  | 
            |
| 26 | 
                - //// FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "")  | 
            |
| 27 | 
                - //// PhotoLocalStorage.instance.updateLocalData(PhotoItem: PhotoItem)  | 
            |
| 28 | 
                - // }  | 
            |
| 29 | 
                - // }  | 
            |
| 30 | 
                -        ////        Delay(3) {
               | 
            |
| 31 | 
                - // let orderQequest = StatusNetworkRequest(param: ["order_id": self.orderId as AnyObject], path: .orderQuery)  | 
            |
| 32 | 
                -        //            self.detailPageApi.post(request: orderQequest, handler: { (res) in
               | 
            |
| 33 | 
                -        //                if res.status == 200 {
               | 
            |
| 34 | 
                - // fetchOrderDetail()  | 
            |
| 35 | 
                -        //                } else {
               | 
            |
| 36 | 
                - //// FFToastView.hideLoadingToast()  | 
            |
| 37 | 
                - //// FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "支付失败")  | 
            |
| 38 | 
                - // }  | 
            |
| 39 | 
                - // })  | 
            |
| 40 | 
                - //// }  | 
            |
| 14 | 
                +public class PhotoPurchaseViewModel {
               | 
            |
| 15 | 
                + private var purchaseAPI: PhotoPurchaseRemoteAPI  | 
            |
| 16 | 
                + private var disposeBag = DisposeBag()  | 
            |
| 17 | 
                + private var orderId: String = ""  | 
            |
| 18 | 
                +  | 
            |
| 19 | 
                + public var notifyPhotoChanged = PublishSubject<PhotoItem>()  | 
            |
| 20 | 
                +  | 
            |
| 21 | 
                +    public init(item: PhotoItem) {
               | 
            |
| 22 | 
                + self.purchaseAPI = PhotoPurchaseRemoteAPI(item: item)  | 
            |
| 23 | 
                +  | 
            |
| 24 | 
                + payDidFinish()  | 
            |
| 41 | 25 | 
                }  | 
            
| 42 | 26 | 
                 | 
            
| 43 | 
                -    public final func getHD(getPriceSuccess: ((_ isExist: Bool) -> Void)?) {
               | 
            |
| 44 | 
                -        //        if !currentPhoto.rurl.isEmpty {
               | 
            |
| 45 | 
                - // getPriceSuccess!(true)  | 
            |
| 46 | 
                - // return  | 
            |
| 47 | 
                -        //        } else {
               | 
            |
| 48 | 
                -        //            if hdPrice != -0.01 {
               | 
            |
| 49 | 
                - // payPrice(photoType: "origin")  | 
            |
| 50 | 
                -        //            } else {
               | 
            |
| 51 | 
                - // getPrice(photoType: "origin", success: getPriceSuccess)  | 
            |
| 52 | 
                - // }  | 
            |
| 53 | 
                - // }  | 
            |
| 27 | 
                +    public func switchItem(item: PhotoItem) {
               | 
            |
| 28 | 
                + self.purchaseAPI = PhotoPurchaseRemoteAPI(item: item)  | 
            |
| 54 | 29 | 
                }  | 
            
| 55 | 30 | 
                 | 
            
| 56 | 
                -    public final func getWatermark(getPriceSuccess: ((_ isExist: Bool) -> Void)?) {
               | 
            |
| 57 | 
                -        //        if !currentPhoto.murl.isEmpty {
               | 
            |
| 58 | 
                - // getPriceSuccess!(true)  | 
            |
| 59 | 
                - // return  | 
            |
| 60 | 
                -        //        } else {
               | 
            |
| 61 | 
                -        //            if watermarkPrice != -0.01 {
               | 
            |
| 62 | 
                - // payPrice(photoType: "nomark")  | 
            |
| 63 | 
                -        //            } else {
               | 
            |
| 64 | 
                - // getPrice(photoType: "nomark", success: getPriceSuccess)  | 
            |
| 65 | 
                - // }  | 
            |
| 66 | 
                - // }  | 
            |
| 31 | 
                +    public func purchase() {
               | 
            |
| 32 | 
                +        purchaseAPI.purchase().subscribe(onSuccess: {[weak self] orderId in
               | 
            |
| 33 | 
                +            guard let `self` = self else { return }
               | 
            |
| 34 | 
                + self.orderId = orderId  | 
            |
| 35 | 
                + }).disposed(by: disposeBag)  | 
            |
| 67 | 36 | 
                }  | 
            
| 68 | 37 | 
                 | 
            
| 69 | 
                -    public final func payPrice(photoType: String) {
               | 
            |
| 70 | 
                - //下单  | 
            |
| 71 | 
                - // let body = photoType == "origin" ? "获取高清照片" : "获取去水印照片"  | 
            |
| 72 | 
                - // let price = photoType == "origin" ? hdPrice : watermarkPrice  | 
            |
| 73 | 
                - // let params = ["user_id": SharedUserInfo.userId, "body": body, "total_fee": price, "trade_type": "APP", "group_id": currentPhoto.group_id, "photo_id": currentPhoto.photo_id, "photo_type": photoType] as [String: AnyObject]  | 
            |
| 74 | 
                -        //        detailPageApi.post(param: params, url: .wxorderCreat) { (result) in
               | 
            |
| 75 | 
                - //// FFToastView.hideLoadingToast()  | 
            |
| 76 | 
                -        //            guard let status = result["status"] as? Int, let items = result["data"] as? [String: AnyObject], status == 200 else {
               | 
            |
| 77 | 
                - // return  | 
            |
| 78 | 
                - // }  | 
            |
| 79 | 
                -        //            if let orderid = items["order_id"] as? String, let prepay_id = items["prepay_id"] as? String, let wxpay_params = items["wxpay_params"] as? [String: AnyObject], let appid = wxpay_params["appid"] as? String, let noncestr = wxpay_params["noncestr"] as? String, let package = wxpay_params["package"] as? String, let sign = wxpay_params["sign"] as? String, let partnerid = wxpay_params["partnerid"] as? String, let timestamp = wxpay_params["timestamp"] as? String {
               | 
            |
| 80 | 
                - // //支付  | 
            |
| 81 | 
                - // self.orderId = orderid  | 
            |
| 82 | 
                - // #if !((arch(i386) || arch(x86_64)))  | 
            |
| 83 | 
                -        //                    guard WXApi.isWXAppInstalled() else {
               | 
            |
| 84 | 
                - // FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "尚未安装微信")  | 
            |
| 85 | 
                - // return  | 
            |
| 86 | 
                - // }  | 
            |
| 87 | 
                - //  | 
            |
| 88 | 
                - // WXApi.registerApp(appid)  | 
            |
| 89 | 
                - // let payRequest = PayReq()  | 
            |
| 90 | 
                - // payRequest.openID = appid  | 
            |
| 91 | 
                - // payRequest.partnerId = partnerid  | 
            |
| 92 | 
                - // payRequest.prepayId = prepay_id  | 
            |
| 93 | 
                - // payRequest.package = package  | 
            |
| 94 | 
                - // payRequest.nonceStr = noncestr  | 
            |
| 95 | 
                - // payRequest.timeStamp = UInt32(timestamp) ?? 0  | 
            |
| 96 | 
                - // payRequest.sign = sign  | 
            |
| 97 | 
                - // WXApi.send(payRequest)  | 
            |
| 98 | 
                - // #endif  | 
            |
| 99 | 
                - // }  | 
            |
| 100 | 
                - // }  | 
            |
| 38 | 
                +    private func payDidFinish() {
               | 
            |
| 39 | 
                +        NotificationCenter.default.rx.notification(Notification.wxNotification.payDidFinish).subscribe(onNext: { (notification) in
               | 
            |
| 40 | 
                + guard let userInfo = notification.userInfo as? [String: Int],  | 
            |
| 41 | 
                +                let code = userInfo["code"] else {
               | 
            |
| 42 | 
                + Toast.show(message: "支付失败")  | 
            |
| 43 | 
                + return  | 
            |
| 44 | 
                + }  | 
            |
| 45 | 
                +  | 
            |
| 46 | 
                +            switch code {
               | 
            |
| 47 | 
                + case 0:  | 
            |
| 48 | 
                + self.getOrderDetail()  | 
            |
| 49 | 
                + break  | 
            |
| 50 | 
                + case -2:  | 
            |
| 51 | 
                + Toast.show(message: "取消支付")  | 
            |
| 52 | 
                + break  | 
            |
| 53 | 
                + default:  | 
            |
| 54 | 
                + Toast.show(message: "发生未知错误")  | 
            |
| 55 | 
                + }  | 
            |
| 56 | 
                + }).disposed(by: disposeBag)  | 
            |
| 101 | 57 | 
                }  | 
            
| 102 | 58 | 
                 | 
            
| 103 | 
                -    public final func getPrice(photoType: String, success: ((_ isExist: Bool) -> Void)?) {
               | 
            |
| 104 | 
                - // let params = ["user_id": SharedUserInfo.userId, "photo_id": currentPhoto.photo_id, "photo_type": photoType] as [String: AnyObject]  | 
            |
| 105 | 
                -        //        detailPageApi.post(param: params, url: .picPrice) {[weak self] (result) in
               | 
            |
| 106 | 
                - // guard let status = result["status"] as? Int,  | 
            |
| 107 | 
                - // let items = result["data"] as? [String: AnyObject],  | 
            |
| 108 | 
                - // status == 200,  | 
            |
| 109 | 
                -        //                let weakself = self else {
               | 
            |
| 110 | 
                - // return  | 
            |
| 111 | 
                - // }  | 
            |
| 112 | 
                -        //            if let price = items["price"] as? Double {
               | 
            |
| 113 | 
                -        //                if photoType == "origin"{
               | 
            |
| 114 | 
                - // weakself.hdPrice = price  | 
            |
| 115 | 
                -        //                } else {
               | 
            |
| 116 | 
                - // weakself.watermarkPrice = price  | 
            |
| 117 | 
                - // }  | 
            |
| 118 | 
                - // success!(false)  | 
            |
| 119 | 
                - // }  | 
            |
| 120 | 
                - // }  | 
            |
| 59 | 
                +    private func getOrderDetail() {
               | 
            |
| 60 | 
                +        purchaseAPI.getOrderDetail(orderId: orderId).subscribe(onSuccess: { item in
               | 
            |
| 61 | 
                + self.notifyPhotoChanged.onNext(item)  | 
            |
| 62 | 
                + }).disposed(by: disposeBag)  | 
            |
| 121 | 63 | 
                }  | 
            
| 122 | 64 | 
                }  | 
            
                @@ -77,7 +77,7 @@ public class UserInfoViewModel {
               | 
            ||
| 77 | 77 | 
                }  | 
            
| 78 | 78 | 
                 | 
            
| 79 | 79 | 
                     public func wxLogin() {
               | 
            
| 80 | 
                -        repository.guestLogin().subscribe(onSuccess: { (userInfo) in
               | 
            |
| 80 | 
                +        repository.wxLogin().subscribe(onSuccess: { (userInfo) in
               | 
            |
| 81 | 81 | 
                self.shareUserInfo.accept(userInfo)  | 
            
| 82 | 82 | 
                self._loginCompleted.onNext(())  | 
            
| 83 | 83 | 
                         }) { (error) in
               | 
            
                @@ -0,0 +1,15 @@  | 
            ||
| 1 | 
                +//  | 
            |
| 2 | 
                +// Notification+wxPay.swift  | 
            |
| 3 | 
                +// PaiaiDataKit  | 
            |
| 4 | 
                +//  | 
            |
| 5 | 
                +// Created by ffib on 2019/4/1.  | 
            |
| 6 | 
                +// Copyright © 2019 yb. All rights reserved.  | 
            |
| 7 | 
                +//  | 
            |
| 8 | 
                +  | 
            |
| 9 | 
                +import Foundation  | 
            |
| 10 | 
                +  | 
            |
| 11 | 
                +public extension Notification {
               | 
            |
| 12 | 
                +    struct wxNotification {
               | 
            |
| 13 | 
                +        public static let payDidFinish = Notification.Name("WXPayDidFinishNotification")
               | 
            |
| 14 | 
                + }  | 
            |
| 15 | 
                +}  | 
            
                @@ -72,7 +72,7 @@ fileprivate extension AppCoordinator {
               | 
            ||
| 72 | 72 | 
                     func makeMineCoordinator() -> MineCoordinator {
               | 
            
| 73 | 73 | 
                let mineVC = makeMineViewController()  | 
            
| 74 | 74 | 
                mineVC.userInfoViewModel = shareUserInfoViewModel  | 
            
| 75 | 
                - let mineCoordinator = MineCoordinator(mineVC, navigationController: navigationController)  | 
            |
| 75 | 
                + let mineCoordinator = MineCoordinator(mineVC, navigationController: navigationController, mainViewController: containerViewController)  | 
            |
| 76 | 76 | 
                 | 
            
| 77 | 77 | 
                return mineCoordinator  | 
            
| 78 | 78 | 
                }  | 
            
                @@ -35,11 +35,10 @@ extension GroupCoordinator: GroupViewModelDelegate {
               | 
            ||
| 35 | 35 | 
                 | 
            
| 36 | 36 | 
                     func didSelect(_ items: [PhotoItem], currIndex: Int) {
               | 
            
| 37 | 37 | 
                let ctl = UIStoryboard.photoDetail.instantiateController(PhotoDetailViewController.self)  | 
            
| 38 | 
                - let viewModel = PhotoDetailViewModel(item: items[currIndex])  | 
            |
| 38 | 
                + let viewModel = PhotoDetailViewModel(items: items, currIndex: currIndex)  | 
            |
| 39 | 39 | 
                viewModel.isHiddenEnterGroupBtn.accept(true)  | 
            
| 40 | 40 | 
                let coordinator = PhotoDetailCoordinator(ctl, nav: navigationController,  | 
            
| 41 | 
                - viewModel: viewModel,  | 
            |
| 42 | 
                - listViewModel: PhotoDetailListViewModel(items: items, currIndex: currIndex))  | 
            |
| 41 | 
                + viewModel: viewModel)  | 
            |
| 43 | 42 | 
                coordinators[.photoDetail] = coordinator  | 
            
| 44 | 43 | 
                coordinator.start()  | 
            
| 45 | 44 | 
                navigationController.pushViewController(coordinator.photoDetailViewController)  | 
            
                @@ -35,8 +35,7 @@ extension HomeCoordinator: HomeViewModelDelegate {
               | 
            ||
| 35 | 35 | 
                     func didSelect(_ items: [PhotoItem], currIndex: Int) {
               | 
            
| 36 | 36 | 
                let ctl = UIStoryboard.photoDetail.instantiateController(PhotoDetailViewController.self)  | 
            
| 37 | 37 | 
                let coordinator = PhotoDetailCoordinator(ctl, nav: navigationController,  | 
            
| 38 | 
                - viewModel: PhotoDetailViewModel(item: items[currIndex]),  | 
            |
| 39 | 
                - listViewModel: PhotoDetailListViewModel(items: items, currIndex: currIndex))  | 
            |
| 38 | 
                + viewModel: PhotoDetailViewModel(items: items, currIndex: currIndex))  | 
            |
| 40 | 39 | 
                coordinators[.photoDetail] = coordinator  | 
            
| 41 | 40 | 
                coordinator.start()  | 
            
| 42 | 41 | 
                navigationController.pushViewController(coordinator.photoDetailViewController)  | 
            
                @@ -1,11 +1,11 @@  | 
            ||
| 1 | 1 | 
                <?xml version="1.0" encoding="UTF-8"?>  | 
            
| 2 | 
                -<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">  | 
            |
| 2 | 
                +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">  | 
            |
| 3 | 3 | 
                <device id="retina4_7" orientation="portrait">  | 
            
| 4 | 4 | 
                <adaptation id="fullscreen"/>  | 
            
| 5 | 5 | 
                </device>  | 
            
| 6 | 6 | 
                <dependencies>  | 
            
| 7 | 7 | 
                <deployment identifier="iOS"/>  | 
            
| 8 | 
                - <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>  | 
            |
| 8 | 
                + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>  | 
            |
| 9 | 9 | 
                <capability name="Safe area layout guides" minToolsVersion="9.0"/>  | 
            
| 10 | 10 | 
                <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>  | 
            
| 11 | 11 | 
                </dependencies>  | 
            
                @@ -43,7 +43,7 @@  | 
            ||
| 43 | 43 | 
                </userDefinedRuntimeAttributes>  | 
            
| 44 | 44 | 
                </imageView>  | 
            
| 45 | 45 | 
                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="GAH-5d-ArA">  | 
            
| 46 | 
                - <rect key="frame" x="339" y="12" width="24" height="36"/>  | 
            |
| 46 | 
                + <rect key="frame" x="355" y="24" width="8" height="12"/>  | 
            |
| 47 | 47 | 
                </imageView>  | 
            
| 48 | 48 | 
                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bx9-cB-B0U">  | 
            
| 49 | 49 | 
                <rect key="frame" x="70" y="6" width="49" height="19.5"/>  | 
            
                @@ -60,7 +60,7 @@  | 
            ||
| 60 | 60 | 
                <nil key="highlightedColor"/>  | 
            
| 61 | 61 | 
                </label>  | 
            
| 62 | 62 | 
                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="有0张照片" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aOD-P8-U4F">  | 
            
| 63 | 
                - <rect key="frame" x="271" y="22" width="62" height="16"/>  | 
            |
| 63 | 
                + <rect key="frame" x="287" y="22" width="62" height="16"/>  | 
            |
| 64 | 64 | 
                <fontDescription key="fontDescription" type="system" pointSize="13"/>  | 
            
| 65 | 65 | 
                <color key="textColor" red="0.29411764709999999" green="0.29411764709999999" blue="0.29411764709999999" alpha="1" colorSpace="calibratedRGB"/>  | 
            
| 66 | 66 | 
                <nil key="highlightedColor"/>  | 
            
                @@ -213,7 +213,7 @@  | 
            ||
| 213 | 213 | 
                <nil key="highlightedColor"/>  | 
            
| 214 | 214 | 
                </label>  | 
            
| 215 | 215 | 
                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="MgR-ta-3jg">  | 
            
| 216 | 
                - <rect key="frame" x="341" y="6" width="24" height="36"/>  | 
            |
| 216 | 
                + <rect key="frame" x="357" y="18" width="8" height="12"/>  | 
            |
| 217 | 217 | 
                </imageView>  | 
            
| 218 | 218 | 
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="L1g-sb-a5F">  | 
            
| 219 | 219 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>  | 
            
                @@ -248,7 +248,7 @@  | 
            ||
| 248 | 248 | 
                <nil key="highlightedColor"/>  | 
            
| 249 | 249 | 
                </label>  | 
            
| 250 | 250 | 
                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="vLw-Zd-Mis">  | 
            
| 251 | 
                - <rect key="frame" x="341" y="6" width="24" height="36"/>  | 
            |
| 251 | 
                + <rect key="frame" x="357" y="18" width="8" height="12"/>  | 
            |
| 252 | 252 | 
                </imageView>  | 
            
| 253 | 253 | 
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FIE-jb-ZGu">  | 
            
| 254 | 254 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>  | 
            
                @@ -283,7 +283,7 @@  | 
            ||
| 283 | 283 | 
                <nil key="highlightedColor"/>  | 
            
| 284 | 284 | 
                </label>  | 
            
| 285 | 285 | 
                <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="mhJ-Uj-tdj">  | 
            
| 286 | 
                - <rect key="frame" x="341" y="6" width="24" height="36"/>  | 
            |
| 286 | 
                + <rect key="frame" x="357" y="18" width="8" height="12"/>  | 
            |
| 287 | 287 | 
                </imageView>  | 
            
| 288 | 288 | 
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VGv-oO-leT">  | 
            
| 289 | 289 | 
                <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>  | 
            
                @@ -539,6 +539,9 @@  | 
            ||
| 539 | 539 | 
                <state key="normal" title="登出" image="BTN-logout">  | 
            
| 540 | 540 | 
                <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>  | 
            
| 541 | 541 | 
                </state>  | 
            
| 542 | 
                + <connections>  | 
            |
| 543 | 
                + <action selector="loginOutAction:" destination="Kfp-Vc-gX5" eventType="touchUpInside" id="P1V-ug-XRT"/>  | 
            |
| 544 | 
                + </connections>  | 
            |
| 542 | 545 | 
                </button>  | 
            
| 543 | 546 | 
                </subviews>  | 
            
| 544 | 547 | 
                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>  | 
            
                @@ -577,7 +580,6 @@  | 
            ||
| 577 | 580 | 
                </view>  | 
            
| 578 | 581 | 
                <connections>  | 
            
| 579 | 582 | 
                <outlet property="headerImageView" destination="diQ-B5-xB7" id="BrO-2N-Srv"/>  | 
            
| 580 | 
                - <outlet property="logoutBtn" destination="uFJ-qP-CrW" id="VHg-fH-Znk"/>  | 
            |
| 581 | 583 | 
                <outlet property="mineView" destination="Jhj-pW-9Bq" id="DAA-ov-Pzt"/>  | 
            
| 582 | 584 | 
                <outlet property="nickNameLabel" destination="59p-Cg-joQ" id="a4i-ff-np8"/>  | 
            
| 583 | 585 | 
                <outlet property="tableView" destination="79F-2W-LpP" id="tPr-Iw-4MA"/>  | 
            
                @@ -589,14 +591,14 @@  | 
            ||
| 589 | 591 | 
                </scene>  | 
            
| 590 | 592 | 
                </scenes>  | 
            
| 591 | 593 | 
                <resources>  | 
            
| 592 | 
                - <image name="BTN-logout" width="32" height="32"/>  | 
            |
| 594 | 
                + <image name="BTN-logout" width="48" height="48"/>  | 
            |
| 593 | 595 | 
                <image name="BTN-send" width="608" height="304"/>  | 
            
| 594 | 596 | 
                <image name="about-contactUs" width="32" height="32"/>  | 
            
| 595 | 597 | 
                <image name="about-score" width="32" height="32"/>  | 
            
| 596 | 598 | 
                <image name="about-userAgreement" width="32" height="32"/>  | 
            
| 597 | 
                - <image name="list-arrow" width="24" height="36"/>  | 
            |
| 599 | 
                + <image name="list-arrow" width="8" height="12"/>  | 
            |
| 598 | 600 | 
                <image name="logo" width="140" height="140"/>  | 
            
| 599 | 
                - <image name="navigation-background" width="12" height="132"/>  | 
            |
| 601 | 
                + <image name="navigation-background" width="6" height="66"/>  | 
            |
| 600 | 602 | 
                <image name="默认头像" width="240" height="240"/>  | 
            
| 601 | 603 | 
                </resources>  | 
            
| 602 | 604 | 
                </document>  | 
            
                @@ -15,11 +15,13 @@ class MineCoordinator: Coordinator {
               | 
            ||
| 15 | 15 | 
                let mineViewController: MineViewController  | 
            
| 16 | 16 | 
                let navigationController: UINavigationController  | 
            
| 17 | 17 | 
                var childCoordinator = [CoordinatorKey: Coordinator]()  | 
            
| 18 | 
                + let mainViewController: ContainerViewController  | 
            |
| 18 | 19 | 
                // let shareUserInfoViewModel  | 
            
| 19 | 20 | 
                 | 
            
| 20 | 
                -    init(_ mineViewController: MineViewController, navigationController: UINavigationController) {
               | 
            |
| 21 | 
                +    init(_ mineViewController: MineViewController, navigationController: UINavigationController, mainViewController: ContainerViewController) {
               | 
            |
| 21 | 22 | 
                self.mineViewController = mineViewController  | 
            
| 22 | 23 | 
                self.navigationController = navigationController  | 
            
| 24 | 
                + self.mainViewController = mainViewController  | 
            |
| 23 | 25 | 
                self.mineViewController.delegate = self  | 
            
| 24 | 26 | 
                }  | 
            
| 25 | 27 | 
                 | 
            
                @@ -30,8 +32,11 @@ class MineCoordinator: Coordinator {
               | 
            ||
| 30 | 32 | 
                 | 
            
| 31 | 33 | 
                 extension MineCoordinator: MineViewControllerDelegate {
               | 
            
| 32 | 34 | 
                     func logout() {
               | 
            
| 35 | 
                + mineViewController.dismissController()  | 
            |
| 36 | 
                +  | 
            |
| 33 | 37 | 
                let vc = makeLoginViewController()  | 
            
| 34 | 
                - navigationController.presentController(vc)  | 
            |
| 38 | 
                + vc.userInfoViewModel = mineViewController.userInfoViewModel  | 
            |
| 39 | 
                + navigationController.addFullScreen(childViewController: vc)  | 
            |
| 35 | 40 | 
                }  | 
            
| 36 | 41 | 
                 | 
            
| 37 | 42 | 
                     func didSelect(_ item: MineItem) {
               | 
            
                @@ -33,7 +33,6 @@ class MineViewController: SideViewController {
               | 
            ||
| 33 | 33 | 
                 | 
            
| 34 | 34 | 
                @IBOutlet weak var headerImageView: UIImageView!  | 
            
| 35 | 35 | 
                @IBOutlet weak var nickNameLabel: UILabel!  | 
            
| 36 | 
                - @IBOutlet weak var logoutBtn: UIButton!  | 
            |
| 37 | 36 | 
                @IBOutlet weak var tableView: UITableView!  | 
            
| 38 | 37 | 
                @IBOutlet weak var mineView: UIView!  | 
            
| 39 | 38 | 
                 | 
            
                @@ -12,23 +12,19 @@ import PaiaiDataKit  | 
            ||
| 12 | 12 | 
                 final class PhotoDetailCoordinator: Coordinator {
               | 
            
| 13 | 13 | 
                let navigationController: UINavigationController  | 
            
| 14 | 14 | 
                let photoDetailViewController: PhotoDetailViewController  | 
            
| 15 | 
                - let shareListViewModel: PhotoDetailListViewModel  | 
            |
| 15 | 
                + let shareViewModel: PhotoDetailViewModel  | 
            |
| 16 | 16 | 
                 | 
            
| 17 | 17 | 
                fileprivate var coordinators = [CoordinatorKey: Coordinator]()  | 
            
| 18 | 18 | 
                 | 
            
| 19 | 19 | 
                init(_ photoDetailVC: PhotoDetailViewController,  | 
            
| 20 | 20 | 
                nav: UINavigationController,  | 
            
| 21 | 
                - viewModel: PhotoDetailViewModel,  | 
            |
| 22 | 
                -         listViewModel: PhotoDetailListViewModel) {
               | 
            |
| 21 | 
                +         viewModel: PhotoDetailViewModel) {
               | 
            |
| 23 | 22 | 
                photoDetailViewController = photoDetailVC  | 
            
| 24 | 
                - shareListViewModel = listViewModel  | 
            |
| 23 | 
                + shareViewModel = viewModel  | 
            |
| 25 | 24 | 
                navigationController = nav  | 
            
| 26 | 
                - photoDetailViewController.listViewModel = shareListViewModel  | 
            |
| 27 | 25 | 
                photoDetailViewController.viewModel = viewModel  | 
            
| 28 | 26 | 
                 | 
            
| 29 | 27 | 
                viewModel.delegate = self  | 
            
| 30 | 
                - shareListViewModel.synchronization = viewModel  | 
            |
| 31 | 
                - shareListViewModel.delegate = self  | 
            |
| 32 | 28 | 
                }  | 
            
| 33 | 29 | 
                 | 
            
| 34 | 30 | 
                     func start() {
               | 
            
                @@ -46,12 +42,10 @@ extension PhotoDetailCoordinator: PhotoDetailViewModelDelegate {
               | 
            ||
| 46 | 42 | 
                 | 
            
| 47 | 43 | 
                navigationController.pushViewController(vc)  | 
            
| 48 | 44 | 
                }  | 
            
| 49 | 
                -}  | 
            |
| 50 | 
                -  | 
            |
| 51 | 
                -extension PhotoDetailCoordinator: PhotoDetailListViewModelDelegate {
               | 
            |
| 45 | 
                +  | 
            |
| 52 | 46 | 
                     func didSelected() {
               | 
            
| 53 | 47 | 
                let vc = UIStoryboard.photoDetail.instantiateController(PhotoPreviewViewController.self)  | 
            
| 54 | 
                - vc.viewModel = shareListViewModel  | 
            |
| 48 | 
                + vc.viewModel = shareViewModel  | 
            |
| 55 | 49 | 
                photoDetailViewController.presentController(vc)  | 
            
| 56 | 50 | 
                }  | 
            
| 57 | 51 | 
                }  | 
            
                @@ -13,9 +13,6 @@ import RxDataSources  | 
            ||
| 13 | 13 | 
                import PaiaiDataKit  | 
            
| 14 | 14 | 
                import PaiaiUIKit  | 
            
| 15 | 15 | 
                 | 
            
| 16 | 
                -let kPhotographerMark = 1  | 
            |
| 17 | 
                -  | 
            |
| 18 | 
                -  | 
            |
| 19 | 16 | 
                 final class PhotoDetailViewController: UIViewController {
               | 
            
| 20 | 17 | 
                 | 
            
| 21 | 18 | 
                @IBOutlet weak var enterGroupView: UIView!  | 
            
                @@ -50,7 +47,6 @@ final class PhotoDetailViewController: UIViewController {
               | 
            ||
| 50 | 47 | 
                 | 
            
| 51 | 48 | 
                // MARK: data property  | 
            
| 52 | 49 | 
                var viewModel: PhotoDetailViewModel!  | 
            
| 53 | 
                - var listViewModel: PhotoDetailListViewModel!  | 
            |
| 54 | 50 | 
                 | 
            
| 55 | 51 | 
                let disposeBag = DisposeBag()  | 
            
| 56 | 52 | 
                 | 
            
                @@ -90,11 +86,11 @@ extension PhotoDetailViewController {
               | 
            ||
| 90 | 86 | 
                }  | 
            
| 91 | 87 | 
                 | 
            
| 92 | 88 | 
                     @IBAction func purchase(_ sender: UITapGestureRecognizer) {
               | 
            
| 93 | 
                -  | 
            |
| 89 | 
                + viewModel.purchase()  | 
            |
| 94 | 90 | 
                }  | 
            
| 95 | 91 | 
                 | 
            
| 96 | 92 | 
                     @IBAction func enterGroup(_ sender: UITapGestureRecognizer) {
               | 
            
| 97 | 
                - self.viewModel.navigateToGroup()  | 
            |
| 93 | 
                + viewModel.navigateToGroup()  | 
            |
| 98 | 94 | 
                }  | 
            
| 99 | 95 | 
                }  | 
            
| 100 | 96 | 
                 | 
            
                @@ -139,7 +135,7 @@ extension PhotoDetailViewController {
               | 
            ||
| 139 | 135 | 
                     var photoCollectionViewDataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>> {
               | 
            
| 140 | 136 | 
                         return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>>(configureCell: { (dataSource, collectionView, indexPath, item) in
               | 
            
| 141 | 137 | 
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoDetailImageCell", for: indexPath) as! PhotoDetailImageCell  | 
            
| 142 | 
                - cell.imageView.setImage(item.photo_thumbnail2_url, placeholder: UIImage.photoPlaceholder)  | 
            |
| 138 | 
                + cell.imageView.setImage(item.murl.isEmpty ? item.photo_thumbnail2_url : item.murl, placeholder: UIImage.photoPlaceholder)  | 
            |
| 143 | 139 | 
                return cell  | 
            
| 144 | 140 | 
                })  | 
            
| 145 | 141 | 
                }  | 
            
                @@ -168,6 +164,11 @@ extension PhotoDetailViewController {
               | 
            ||
| 168 | 164 | 
                bindCollectionViewToListViewModel()  | 
            
| 169 | 165 | 
                bindListViewModelToCollectionView()  | 
            
| 170 | 166 | 
                 | 
            
| 167 | 
                + bindViewModelToWatermarkImage()  | 
            |
| 168 | 
                + bindViewModelToWatermarkLabel()  | 
            |
| 169 | 
                + bindViewModelToWatermarkImageWithBought()  | 
            |
| 170 | 
                + bindViewModelToWatermarkLabelWithBought()  | 
            |
| 171 | 
                +  | 
            |
| 171 | 172 | 
                bindViewWillAppear()  | 
            
| 172 | 173 | 
                 | 
            
| 173 | 174 | 
                monitorKeyboardWillShow()  | 
            
                @@ -244,7 +245,7 @@ extension PhotoDetailViewController {
               | 
            ||
| 244 | 245 | 
                }  | 
            
| 245 | 246 | 
                 | 
            
| 246 | 247 | 
                     func bindListViewModelToCollectionView() {
               | 
            
| 247 | 
                - listViewModel.content  | 
            |
| 248 | 
                + viewModel.content  | 
            |
| 248 | 249 | 
                .bind(to: photoCollectionView.rx.items(dataSource: photoCollectionViewDataSource))  | 
            
| 249 | 250 | 
                .disposed(by: disposeBag)  | 
            
| 250 | 251 | 
                }  | 
            
                @@ -253,7 +254,7 @@ extension PhotoDetailViewController {
               | 
            ||
| 253 | 254 | 
                photoCollectionView.rx.willDisplayCell  | 
            
| 254 | 255 | 
                .asDriver()  | 
            
| 255 | 256 | 
                             .drive(onNext: { [unowned self] in
               | 
            
| 256 | 
                - self.listViewModel.willShow(index: $0.at.row)  | 
            |
| 257 | 
                + self.viewModel.willShow(index: $0.at.row)  | 
            |
| 257 | 258 | 
                })  | 
            
| 258 | 259 | 
                .disposed(by: disposeBag)  | 
            
| 259 | 260 | 
                }  | 
            
                @@ -261,15 +262,31 @@ extension PhotoDetailViewController {
               | 
            ||
| 261 | 262 | 
                     func bindCollectionViewSelected() {
               | 
            
| 262 | 263 | 
                photoCollectionView.rx.itemSelected  | 
            
| 263 | 264 | 
                .asDriver(onErrorJustReturn: IndexPath(item: 0, section: 0))  | 
            
| 264 | 
                -            .drive(onNext: { [unowned self] _ in self.listViewModel.didSelected() })
               | 
            |
| 265 | 
                +            .drive(onNext: { [unowned self] _ in self.viewModel.didSelected() })
               | 
            |
| 265 | 266 | 
                .disposed(by: disposeBag)  | 
            
| 266 | 267 | 
                }  | 
            
| 267 | 268 | 
                 | 
            
| 269 | 
                +    func bindViewModelToWatermarkImage() {
               | 
            |
| 270 | 
                + viewModel.watermarkImage.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag)  | 
            |
| 271 | 
                + }  | 
            |
| 272 | 
                +  | 
            |
| 273 | 
                +    func bindViewModelToWatermarkLabel() {
               | 
            |
| 274 | 
                + viewModel.watermarkText.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag)  | 
            |
| 275 | 
                + }  | 
            |
| 276 | 
                +  | 
            |
| 277 | 
                +    func bindViewModelToWatermarkImageWithBought() {
               | 
            |
| 278 | 
                + viewModel.watermarkImageWithBought.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag)  | 
            |
| 279 | 
                + }  | 
            |
| 280 | 
                +  | 
            |
| 281 | 
                +    func bindViewModelToWatermarkLabelWithBought() {
               | 
            |
| 282 | 
                + viewModel.watermarkTextWithBought.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag)  | 
            |
| 283 | 
                + }  | 
            |
| 284 | 
                +  | 
            |
| 268 | 285 | 
                     func bindViewWillAppear() {
               | 
            
| 269 | 286 | 
                viewModel.viewWillAppear  | 
            
| 270 | 287 | 
                .asDriver()  | 
            
| 271 | 288 | 
                             .drive(onNext: { [unowned self] _ in
               | 
            
| 272 | 
                - self.photoCollectionView.scrollToItem(at: IndexPath(item: self.listViewModel.currIndex, section: 0), at: .right, animated: false)  | 
            |
| 289 | 
                + self.photoCollectionView.scrollToItem(at: IndexPath(item: self.viewModel.currIndex, section: 0), at: .right, animated: false)  | 
            |
| 273 | 290 | 
                })  | 
            
| 274 | 291 | 
                .disposed(by: disposeBag)  | 
            
| 275 | 292 | 
                }  | 
            
                @@ -17,7 +17,7 @@ final class PhotoPreviewViewController: UIViewController {
               | 
            ||
| 17 | 17 | 
                 | 
            
| 18 | 18 | 
                /// MARK: Storyboard property  | 
            
| 19 | 19 | 
                @IBOutlet weak var collectionView: UICollectionView!  | 
            
| 20 | 
                - var viewModel: PhotoDetailListViewModel!  | 
            |
| 20 | 
                + var viewModel: PhotoDetailViewModel!  | 
            |
| 21 | 21 | 
                var disposeBag = DisposeBag()  | 
            
| 22 | 22 | 
                 | 
            
| 23 | 23 | 
                     override var prefersStatusBarHidden: Bool {
               | 
            
                @@ -29,7 +29,6 @@ final class PhotoPreviewViewController: UIViewController {
               | 
            ||
| 29 | 29 | 
                binding()  | 
            
| 30 | 30 | 
                scrollToSpecifiedImage()  | 
            
| 31 | 31 | 
                navigationController?.setNavigationBarHidden(true, animated: true)  | 
            
| 32 | 
                -  | 
            |
| 33 | 32 | 
                }  | 
            
| 34 | 33 | 
                 | 
            
| 35 | 34 | 
                     func scrollToSpecifiedImage() {
               |