public var userAvatar: Observable<String> {
- return item.map({ v in
+ return itemViewModel.item.map({ v in
return v.avatar
})
}
public var photoTime: Observable<String> {
- return item.map({ v in
+ return itemViewModel.item.map({ v in
return v.create_at_time_interval
})
}
public var thumbupCount: Observable<String> {
- return _thumbupItems.map({ v in
+ return itemViewModel.thumbupItems.map({ v in
return "(\(v.count))"
})
}
public var commentCount: Observable<String> {
- return _commentItems.map({ v in
- return "(\(v.count))"
+ return itemViewModel.commentItems.map({ v in
+ return "(\(v.count))"
})
}
public var canBuy: Observable<Bool> {
- return item.map({ v in
+ return itemViewModel.item.map({ v in
return v.display_payment_btn > 0
})
}
+ public var watermarkImage: Observable<Bool> {
+ return _hasGetPrice.asObservable()
+ }
+
+ public var watermarkText: Observable<String> {
+ return _hasGetPrice.map ({ hasGetPrice in
+ return hasGetPrice ? "¥\(CGFloat(self.itemViewModel.item.value.nomark) / 100)" : "去除水印"
+ })
+ }
+
+ public var watermarkTextWithBought: Observable<String> {
+ return itemViewModel.item.map({ v in
+ return v.murl.isEmpty ? "去除水印" : "查看无水印照片"
+ })
+ }
+
+ public var watermarkImageWithBought: Observable<Bool> {
+ return itemViewModel.item.map({ v in
+ return !v.murl.isEmpty
+ })
+ }
+
public var isHiddenEnterGroupBtn = BehaviorRelay<Bool>(value: false)
public var viewWillAppear = BehaviorRelay<Void>(value: ())
public weak var delegate: PhotoDetailViewModelDelegate?
- private var item: BehaviorRelay<PhotoItem>
- private var _thumbupItems = BehaviorRelay<[PhotoThumbupUserItem]>(value: [])
- private var _commentItems = BehaviorRelay<[PhotoCommentItem]>(value: [])
-
- var repository: PhotoDetailRepository
+ public var content: Observable<[AnimatableSectionModel<Int, PhotoItem>]> {
+ return items.map({ model in
+ return [AnimatableSectionModel(model: 0, items: model)]
+ })
+ }
+
+ public init(items: [PhotoItem], currIndex: Int) {
+ self.items = BehaviorRelay<[PhotoItem]>(value: items)
+ self.currIndex = currIndex
+ self.itemViewModel = PhotoDetailItemViewModel(item: items[currIndex])
+ self.purchaseViewModel = PhotoPurchaseViewModel(item: items[currIndex])
+ }
- var disposeBag = DisposeBag()
-
- public init(item: PhotoItem) {
- self.item = BehaviorRelay<PhotoItem>(value: item)
- repository = PhotoDetailRepository(photoId: item.photo_id, groupId: item.group_id)
+ public func willShow(index: Int) {
+ currIndex = index
+ _hasGetPrice.accept(false)
+ itemViewModel.item.accept(items.value[index])
+ purchaseViewModel.switchItem(item: items.value[index])
- self.item.subscribe(onNext: {[unowned self] (photoItem) in
- self.repository = PhotoDetailRepository(photoId: photoItem.photo_id, groupId: photoItem.group_id)
- self.loadCommentItems()
- self.loadThumbupUserItems()
- }).disposed(by: disposeBag)
+ purchaseViewModel.notifyPhotoChanged.subscribe(onNext: payDidFinish(item:)).disposed(by: disposeBag)
}
- private func loadThumbupUserItems() {
- repository.loadThumbups().subscribe(onSuccess: { (items) in
- self._thumbupItems.accept(items)
- }).disposed(by: disposeBag)
+ public func submitThumbup() {
+ itemViewModel.submitThumbup()
}
- private func loadCommentItems() {
- repository.loadComments().subscribe(onSuccess: { (items) in
- self._commentItems.accept(items)
- }).disposed(by: disposeBag)
+ public func submitComment(text: String) {
+ itemViewModel.submitComment(text: text)
}
-
- public final func submitThumbup() {
- repository.submitThumbup().subscribe(onSuccess: { items in
- self._thumbupItems.accept(items)
- }).disposed(by: disposeBag)
+
+ public func purchase() {
+ if !itemViewModel.item.value.murl.isEmpty {
+ delegate?.didSelected()
+ return
+ }
+ if !_hasGetPrice.value {
+ _hasGetPrice.accept(true)
+ } else {
+ Toast.showActivity(message: "正在支付")
+ purchaseViewModel.purchase()
+ }
}
-
- public final func submitComment(text: String) {
- repository.submitComment(text: text).subscribe(onSuccess: { (items) in
- self._commentItems.accept(items)
- }).disposed(by: disposeBag)
+
+ public func payDidFinish(item: PhotoItem) {
+ var originItems = items.value
+ originItems[currIndex] = item
+ items.accept(originItems)
+ itemViewModel.item.accept(item)
}
public func navigateToGroup() {
- delegate?.navigateToGroup(GroupItem(json: item.value.toJSON() as [String : AnyObject]))
+ delegate?.navigateToGroup(GroupItem(json: items.value[currIndex].toJSON() as [String : AnyObject]))
}
-}
-
-extension PhotoDetailViewModel: PhotoDetailListViewModelSynchronization {
- public func willShow(_ item: PhotoItem) {
- self.item.accept(item)
+
+ public func didSelected() {
+ delegate?.didSelected()
}
}
@@ -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() {
|