nes-code">
-
- /*
- // MARK: - Navigation
-
- // In a storyboard-based application, you will often want to do a little preparation before navigation
- override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
- // Get the new view controller using segue.destination.
- // Pass the selected object to the new view controller.
+ @available(*, unavailable, message: "Loading this view controller from a nib is unsupported")
+ public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
+ super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
+ }
+
+ @available(*, unavailable, message: "Loading this view controller from a nib is unsupported")
+ public required init(coder aDecoder: NSCoder) {
+ fatalError("Loading this view controller from a nib is unsupported")
}
- */
-
}
@@ -28,6 +28,7 @@ final class PresentAppearAnimatedTransitioning: NSObject, UIViewControllerAnimat |
||
| 28 | 28 |
let animationView = delegate?.animationView else { return }
|
| 29 | 29 |
|
| 30 | 30 |
transitionContext.containerView.addSubview(toView) |
| 31 |
+ toView.addSubview(animationView) |
|
| 31 | 32 |
|
| 32 | 33 |
let duration = transitionDuration(using: transitionContext) |
| 33 | 34 |
|
@@ -28,7 +28,7 @@ final class PresentDisappearAnimatedTransitioning: NSObject, UIViewControllerAni |
||
| 28 | 28 |
let toVC = transitionContext.viewController(forKey: .to), |
| 29 | 29 |
let toView = toVC.view, |
| 30 | 30 |
let animationView = delegate?.animationView else { return }
|
| 31 |
- |
|
| 31 |
+ |
|
| 32 | 32 |
let duration = transitionDuration(using: transitionContext) |
| 33 | 33 |
|
| 34 | 34 |
animator.fromViewPresentingAnimation(duration: duration, in: fromView) |
@@ -37,7 +37,7 @@ extension NSObject {
|
||
| 37 | 37 |
} |
| 38 | 38 |
} |
| 39 | 39 |
|
| 40 |
-extension UIImage {
|
|
| 40 |
+public extension UIImage {
|
|
| 41 | 41 |
//init with qr code string |
| 42 | 42 |
|
| 43 | 43 |
/// 初始化一个qr |
@@ -45,7 +45,7 @@ extension UIImage {
|
||
| 45 | 45 |
/// - Parameters: |
| 46 | 46 |
/// - qr: qr携带的信息 |
| 47 | 47 |
/// - size: qr的大小 |
| 48 |
- convenience init?(qr: String, size: CGSize?) {
|
|
| 48 |
+ convenience init?(qr: String, size: CGSize? = nil) {
|
|
| 49 | 49 |
|
| 50 | 50 |
guard let qrImageFilter = CIFilter(name: "CIQRCodeGenerator") else {
|
| 51 | 51 |
self.init(named: "") |
@@ -13,9 +13,9 @@ private let globalInstance = Toast() |
||
| 13 | 13 |
public class Toast {
|
| 14 | 14 |
public enum ToastType {
|
| 15 | 15 |
case text(String) |
| 16 |
- case image(UIImage) |
|
| 17 |
- case imageWithText(UIImage, String) |
|
| 18 |
- case activityIndicator |
|
| 16 |
+ case image(UIImage?) |
|
| 17 |
+ case imageWithText(UIImage?, String) |
|
| 18 |
+ case activityIndicator(String?) |
|
| 19 | 19 |
} |
| 20 | 20 |
|
| 21 | 21 |
public enum PresentationStyle {
|
@@ -64,6 +64,24 @@ public extension Toast {
|
||
| 64 | 64 |
show(config: config, in: view) |
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 |
+ func show(image: UIImage?, in view: UIView? = UIApplication.shared.keyWindow) {
|
|
| 68 |
+ var config = Config() |
|
| 69 |
+ config.toastType = .image(image) |
|
| 70 |
+ show(config: config, in: view) |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ func show(message: String, image: UIImage?, in view: UIView? = UIApplication.shared.keyWindow) {
|
|
| 74 |
+ var config = Config() |
|
| 75 |
+ config.toastType = .imageWithText(image, message) |
|
| 76 |
+ show(config: config, in: view) |
|
| 77 |
+ } |
|
| 78 |
+ |
|
| 79 |
+ func showActivity(message: String?, in view: UIView? = UIApplication.shared.keyWindow) {
|
|
| 80 |
+ var config = Config() |
|
| 81 |
+ config.toastType = .activityIndicator(message) |
|
| 82 |
+ show(config: config, in: view) |
|
| 83 |
+ } |
|
| 84 |
+ |
|
| 67 | 85 |
func hide() {
|
| 68 | 86 |
hideAnimation() |
| 69 | 87 |
} |
@@ -101,6 +119,18 @@ public extension Toast {
|
||
| 101 | 119 |
globalInstance.show(message: message, in: view) |
| 102 | 120 |
} |
| 103 | 121 |
|
| 122 |
+ static func show(image: UIImage?, in view: UIView? = UIApplication.shared.keyWindow) {
|
|
| 123 |
+ globalInstance.show(image: image, in: view) |
|
| 124 |
+ } |
|
| 125 |
+ |
|
| 126 |
+ static func show(message: String, image: UIImage?, in view: UIView? = UIApplication.shared.keyWindow) {
|
|
| 127 |
+ globalInstance.show(message: message, image: image, in: view) |
|
| 128 |
+ } |
|
| 129 |
+ |
|
| 130 |
+ static func showActivity(message: String?, in view: UIView? = UIApplication.shared.keyWindow) {
|
|
| 131 |
+ globalInstance.showActivity(message: message, in: view) |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 104 | 134 |
static func hide() {
|
| 105 | 135 |
globalInstance.hide() |
| 106 | 136 |
} |
@@ -11,6 +11,7 @@ import Foundation |
||
| 11 | 11 |
public struct ToastOption {
|
| 12 | 12 |
var tintColor: UIColor = UIColor.white |
| 13 | 13 |
var backgroundColor: UIColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.5) |
| 14 |
+ var font: UIFont = UIFont.systemFont(ofSize: 14) |
|
| 14 | 15 |
|
| 15 | 16 |
public static var `default`: ToastOption {
|
| 16 | 17 |
return ToastOption() |
@@ -8,33 +8,28 @@ |
||
| 8 | 8 |
|
| 9 | 9 |
import UIKit |
| 10 | 10 |
|
| 11 |
-class ToastView: UIView {
|
|
| 11 |
+class ToastView: NiblessView {
|
|
| 12 | 12 |
|
| 13 |
- fileprivate(set) var option: ToastOption |
|
| 14 |
- fileprivate(set) var toastType: Toast.ToastType = .text("")
|
|
| 15 |
- fileprivate(set) var contentView: UIView = UIView() |
|
| 13 |
+ fileprivate var option: ToastOption |
|
| 14 |
+ fileprivate var toastType: Toast.ToastType |
|
| 16 | 15 |
|
| 17 |
- fileprivate var _constraints: [NSLayoutConstraint] = [] |
|
| 16 |
+ fileprivate var label: UILabel? |
|
| 17 |
+ fileprivate var imageView: UIImageView? |
|
| 18 |
+ fileprivate var activityIndicatorView: UIActivityIndicatorView? |
|
| 18 | 19 |
|
| 19 |
- override init(frame: CGRect) {
|
|
| 20 |
- option = .default |
|
| 21 |
- super.init(frame: CGRect.zero) |
|
| 22 |
- } |
|
| 20 |
+ fileprivate var text: String? |
|
| 21 |
+ fileprivate var image: UIImage? |
|
| 22 |
+ fileprivate var isActivity: Bool = false |
|
| 23 |
+ |
|
| 24 |
+ fileprivate var topView: UIView? |
|
| 25 |
+ fileprivate var bottomView: UIView? |
|
| 26 |
+ fileprivate var padding = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12) |
|
| 23 | 27 |
|
| 24 |
- required init?(coder aDecoder: NSCoder) {
|
|
| 25 |
- fatalError("init(coder:) has not been implemented")
|
|
| 26 |
- } |
|
| 27 | 28 |
|
| 28 |
- convenience init(option: ToastOption, type: Toast.ToastType) {
|
|
| 29 |
- self.init(frame: CGRect.zero) |
|
| 29 |
+ init(option: ToastOption, type: Toast.ToastType) {
|
|
| 30 | 30 |
self.option = option |
| 31 |
- |
|
| 32 |
- switch type {
|
|
| 33 |
- case let .text(text): |
|
| 34 |
- contentView = ToastTextView(text: text, option: option) |
|
| 35 |
- default: |
|
| 36 |
- break |
|
| 37 |
- } |
|
| 31 |
+ self.toastType = type |
|
| 32 |
+ super.init(frame: CGRect.zero) |
|
| 38 | 33 |
|
| 39 | 34 |
initProperty() |
| 40 | 35 |
} |
@@ -47,50 +42,156 @@ class ToastView: UIView {
|
||
| 47 | 42 |
|
| 48 | 43 |
override func didMoveToWindow() {
|
| 49 | 44 |
switch toastType {
|
| 50 |
- case .text: |
|
| 51 |
- constructViewHierarchyText() |
|
| 52 |
- activateConstraintsText() |
|
| 53 |
- default: |
|
| 54 |
- break |
|
| 45 |
+ case let .text(t): |
|
| 46 |
+ text = t |
|
| 47 |
+ case let .image(i): |
|
| 48 |
+ image = i |
|
| 49 |
+ case let .imageWithText(i, t): |
|
| 50 |
+ image = i |
|
| 51 |
+ text = t |
|
| 52 |
+ case let .activityIndicator(t): |
|
| 53 |
+ text = t |
|
| 54 |
+ isActivity = true |
|
| 55 | 55 |
} |
| 56 |
+ |
|
| 57 |
+ constructViewHierarchy() |
|
| 58 |
+ activateConstraints() |
|
| 56 | 59 |
} |
| 57 | 60 |
} |
| 58 | 61 |
|
| 59 |
-/// text |
|
| 62 |
+/// construct view and layout |
|
| 60 | 63 |
fileprivate extension ToastView {
|
| 61 |
- func constructViewHierarchyText() {
|
|
| 62 |
- addSubview(contentView) |
|
| 64 |
+ |
|
| 65 |
+ func constructViewHierarchy() {
|
|
| 66 |
+ if image != nil {
|
|
| 67 |
+ imageView = makeImageView() |
|
| 68 |
+ addSubview(imageView!) |
|
| 69 |
+ } |
|
| 70 |
+ |
|
| 71 |
+ if isActivity {
|
|
| 72 |
+ activityIndicatorView = makeActivityIndicatorView() |
|
| 73 |
+ addSubview(activityIndicatorView!) |
|
| 74 |
+ } |
|
| 75 |
+ |
|
| 76 |
+ if text != nil {
|
|
| 77 |
+ label = makeLabel() |
|
| 78 |
+ addSubview(label!) |
|
| 79 |
+ } |
|
| 80 |
+ } |
|
| 81 |
+ |
|
| 82 |
+ func activateConstraints() {
|
|
| 83 |
+ activateConstraintsImage() |
|
| 84 |
+ activateConstraintsIndicator() |
|
| 85 |
+ activateConstraintsText() |
|
| 86 |
+ activateConstraintsContentView() |
|
| 87 |
+ } |
|
| 88 |
+ |
|
| 89 |
+ func activateConstraintsImage() {
|
|
| 90 |
+ guard let imageView = imageView else { return }
|
|
| 91 |
+ |
|
| 92 |
+ imageView.translatesAutoresizingMaskIntoConstraints = false |
|
| 93 |
+ |
|
| 94 |
+ NSLayoutConstraint.activate([ |
|
| 95 |
+ imageView.widthAnchor.constraint(equalToConstant: 50), |
|
| 96 |
+ imageView.heightAnchor.constraint(equalToConstant: 50), |
|
| 97 |
+ imageView.centerXAnchor.constraint(equalTo: centerXAnchor), |
|
| 98 |
+ imageView.topAnchor.constraint(equalTo: topAnchor, constant: padding.top) |
|
| 99 |
+ ]) |
|
| 100 |
+ |
|
| 101 |
+ topView = imageView |
|
| 102 |
+ } |
|
| 103 |
+ |
|
| 104 |
+ func activateConstraintsIndicator() {
|
|
| 105 |
+ guard let activityIndicatorView = activityIndicatorView else { return }
|
|
| 106 |
+ |
|
| 107 |
+ activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false |
|
| 108 |
+ |
|
| 109 |
+ NSLayoutConstraint.activate([ |
|
| 110 |
+ activityIndicatorView.centerXAnchor.constraint(equalTo: centerXAnchor), |
|
| 111 |
+ activityIndicatorView.topAnchor.constraint(equalTo: topAnchor, constant: padding.top) |
|
| 112 |
+ ]) |
|
| 113 |
+ |
|
| 114 |
+ topView = activityIndicatorView |
|
| 115 |
+ activityIndicatorView.startAnimating() |
|
| 63 | 116 |
} |
| 64 | 117 |
|
| 65 | 118 |
func activateConstraintsText() {
|
| 66 |
- activateContraintsToastView() |
|
| 67 |
- activateContraintsToastTextView() |
|
| 119 |
+ guard let label = label else { return }
|
|
| 120 |
+ |
|
| 121 |
+ let windowSize = UIScreen.main.bounds.size |
|
| 122 |
+ |
|
| 123 |
+ label.translatesAutoresizingMaskIntoConstraints = false |
|
| 124 |
+ |
|
| 125 |
+ NSLayoutConstraint.activate([ |
|
| 126 |
+ label.centerXAnchor.constraint(equalTo: centerXAnchor), |
|
| 127 |
+ widthAnchor.constraint(lessThanOrEqualToConstant: windowSize.width - 52), |
|
| 128 |
+ label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding.bottom), |
|
| 129 |
+ label.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding.left), |
|
| 130 |
+ label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding.right), |
|
| 131 |
+ label.topAnchor.constraint(equalTo: topView?.bottomAnchor ?? topAnchor, constant: 6), |
|
| 132 |
+ ]) |
|
| 133 |
+ |
|
| 134 |
+ if (text?.count ?? 0) <= 3 {
|
|
| 135 |
+ |
|
| 136 |
+ } else {
|
|
| 137 |
+ NSLayoutConstraint.activate([ |
|
| 138 |
+ ]) |
|
| 139 |
+ } |
|
| 140 |
+ |
|
| 141 |
+ if topView != nil {
|
|
| 142 |
+ NSLayoutConstraint.activate([ |
|
| 143 |
+ label.widthAnchor.constraint(greaterThanOrEqualTo: heightAnchor) |
|
| 144 |
+ ]) |
|
| 145 |
+ } |
|
| 146 |
+ |
|
| 147 |
+ bottomView = label |
|
| 68 | 148 |
} |
| 69 | 149 |
|
| 70 |
- func activateContraintsToastView() {
|
|
| 150 |
+ func activateConstraintsContentView() {
|
|
| 71 | 151 |
guard let v = superview else { return }
|
| 72 | 152 |
translatesAutoresizingMaskIntoConstraints = false |
| 73 | 153 |
|
| 74 | 154 |
NSLayoutConstraint.activate([ |
| 75 |
- contentView.centerXAnchor.constraint(equalTo: v.centerXAnchor), |
|
| 76 |
- contentView.centerYAnchor.constraint(equalTo: v.centerYAnchor) |
|
| 77 |
- ]) |
|
| 155 |
+ centerXAnchor.constraint(equalTo: v.centerXAnchor), |
|
| 156 |
+ centerYAnchor.constraint(equalTo: v.centerYAnchor) |
|
| 157 |
+ ]) |
|
| 158 |
+ |
|
| 159 |
+ if topView == nil {
|
|
| 160 |
+ NSLayoutConstraint.activate([ |
|
| 161 |
+ bottomView!.topAnchor.constraint(equalTo: topAnchor, constant: padding.top) |
|
| 162 |
+ ]) |
|
| 163 |
+ } else if bottomView == nil {
|
|
| 164 |
+ NSLayoutConstraint.activate([ |
|
| 165 |
+ topView!.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding.bottom), |
|
| 166 |
+ topView!.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding.left), |
|
| 167 |
+ topView!.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding.right) |
|
| 168 |
+ ]) |
|
| 169 |
+ } |
|
| 78 | 170 |
} |
| 79 |
- |
|
| 80 |
- func activateContraintsToastTextView() {
|
|
| 81 |
- let windowSize = UIScreen.main.bounds.size |
|
| 82 |
- contentView.translatesAutoresizingMaskIntoConstraints = false |
|
| 171 |
+} |
|
| 172 |
+ |
|
| 173 |
+fileprivate extension ToastView {
|
|
| 174 |
+ func makeLabel() -> UILabel {
|
|
| 175 |
+ let l = UILabel() |
|
| 176 |
+ l.text = text |
|
| 177 |
+ l.numberOfLines = 0 |
|
| 178 |
+ l.font = option.font |
|
| 179 |
+ l.textAlignment = .center |
|
| 180 |
+ l.textColor = option.tintColor |
|
| 83 | 181 |
|
| 84 |
- let textConstraints = [ |
|
| 85 |
- contentView.topAnchor.constraint(equalTo: topAnchor, constant: 6), |
|
| 86 |
- contentView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -6), |
|
| 87 |
- contentView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 6), |
|
| 88 |
- contentView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -6), |
|
| 89 |
- contentView.widthAnchor.constraint(lessThanOrEqualToConstant: windowSize.width - 40) |
|
| 90 |
- ] |
|
| 182 |
+ return l |
|
| 183 |
+ } |
|
| 184 |
+ |
|
| 185 |
+ func makeImageView() -> UIImageView {
|
|
| 186 |
+ let i = UIImageView() |
|
| 187 |
+ i.image = image |
|
| 91 | 188 |
|
| 92 |
- NSLayoutConstraint.activate(textConstraints) |
|
| 189 |
+ return i |
|
| 190 |
+ } |
|
| 191 |
+ |
|
| 192 |
+ func makeActivityIndicatorView() -> UIActivityIndicatorView {
|
|
| 193 |
+ let a = UIActivityIndicatorView(style: .white) |
|
| 93 | 194 |
|
| 94 |
- _constraints += textConstraints |
|
| 195 |
+ return a |
|
| 95 | 196 |
} |
| 96 | 197 |
} |
@@ -9,7 +9,7 @@ |
||
| 9 | 9 |
import UIKit |
| 10 | 10 |
import WebKit |
| 11 | 11 |
|
| 12 |
-public class WebViewController: UIViewController {
|
|
| 12 |
+public class WebViewController: NiblessViewController {
|
|
| 13 | 13 |
|
| 14 | 14 |
public private(set) var path: String? |
| 15 | 15 |
|
@@ -20,15 +20,11 @@ public class WebViewController: UIViewController {
|
||
| 20 | 20 |
}() |
| 21 | 21 |
|
| 22 | 22 |
public init(title: String, path: String) {
|
| 23 |
- super.init(nibName: nil, bundle: nil) |
|
| 23 |
+ super.init() |
|
| 24 | 24 |
self.title = title |
| 25 | 25 |
self.path = path |
| 26 | 26 |
} |
| 27 | 27 |
|
| 28 |
- required init?(coder aDecoder: NSCoder) {
|
|
| 29 |
- fatalError("init(coder:) has not been implemented")
|
|
| 30 |
- } |
|
| 31 |
- |
|
| 32 | 28 |
override public func viewDidLoad() {
|
| 33 | 29 |
super.viewDidLoad() |
| 34 | 30 |
view.backgroundColor = UIColor.white |
@@ -6,14 +6,35 @@ |
||
| 6 | 6 |
// Copyright © 2019 yb. All rights reserved. |
| 7 | 7 |
// |
| 8 | 8 |
|
| 9 |
-import Foundation |
|
| 9 |
+import UIKit |
|
| 10 |
+import PaiaiDataKit |
|
| 10 | 11 |
|
| 11 | 12 |
class GroupCoordinator: Coordinator {
|
| 12 | 13 |
|
| 13 |
- var navigationController: UINavigationController |
|
| 14 |
+ let navigationController: UINavigationController |
|
| 15 |
+ let groupViewController: GroupViewController |
|
| 14 | 16 |
|
| 15 |
- init(navigationController: UINavigationController) {
|
|
| 17 |
+ init(_ groupVC: GroupViewController, navigationController: UINavigationController) {
|
|
| 18 |
+ self.groupViewController = groupVC |
|
| 16 | 19 |
self.navigationController = navigationController |
| 20 |
+ |
|
| 21 |
+ groupViewController.viewModel.delegate = self |
|
| 22 |
+ } |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+extension GroupCoordinator: GroupViewModelDelegate {
|
|
| 26 |
+ func navigateToGroupDetail() {
|
|
| 27 |
+ |
|
| 28 |
+ } |
|
| 29 |
+ |
|
| 30 |
+ func didSelect(_ item: PhotoItem) {
|
|
| 31 |
+ |
|
| 32 |
+ } |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+fileprivate extension GroupCoordinator {
|
|
| 36 |
+ func makeGroupDetailViewController() {
|
|
| 37 |
+ |
|
| 17 | 38 |
} |
| 18 | 39 |
} |
| 19 | 40 |
|
@@ -1,10 +1,6 @@ |
||
| 1 | 1 |
<?xml version="1.0" encoding="UTF-8"?> |
| 2 | 2 |
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" colorMatched="YES" initialViewController="s9X-RR-Rat"> |
| 3 |
- <device id="retina4_7" orientation="portrait"> |
|
| 4 |
- <adaptation id="fullscreen"/> |
|
| 5 |
- </device> |
|
| 6 | 3 |
<dependencies> |
| 7 |
- <deployment identifier="iOS"/> |
|
| 8 | 4 |
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/> |
| 9 | 5 |
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> |
| 10 | 6 |
</dependencies> |
@@ -101,10 +97,10 @@ |
||
| 101 | 97 |
</objects> |
| 102 | 98 |
<point key="canvasLocation" x="-232" y="2161.6191904047978"/> |
| 103 | 99 |
</scene> |
| 104 |
- <!--GroupDetailController--> |
|
| 100 |
+ <!--GroupDetailViewController--> |
|
| 105 | 101 |
<scene sceneID="Oa4-Yi-HJu"> |
| 106 | 102 |
<objects> |
| 107 |
- <viewController storyboardIdentifier="GroupDetailController" id="s9X-RR-Rat" userLabel="GroupDetailController" customClass="GroupDetailController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController"> |
|
| 103 |
+ <viewController storyboardIdentifier="GroupDetailViewController" id="s9X-RR-Rat" userLabel="GroupDetailViewController" customClass="GroupDetailViewController" customModule="Paiai_iOS" customModuleProvider="target" sceneMemberID="viewController"> |
|
| 108 | 104 |
<layoutGuides> |
| 109 | 105 |
<viewControllerLayoutGuide type="top" id="w38-w0-jLd"/> |
| 110 | 106 |
<viewControllerLayoutGuide type="bottom" id="a7q-m3-cDV"/> |
@@ -420,7 +416,7 @@ |
||
| 420 | 416 |
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> |
| 421 | 417 |
<subviews> |
| 422 | 418 |
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="cas-Ep-jsP"> |
| 423 |
- <rect key="frame" x="0.0" y="0.0" width="375" height="667"/> |
|
| 419 |
+ <rect key="frame" x="0.0" y="6" width="375" height="661"/> |
|
| 424 | 420 |
<color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| 425 | 421 |
<color key="separatorColor" red="0.94117647058823528" green="0.94117647058823528" blue="0.94117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> |
| 426 | 422 |
<prototypes> |
@@ -8,7 +8,17 @@ |
||
| 8 | 8 |
|
| 9 | 9 |
import Foundation |
| 10 | 10 |
|
| 11 |
- |
|
| 11 |
+class GroupDetailCoordinator: Coordinator {
|
|
| 12 |
+ let navigationController: UINavigationController |
|
| 13 |
+ let groupDetailViewController: GroupDetailViewController |
|
| 14 |
+ |
|
| 15 |
+ init(_ groupDetailVC: GroupDetailViewController, navigationController: UINavigationController) {
|
|
| 16 |
+ self.groupDetailViewController = groupDetailVC |
|
| 17 |
+ self.navigationController = navigationController |
|
| 18 |
+ |
|
| 19 |
+// groupViewController.viewModel.delegate = self |
|
| 20 |
+ } |
|
| 21 |
+} |
|
| 12 | 22 |
|
| 13 | 23 |
extension UIStoryboard {
|
| 14 | 24 |
static var groupDetail: UIStoryboard {
|
@@ -1,5 +1,5 @@ |
||
| 1 | 1 |
// |
| 2 |
-// GroupDetailController.swift |
|
| 2 |
+// GroupDetailViewController.swift |
|
| 3 | 3 |
// PaiAi |
| 4 | 4 |
// |
| 5 | 5 |
// Created by zhengjianfei on 16/4/5. |
@@ -12,7 +12,7 @@ import RxCocoa |
||
| 12 | 12 |
import PaiaiUIKit |
| 13 | 13 |
import PaiaiDataKit |
| 14 | 14 |
|
| 15 |
-final class GroupDetailController: UIViewController {
|
|
| 15 |
+final class GroupDetailViewController: UIViewController {
|
|
| 16 | 16 |
|
| 17 | 17 |
// MARK: Storyboard property |
| 18 | 18 |
@IBOutlet weak var scrollViewConstraint: NSLayoutConstraint! |
@@ -7,15 +7,132 @@ |
||
| 7 | 7 |
// |
| 8 | 8 |
|
| 9 | 9 |
import UIKit |
| 10 |
+import PaiaiUIKit |
|
| 10 | 11 |
|
| 11 |
-class GroupQRView: UIView {
|
|
| 12 |
- |
|
| 13 |
- /* |
|
| 14 |
- // Only override draw() if you perform custom drawing. |
|
| 15 |
- // An empty implementation adversely affects performance during animation. |
|
| 16 |
- override func draw(_ rect: CGRect) {
|
|
| 17 |
- // Drawing code |
|
| 12 |
+class GroupQRView: NiblessView {
|
|
| 13 |
+ |
|
| 14 |
+ private var groupName: String |
|
| 15 |
+ private var groupAvatar: String |
|
| 16 |
+ private var groupQR: String |
|
| 17 |
+ |
|
| 18 |
+ lazy var groupAvatarImageView: UIImageView = {
|
|
| 19 |
+ let imageView = UIImageView() |
|
| 20 |
+ |
|
| 21 |
+ imageView.image = UIImage(named: groupAvatar) |
|
| 22 |
+ |
|
| 23 |
+ return imageView |
|
| 24 |
+ }() |
|
| 25 |
+ |
|
| 26 |
+ lazy var groupNameLabel: UILabel = {
|
|
| 27 |
+ let label = UILabel() |
|
| 28 |
+ |
|
| 29 |
+ label.text = groupName |
|
| 30 |
+ label.font = UIFont.systemFont(ofSize: 17) |
|
| 31 |
+ |
|
| 32 |
+ return label |
|
| 33 |
+ }() |
|
| 34 |
+ |
|
| 35 |
+ lazy var qrImageView: UIImageView = {
|
|
| 36 |
+ let imageView = UIImageView() |
|
| 37 |
+ |
|
| 38 |
+ imageView.image = UIImage(qr: groupQR) |
|
| 39 |
+ |
|
| 40 |
+ return imageView |
|
| 41 |
+ }() |
|
| 42 |
+ |
|
| 43 |
+ lazy var qrLabel: UILabel = {
|
|
| 44 |
+ let label = UILabel() |
|
| 45 |
+ |
|
| 46 |
+ label.text = "扫描二维码加入群" |
|
| 47 |
+ label.textColor = UIColor(gray: 153) |
|
| 48 |
+ label.font = UIFont.systemFont(ofSize: 14) |
|
| 49 |
+ |
|
| 50 |
+ return label |
|
| 51 |
+ }() |
|
| 52 |
+ |
|
| 53 |
+ init(groupName: String, groupAvatar: String, groupQR: String) {
|
|
| 54 |
+ self.groupName = groupName |
|
| 55 |
+ self.groupAvatar = groupAvatar |
|
| 56 |
+ self.groupQR = groupQR |
|
| 57 |
+ |
|
| 58 |
+ super.init(frame: CGRect.zero) |
|
| 59 |
+ } |
|
| 60 |
+ |
|
| 61 |
+ override func didMoveToWindow() {
|
|
| 62 |
+ super.didMoveToWindow() |
|
| 63 |
+ constructViewHierarchy() |
|
| 64 |
+ activateConstraints() |
|
| 65 |
+ backgroundColor = UIColor.white |
|
| 66 |
+ } |
|
| 67 |
+ |
|
| 68 |
+ private func constructViewHierarchy() {
|
|
| 69 |
+ addSubview(groupAvatarImageView) |
|
| 70 |
+ addSubview(groupNameLabel) |
|
| 71 |
+ addSubview(qrImageView) |
|
| 72 |
+ addSubview(qrLabel) |
|
| 18 | 73 |
} |
| 19 |
- */ |
|
| 74 |
+} |
|
| 20 | 75 |
|
| 76 |
+fileprivate extension GroupQRView {
|
|
| 77 |
+ func activateConstraints() {
|
|
| 78 |
+ activateConstraintsContent() |
|
| 79 |
+ activateConstraintsQRImageView() |
|
| 80 |
+ activateConstraintsQRLabel() |
|
| 81 |
+ activateConstraintsGroupAvatarImageView() |
|
| 82 |
+ activateConstraintsGroupNameLabel() |
|
| 83 |
+ } |
|
| 84 |
+ |
|
| 85 |
+ func activateConstraintsContent() {
|
|
| 86 |
+ guard let superView = superview else { return }
|
|
| 87 |
+ |
|
| 88 |
+ translatesAutoresizingMaskIntoConstraints = false |
|
| 89 |
+ |
|
| 90 |
+ NSLayoutConstraint.activate([ |
|
| 91 |
+ widthAnchor.constraint(equalToConstant: 300), |
|
| 92 |
+ centerXAnchor.constraint(equalTo: superView.centerXAnchor), |
|
| 93 |
+ centerYAnchor.constraint(equalTo: superView.centerYAnchor) |
|
| 94 |
+ ]) |
|
| 95 |
+ } |
|
| 96 |
+ |
|
| 97 |
+ func activateConstraintsGroupAvatarImageView() {
|
|
| 98 |
+ groupAvatarImageView.translatesAutoresizingMaskIntoConstraints = false |
|
| 99 |
+ |
|
| 100 |
+ NSLayoutConstraint.activate([ |
|
| 101 |
+ groupAvatarImageView.widthAnchor.constraint(equalToConstant: 50), |
|
| 102 |
+ groupAvatarImageView.heightAnchor.constraint(equalToConstant: 50), |
|
| 103 |
+ groupAvatarImageView.centerXAnchor.constraint(equalTo: centerXAnchor), |
|
| 104 |
+ groupAvatarImageView.topAnchor.constraint(equalTo: topAnchor, constant: 12), |
|
| 105 |
+ ]) |
|
| 106 |
+ } |
|
| 107 |
+ |
|
| 108 |
+ func activateConstraintsGroupNameLabel() {
|
|
| 109 |
+ groupNameLabel.translatesAutoresizingMaskIntoConstraints = false |
|
| 110 |
+ |
|
| 111 |
+ NSLayoutConstraint.activate([ |
|
| 112 |
+ groupNameLabel.centerXAnchor.constraint(equalTo: centerXAnchor), |
|
| 113 |
+ groupNameLabel.topAnchor.constraint(equalTo: groupAvatarImageView.bottomAnchor, constant: 6) |
|
| 114 |
+ ]) |
|
| 115 |
+ |
|
| 116 |
+ } |
|
| 117 |
+ |
|
| 118 |
+ func activateConstraintsQRImageView() {
|
|
| 119 |
+ qrImageView.translatesAutoresizingMaskIntoConstraints = false |
|
| 120 |
+ |
|
| 121 |
+ NSLayoutConstraint.activate([ |
|
| 122 |
+ qrImageView.widthAnchor.constraint(equalToConstant: 250), |
|
| 123 |
+ qrImageView.centerXAnchor.constraint(equalTo: centerXAnchor), |
|
| 124 |
+ qrImageView.widthAnchor.constraint(equalTo: qrImageView.heightAnchor), |
|
| 125 |
+ qrImageView.topAnchor.constraint(equalTo: groupNameLabel.bottomAnchor, constant: 12), |
|
| 126 |
+ ]) |
|
| 127 |
+ } |
|
| 128 |
+ |
|
| 129 |
+ func activateConstraintsQRLabel() {
|
|
| 130 |
+ qrLabel.translatesAutoresizingMaskIntoConstraints = false |
|
| 131 |
+ |
|
| 132 |
+ NSLayoutConstraint.activate([ |
|
| 133 |
+ qrLabel.centerXAnchor.constraint(equalTo: centerXAnchor), |
|
| 134 |
+ qrLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -12), |
|
| 135 |
+ qrLabel.topAnchor.constraint(equalTo: qrImageView.bottomAnchor, constant: 6), |
|
| 136 |
+ ]) |
|
| 137 |
+ } |
|
| 21 | 138 |
} |
@@ -37,7 +37,7 @@ final class GroupViewController: UIViewController {
|
||
| 37 | 37 |
|
| 38 | 38 |
var navigationBarViewImage: UIImageView = {
|
| 39 | 39 |
let image = UIImageView() |
| 40 |
- image.cornerRadius = 20 |
|
| 40 |
+ image.cornerRadius = 18 |
|
| 41 | 41 |
return image |
| 42 | 42 |
}() |
| 43 | 43 |
|
@@ -70,6 +70,7 @@ final class GroupViewController: UIViewController {
|
||
| 70 | 70 |
[unowned self] in |
| 71 | 71 |
self.viewModel.reload() |
| 72 | 72 |
} |
| 73 |
+ collectionView.startRefreshing(at: .top) |
|
| 73 | 74 |
} |
| 74 | 75 |
} |
| 75 | 76 |
|
@@ -86,7 +87,6 @@ fileprivate extension GroupViewController {
|
||
| 86 | 87 |
} |
| 87 | 88 |
|
| 88 | 89 |
func binding() {
|
| 89 |
- bindInteraction() |
|
| 90 | 90 |
bindViewModelToRefreshing() |
| 91 | 91 |
bindCollectionViewDelegate() |
| 92 | 92 |
bindViewModelToCollectionView() |
@@ -95,10 +95,6 @@ fileprivate extension GroupViewController {
|
||
| 95 | 95 |
bindViewModelToNavigationBarTitle() |
| 96 | 96 |
} |
| 97 | 97 |
|
| 98 |
- func bindInteraction() {
|
|
| 99 |
- photographBtn.rx.tap.bind(to: viewModel.photographBtnTapped).disposed(by: disposeBag) |
|
| 100 |
- } |
|
| 101 |
- |
|
| 102 | 98 |
func bindViewModelToRefreshing() {
|
| 103 | 99 |
viewModel.isLoading |
| 104 | 100 |
.subscribe(onNext: {[unowned self] flag in
|
@@ -156,15 +152,23 @@ extension GroupViewController: NavigationBarInteractiveViewController {
|
||
| 156 | 152 |
private func setRightBarButtonItems() {
|
| 157 | 153 |
let item = UIBarButtonItem(images: [UIImage(named: "navigation-QR"), |
| 158 | 154 |
UIImage(named: "navigation-right")], |
| 159 |
- btnSpace: 6, |
|
| 160 |
- target: self, |
|
| 161 |
- actions: [#selector(viewModel!.presentGroupQR), |
|
| 162 |
- #selector(viewModel!.navigateToGroupDetail)]) |
|
| 155 |
+ targets: [self, viewModel], |
|
| 156 |
+ actions: [#selector(GroupViewController.presentGroupQR), |
|
| 157 |
+ #selector(GroupViewModel.navigateToGroupDetail)]) |
|
| 158 |
+ |
|
| 163 | 159 |
navigationItem.rightBarButtonItem = item |
| 164 | 160 |
} |
| 161 |
+ |
|
| 162 |
+ @objc func presentGroupQR() {
|
|
| 163 |
+ let alert = AlertViewController(style: .custom(GroupQRView(groupName: groupItem.group_name, |
|
| 164 |
+ groupAvatar: "Group\(groupItem.group_default_avatar)", |
|
| 165 |
+ groupQR: "https:pai.ai/g/\(groupItem.group_id)"), |
|
| 166 |
+ AlertAnimator()) ) |
|
| 167 |
+ presentController(alert) |
|
| 168 |
+ } |
|
| 165 | 169 |
} |
| 166 | 170 |
|
| 167 |
-/// layout |
|
| 171 |
+/// navigation bar layout |
|
| 168 | 172 |
fileprivate extension GroupViewController {
|
| 169 | 173 |
|
| 170 | 174 |
func activateConstraintsNavigation() {
|
@@ -199,14 +203,18 @@ fileprivate extension GroupViewController {
|
||
| 199 | 203 |
navigationBarViewImage.translatesAutoresizingMaskIntoConstraints = false |
| 200 | 204 |
|
| 201 | 205 |
NSLayoutConstraint.activate([ |
| 202 |
- navigationBarViewImage.widthAnchor.constraint(equalToConstant: 40), |
|
| 203 |
- navigationBarViewImage.heightAnchor.constraint(equalToConstant: 40), |
|
| 206 |
+ navigationBarViewImage.widthAnchor.constraint(equalToConstant: 36), |
|
| 207 |
+ navigationBarViewImage.heightAnchor.constraint(equalToConstant: 36), |
|
| 204 | 208 |
navigationBarViewImage.centerYAnchor.constraint(equalTo: navigationBarView.centerYAnchor), |
| 205 | 209 |
navigationBarViewImage.leadingAnchor.constraint(equalTo: navigationBarView.leadingAnchor), |
| 206 | 210 |
]) |
| 207 | 211 |
} |
| 208 | 212 |
} |
| 209 | 213 |
|
| 214 |
+extension GroupViewController {
|
|
| 215 |
+ |
|
| 216 |
+} |
|
| 217 |
+ |
|
| 210 | 218 |
extension GroupViewController: UICollectionViewDelegateFlowLayout {
|
| 211 | 219 |
func collectionView(_ collectionView: UICollectionView, |
| 212 | 220 |
layout collectionViewLayout: UICollectionViewLayout, |
@@ -231,10 +239,10 @@ extension GroupViewController: UIImagePickerControllerDelegate, UINavigationCont |
||
| 231 | 239 |
|
| 232 | 240 |
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
|
| 233 | 241 |
dismiss(animated: true, completion: nil) |
| 242 |
+ guard let image = info[.originalImage] as? UIImage, |
|
| 243 |
+ let data = image.scaledImage(length: 1280, with: 0.4) else { return }
|
|
| 234 | 244 |
|
| 235 |
- guard let image = info[.originalImage] as? UIImage else { return }
|
|
| 236 |
- |
|
| 237 |
- viewModel.submit(image: image) |
|
| 245 |
+ viewModel.submit(data: data) |
|
| 238 | 246 |
} |
| 239 | 247 |
|
| 240 | 248 |
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
@@ -24,7 +24,7 @@ final class ScanQRViewController: UIViewController {
|
||
| 24 | 24 |
// MARK: view function |
| 25 | 25 |
override func viewDidLoad() {
|
| 26 | 26 |
super.viewDidLoad() |
| 27 |
- navigationController?.navigationBar.setBackgroundImage(UIImage.imageWithColor(UIColor.black), for: .default) |
|
| 27 |
+// navigationController?.navigationBar.setBackgroundImage(UIImage.imageWithColor(UIColor.black), for: .default) |
|
| 28 | 28 |
scanView.delegate = self |
| 29 | 29 |
} |
| 30 | 30 |
|
@@ -60,11 +60,10 @@ extension MineCoordinator: MineViewControllerDelegate {
|
||
| 60 | 60 |
|
| 61 | 61 |
extension MineCoordinator: MineGroupViewModelDelegate {
|
| 62 | 62 |
func didSelect(_ item: GroupItem) {
|
| 63 |
- let vc = makeGroupViewController(item: item) |
|
| 64 |
- let coordinator = GroupCoordinator(navigationController: navigationController) |
|
| 63 |
+ let coordinator = GroupCoordinator(makeGroupViewController(item: item), |
|
| 64 |
+ navigationController: navigationController) |
|
| 65 | 65 |
childCoordinator["group"] = coordinator |
| 66 |
- |
|
| 67 |
- navigationController.pushViewController(vc) |
|
| 66 |
+ navigationController.pushViewController(coordinator.groupViewController) |
|
| 68 | 67 |
} |
| 69 | 68 |
} |
| 70 | 69 |
|
@@ -82,7 +82,7 @@ extension MineViewController: UITableViewDataSource {
|
||
| 82 | 82 |
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
| 83 | 83 |
let cell = tableView.dequeueReusableCell(withIdentifier: "mineCell", for: indexPath) |
| 84 | 84 |
cell.textLabel?.text = menuTitle[indexPath.row] |
| 85 |
- cell.textLabel?.textColor = UIColor(r: 51, g: 51, b: 51, a: 1.0) |
|
| 85 |
+ cell.textLabel?.textColor = UIColor(gray: 51) |
|
| 86 | 86 |
cell.imageView?.image = UIImage(named: menuImage[indexPath.row]) |
| 87 | 87 |
|
| 88 | 88 |
return cell |
@@ -19,7 +19,7 @@ final class ImageCell: UICollectionViewCell, UIScrollViewDelegate {
|
||
| 19 | 19 |
photoImage.contentMode = .scaleAspectFit |
| 20 | 20 |
scrollView.contentSize = size |
| 21 | 21 |
scrollView.addSubview(photoImage) |
| 22 |
- photoImage.image = UIImage.imageWithColor(UIColor.black) |
|
| 22 |
+// photoImage.image = UIImage.imageWithColor(UIColor.black) |
|
| 23 | 23 |
if !url.isEmpty {
|
| 24 | 24 |
// photoImage.setImageWithNullableURL(url, placeholderImage: UIImage(named: "详情页占位图")) |
| 25 | 25 |
} else {
|