Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1086 Added multiline support to signature badge #2377

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions FlowCrypt/App/GeneralConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ enum GeneralConstants {

enum Global {
static let attachmentSizeLimit = 10_000_000
static let signatureSeparator = "______"
}

enum Mock {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,14 @@ extension ThreadMessageInfoCellNode.Input {
return nil
}

let components = signature.message.components(separatedBy: GeneralConstants.Global.signatureSeparator)
return BadgeNode.Input(
icon: signature.icon,
text: NSAttributedString.text(from: signature.message, style: .regular(12), color: .white),
text: components[safe: 0]?.attributed(.regular(12), color: .white),
additionalText: components[safe: 1]?.attributed(.regular(12), color: .white),
color: signature.color,
textAccessibilityIdentifier: "aid-signature-badge"
textAccessibilityIdentifier: "aid-signature-badge",
additionalTextAccessibilityIdentifier: "aid-signature-additional-text"
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,12 @@ struct ProcessedMessage {
case .unsigned:
return "message_not_signed".localized
case let .error(message):
return "message_signature_verify_error".localizeWithArguments(message.lowercasingFirstLetter())
let signaturErrorString = "message_signature_verify_error".localized
ioanmo226 marked this conversation as resolved.
Show resolved Hide resolved
return signaturErrorString + GeneralConstants.Global.signatureSeparator + message.lowercasingFirstLetter()
case let .missingPubkey(longid):
let message = "message_missing_pubkey".localizeWithArguments(longid)
return "message_signature_verify_error".localizeWithArguments(message)
let missigngPubKeyString = "message_missing_pubkey".localizeWithArguments(longid.spaced(every: 4))
let signaturErrorString = "message_signature_verify_error".localized
ioanmo226 marked this conversation as resolved.
Show resolved Hide resolved
return signaturErrorString + GeneralConstants.Global.signatureSeparator + missigngPubKeyString
case .partial:
return "message_signature_partial".localized
case .bad:
Expand Down
2 changes: 1 addition & 1 deletion FlowCrypt/Resources/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"message_not_signed" = "not signed";
"message_missing_pubkey" = "no public key %@";
"message_signature_partial" = "only partially signed";
"message_signature_verify_error" = "cannot verify signature: %@";
"message_signature_verify_error" = "cannot verify signature";
"message_bad_signature" = "bad signature";
"message_signature_pending" = "verifying signature...";
"message_signature_fail_reason" = "Failed to verify signature due to: %@";
Expand Down
2 changes: 2 additions & 0 deletions FlowCryptUI/Cell Nodes/ThreadMessageInfoCellNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ public final class ThreadMessageInfoCellNode: CellNode {
let spacer = ASLayoutSpec()
spacer.style.flexGrow = 1.0

signatureNode?.style.flexShrink = 1.0

return ASStackLayoutSpec(
direction: .horizontal,
spacing: 4,
Expand Down
31 changes: 29 additions & 2 deletions FlowCryptUI/Nodes/BadgeNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@ public final class BadgeNode: ASDisplayNode {
public struct Input {
public let icon: String?
public let text: NSAttributedString?
public let additionalText: NSAttributedString?
public let color: UIColor?
public let textAccessibilityIdentifier: String
public let additionalTextAccessibilityIdentifier: String?

public init(icon: String?,
text: NSAttributedString?,
additionalText: NSAttributedString? = nil,
color: UIColor?,
textAccessibilityIdentifier: String) {
textAccessibilityIdentifier: String,
additionalTextAccessibilityIdentifier: String? = nil) {
self.icon = icon
self.text = text
self.additionalText = additionalText
self.color = color
self.textAccessibilityIdentifier = textAccessibilityIdentifier
self.additionalTextAccessibilityIdentifier = additionalTextAccessibilityIdentifier
}
}

Expand All @@ -36,7 +42,9 @@ public final class BadgeNode: ASDisplayNode {
}()

private let textNode = ASTextNode2()
private let additionalTextNode = ASTextNode2()
private let input: BadgeNode.Input
private var showAdditionalText = false

init(input: BadgeNode.Input) {
self.input = input
Expand All @@ -45,18 +53,37 @@ public final class BadgeNode: ASDisplayNode {
automaticallyManagesSubnodes = true

textNode.attributedText = input.text
additionalTextNode.attributedText = input.additionalText
ioanmo226 marked this conversation as resolved.
Show resolved Hide resolved
textNode.accessibilityIdentifier = input.textAccessibilityIdentifier
additionalTextNode.accessibilityIdentifier = input.additionalTextAccessibilityIdentifier
backgroundColor = input.color
cornerRadius = 4
DispatchQueue.main.async {
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.handleTap)))
}
}

@objc private func handleTap() {
if input.additionalText != nil {
showAdditionalText = !showAdditionalText
setNeedsLayout()
}
}

override public func layoutSpecThatFits(_: ASSizeRange) -> ASLayoutSpec {
let textSpec = ASStackLayoutSpec(
direction: .vertical,
spacing: 5.0,
ioanmo226 marked this conversation as resolved.
Show resolved Hide resolved
justifyContent: .start,
alignItems: .start,
children: showAdditionalText ? [textNode, additionalTextNode] : [textNode]
)
let contentSpec = ASStackLayoutSpec(
direction: .horizontal,
spacing: 2,
justifyContent: .spaceBetween,
alignItems: .center,
children: [iconNode, textNode].compactMap { $0 }
children: [iconNode, textSpec].compactMap { $0 }
)

return ASInsetLayoutSpec(
Expand Down
12 changes: 11 additions & 1 deletion appium/tests/screenobjects/email.screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const SELECTORS = {
SENDER_EMAIL: '~aid-message-sender-label',
ENCRYPTION_BADGE: '~aid-encryption-badge',
SIGNATURE_BADGE: '~aid-signature-badge',
SIGNATURE_ADDITIONAL_TEXT_BADGE: '~aid-signature-additional-text',
ATTACHMENT_TEXT_VIEW: '~aid-attachment-text-view',
PUBLIC_KEY_LABEL: '~aid-public-key-label',
FINGEPRINT_LABEL_VALUE: '~aid-fingerprint-value',
Expand Down Expand Up @@ -143,6 +144,10 @@ class EmailScreen extends BaseScreen {
return $(SELECTORS.SIGNATURE_BADGE);
}

get additionalSignatureTextBadge() {
return $(SELECTORS.SIGNATURE_ADDITIONAL_TEXT_BADGE);
}

get publicKeyLabel() {
return $(SELECTORS.PUBLIC_KEY_LABEL);
}
Expand Down Expand Up @@ -348,8 +353,13 @@ class EmailScreen extends BaseScreen {
await ElementHelper.checkStaticText(await this.encryptionBadge, value);
};

checkSignatureBadge = async (value: string) => {
checkSignatureBadge = async (value: string, additionalText?: string) => {
const signatureBadge = await this.signatureBadge;
await ElementHelper.checkStaticText(await this.signatureBadge, value);
if (additionalText) {
await ElementHelper.waitAndClick(signatureBadge);
await ElementHelper.checkStaticText(await this.additionalSignatureTextBadge, additionalText);
}
};

checkAttachmentTextView = async (value: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ describe('INBOX: ', () => {
await MailFolderScreen.clickOnEmailBySubject('Signed only message where the pubkey is not available');

await EmailScreen.checkEncryptionBadge('not encrypted');
await EmailScreen.checkSignatureBadge('cannot verify signature: no public key A54D82BE1521D20E');
await EmailScreen.checkSignatureBadge('cannot verify signature', 'no public key A54D 82BE 1521 D20E');
await EmailScreen.clickBackButton();

// signed only message that was tempered during transit
await MailFolderScreen.clickOnEmailBySubject('Signed only message that was tempered during transit');
await EmailScreen.checkEncryptionBadge('not encrypted');
await EmailScreen.checkSignatureBadge('cannot verify signature: signed digest did not match');
await EmailScreen.checkSignatureBadge('cannot verify signature', 'signed digest did not match');
await EmailScreen.clickBackButton();

// partially signed only message
Expand Down