Skip to content

Commit

Permalink
[WIP] Generate QR-code for a proxy and show it (#2394)
Browse files Browse the repository at this point in the history
  • Loading branch information
zeitschlag committed Nov 15, 2024
1 parent 0011d62 commit 3880d8f
Show file tree
Hide file tree
Showing 3 changed files with 168 additions and 1 deletion.
4 changes: 4 additions & 0 deletions deltachat-ios.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@
D8A072A02BED0FD8001A4C7C /* InstantOnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8A0729F2BED0FD8001A4C7C /* InstantOnboardingView.swift */; };
D8C19DCE2C1B456700B32F6D /* SendContactViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8C19DCD2C1B456700B32F6D /* SendContactViewController.swift */; };
D8C19DD02C1C9FFE00B32F6D /* ContactCardPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8C19DCF2C1C95A900B32F6D /* ContactCardPreview.swift */; };
D8C1B0DD2CE7421C00C233A7 /* ShareProxyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8C1B0DC2CE7421C00C233A7 /* ShareProxyViewController.swift */; };
D8CDEFE02C087CDA00146773 /* ContactCardCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CDEFDF2C087CDA00146773 /* ContactCardCell.swift */; };
D8CDEFE22C087D1000146773 /* ContactCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CDEFE12C087D1000146773 /* ContactCardView.swift */; };
D8CF2DDC2CDD110F001C2352 /* ProxySettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CF2DD92CDD110F001C2352 /* ProxySettingsViewController.swift */; };
Expand Down Expand Up @@ -609,6 +610,7 @@
D8A0729F2BED0FD8001A4C7C /* InstantOnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstantOnboardingView.swift; sourceTree = "<group>"; };
D8C19DCD2C1B456700B32F6D /* SendContactViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendContactViewController.swift; sourceTree = "<group>"; };
D8C19DCF2C1C95A900B32F6D /* ContactCardPreview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactCardPreview.swift; sourceTree = "<group>"; };
D8C1B0DC2CE7421C00C233A7 /* ShareProxyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareProxyViewController.swift; sourceTree = "<group>"; };
D8CDEFDF2C087CDA00146773 /* ContactCardCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactCardCell.swift; sourceTree = "<group>"; };
D8CDEFE12C087D1000146773 /* ContactCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactCardView.swift; sourceTree = "<group>"; };
D8CF2DD92CDD110F001C2352 /* ProxySettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProxySettingsViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1175,6 +1177,7 @@
children = (
D8CF2DD92CDD110F001C2352 /* ProxySettingsViewController.swift */,
D8CF2DDA2CDD110F001C2352 /* ProxyTableViewCell.swift */,
D8C1B0DC2CE7421C00C233A7 /* ShareProxyViewController.swift */,
);
path = Proxy;
sourceTree = "<group>";
Expand Down Expand Up @@ -1658,6 +1661,7 @@
305501742798CDE1008FD5CA /* WebxdcViewController.swift in Sources */,
3034929F25752FC800A523D0 /* MediaPreview.swift in Sources */,
5F785F6E2CB9344F003FFFB9 /* ReusableCellProtocol.swift in Sources */,
D8C1B0DD2CE7421C00C233A7 /* ShareProxyViewController.swift in Sources */,
AE76E5EE242BF2EA003CF461 /* WelcomeViewController.swift in Sources */,
3052C60A253F082E007D13EA /* MessageLabelDelegate.swift in Sources */,
AE0AA9562478191900D42A7F /* GridCollectionViewFlowLayout.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,13 @@ class ProxySettingsViewController: UITableViewController {
present(deleteAlert, animated: true)
}

private func shareProxy(at indexPath: IndexPath) {
let proxyToShare = proxies[indexPath.row]
let shareProxyViewController = ShareProxyViewController(dcContext: dcContext, proxyUrlString: proxyToShare)

show(UINavigationController(rootViewController: shareProxyViewController), sender: self)
}

// MARK: - Notifications

@objc private func handleConnectivityChanged(_ notification: Notification) {
Expand Down Expand Up @@ -262,6 +269,33 @@ extension ProxySettingsViewController {
tableView.deselectRow(at: indexPath, animated: true)
}

override func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
guard
proxies.isEmpty == false,
indexPath.section == ProxySettingsSection.proxies.rawValue
else { return nil }

let shareAction = UIContextualAction(style: .destructive, title: nil) { [weak self] _, _, completion in
DispatchQueue.main.async {
self?.shareProxy(at: indexPath)
completion(true)
}
}
shareAction.backgroundColor = .systemGreen
shareAction.accessibilityLabel = String.localized("proxy_share_link")
if #available(iOS 13.0, *) {
shareAction.image = Utils.makeImageWithText(image: UIImage(systemName: "square.and.arrow.up"), text: String.localized("proxy_share_link"))
} else {
shareAction.title = String.localized("proxy_share_link")
}

let configuration = UISwipeActionsConfiguration(actions: [shareAction])
configuration.performsFirstActionWithFullSwipe = true

return configuration

}

override func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
guard
proxies.isEmpty == false,
Expand All @@ -282,7 +316,6 @@ extension ProxySettingsViewController {
deleteAction.title = String.localized("delete")
}


let configuration = UISwipeActionsConfiguration(actions: [deleteAction])
configuration.performsFirstActionWithFullSwipe = true

Expand Down
130 changes: 130 additions & 0 deletions deltachat-ios/Controller/Settings/Proxy/ShareProxyViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import UIKit
import DcCore
import SDWebImageSVGKitPlugin

class ShareProxyViewController: UIViewController {
private let dcContext: DcContext

private let contentStackView: UIStackView
private let contentScrollView: UIScrollView
private let qrContentView: UIImageView
private let shareLinkButton: UIButton

private let proxyUrlString: String

var verticalCenterConstraint: NSLayoutConstraint?
var contentTopAnchor: NSLayoutConstraint?
var contentBottomAnchor: NSLayoutConstraint?

init(dcContext: DcContext, proxyUrlString: String) {
self.dcContext = dcContext
self.proxyUrlString = proxyUrlString

qrContentView = UIImageView()
qrContentView.contentMode = .scaleAspectFit
qrContentView.translatesAutoresizingMaskIntoConstraints = false

shareLinkButton = UIButton(type: .system)
shareLinkButton.setTitle(String.localized("proxy_share_link"), for: .normal)
shareLinkButton.translatesAutoresizingMaskIntoConstraints = false

contentStackView = UIStackView(arrangedSubviews: [qrContentView, shareLinkButton, UIView()])
contentStackView.translatesAutoresizingMaskIntoConstraints = false
contentStackView.axis = .vertical
contentStackView.alignment = .center
contentStackView.spacing = 16

contentScrollView = UIScrollView()
contentScrollView.translatesAutoresizingMaskIntoConstraints = false
contentScrollView.addSubview(contentStackView)

super.init(nibName: nil, bundle: nil)

if #available(iOS 13, *) {
view.backgroundColor = .secondarySystemBackground
} else {
view.backgroundColor = DcColors.defaultBackgroundColor
}

shareLinkButton.addTarget(self, action: #selector(ShareProxyViewController.shareInviteLink(_:)), for: .touchUpInside)
shareLinkButton.setTitleColor(DcColors.primary, for: .normal)

let svg = dcContext.createQRSVG(for: proxyUrlString)
qrContentView.image = getQrImage(svg: svg)

view.addSubview(contentScrollView)

setupConstraints()
}

required init?(coder: NSCoder) { fatalError() }

private func setupConstraints() {

let qrImageRatio: CGFloat
if let image = qrContentView.image {
qrImageRatio = image.size.height / image.size.width
} else {
qrImageRatio = 1
}

verticalCenterConstraint = contentStackView.centerYAnchor.constraint(equalTo: contentScrollView.centerYAnchor)
contentTopAnchor = contentStackView.topAnchor.constraint(equalTo: contentScrollView.topAnchor, constant: 16)
contentBottomAnchor = contentScrollView.bottomAnchor.constraint(equalTo: contentStackView.bottomAnchor, constant: 16)

let constraints = [
qrContentView.widthAnchor.constraint(lessThanOrEqualTo: view.safeAreaLayoutGuide.widthAnchor, multiplier: 0.75),
qrContentView.widthAnchor.constraint(lessThanOrEqualToConstant: 260),
qrContentView.heightAnchor.constraint(equalTo: qrContentView.widthAnchor, multiplier: qrImageRatio),

contentScrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
contentScrollView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
view.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: contentScrollView.trailingAnchor),
view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: contentScrollView.bottomAnchor),

contentStackView.leadingAnchor.constraint(equalTo: contentScrollView.leadingAnchor),
contentScrollView.trailingAnchor.constraint(equalTo: contentStackView.trailingAnchor),

contentStackView.centerXAnchor.constraint(equalTo: contentScrollView.centerXAnchor),
]

traitCollectionDidChange(traitCollection)
NSLayoutConstraint.activate(constraints)
}

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
let orientation = UIApplication.shared.statusBarOrientation

switch orientation {
case .portrait, .portraitUpsideDown:
verticalCenterConstraint?.isActive = true
contentTopAnchor?.isActive = false
contentBottomAnchor?.isActive = false
case .landscapeLeft, .landscapeRight:
verticalCenterConstraint?.isActive = false
contentTopAnchor?.isActive = true
contentBottomAnchor?.isActive = true
case .unknown:
// do nothing
break
@unknown default:
break
}
}

// MARK: - lifecycle
func getQrImage(svg: String?) -> UIImage? {
guard let svg else { return nil }

let svgData = svg.data(using: .utf8)
let image = SDImageSVGKCoder.shared.decodedImage(with: svgData, options: [:])
return image
}

// MARK: - Actions
@objc private func shareInviteLink(_ sender: UIButton) {
guard let inviteLinkURL = URL(string: proxyUrlString) else { return }

Utils.share(url: inviteLinkURL, parentViewController: self, sourceView: sender)
}
}

0 comments on commit 3880d8f

Please sign in to comment.