Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions FlowCrypt.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
5180CB97273724E9001FC7EF /* ThreadMessageSenderCellNode.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5180CB96273724E9001FC7EF /* ThreadMessageSenderCellNode.swift */; };
518389C82726D7DD00131B2C /* UIViewController+Spinner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 518389C72726D7DD00131B2C /* UIViewController+Spinner.swift */; };
518389CA2726D8F700131B2C /* UIApplicationExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 518389C92726D8F700131B2C /* UIApplicationExtension.swift */; };
51938DC1274CC291007AD57B /* MessageQuoteType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51938DC0274CC291007AD57B /* MessageQuoteType.swift */; };
51B0C7712729861C00124663 /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B0C7702729861C00124663 /* String+Extension.swift */; };
51B0C774272AB61000124663 /* StringTestExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B0C773272AB61000124663 /* StringTestExtension.swift */; };
51B4AE51271444580001F33B /* PubKeyRealmObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B4AE50271444580001F33B /* PubKeyRealmObject.swift */; };
Expand Down Expand Up @@ -491,6 +492,7 @@
5180CB96273724E9001FC7EF /* ThreadMessageSenderCellNode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadMessageSenderCellNode.swift; sourceTree = "<group>"; };
518389C72726D7DD00131B2C /* UIViewController+Spinner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Spinner.swift"; sourceTree = "<group>"; };
518389C92726D8F700131B2C /* UIApplicationExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplicationExtension.swift; sourceTree = "<group>"; };
51938DC0274CC291007AD57B /* MessageQuoteType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageQuoteType.swift; sourceTree = "<group>"; };
51B0C7702729861C00124663 /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
51B0C773272AB61000124663 /* StringTestExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringTestExtension.swift; sourceTree = "<group>"; };
51B4AE50271444580001F33B /* PubKeyRealmObject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PubKeyRealmObject.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1555,6 +1557,7 @@
9F9ABC8623AC1EAA00D560E3 /* MessageContext.swift */,
9FE1B39F2565B0CD00D6D086 /* Message.swift */,
9F5C2A76257D705100DE9B4B /* MessageLabel.swift */,
51938DC0274CC291007AD57B /* MessageQuoteType.swift */,
);
path = Model;
sourceTree = "<group>";
Expand Down Expand Up @@ -2550,6 +2553,7 @@
9FDF3654235A218E00614596 /* main.swift in Sources */,
D2E26F6C24F25B1F00612AF1 /* KeyAlgo.swift in Sources */,
D2891AC424C62446008918E3 /* ErrorHandler.swift in Sources */,
51938DC1274CC291007AD57B /* MessageQuoteType.swift in Sources */,
9F41FA2F253B7624003B970D /* BackupSelectKeyDecorator.swift in Sources */,
D227C0E8250538A90070F805 /* FoldersService.swift in Sources */,
5ADEDCB623A426E300EC495E /* KeyDetailViewController.swift in Sources */,
Expand Down
30 changes: 16 additions & 14 deletions FlowCrypt/Controllers/Compose/ComposeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ private struct ComposedDraft: Equatable {
/**
* View controller to compose the message and send it
* - User can be redirected here from *InboxViewController* by tapping on *+*
* - Or from *ThreadDetailsViewController* controller by tapping on *reply*
* - Or from *ThreadDetailsViewController* controller by tapping on *reply* or *forward*
**/
final class ComposeViewController: TableNodeViewController {
private lazy var logger = Logger.nested(Self.self)
Expand Down Expand Up @@ -119,7 +119,7 @@ final class ComposeViewController: TableNodeViewController {
setupNavigationBar()
observeKeyboardNotifications()
observerAppStates()
setupReply()
setupQuote()
}

override func viewWillDisappear(_ animated: Bool) {
Expand Down Expand Up @@ -250,12 +250,14 @@ extension ComposeViewController {
}
}

private func setupReply() {
guard input.isReply, let email = input.recipientReplyTitle else { return }
private func setupQuote() {
guard input.isQuote else { return }

let recipient = ComposeMessageRecipient(email: email, state: decorator.recipientIdleState)
contextToSend.recipients.append(recipient)
evaluate(recipient: recipient)
input.quoteRecipients.forEach { email in
let recipient = ComposeMessageRecipient(email: email, state: decorator.recipientIdleState)
contextToSend.recipients.append(recipient)
evaluate(recipient: recipient)
}
}
}

Expand Down Expand Up @@ -549,22 +551,22 @@ extension ComposeViewController {
}
.onShouldReturn { [weak self] _ in
guard let self = self else { return true }
if !self.input.isReply, let node = self.node.visibleNodes.compactMap({ $0 as? TextViewCellNode }).first {
if !self.input.isQuote, let node = self.node.visibleNodes.compactMap({ $0 as? TextViewCellNode }).first {
node.becomeFirstResponder()
} else {
self.node.view.endEditing(true)
}
return true
}
.then {
let subject = input.isReply ? input.subjectReplyTitle : contextToSend.subject
let subject = input.isQuote ? input.subjectQuoteTitle : contextToSend.subject
$0.attributedText = decorator.styledTitle(with: subject)
}
}

private func textNode() -> ASCellNode {
let replyQuote = decorator.styledReplyQuote(with: input)
let height = max(decorator.frame(for: replyQuote).height, 40)
let styledQuote = decorator.styledQuote(with: input)
let height = max(decorator.frame(for: styledQuote).height, 40)

return TextViewCellNode(
decorator.styledTextViewInput(with: height)
Expand All @@ -579,9 +581,9 @@ extension ComposeViewController {
.then {
let messageText = decorator.styledMessage(with: contextToSend.message ?? "")

if input.isReply && !messageText.string.contains(replyQuote.string) {
if input.isQuote && !messageText.string.contains(styledQuote.string) {
let mutableString = NSMutableAttributedString(attributedString: messageText)
mutableString.append(replyQuote)
mutableString.append(styledQuote)
$0.textView.attributedText = mutableString
$0.becomeFirstResponder()
} else {
Expand Down Expand Up @@ -615,7 +617,7 @@ extension ComposeViewController {
}
.then {
$0.isLowercased = true
if !self.input.isReply {
if !self.input.isQuote {
$0.becomeFirstResponder()
}
}
Expand Down
36 changes: 21 additions & 15 deletions FlowCrypt/Controllers/Compose/ComposeViewControllerInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ import Foundation
struct ComposeMessageInput: Equatable {
static let empty = ComposeMessageInput(type: .idle)

struct ReplyInfo: Equatable {
let recipient: String?
struct MessageQuoteInfo: Equatable {
let recipients: [String]
let sender: String?
let subject: String?
let mime: Data?
let sentDate: Date
Expand All @@ -22,47 +23,52 @@ struct ComposeMessageInput: Equatable {

enum InputType: Equatable {
case idle
case reply(ReplyInfo)
case quote(MessageQuoteInfo)
}

let type: InputType

var isReply: Bool {
var isQuote: Bool {
switch type {
case .idle: return false
case .reply: return true
case .quote: return true
}
}

var recipientReplyTitle: String? {
guard case let .reply(info) = type else { return nil }
return info.recipient
var quoteRecipients: [String] {
guard case let .quote(info) = type else { return [] }
return info.recipients
}

var subjectReplyTitle: String? {
guard case let .reply(info) = type else { return nil }
return "Re: \(info.subject ?? "(no subject)")"
var subjectQuoteTitle: String? {
guard case let .quote(info) = type else { return nil }
return info.subject
}

var successfullySentToast: String {
switch type {
case .idle: return "compose_encrypted_sent".localized
case .reply: return "compose_reply_successfull".localized
case .quote(let info):
if info.recipients.isEmpty {
return "compose_forward_successful".localized
} else {
return "compose_reply_successful".localized
}
}
}

var subject: String? {
guard case let .reply(info) = type else { return nil }
guard case let .quote(info) = type else { return nil }
return info.subject
}

var replyToMime: Data? {
guard case let .reply(info) = type else { return nil }
guard case let .quote(info) = type else { return nil }
return info.mime
}

var threadId: String? {
guard case let .reply(info) = type else { return nil }
guard case let .quote(info) = type else { return nil }
return info.threadId
}
}
8 changes: 4 additions & 4 deletions FlowCrypt/Controllers/Compose/ComposeViewDecorator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ struct ComposeViewDecorator {
text.attributed(.regular(17))
}

func styledReplyQuote(with input: ComposeMessageInput) -> NSAttributedString {
guard case let .reply(info) = input.type else { return NSAttributedString(string: "") }
func styledQuote(with input: ComposeMessageInput) -> NSAttributedString {
guard case let .quote(info) = input.type else { return NSAttributedString(string: "") }

let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .short
Expand All @@ -85,10 +85,10 @@ struct ComposeViewDecorator {
dateFormatter.timeStyle = .short
let time = dateFormatter.string(from: info.sentDate)

let from = info.recipient ?? "unknown sender"
let from = info.sender ?? "unknown sender"

let text: String = "\n\n"
+ "compose_reply_from".localizeWithArguments(date, time, from)
+ "compose_quote_from".localizeWithArguments(date, time, from)
+ "\n"

let message = " > " + info.message.replacingOccurrences(of: "\n", with: "\n > ")
Expand Down
2 changes: 1 addition & 1 deletion FlowCrypt/Controllers/Inbox/InboxProviders.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by Anton Kharchevskyi on 11.10.2021
// Copyright © 2017-present FlowCrypt a. s. All rights reserved.
//

import Foundation

struct InboxContext {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by Roma Sosnovsky on 13/10/21
// Copyright © 2017-present FlowCrypt a. s. All rights reserved.
//

import FlowCryptUI
import Foundation

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// Created by Roma Sosnovsky on 13/10/21
// Copyright © 2017-present FlowCrypt a. s. All rights reserved.
//

import AsyncDisplayKit
import FlowCryptCommon
import FlowCryptUI
Expand Down
1 change: 0 additions & 1 deletion FlowCrypt/Controllers/Threads/MessageAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
// Copyright © 2017-present FlowCrypt a. s. All rights reserved.
//


import Foundation

typealias MessageActionCompletion = (MessageAction, InboxRenderable) -> Void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ extension ThreadMessageSenderCellNode.Input {
sender: NSAttributedString.text(from: sender, style: style, color: textColor),
date: NSAttributedString.text(from: date, style: style, color: dateColor),
isExpanded: threadMessage.isExpanded,
buttonColor: .messageButtonColor
buttonColor: .messageButtonColor,
nodeInsets: UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 8)
)
}
}
Expand Down
Loading