Implement seed reminder view
Also fix up QR codes and give RSS feeds their own icon
This commit is contained in:
parent
d05df87dd2
commit
1ab82341b9
|
@ -574,6 +574,8 @@
|
||||||
B82B4094239DF15900A248E7 /* ConversationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B4093239DF15900A248E7 /* ConversationTitleView.swift */; };
|
B82B4094239DF15900A248E7 /* ConversationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B82B4093239DF15900A248E7 /* ConversationTitleView.swift */; };
|
||||||
B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; };
|
B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; };
|
||||||
B84664F5235022F30083A1CD /* MentionUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B84664F4235022F30083A1CD /* MentionUtilities.swift */; };
|
B84664F5235022F30083A1CD /* MentionUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = B84664F4235022F30083A1CD /* MentionUtilities.swift */; };
|
||||||
|
B85357BF23A1AE0800AAF6CD /* SeedReminderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B85357BE23A1AE0800AAF6CD /* SeedReminderView.swift */; };
|
||||||
|
B85357C123A1B81900AAF6CD /* SeedReminderViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B85357C023A1B81900AAF6CD /* SeedReminderViewDelegate.swift */; };
|
||||||
B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08323399ACF000F5AE3 /* Modal.swift */; };
|
B86BD08423399ACF000F5AE3 /* Modal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08323399ACF000F5AE3 /* Modal.swift */; };
|
||||||
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08523399CEF000F5AE3 /* SeedModal.swift */; };
|
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B86BD08523399CEF000F5AE3 /* SeedModal.swift */; };
|
||||||
B885D5F4233491AB00EE0D8E /* DeviceLinkingModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */; };
|
B885D5F4233491AB00EE0D8E /* DeviceLinkingModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */; };
|
||||||
|
@ -1409,6 +1411,8 @@
|
||||||
B82B4093239DF15900A248E7 /* ConversationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTitleView.swift; sourceTree = "<group>"; };
|
B82B4093239DF15900A248E7 /* ConversationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationTitleView.swift; sourceTree = "<group>"; };
|
||||||
B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = "<group>"; };
|
B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = "<group>"; };
|
||||||
B84664F4235022F30083A1CD /* MentionUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionUtilities.swift; sourceTree = "<group>"; };
|
B84664F4235022F30083A1CD /* MentionUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MentionUtilities.swift; sourceTree = "<group>"; };
|
||||||
|
B85357BE23A1AE0800AAF6CD /* SeedReminderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedReminderView.swift; sourceTree = "<group>"; };
|
||||||
|
B85357C023A1B81900AAF6CD /* SeedReminderViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedReminderViewDelegate.swift; sourceTree = "<group>"; };
|
||||||
B86BD08323399ACF000F5AE3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = "<group>"; };
|
B86BD08323399ACF000F5AE3 /* Modal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Modal.swift; sourceTree = "<group>"; };
|
||||||
B86BD08523399CEF000F5AE3 /* SeedModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedModal.swift; sourceTree = "<group>"; };
|
B86BD08523399CEF000F5AE3 /* SeedModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedModal.swift; sourceTree = "<group>"; };
|
||||||
B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceLinkingModal.swift; sourceTree = "<group>"; };
|
B885D5F3233491AB00EE0D8E /* DeviceLinkingModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceLinkingModal.swift; sourceTree = "<group>"; };
|
||||||
|
@ -2785,6 +2789,8 @@
|
||||||
B8BB82B82394911B00BA5194 /* Separator.swift */,
|
B8BB82B82394911B00BA5194 /* Separator.swift */,
|
||||||
B8CCF638239721E20091D419 /* TabBar.swift */,
|
B8CCF638239721E20091D419 /* TabBar.swift */,
|
||||||
B8BB82B423947F2D00BA5194 /* TextField.swift */,
|
B8BB82B423947F2D00BA5194 /* TextField.swift */,
|
||||||
|
B85357BE23A1AE0800AAF6CD /* SeedReminderView.swift */,
|
||||||
|
B85357C023A1B81900AAF6CD /* SeedReminderViewDelegate.swift */,
|
||||||
);
|
);
|
||||||
path = Components;
|
path = Components;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3878,6 +3884,7 @@
|
||||||
340FC8BA204DAC8D007AEB0F /* FingerprintViewScanController.m in Sources */,
|
340FC8BA204DAC8D007AEB0F /* FingerprintViewScanController.m in Sources */,
|
||||||
4585C4681ED8F8D200896AEA /* SafetyNumberConfirmationAlert.swift in Sources */,
|
4585C4681ED8F8D200896AEA /* SafetyNumberConfirmationAlert.swift in Sources */,
|
||||||
4C20B2B920CA10DE001BAC90 /* ConversationSearchViewController.swift in Sources */,
|
4C20B2B920CA10DE001BAC90 /* ConversationSearchViewController.swift in Sources */,
|
||||||
|
B85357C123A1B81900AAF6CD /* SeedReminderViewDelegate.swift in Sources */,
|
||||||
450D19131F85236600970622 /* RemoteVideoView.m in Sources */,
|
450D19131F85236600970622 /* RemoteVideoView.m in Sources */,
|
||||||
34129B8621EF877A005457A8 /* LinkPreviewView.swift in Sources */,
|
34129B8621EF877A005457A8 /* LinkPreviewView.swift in Sources */,
|
||||||
34386A54207D271D009F5D9C /* NeverClearView.swift in Sources */,
|
34386A54207D271D009F5D9C /* NeverClearView.swift in Sources */,
|
||||||
|
@ -4046,6 +4053,7 @@
|
||||||
4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */,
|
4521C3C01F59F3BA00B4C582 /* TextFieldHelper.swift in Sources */,
|
||||||
34D2CCDF206939B400CB1A14 /* DebugUIMessagesAction.m in Sources */,
|
34D2CCDF206939B400CB1A14 /* DebugUIMessagesAction.m in Sources */,
|
||||||
340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */,
|
340FC8AC204DAC8D007AEB0F /* PrivacySettingsTableViewController.m in Sources */,
|
||||||
|
B85357BF23A1AE0800AAF6CD /* SeedReminderView.swift in Sources */,
|
||||||
340FC8C5204DE223007AEB0F /* DebugUIBackup.m in Sources */,
|
340FC8C5204DE223007AEB0F /* DebugUIBackup.m in Sources */,
|
||||||
4C11AA5020FD59C700351FBD /* MessageStatusView.swift in Sources */,
|
4C11AA5020FD59C700351FBD /* MessageStatusView.swift in Sources */,
|
||||||
340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */,
|
340FC8AE204DAC8D007AEB0F /* OWSSoundSettingsViewController.m in Sources */,
|
||||||
|
|
|
@ -8,7 +8,7 @@ final class Button : UIButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Size {
|
enum Size {
|
||||||
case medium, large
|
case medium, large, small
|
||||||
}
|
}
|
||||||
|
|
||||||
init(style: Style, size: Size) {
|
init(style: Style, size: Size) {
|
||||||
|
@ -50,6 +50,7 @@ final class Button : UIButton {
|
||||||
}
|
}
|
||||||
let height: CGFloat
|
let height: CGFloat
|
||||||
switch size {
|
switch size {
|
||||||
|
case .small: height = Values.smallButtonHeight
|
||||||
case .medium: height = Values.mediumButtonHeight
|
case .medium: height = Values.mediumButtonHeight
|
||||||
case .large: height = Values.largeButtonHeight
|
case .large: height = Values.largeButtonHeight
|
||||||
}
|
}
|
||||||
|
@ -58,7 +59,8 @@ final class Button : UIButton {
|
||||||
backgroundColor = fillColor
|
backgroundColor = fillColor
|
||||||
layer.borderColor = borderColor.cgColor
|
layer.borderColor = borderColor.cgColor
|
||||||
layer.borderWidth = Values.borderThickness
|
layer.borderWidth = Values.borderThickness
|
||||||
titleLabel!.font = Fonts.spaceMono(ofSize: Values.mediumFontSize)
|
let fontSize = (size == .small) ? Values.smallFontSize : Values.mediumFontSize
|
||||||
|
titleLabel!.font = Fonts.spaceMono(ofSize: fontSize)
|
||||||
setTitleColor(textColor, for: UIControl.State.normal)
|
setTitleColor(textColor, for: UIControl.State.normal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,9 +121,11 @@ final class ConversationCell : UITableViewCell {
|
||||||
} else {
|
} else {
|
||||||
// TODO: Handle
|
// TODO: Handle
|
||||||
}
|
}
|
||||||
|
profilePictureView.isRSSFeed = (threadViewModel.threadRecord as? TSGroupThread)?.isRSSFeed ?? false
|
||||||
} else {
|
} else {
|
||||||
profilePictureView.hexEncodedPublicKey = threadViewModel.contactIdentifier!
|
profilePictureView.hexEncodedPublicKey = threadViewModel.contactIdentifier!
|
||||||
profilePictureView.additionalHexEncodedPublicKey = nil
|
profilePictureView.additionalHexEncodedPublicKey = nil
|
||||||
|
profilePictureView.isRSSFeed = false
|
||||||
}
|
}
|
||||||
profilePictureView.update()
|
profilePictureView.update()
|
||||||
displayNameLabel.text = getDisplayName()
|
displayNameLabel.text = getDisplayName()
|
||||||
|
|
|
@ -144,11 +144,11 @@
|
||||||
private func updateSubtitleForCurrentStatus() {
|
private func updateSubtitleForCurrentStatus() {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
switch self.currentStatus {
|
switch self.currentStatus {
|
||||||
case .calculatingPoW: self.subtitleLabel.text = "Calculating proof of work"
|
case .calculatingPoW: self.subtitleLabel.text = NSLocalizedString("Encrypting message", comment: "")
|
||||||
case .contactingNetwork: self.subtitleLabel.text = "Contacting service node network"
|
case .contactingNetwork: self.subtitleLabel.text = NSLocalizedString("Tracing a path", comment: "")
|
||||||
case .sendingMessage: self.subtitleLabel.text = "Sending message"
|
case .sendingMessage: self.subtitleLabel.text = NSLocalizedString("Sending message", comment: "")
|
||||||
case .messageSent: self.subtitleLabel.text = "Message sent securely"
|
case .messageSent: self.subtitleLabel.text = NSLocalizedString("Message sent securely", comment: "")
|
||||||
case .messageFailed: self.subtitleLabel.text = "Message failed to send"
|
case .messageFailed: self.subtitleLabel.text = NSLocalizedString("Message failed to send", comment: "")
|
||||||
case nil:
|
case nil:
|
||||||
let subtitle = NSMutableAttributedString()
|
let subtitle = NSMutableAttributedString()
|
||||||
if self.thread.isMuted {
|
if self.thread.isMuted {
|
||||||
|
|
|
@ -4,6 +4,7 @@ final class ProfilePictureView : UIView {
|
||||||
private var imageViewWidthConstraint: NSLayoutConstraint!
|
private var imageViewWidthConstraint: NSLayoutConstraint!
|
||||||
private var imageViewHeightConstraint: NSLayoutConstraint!
|
private var imageViewHeightConstraint: NSLayoutConstraint!
|
||||||
@objc var size: CGFloat = 0 // Not an implicitly unwrapped optional due to Obj-C limitations
|
@objc var size: CGFloat = 0 // Not an implicitly unwrapped optional due to Obj-C limitations
|
||||||
|
@objc var isRSSFeed = false
|
||||||
@objc var hexEncodedPublicKey: String!
|
@objc var hexEncodedPublicKey: String!
|
||||||
@objc var additionalHexEncodedPublicKey: String?
|
@objc var additionalHexEncodedPublicKey: String?
|
||||||
|
|
||||||
|
@ -11,6 +12,15 @@ final class ProfilePictureView : UIView {
|
||||||
private lazy var imageView = getImageView()
|
private lazy var imageView = getImageView()
|
||||||
private lazy var additionalImageView = getImageView()
|
private lazy var additionalImageView = getImageView()
|
||||||
|
|
||||||
|
private lazy var rssLabel: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = .systemFont(ofSize: Values.smallFontSize)
|
||||||
|
result.textAlignment = .center
|
||||||
|
result.text = "RSS"
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
// MARK: Lifecycle
|
// MARK: Lifecycle
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
@ -35,6 +45,12 @@ final class ProfilePictureView : UIView {
|
||||||
additionalImageView.set(.width, to: additionalImageViewSize)
|
additionalImageView.set(.width, to: additionalImageViewSize)
|
||||||
additionalImageView.set(.height, to: additionalImageViewSize)
|
additionalImageView.set(.height, to: additionalImageViewSize)
|
||||||
additionalImageView.layer.cornerRadius = additionalImageViewSize / 2
|
additionalImageView.layer.cornerRadius = additionalImageViewSize / 2
|
||||||
|
// Set up RSS label
|
||||||
|
addSubview(rssLabel)
|
||||||
|
rssLabel.pin(.leading, to: .leading, of: self)
|
||||||
|
rssLabel.pin(.top, to: .top, of: self)
|
||||||
|
rssLabel.autoPinWidth(toWidthOf: imageView)
|
||||||
|
rssLabel.autoPinHeight(toHeightOf: imageView)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Updating
|
// MARK: Updating
|
||||||
|
@ -47,7 +63,7 @@ final class ProfilePictureView : UIView {
|
||||||
return OWSProfileManager.shared().profileAvatar(forRecipientId: hexEncodedPublicKey) ?? Identicon.generateIcon(string: hexEncodedPublicKey, size: size)
|
return OWSProfileManager.shared().profileAvatar(forRecipientId: hexEncodedPublicKey) ?? Identicon.generateIcon(string: hexEncodedPublicKey, size: size)
|
||||||
}
|
}
|
||||||
let size: CGFloat
|
let size: CGFloat
|
||||||
if let additionalHexEncodedPublicKey = additionalHexEncodedPublicKey {
|
if let additionalHexEncodedPublicKey = additionalHexEncodedPublicKey, !isRSSFeed {
|
||||||
size = Values.smallProfilePictureSize
|
size = Values.smallProfilePictureSize
|
||||||
imageViewWidthConstraint = imageView.set(.width, to: size)
|
imageViewWidthConstraint = imageView.set(.width, to: size)
|
||||||
imageViewHeightConstraint = imageView.set(.height, to: size)
|
imageViewHeightConstraint = imageView.set(.height, to: size)
|
||||||
|
@ -60,8 +76,10 @@ final class ProfilePictureView : UIView {
|
||||||
additionalImageView.isHidden = true
|
additionalImageView.isHidden = true
|
||||||
additionalImageView.image = nil
|
additionalImageView.image = nil
|
||||||
}
|
}
|
||||||
imageView.image = getProfilePicture(of: size, for: hexEncodedPublicKey)
|
imageView.image = isRSSFeed ? nil : getProfilePicture(of: size, for: hexEncodedPublicKey)
|
||||||
|
imageView.backgroundColor = isRSSFeed ? UIColor(hex: 0x353535) : Colors.unimportant
|
||||||
imageView.layer.cornerRadius = size / 2
|
imageView.layer.cornerRadius = size / 2
|
||||||
|
rssLabel.isHidden = !isRSSFeed
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Convenience
|
// MARK: Convenience
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
|
||||||
|
final class SeedReminderView : UIView {
|
||||||
|
var title = NSAttributedString(string: "") { didSet { titleLabel.attributedText = title } }
|
||||||
|
var subtitle = "" { didSet { subtitleLabel.text = subtitle } }
|
||||||
|
var delegate: SeedReminderViewDelegate?
|
||||||
|
|
||||||
|
// MARK: Components
|
||||||
|
private lazy var progressIndicatorView: UIProgressView = {
|
||||||
|
let result = UIProgressView()
|
||||||
|
result.progressViewStyle = .bar
|
||||||
|
result.progressTintColor = Colors.accent
|
||||||
|
result.backgroundColor = UIColor(hex: 0xFFFFFF).withAlphaComponent(0.1)
|
||||||
|
result.set(.height, to: Values.progressBarThickness)
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text
|
||||||
|
result.font = .boldSystemFont(ofSize: Values.smallFontSize)
|
||||||
|
result.lineBreakMode = .byTruncatingTail
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var subtitleLabel: UILabel = {
|
||||||
|
let result = UILabel()
|
||||||
|
result.textColor = Colors.text.withAlphaComponent(Values.unimportantElementOpacity)
|
||||||
|
result.font = .systemFont(ofSize: Values.verySmallFontSize)
|
||||||
|
result.lineBreakMode = .byTruncatingTail
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
|
// MARK: Lifecycle
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
setUpViewHierarchy()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
setUpViewHierarchy()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setUpViewHierarchy() {
|
||||||
|
// Set background color
|
||||||
|
backgroundColor = Colors.cellBackground
|
||||||
|
// Set up label stack view
|
||||||
|
let labelStackView = UIStackView(arrangedSubviews: [ titleLabel, subtitleLabel ])
|
||||||
|
labelStackView.axis = .vertical
|
||||||
|
labelStackView.spacing = 4
|
||||||
|
// Set up button
|
||||||
|
let button = Button(style: .prominentOutline, size: .small)
|
||||||
|
button.setTitle(NSLocalizedString("Continue", comment: ""), for: UIControl.State.normal)
|
||||||
|
button.set(.width, to: 80)
|
||||||
|
button.addTarget(self, action: #selector(handleContinueButtonTapped), for: UIControl.Event.touchUpInside)
|
||||||
|
// Set up content stack view
|
||||||
|
let contentStackView = UIStackView(arrangedSubviews: [ labelStackView, UIView.hStretchingSpacer(), button ])
|
||||||
|
contentStackView.axis = .horizontal
|
||||||
|
contentStackView.spacing = 4
|
||||||
|
contentStackView.alignment = .center
|
||||||
|
contentStackView.layoutMargins = UIEdgeInsets(top: 0, leading: Values.mediumSpacing + Values.accentLineThickness, bottom: 0, trailing: Values.mediumSpacing)
|
||||||
|
contentStackView.isLayoutMarginsRelativeArrangement = true
|
||||||
|
// Set up separator
|
||||||
|
let separator = UIView()
|
||||||
|
separator.set(.height, to: Values.separatorThickness)
|
||||||
|
separator.backgroundColor = Colors.separator
|
||||||
|
// Set up stack view
|
||||||
|
let stackView = UIStackView(arrangedSubviews: [ progressIndicatorView, contentStackView, separator ])
|
||||||
|
stackView.axis = .vertical
|
||||||
|
stackView.spacing = Values.mediumSpacing
|
||||||
|
addSubview(stackView)
|
||||||
|
stackView.pin(to: self)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Updating
|
||||||
|
func setProgress(_ progress: Float, animated isAnimated: Bool) {
|
||||||
|
progressIndicatorView.setProgress(progress, animated: isAnimated)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Updating
|
||||||
|
@objc private func handleContinueButtonTapped() {
|
||||||
|
delegate?.handleContinueButtonTapped(from: self)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
protocol SeedReminderViewDelegate {
|
||||||
|
|
||||||
|
func handleContinueButtonTapped(from seedReminderView: SeedReminderView)
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ final class Values : NSObject {
|
||||||
@objc static let massiveFontSize = CGFloat(50)
|
@objc static let massiveFontSize = CGFloat(50)
|
||||||
|
|
||||||
// MARK: - Element Sizes
|
// MARK: - Element Sizes
|
||||||
|
@objc static let smallButtonHeight = CGFloat(27)
|
||||||
@objc static let mediumButtonHeight = CGFloat(34)
|
@objc static let mediumButtonHeight = CGFloat(34)
|
||||||
@objc static let largeButtonHeight = CGFloat(45)
|
@objc static let largeButtonHeight = CGFloat(45)
|
||||||
@objc static let accentLineThickness = CGFloat(4)
|
@objc static let accentLineThickness = CGFloat(4)
|
||||||
|
@ -43,7 +44,7 @@ final class Values : NSObject {
|
||||||
@objc static let fakeChatViewHeight = CGFloat(234)
|
@objc static let fakeChatViewHeight = CGFloat(234)
|
||||||
@objc static var composeViewTextFieldBorderThickness: CGFloat { return 1 / UIScreen.main.scale }
|
@objc static var composeViewTextFieldBorderThickness: CGFloat { return 1 / UIScreen.main.scale }
|
||||||
@objc static let messageBubbleCornerRadius: CGFloat = 10
|
@objc static let messageBubbleCornerRadius: CGFloat = 10
|
||||||
@objc static let messageProgressBarThickness: CGFloat = 2
|
@objc static let progressBarThickness: CGFloat = 2
|
||||||
|
|
||||||
// MARK: - Distances
|
// MARK: - Distances
|
||||||
@objc static let verySmallSpacing = CGFloat(4)
|
@objc static let verySmallSpacing = CGFloat(4)
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
|
|
||||||
enum QRCode {
|
enum QRCode {
|
||||||
|
|
||||||
static func generate(for string: String, isInverted: Bool = true) -> UIImage {
|
static func generate(for string: String, hasBackground: Bool = false) -> UIImage {
|
||||||
let data = string.data(using: .utf8)
|
let data = string.data(using: .utf8)
|
||||||
var qrCodeAsCIImage: CIImage
|
var qrCodeAsCIImage: CIImage
|
||||||
let filter1 = CIFilter(name: "CIQRCodeGenerator")!
|
let filter1 = CIFilter(name: "CIQRCodeGenerator")!
|
||||||
filter1.setValue(data, forKey: "inputMessage")
|
filter1.setValue(data, forKey: "inputMessage")
|
||||||
qrCodeAsCIImage = filter1.outputImage!
|
qrCodeAsCIImage = filter1.outputImage!
|
||||||
if isInverted {
|
if hasBackground {
|
||||||
|
let filter2 = CIFilter(name: "CIFalseColor")!
|
||||||
|
filter2.setValue(qrCodeAsCIImage, forKey: "inputImage")
|
||||||
|
filter2.setValue(CIColor(color: UIColor(hex: 0xFFFFFF)), forKey: "inputColor0")
|
||||||
|
filter2.setValue(CIColor(color: UIColor(hex: 0x1B1B1B)), forKey: "inputColor1")
|
||||||
|
qrCodeAsCIImage = filter2.outputImage!
|
||||||
|
} else {
|
||||||
let filter2 = CIFilter(name: "CIColorInvert")!
|
let filter2 = CIFilter(name: "CIColorInvert")!
|
||||||
filter2.setValue(qrCodeAsCIImage, forKey: "inputImage")
|
filter2.setValue(qrCodeAsCIImage, forKey: "inputImage")
|
||||||
qrCodeAsCIImage = filter2.outputImage!
|
qrCodeAsCIImage = filter2.outputImage!
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate, UIViewControllerPreviewingDelegate {
|
final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate, UIViewControllerPreviewingDelegate, SeedReminderViewDelegate {
|
||||||
private var threadViewModelCache: [String:ThreadViewModel] = [:]
|
private var threadViewModelCache: [String:ThreadViewModel] = [:]
|
||||||
private var isObservingDatabase = true
|
private var isObservingDatabase = true
|
||||||
private var isViewVisible = false { didSet { updateIsObservingDatabase() } }
|
private var isViewVisible = false { didSet { updateIsObservingDatabase() } }
|
||||||
|
@ -22,6 +22,18 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
|
||||||
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
|
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
|
||||||
|
|
||||||
// MARK: Components
|
// MARK: Components
|
||||||
|
private lazy var seedReminderView: SeedReminderView = {
|
||||||
|
let result = SeedReminderView()
|
||||||
|
let title = "You're almost finished! 80%"
|
||||||
|
let attributedTitle = NSMutableAttributedString(string: title)
|
||||||
|
attributedTitle.addAttribute(.foregroundColor, value: Colors.accent, range: (title as NSString).range(of: "80%"))
|
||||||
|
result.title = attributedTitle
|
||||||
|
result.subtitle = NSLocalizedString("Secure your account by saving your seed", comment: "")
|
||||||
|
result.setProgress(0.8, animated: false)
|
||||||
|
result.delegate = self
|
||||||
|
return result
|
||||||
|
}()
|
||||||
|
|
||||||
private lazy var searchBar = SearchBar()
|
private lazy var searchBar = SearchBar()
|
||||||
|
|
||||||
private lazy var tableView: UITableView = {
|
private lazy var tableView: UITableView = {
|
||||||
|
@ -74,11 +86,19 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
|
||||||
titleLabel.textColor = Colors.text
|
titleLabel.textColor = Colors.text
|
||||||
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
|
titleLabel.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
|
||||||
navigationItem.titleView = titleLabel
|
navigationItem.titleView = titleLabel
|
||||||
|
// Set up seed reminder view
|
||||||
|
view.addSubview(seedReminderView)
|
||||||
|
seedReminderView.pin(.leading, to: .leading, of: view)
|
||||||
|
seedReminderView.pin(.top, to: .top, of: view)
|
||||||
|
seedReminderView.pin(.trailing, to: .trailing, of: view)
|
||||||
// Set up table view
|
// Set up table view
|
||||||
tableView.dataSource = self
|
tableView.dataSource = self
|
||||||
tableView.delegate = self
|
tableView.delegate = self
|
||||||
view.addSubview(tableView)
|
view.addSubview(tableView)
|
||||||
tableView.pin(to: view)
|
tableView.pin(.leading, to: .leading, of: view)
|
||||||
|
tableView.pin(.top, to: .bottom, of: seedReminderView)
|
||||||
|
tableView.pin(.trailing, to: .trailing, of: view)
|
||||||
|
tableView.pin(.bottom, to: .bottom, of: view)
|
||||||
// Set up search bar
|
// Set up search bar
|
||||||
tableView.tableHeaderView = searchBar
|
tableView.tableHeaderView = searchBar
|
||||||
searchBar.sizeToFit()
|
searchBar.sizeToFit()
|
||||||
|
@ -219,6 +239,10 @@ final class HomeVC : UIViewController, UITableViewDataSource, UITableViewDelegat
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Interaction
|
// MARK: Interaction
|
||||||
|
func handleContinueButtonTapped(from seedReminderView: SeedReminderView) {
|
||||||
|
// TODO: Implement
|
||||||
|
}
|
||||||
|
|
||||||
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
|
||||||
searchBar.resignFirstResponder()
|
searchBar.resignFirstResponder()
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,6 +170,14 @@ private final class ViewMyQRCodeVC : UIViewController {
|
||||||
let qrCode = QRCode.generate(for: userHexEncodedPublicKey)
|
let qrCode = QRCode.generate(for: userHexEncodedPublicKey)
|
||||||
qrCodeImageView.image = qrCode
|
qrCodeImageView.image = qrCode
|
||||||
qrCodeImageView.contentMode = .scaleAspectFit
|
qrCodeImageView.contentMode = .scaleAspectFit
|
||||||
|
qrCodeImageView.set(.height, to: 240)
|
||||||
|
qrCodeImageView.set(.width, to: 240)
|
||||||
|
// Set up QR code image view container
|
||||||
|
let qrCodeImageViewContainer = UIView()
|
||||||
|
qrCodeImageViewContainer.addSubview(qrCodeImageView)
|
||||||
|
qrCodeImageView.center(.horizontal, in: qrCodeImageViewContainer)
|
||||||
|
qrCodeImageView.pin(.top, to: .top, of: qrCodeImageViewContainer)
|
||||||
|
qrCodeImageView.pin(.bottom, to: .bottom, of: qrCodeImageViewContainer)
|
||||||
// Set up explanation label
|
// Set up explanation label
|
||||||
let explanationLabel = UILabel()
|
let explanationLabel = UILabel()
|
||||||
explanationLabel.textColor = Colors.text
|
explanationLabel.textColor = Colors.text
|
||||||
|
@ -193,7 +201,7 @@ private final class ViewMyQRCodeVC : UIViewController {
|
||||||
shareButtonContainer.pin(.trailing, to: .trailing, of: shareButton, withInset: 80)
|
shareButtonContainer.pin(.trailing, to: .trailing, of: shareButton, withInset: 80)
|
||||||
shareButtonContainer.pin(.bottom, to: .bottom, of: shareButton)
|
shareButtonContainer.pin(.bottom, to: .bottom, of: shareButton)
|
||||||
// Set up stack view
|
// Set up stack view
|
||||||
let stackView = UIStackView(arrangedSubviews: [ titleLabel, qrCodeImageView, explanationLabel, shareButtonContainer, UIView.vStretchingSpacer() ])
|
let stackView = UIStackView(arrangedSubviews: [ titleLabel, qrCodeImageViewContainer, explanationLabel, shareButtonContainer, UIView.vStretchingSpacer() ])
|
||||||
stackView.axis = .vertical
|
stackView.axis = .vertical
|
||||||
stackView.spacing = Values.largeSpacing
|
stackView.spacing = Values.largeSpacing
|
||||||
stackView.alignment = .fill
|
stackView.alignment = .fill
|
||||||
|
@ -215,7 +223,7 @@ private final class ViewMyQRCodeVC : UIViewController {
|
||||||
|
|
||||||
// MARK: Interaction
|
// MARK: Interaction
|
||||||
@objc private func shareQRCode() {
|
@objc private func shareQRCode() {
|
||||||
let qrCode = QRCode.generate(for: userHexEncodedPublicKey, isInverted: false)
|
let qrCode = QRCode.generate(for: userHexEncodedPublicKey, hasBackground: true)
|
||||||
let shareVC = UIActivityViewController(activityItems: [ qrCode ], applicationActivities: nil)
|
let shareVC = UIActivityViewController(activityItems: [ qrCode ], applicationActivities: nil)
|
||||||
qrCodeVC.navigationController!.present(shareVC, animated: true, completion: nil)
|
qrCodeVC.navigationController!.present(shareVC, animated: true, completion: nil)
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
if (!self.capture) {
|
if (!self.capture) {
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
self.capture = [[ZXCapture alloc] init];
|
self.capture = [[ZXCapture alloc] init];
|
||||||
|
self.capture.invert = YES;
|
||||||
self.capture.camera = self.capture.back;
|
self.capture.camera = self.capture.back;
|
||||||
self.capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
|
self.capture.focusMode = AVCaptureFocusModeContinuousAutoFocus;
|
||||||
self.capture.delegate = self;
|
self.capture.delegate = self;
|
||||||
|
|
|
@ -697,7 +697,7 @@ typedef enum : NSUInteger {
|
||||||
[self.collectionView autoPinEdgeToSuperviewSafeArea:ALEdgeTrailing];
|
[self.collectionView autoPinEdgeToSuperviewSafeArea:ALEdgeTrailing];
|
||||||
|
|
||||||
_progressIndicatorView = [UIProgressView new];
|
_progressIndicatorView = [UIProgressView new];
|
||||||
[self.progressIndicatorView autoSetDimension:ALDimensionHeight toSize:LKValues.messageProgressBarThickness];
|
[self.progressIndicatorView autoSetDimension:ALDimensionHeight toSize:LKValues.progressBarThickness];
|
||||||
self.progressIndicatorView.progressViewStyle = UIProgressViewStyleBar;
|
self.progressIndicatorView.progressViewStyle = UIProgressViewStyleBar;
|
||||||
self.progressIndicatorView.progressTintColor = LKColors.accent;
|
self.progressIndicatorView.progressTintColor = LKColors.accent;
|
||||||
self.progressIndicatorView.trackTintColor = UIColor.clearColor;
|
self.progressIndicatorView.trackTintColor = UIColor.clearColor;
|
||||||
|
|
|
@ -2740,3 +2740,10 @@
|
||||||
"Enter your seed" = "Enter your seed";
|
"Enter your seed" = "Enter your seed";
|
||||||
"Message" = "Message";
|
"Message" = "Message";
|
||||||
"You" = "You";
|
"You" = "You";
|
||||||
|
"Encrypting message" = "Encrypting message";
|
||||||
|
"Tracing a path" = "Tracing a path";
|
||||||
|
"Sending message" = "Sending message";
|
||||||
|
"Message sent securely" = "Message sent securely";
|
||||||
|
"Message failed to send" = "Message failed to send";
|
||||||
|
"Secure your account by saving your seed" = "Secure your account by saving your seed";
|
||||||
|
"Continue" = "Continue";
|
||||||
|
|
Loading…
Reference in New Issue