diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 74932e1c5..52577c2b6 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -569,6 +569,7 @@ B845B4D4230CD09100D759F0 /* LokiGroupChatPoller.swift in Sources */ = {isa = PBXBuildFile; fileRef = B845B4D3230CD09000D759F0 /* LokiGroupChatPoller.swift */; }; B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; }; B885D5F4233491AB00EE0D8E /* DeviceLinkingModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */; }; + B885D5F62334A32100EE0D8E /* UIView+Constraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F52334A32100EE0D8E /* UIView+Constraint.swift */; }; B891105C2320872800F15FCC /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B891105B2320872800F15FCC /* GoogleService-Info.plist */; }; B891105E2320872800F15FCC /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B891105B2320872800F15FCC /* GoogleService-Info.plist */; }; B891105F2320872800F15FCC /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = B891105B2320872800F15FCC /* GoogleService-Info.plist */; }; @@ -1373,6 +1374,7 @@ B845B4D3230CD09000D759F0 /* LokiGroupChatPoller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LokiGroupChatPoller.swift; sourceTree = ""; }; B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = ""; }; B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceLinkingModal.swift; sourceTree = ""; }; + B885D5F52334A32100EE0D8E /* UIView+Constraint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Constraint.swift"; sourceTree = ""; }; B891105B2320872800F15FCC /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; B89841E222B7579F00B1BDC6 /* NewConversationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewConversationViewController.swift; sourceTree = ""; }; B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = ""; }; @@ -2632,6 +2634,7 @@ isa = PBXGroup; children = ( B821F2F72272CED3002C88C0 /* AccountDetailsViewController.swift */, + B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */, B8162F0222891AD600D46544 /* FriendRequestView.swift */, B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */, B845B4D3230CD09000D759F0 /* LokiGroupChatPoller.swift */, @@ -2642,7 +2645,7 @@ B8258491230FA5DA001B41CB /* ScanQRCodeViewController.h */, B8258492230FA5E9001B41CB /* ScanQRCodeViewController.m */, B821F2F92272CEEE002C88C0 /* SeedViewController.swift */, - B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */, + B885D5F52334A32100EE0D8E /* UIView+Constraint.swift */, ); path = Loki; sourceTree = ""; @@ -3800,6 +3803,7 @@ 34ABC0E421DD20C500ED9469 /* ConversationMessageMapping.swift in Sources */, B821F2F82272CED3002C88C0 /* AccountDetailsViewController.swift in Sources */, 34D8C0271ED3673300188D7C /* DebugUIMessages.m in Sources */, + B885D5F62334A32100EE0D8E /* UIView+Constraint.swift in Sources */, 34DBF003206BD5A500025978 /* OWSMessageTextView.m in Sources */, 34D1F0B41F86D31D0066283D /* ConversationCollectionView.m in Sources */, 34B3F8821E8DF1700035BE1A /* NewContactThreadViewController.m in Sources */, diff --git a/Signal/src/Loki/DeviceLinkingModal.swift b/Signal/src/Loki/DeviceLinkingModal.swift index 6650bb728..a90d3024a 100644 --- a/Signal/src/Loki/DeviceLinkingModal.swift +++ b/Signal/src/Loki/DeviceLinkingModal.swift @@ -60,49 +60,34 @@ final class DeviceLinkingModal : UIViewController, LokiDeviceLinkingSessionDeleg view.backgroundColor = .clear // Content view view.addSubview(contentView) - contentView.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 32), - view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 32), - contentView.centerYAnchor.constraint(equalTo: view.centerYAnchor) - ]) + contentView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 32).isActive = true + view.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 32).isActive = true + contentView.center(.vertical, in: view) // Spinner contentView.addSubview(spinner) - spinner.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - spinner.centerXAnchor.constraint(equalTo: contentView.centerXAnchor), - spinner.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 32), - spinner.heightAnchor.constraint(equalToConstant: 64), - spinner.widthAnchor.constraint(equalToConstant: 64) - ]) + spinner.center(.horizontal, in: contentView) + spinner.pin(.top, to: .top, of: contentView, withInset: 32) + spinner.set(.width, to: 64) + spinner.set(.height, to: 64) spinner.startAnimating() // Title label contentView.addSubview(titleLabel) - titleLabel.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - titleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), - titleLabel.topAnchor.constraint(equalTo: spinner.bottomAnchor, constant: 32), - contentView.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor, constant: 16) - ]) + titleLabel.pin(.leading, to: .leading, of: contentView, withInset: 16) + titleLabel.pin(.top, to: .bottom, of: spinner, withInset: 32) + contentView.pin(.trailing, to: .trailing, of: titleLabel, withInset: 16) // Subtitle label contentView.addSubview(subtitleLabel) - subtitleLabel.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - subtitleLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), - subtitleLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 16), - contentView.trailingAnchor.constraint(equalTo: subtitleLabel.trailingAnchor, constant: 16) - ]) + subtitleLabel.pin(.leading, to: .leading, of: contentView, withInset: 16) + subtitleLabel.pin(.top, to: .bottom, of: titleLabel, withInset: 32) + contentView.pin(.trailing, to: .trailing, of: subtitleLabel, withInset: 16) // Cancel button contentView.addSubview(cancelButton) - cancelButton.translatesAutoresizingMaskIntoConstraints = false + cancelButton.pin(.leading, to: .leading, of: contentView, withInset: 16) + cancelButton.pin(.top, to: .bottom, of: subtitleLabel, withInset: 16) + contentView.pin(.trailing, to: .trailing, of: cancelButton, withInset: 16) + contentView.pin(.bottom, to: .bottom, of: cancelButton, withInset: 16) let cancelButtonHeight = cancelButton.button.titleLabel!.font.pointSize * 48 / 17 - NSLayoutConstraint.activate([ - cancelButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16), - cancelButton.topAnchor.constraint(equalTo: subtitleLabel.bottomAnchor, constant: 16), - contentView.trailingAnchor.constraint(equalTo: cancelButton.trailingAnchor, constant: 16), - contentView.bottomAnchor.constraint(equalTo: cancelButton.bottomAnchor, constant: 16), - cancelButton.heightAnchor.constraint(equalToConstant: cancelButtonHeight) - ]) + cancelButton.set(.height, to: cancelButtonHeight) } // MARK: Device Linking @@ -121,11 +106,12 @@ final class DeviceLinkingModal : UIViewController, LokiDeviceLinkingSessionDeleg if contentView.frame.contains(location) { super.touchesBegan(touches, with: event) } else { - dismiss(animated: true, completion: nil) + cancel() } } @objc private func cancel() { + deviceLinkingSession.stopListeningForLinkingRequests() dismiss(animated: true, completion: nil) } } diff --git a/Signal/src/Loki/UIView+Constraint.swift b/Signal/src/Loki/UIView+Constraint.swift new file mode 100644 index 000000000..22c2dea98 --- /dev/null +++ b/Signal/src/Loki/UIView+Constraint.swift @@ -0,0 +1,50 @@ + +extension UIView { + + enum HorizontalEdge { case left, leading, right, trailing } + enum VerticalEdge { case top, bottom } + enum Direction { case horizontal, vertical } + enum Dimension { case width, height } + + private func anchor(from edge: HorizontalEdge) -> NSLayoutXAxisAnchor { + switch edge { + case .left: return leftAnchor + case .leading: return leadingAnchor + case .right: return rightAnchor + case .trailing: return trailingAnchor + } + } + + private func anchor(from edge: VerticalEdge) -> NSLayoutYAxisAnchor { + switch edge { + case .top: return topAnchor + case .bottom: return bottomAnchor + } + } + + func pin(_ constraineeEdge: HorizontalEdge, to constrainerEdge: HorizontalEdge, of view: UIView, withInset inset: CGFloat) { + translatesAutoresizingMaskIntoConstraints = false + anchor(from: constraineeEdge).constraint(equalTo: view.anchor(from: constrainerEdge), constant: inset).isActive = true + } + + func pin(_ constraineeEdge: VerticalEdge, to constrainerEdge: VerticalEdge, of view: UIView, withInset inset: CGFloat) { + translatesAutoresizingMaskIntoConstraints = false + anchor(from: constraineeEdge).constraint(equalTo: view.anchor(from: constrainerEdge), constant: inset).isActive = true + } + + func center(_ direction: Direction, in view: UIView) { + translatesAutoresizingMaskIntoConstraints = false + switch direction { + case .horizontal: centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true + case .vertical: centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true + } + } + + func set(_ dimension: Dimension, to size: CGFloat) { + translatesAutoresizingMaskIntoConstraints = false + switch dimension { + case .width: widthAnchor.constraint(equalToConstant: size).isActive = true + case .height: heightAnchor.constraint(equalToConstant: size).isActive = true + } + } +}