|
@@ -2,11 +2,11 @@ import Foundation
|
|
import UIKit
|
|
import UIKit
|
|
import DcCore
|
|
import DcCore
|
|
|
|
|
|
-class QrViewController: UITableViewController {
|
|
|
|
- private let rowQRCode = 0
|
|
|
|
|
|
+class QrViewController: UIViewController {
|
|
|
|
|
|
- var dcContext: DcContext
|
|
|
|
- var contact: DcContact? {
|
|
|
|
|
|
+ private let dcContext: DcContext
|
|
|
|
+
|
|
|
|
+ private var contact: DcContact? {
|
|
// This is nil if we do not have an account setup yet
|
|
// This is nil if we do not have an account setup yet
|
|
if !dcContext.isConfigured() {
|
|
if !dcContext.isConfigured() {
|
|
return nil
|
|
return nil
|
|
@@ -14,6 +14,19 @@ class QrViewController: UITableViewController {
|
|
return DcContact(id: Int(DC_CONTACT_ID_SELF))
|
|
return DcContact(id: Int(DC_CONTACT_ID_SELF))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private lazy var scrollView: UIScrollView = {
|
|
|
|
+ let scrollView = UIScrollView()
|
|
|
|
+ scrollView.showsVerticalScrollIndicator = false
|
|
|
|
+ return scrollView
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ private lazy var qrContentView: QrViewContentView = {
|
|
|
|
+ let qrCode = dcContext.getSecurejoinQr(chatId: 0)
|
|
|
|
+ let view = QrViewContentView(contact: contact, qrCode: qrCode)
|
|
|
|
+ view.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
+ return view
|
|
|
|
+ }()
|
|
|
|
+
|
|
init(dcContext: DcContext) {
|
|
init(dcContext: DcContext) {
|
|
self.dcContext = dcContext
|
|
self.dcContext = dcContext
|
|
super.init(nibName: nil, bundle: nil)
|
|
super.init(nibName: nil, bundle: nil)
|
|
@@ -23,93 +36,144 @@ class QrViewController: UITableViewController {
|
|
fatalError("init(coder:) has not been implemented")
|
|
fatalError("init(coder:) has not been implemented")
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // MARK: - lifecycle
|
|
override func viewDidLoad() {
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
super.viewDidLoad()
|
|
title = String.localized("qr_code")
|
|
title = String.localized("qr_code")
|
|
- tableView.separatorStyle = .none
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- override func tableView(_: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
|
|
|
- let row = indexPath.row
|
|
|
|
- switch row {
|
|
|
|
- case rowQRCode:
|
|
|
|
- return createQRCodeCell()
|
|
|
|
- default:
|
|
|
|
- return UITableViewCell(style: .default, reuseIdentifier: nil)
|
|
|
|
- }
|
|
|
|
|
|
+ setupSubviews()
|
|
}
|
|
}
|
|
|
|
|
|
- override func numberOfSections(in _: UITableView) -> Int {
|
|
|
|
- return 1
|
|
|
|
|
|
+ override func viewDidLayoutSubviews() {
|
|
|
|
+ super.viewDidLayoutSubviews()
|
|
|
|
+ qrContentView.minContainerHeight = view.frame.height - (view.safeAreaInsets.top + view.safeAreaInsets.bottom)
|
|
}
|
|
}
|
|
|
|
|
|
- override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
|
|
|
|
- return 2
|
|
|
|
|
|
+ override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
|
|
|
|
+ super.viewWillTransition(to: size, with: coordinator)
|
|
|
|
+ qrContentView.minContainerHeight = size.height - (view.safeAreaInsets.top + view.safeAreaInsets.bottom)
|
|
|
|
+ scrollView.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
|
|
}
|
|
}
|
|
|
|
|
|
- override func tableView(_: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
|
|
|
- switch indexPath.row {
|
|
|
|
- case rowQRCode:
|
|
|
|
- return 325
|
|
|
|
- default:
|
|
|
|
- return 10
|
|
|
|
- }
|
|
|
|
|
|
+ // MARK: - setup
|
|
|
|
+ private func setupSubviews() {
|
|
|
|
+ view.addSubview(scrollView)
|
|
|
|
+ scrollView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
+ scrollView.addSubview(qrContentView)
|
|
|
|
+
|
|
|
|
+ let frameGuide = scrollView.frameLayoutGuide
|
|
|
|
+ let contentGuide = scrollView.contentLayoutGuide
|
|
|
|
+
|
|
|
|
+ frameGuide.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
|
|
|
|
+ frameGuide.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
|
|
|
|
+ frameGuide.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
|
|
|
|
+ frameGuide.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
|
|
|
|
+
|
|
|
|
+ contentGuide.leadingAnchor.constraint(equalTo: qrContentView.leadingAnchor).isActive = true
|
|
|
|
+ contentGuide.topAnchor.constraint(equalTo: qrContentView.topAnchor).isActive = true
|
|
|
|
+ contentGuide.trailingAnchor.constraint(equalTo: qrContentView.trailingAnchor).isActive = true
|
|
|
|
+ contentGuide.bottomAnchor.constraint(equalTo: qrContentView.bottomAnchor).isActive = true
|
|
|
|
+
|
|
|
|
+ // this enables vertical scrolling
|
|
|
|
+ frameGuide.widthAnchor.constraint(equalTo: contentGuide.widthAnchor).isActive = true
|
|
}
|
|
}
|
|
|
|
|
|
- private func createQRCodeCell() -> UITableViewCell {
|
|
|
|
- let cell = UITableViewCell(style: .default, reuseIdentifier: "qrCodeCell")
|
|
|
|
- let qrCode = createQRCodeView()
|
|
|
|
- let infolabel = createInfoLabel()
|
|
|
|
-
|
|
|
|
- cell.contentView.addSubview(qrCode)
|
|
|
|
- cell.contentView.addSubview(infolabel)
|
|
|
|
- cell.selectionStyle = .none
|
|
|
|
-
|
|
|
|
- let qrCodeConstraints = [qrCode.constraintAlignTopTo(cell.contentView, paddingTop: 25),
|
|
|
|
- qrCode.constraintCenterXTo(cell.contentView)]
|
|
|
|
- let infoLabelConstraints = [infolabel.constraintToBottomOf(qrCode, paddingTop: 25),
|
|
|
|
- infolabel.constraintAlignLeadingTo(cell.contentView, paddingLeading: 8),
|
|
|
|
- infolabel.constraintAlignTrailingTo(cell.contentView, paddingTrailing: 8)]
|
|
|
|
- cell.contentView.addConstraints(qrCodeConstraints)
|
|
|
|
- cell.contentView.addConstraints(infoLabelConstraints)
|
|
|
|
- return cell
|
|
|
|
|
|
+ // MARK: - actions
|
|
|
|
+ private func displayNewChat(contactId: Int) {
|
|
|
|
+ let chatId = dcContext.createChatByContactId(contactId: contactId)
|
|
|
|
+ let chatVC = ChatViewController(dcContext: dcContext, chatId: Int(chatId))
|
|
|
|
+
|
|
|
|
+ chatVC.hidesBottomBarWhenPushed = true
|
|
|
|
+ navigationController?.pushViewController(chatVC, animated: true)
|
|
}
|
|
}
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// MARK: - QrViewContentView
|
|
|
|
+class QrViewContentView: UIView {
|
|
|
|
+
|
|
|
|
+ private var qrCodeView: QRCodeView = {
|
|
|
|
+ let view = QRCodeView(frame: .zero)
|
|
|
|
+ return view
|
|
|
|
+ }()
|
|
|
|
|
|
- private func createInfoLabel() -> UIView {
|
|
|
|
|
|
+ private var hintLabel: UILabel = {
|
|
let label = UILabel.init()
|
|
let label = UILabel.init()
|
|
- label.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
- if let contact = contact {
|
|
|
|
- label.text = String.localizedStringWithFormat(String.localized("qrshow_join_contact_hint"), contact.email)
|
|
|
|
- }
|
|
|
|
label.lineBreakMode = .byWordWrapping
|
|
label.lineBreakMode = .byWordWrapping
|
|
label.numberOfLines = 0
|
|
label.numberOfLines = 0
|
|
label.textAlignment = .center
|
|
label.textAlignment = .center
|
|
label.font = UIFont.systemFont(ofSize: 14)
|
|
label.font = UIFont.systemFont(ofSize: 14)
|
|
return label
|
|
return label
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ private let container = UIView()
|
|
|
|
+
|
|
|
|
+ var minContainerHeight: CGFloat = 0 {
|
|
|
|
+ didSet {
|
|
|
|
+ containerMinHeightConstraint.constant = minContainerHeight
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- private func createQRCodeView() -> UIView {
|
|
|
|
- let width: CGFloat = 230
|
|
|
|
- let frame = CGRect(origin: .zero, size: .init(width: width, height: width))
|
|
|
|
- let imageView = QRCodeView(frame: frame)
|
|
|
|
- if let qrCode = dcContext.getSecurejoinQr(chatId: 0) {
|
|
|
|
- imageView.generateCode(
|
|
|
|
|
|
+ private lazy var containerMinHeightConstraint: NSLayoutConstraint = {
|
|
|
|
+ return container.heightAnchor.constraint(greaterThanOrEqualToConstant: 0)
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ init(contact: DcContact?, qrCode: String?) {
|
|
|
|
+ super.init(frame: .zero)
|
|
|
|
+ if let contact = contact {
|
|
|
|
+ hintLabel.text = String.localizedStringWithFormat(
|
|
|
|
+ String.localized("qrshow_join_contact_hint"),
|
|
|
|
+ contact.email
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ if let qrCode = qrCode {
|
|
|
|
+ qrCodeView.generateCode(
|
|
qrCode,
|
|
qrCode,
|
|
foregroundColor: .darkText,
|
|
foregroundColor: .darkText,
|
|
backgroundColor: .white
|
|
backgroundColor: .white
|
|
)
|
|
)
|
|
}
|
|
}
|
|
- imageView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
- imageView.widthAnchor.constraint(equalToConstant: width).isActive = true
|
|
|
|
- imageView.heightAnchor.constraint(equalToConstant: width).isActive = true
|
|
|
|
- return imageView
|
|
|
|
|
|
+ setupSubviews()
|
|
}
|
|
}
|
|
|
|
|
|
- func displayNewChat(contactId: Int) {
|
|
|
|
- let chatId = dcContext.createChatByContactId(contactId: contactId)
|
|
|
|
- let chatVC = ChatViewController(dcContext: dcContext, chatId: Int(chatId))
|
|
|
|
|
|
+ required init?(coder: NSCoder) {
|
|
|
|
+ fatalError("init(coder:) has not been implemented")
|
|
|
|
+ }
|
|
|
|
|
|
- chatVC.hidesBottomBarWhenPushed = true
|
|
|
|
- navigationController?.pushViewController(chatVC, animated: true)
|
|
|
|
|
|
+ private func setupSubviews() {
|
|
|
|
+ addSubview(container)
|
|
|
|
+ container.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
+
|
|
|
|
+ container.topAnchor.constraint(equalTo: topAnchor).isActive = true
|
|
|
|
+ container.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
|
|
|
|
+ container.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.75).isActive = true
|
|
|
|
+ container.centerXAnchor.constraint(equalTo: centerXAnchor, constant: 0).isActive = true
|
|
|
|
+
|
|
|
|
+ containerMinHeightConstraint.isActive = true
|
|
|
|
+
|
|
|
|
+ let stackView = UIStackView(arrangedSubviews: [qrCodeView, hintLabel])
|
|
|
|
+ stackView.axis = .vertical
|
|
|
|
+ stackView.spacing = 10
|
|
|
|
+ stackView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
+ container.addSubview(stackView)
|
|
|
|
+ stackView.centerXAnchor.constraint(equalTo: container.centerXAnchor).isActive = true
|
|
|
|
+ stackView.centerYAnchor.constraint(equalTo: container.centerYAnchor).isActive = true
|
|
|
|
+
|
|
|
|
+ qrCodeView.translatesAutoresizingMaskIntoConstraints = false
|
|
|
|
+ let qrCodeMinWidth = stackView.widthAnchor.constraint(lessThanOrEqualToConstant: 260)
|
|
|
|
+ qrCodeMinWidth.priority = UILayoutPriority(rawValue: 1000)
|
|
|
|
+ qrCodeMinWidth.isActive = true
|
|
|
|
+ let qrCodeDefaultWidth = stackView.widthAnchor.constraint(equalTo: container.widthAnchor, multiplier: 1)
|
|
|
|
+ qrCodeDefaultWidth.priority = UILayoutPriority(500)
|
|
|
|
+ qrCodeDefaultWidth.isActive = true
|
|
|
|
+ qrCodeView.heightAnchor.constraint(equalTo: qrCodeView.widthAnchor, multiplier: 1).isActive = true
|
|
|
|
+
|
|
|
|
+ hintLabel.setContentHuggingPriority(.defaultHigh, for: .vertical)
|
|
|
|
+
|
|
|
|
+ let stackTopAnchor = stackView.topAnchor.constraint(equalTo: container.layoutMarginsGuide.topAnchor)
|
|
|
|
+ stackTopAnchor.priority = .defaultLow
|
|
|
|
+ stackTopAnchor.isActive = true
|
|
|
|
+
|
|
|
|
+ let stackBottomAnchor = stackView.bottomAnchor.constraint(equalTo: container.layoutMarginsGuide.bottomAnchor)
|
|
|
|
+ stackBottomAnchor.priority = .defaultLow
|
|
|
|
+ stackBottomAnchor.isActive = true
|
|
}
|
|
}
|
|
}
|
|
}
|