From a6ff2ddb7211f338926274ec03cbcab5816415bb Mon Sep 17 00:00:00 2001 From: Oliver Wiese <oliver.wiese@fu-berlin.de> Date: Mon, 13 Apr 2020 17:03:29 +0200 Subject: [PATCH] work on buttons --- enzevalos_iphone.xcodeproj/project.pbxproj | 6 +- enzevalos_iphone/CryptoObject.swift | 21 ++- enzevalos_iphone/Dialog/DialogOption.swift | 71 -------- .../SwiftUI/Data/DialogProtocols.swift | 88 ++++++++++ .../SwiftUI/Data/DisplayProtocols.swift | 20 +-- .../SwiftUI/Data/SimulatorData.swift | 2 + .../SwiftUI/Read/ReadViewCoordinator.swift | 121 ++++++++++++- .../Tabbed Views/SecurityBriefingView.swift | 163 +++++++++++++++--- enzevalos_iphone/en.lproj/Localizable.strings | 3 + 9 files changed, 378 insertions(+), 117 deletions(-) create mode 100644 enzevalos_iphone/SwiftUI/Data/DialogProtocols.swift diff --git a/enzevalos_iphone.xcodeproj/project.pbxproj b/enzevalos_iphone.xcodeproj/project.pbxproj index 9a3f8ad0..3595b099 100644 --- a/enzevalos_iphone.xcodeproj/project.pbxproj +++ b/enzevalos_iphone.xcodeproj/project.pbxproj @@ -121,6 +121,7 @@ 4775D7A8243F0D630052F2CC /* DisplayProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4775D7A7243F0D630052F2CC /* DisplayProtocols.swift */; }; 4775D7AA243F0E260052F2CC /* SimulatorData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4775D7A9243F0E260052F2CC /* SimulatorData.swift */; }; 4775D7AC243F18BC0052F2CC /* SecurityBriefingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4775D7AB243F18BC0052F2CC /* SecurityBriefingView.swift */; }; + 4775D7B02443539E0052F2CC /* DialogProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4775D7AF2443539E0052F2CC /* DialogProtocols.swift */; }; 477670C4228453FB00043604 /* ButtonCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 477670C3228453FB00043604 /* ButtonCell.xib */; }; 477670C6228454F700043604 /* ButtonCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 477670C5228454F700043604 /* ButtonCell.swift */; }; 478154A721FF3F0900A931EC /* Warning.swift in Sources */ = {isa = PBXBuildFile; fileRef = 478154A621FF3F0900A931EC /* Warning.swift */; }; @@ -571,6 +572,7 @@ 4775D7A7243F0D630052F2CC /* DisplayProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayProtocols.swift; sourceTree = "<group>"; }; 4775D7A9243F0E260052F2CC /* SimulatorData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulatorData.swift; sourceTree = "<group>"; }; 4775D7AB243F18BC0052F2CC /* SecurityBriefingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecurityBriefingView.swift; sourceTree = "<group>"; }; + 4775D7AF2443539E0052F2CC /* DialogProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DialogProtocols.swift; sourceTree = "<group>"; }; 477670C3228453FB00043604 /* ButtonCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ButtonCell.xib; sourceTree = "<group>"; }; 477670C5228454F700043604 /* ButtonCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonCell.swift; sourceTree = "<group>"; }; 478154A621FF3F0900A931EC /* Warning.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Warning.swift; sourceTree = "<group>"; }; @@ -1211,6 +1213,7 @@ children = ( 4775D7A7243F0D630052F2CC /* DisplayProtocols.swift */, 4775D7A9243F0E260052F2CC /* SimulatorData.swift */, + 4775D7AF2443539E0052F2CC /* DialogProtocols.swift */, ); path = Data; sourceTree = "<group>"; @@ -1289,10 +1292,10 @@ 47C8224E24379EAE005BCE73 /* MessageViewMain.swift */, 47C8226A2438A86A005BCE73 /* SenderViewMain.swift */, 47C8224324379EAE005BCE73 /* AttachmentsViewMain.swift */, + 4775D7AB243F18BC0052F2CC /* SecurityBriefingView.swift */, 47C822632438A84C005BCE73 /* SenderViewChildren */, 47C8224824379EAE005BCE73 /* MessageViewChildren */, 47C8224B24379EAE005BCE73 /* AttachmentChildren */, - 4775D7AB243F18BC0052F2CC /* SecurityBriefingView.swift */, ); path = "Tabbed Views"; sourceTree = "<group>"; @@ -2304,6 +2307,7 @@ 475B00351F7B9565006CDD41 /* CryptoObject.swift in Sources */, A1EB057E1D956848008659C1 /* VENDataDelegate.swift in Sources */, 4706D661225CD21D00B3F1D3 /* ExportKeyHelper.swift in Sources */, + 4775D7B02443539E0052F2CC /* DialogProtocols.swift in Sources */, 8428A86F1F436A1E007649A5 /* InviteFriendViewController.swift in Sources */, A1735DFA205AB88500B336DB /* SendViewState.swift in Sources */, 475B00331F7B9565006CDD41 /* SwiftPGP.swift in Sources */, diff --git a/enzevalos_iphone/CryptoObject.swift b/enzevalos_iphone/CryptoObject.swift index a3761a32..e74ef3f3 100644 --- a/enzevalos_iphone/CryptoObject.swift +++ b/enzevalos_iphone/CryptoObject.swift @@ -7,7 +7,9 @@ import Foundation - +enum Rating { + case Positiv, Neutral, Negativ +} enum SignatureState: Int16 { case NoSignature = 0 // -> no authenticity -> no actions possible @@ -29,6 +31,14 @@ enum SignatureState: Int16 { } } } + + var rating: Rating { + switch self { + case .NoSignature, .NoPublicKey: return .Neutral + case .ValidSignature: return .Positiv + case .InvalidSignature: return .Negativ + } + } public static let allStates = [NoSignature, NoPublicKey, InvalidSignature, ValidSignature] } @@ -52,6 +62,15 @@ enum EncryptionState: Int16 { } } } + + var rating: Rating { + switch self { + case .NoEncryption: return .Neutral + case .ValidedEncryptedWithCurrentKey, .ValidEncryptedWithOldKey: return .Positiv + case .UnableToDecrypt: return .Neutral + } + } + public static let allStates = [NoEncryption, UnableToDecrypt, ValidEncryptedWithOldKey, ValidedEncryptedWithCurrentKey] } diff --git a/enzevalos_iphone/Dialog/DialogOption.swift b/enzevalos_iphone/Dialog/DialogOption.swift index 7a220e3a..ede6f098 100644 --- a/enzevalos_iphone/Dialog/DialogOption.swift +++ b/enzevalos_iphone/Dialog/DialogOption.swift @@ -21,33 +21,6 @@ import UIKit import SwiftUI -protocol Dialog { - var dialogColor: Color { get } - var title: String { get } - var body: String { get } - var img: Image { get } - var ctaButtonTitle: String? { get } - var ctaButtonAction: ButtonAction? { get } - var infoButtonTitle: String? { get } - - var moreButtons: [ButtonStruct] { get } - - var dismissButtonTitle: String? { get } - var dismissButtonAction: ButtonAction? { get } - -} - -struct ButtonStruct { - let titleKey: String - let action: ButtonAction - - var title: String { - get { - return NSLocalizedString(titleKey, comment: "") - } - } -} - struct DialogStruct: Dialog { let dialogColor: Color @@ -69,50 +42,6 @@ struct DialogStruct: Dialog { let dismissButtonAction: ButtonAction? } -enum ButtonAction { - case AskSenderToConfirm, AskSenderToSendPK, AskSenderToResendForPK, InvitePerson, IgnoreMail, AskUserToImportSK, ImportSK, ImportPK, MoreInformation, ExportSK, OK, IgnoreWarning, SendPK - - var title: LocalizedStringKey { - get { - switch self { - case .AskSenderToConfirm: return "Security.Dialog.Button.Title.Confirmation" - case .AskSenderToSendPK: return "Security.Dialog.Button.Title.Ask.ForPK" - case .AskSenderToResendForPK: return "Security.Dialog.Button.Title.Ask.Resend.ForPK" - case .InvitePerson: return "Security.Dialog.Button.Title.Invite" - case .IgnoreMail: return "Security.Dialog.Button.Title.Ignore.Mail" - case .AskUserToImportSK: return "MISSING" - case .ImportSK: return "Security.Dialog.Button.Title.Import.SK" - case .ImportPK: return "MISSING" - case .MoreInformation: return "MoreInformation" - case .ExportSK: return "MISSING" - case .OK: return "Security.Dialog.Button.Title.OK" - case .IgnoreWarning: return "MISSING" - case .SendPK: return "Security.Dialog.Button.Title.Send.PK" - } - } - } - - var color: Color { - get { - let defaultColor = Color.blue - switch self { - case .AskSenderToConfirm: return defaultColor - case .AskSenderToSendPK: return defaultColor - case .AskSenderToResendForPK: return defaultColor - case .InvitePerson: return defaultColor - case .IgnoreMail: return defaultColor - case .AskUserToImportSK: return defaultColor - case .ImportSK: return defaultColor - case .ImportPK: return defaultColor - case .MoreInformation: return defaultColor - case .ExportSK: return defaultColor - case .OK: return defaultColor - case .IgnoreWarning: return defaultColor - case .SendPK: return defaultColor - } - } - } -} enum DialogOption: Dialog { var dialogColor: Color { diff --git a/enzevalos_iphone/SwiftUI/Data/DialogProtocols.swift b/enzevalos_iphone/SwiftUI/Data/DialogProtocols.swift new file mode 100644 index 00000000..cc72f7f2 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Data/DialogProtocols.swift @@ -0,0 +1,88 @@ +// +// DialogProtocols.swift +// enzevalos_iphone +// +// Created by Oliver Wiese on 12.04.20. +// Copyright © 2020 fu-berlin. All rights reserved. +// + +import SwiftUI + +protocol Dialog { + var dialogColor: Color { get } + var title: String { get } + var body: String { get } + var img: Image { get } + var ctaButtonTitle: String? { get } + var ctaButtonAction: ButtonAction? { get } + var infoButtonTitle: String? { get } + + var moreButtons: [ButtonStruct] { get } + + var dismissButtonTitle: String? { get } + var dismissButtonAction: ButtonAction? { get } + +} + + +struct ButtonStruct { + let titleKey: String + let action: ButtonAction + let type: ButtonType + + var title: String { + get { + return NSLocalizedString(titleKey, comment: "") + } + } +} + +enum ButtonType { + case CTA, DISMISS, MORE +} + +enum ButtonAction { + case AskSenderToConfirm, AskSenderToSendPK, AskSenderToResendForPK, InvitePerson, IgnoreMail, AskUserToImportSK, ImportSK, ImportPK, MoreInformation, ExportSK, OK, IgnoreWarning, SendPK + + var title: LocalizedStringKey { + get { + switch self { + case .AskSenderToConfirm: return "Security.Dialog.Button.Title.Confirmation" + case .AskSenderToSendPK: return "Security.Dialog.Button.Title.Ask.ForPK" + case .AskSenderToResendForPK: return "Security.Dialog.Button.Title.Ask.Resend.ForPK" + case .InvitePerson: return "Security.Dialog.Button.Title.Invite" + case .IgnoreMail: return "Security.Dialog.Button.Title.Ignore.Mail" + case .AskUserToImportSK: return "MISSING" + case .ImportSK: return "Security.Dialog.Button.Title.Import.SK" + case .ImportPK: return "MISSING" + case .MoreInformation: return "MoreInformation" + case .ExportSK: return "MISSING" + case .OK: return "Security.Dialog.Button.Title.OK" + case .IgnoreWarning: return "MISSING" + case .SendPK: return "Security.Dialog.Button.Title.Send.PK" + } + } + } + + var color: Color { + get { + let defaultColor = Color.blue + switch self { + case .AskSenderToConfirm: return defaultColor + case .AskSenderToSendPK: return defaultColor + case .AskSenderToResendForPK: return defaultColor + case .InvitePerson: return defaultColor + case .IgnoreMail: return defaultColor + case .AskUserToImportSK: return defaultColor + case .ImportSK: return defaultColor + case .ImportPK: return defaultColor + case .MoreInformation: return defaultColor + case .ExportSK: return defaultColor + case .OK: return defaultColor + case .IgnoreWarning: return defaultColor + case .SendPK: return defaultColor + } + } + } +} + diff --git a/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift b/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift index 616e42fe..85537697 100644 --- a/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift +++ b/enzevalos_iphone/SwiftUI/Data/DisplayProtocols.swift @@ -86,6 +86,8 @@ protocol DisplayMail { var bccs: [C] { get } var routingStops: [Landmark] { get } + var date: Date { get } + var isRead: Bool {get set} var folderType: FolderType { get } @@ -107,8 +109,6 @@ extension DisplayMail { /* TODO: MORE DIALOGS //else if (mail.isNewPubKey) && !(mail.deleteWhileTravel){} // message contained new public key - } - */ var title: String { @@ -181,10 +181,10 @@ extension DisplayMail { bodyKey = "ReceiveInsecureInfoDecryptionFailed" // cta Button -> OK // add -> Import Key - var btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.Import.SK", action: .AskUserToImportSK) + var btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.Import.SK", action: .AskUserToImportSK, type: .MORE) moreButtons.append(btn) // add -> Ask to resend for differnet PK - btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.Ask.Resend.ForPK", action: .AskSenderToResendForPK) + btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.Ask.Resend.ForPK", action: .AskSenderToResendForPK, type: .MORE) moreButtons.append(btn) case (_, .InvalidSignature): @@ -194,7 +194,7 @@ extension DisplayMail { ctaButtonTitleKey = "Security.Dialog.Button.Title.Ignore.Mail" ctaButtonAction = .IgnoreMail // add -> ask sender - let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.Confirmation", action: .AskSenderToConfirm) + let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.Confirmation", action: .AskSenderToConfirm, type: .MORE) moreButtons.append(btn) // dismiss -> Ignore Warning dismissButtonTitleKey = "Security.Dialog.Button.Title.OK" @@ -207,7 +207,7 @@ extension DisplayMail { ctaButtonTitleKey = "Security.Dialog.Button.Title.Invite" ctaButtonAction = .InvitePerson // add -> OK - let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK) + let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK, type: .MORE) moreButtons.append(btn) case (_, .PlainMissingPublicKeyToVerify): @@ -217,7 +217,7 @@ extension DisplayMail { ctaButtonTitleKey = "Security.Dialog.Button.Title.Ask.ForPK" ctaButtonAction = .AskSenderToSendPK // add -> OK - let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK) + let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK, type: .MORE) moreButtons.append(btn) case (_, .PlainButValidSignature): @@ -227,7 +227,7 @@ extension DisplayMail { ctaButtonTitleKey = "Security.Dialog.Button.Title.Send.PK" ctaButtonAction = .SendPK // add -> OK - let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK) + let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK, type: .MORE) moreButtons.append(btn) case (_, .EncNoSignature): @@ -235,7 +235,7 @@ extension DisplayMail { bodyKey = "Information.General.OnlyEncryted" // cta button -> Ask to confirm // add -> OK - let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK) + let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK, type: .MORE) moreButtons.append(btn) case (_, .EncButMissingPublicKeyToVerify): @@ -245,7 +245,7 @@ extension DisplayMail { ctaButtonTitleKey = "Security.Dialog.Button.Title.Ask.ForPK" ctaButtonAction = .AskSenderToSendPK // add -> OK - let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK) + let btn = ButtonStruct(titleKey: "Security.Dialog.Button.Title.OK", action: .OK, type: .MORE) moreButtons.append(btn) } diff --git a/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift b/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift index 770db50a..1ad93f44 100644 --- a/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift +++ b/enzevalos_iphone/SwiftUI/Data/SimulatorData.swift @@ -151,6 +151,8 @@ struct PseuoMail: DisplayMail { var isRead: Bool = false + var date = Date() + var subject: String? = "Hello World" var body: String? = "This is my message." diff --git a/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift index cc9441a1..570a2e2f 100644 --- a/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift +++ b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift @@ -21,7 +21,6 @@ import SwiftUI /* TODOS: * Does Views disappear? - * Add Security indicator */ class ReadViewCoordinator { @@ -30,8 +29,29 @@ class ReadViewCoordinator { private let mainStoryboardName = "Main" private let mainStoryboard: UIStoryboard private var readView: UIViewController? + private var mail: PersistentMail? - + func makeAction(action: ButtonAction) { + guard let mail = mail else { + print("No mail!") + return + } + switch action { + case .AskSenderToConfirm: askSenderToConfirm(mail: mail) + case .AskSenderToSendPK: askSenderToSendPK(mail: mail) + case .AskSenderToResendForPK: askSenderToResendForPK(mail: mail) + case .InvitePerson: invitePerson(mail: mail) + case .IgnoreMail: ignoreMail(mail: mail) + case .AskUserToImportSK: break + case .ImportSK: break + case .ImportPK: break + case .MoreInformation: break + case .ExportSK: break + case .OK: break + case .IgnoreWarning: break + case .SendPK: break + } + } init(root: UINavigationController) { self.root = root @@ -39,6 +59,7 @@ class ReadViewCoordinator { } func pushReadView(mail: PersistentMail){ + self.mail = mail root.isToolbarHidden = true try? AppDelegate.getAppDelegate().mailHandler.startIMAPIdleIfSupported() AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: Folder.inbox, completionCallback: {_ in @@ -94,10 +115,6 @@ class ReadViewCoordinator { } func shareData(_ data:NSData){ - //let shareText = "Hello, world!" - - //let data:NSData = data - let vc = UIActivityViewController(activityItems: [data], applicationActivities: []) root.present(vc, animated: true) } @@ -132,5 +149,97 @@ class ReadViewCoordinator { UIView.animate(withDuration: 0.3, animations: { self.root.navigationBar.barTintColor = c }) } + + /// AskUserToImportSK, ImportSK, ImportPK, MoreInformation, ExportSK, OK, IgnoreWarning, SendPK + func ignoreMail <M: DisplayMail> (mail: M) { + guard let m = mail.persistentMail else { + return + } + delete(mail: m) + } + func invitePerson <M: DisplayMail> (mail: M) { + guard let sender = mail.sender.keyRecord else { + return + } + let body = String(format: NSLocalizedString("inviteText", comment: "Body for the invitation mail"),StudySettings.studyID) + let subject = NSLocalizedString("inviteSubject", comment: "Subject for the invitation mail") + var to = [EnzevalosContact] () + to.append(sender.ezContact) + to.append(contentsOf: findPersisentContact(persons: mail.ccs)) + to.append(contentsOf: findPersisentContact(persons: mail.tos)) + to = to.filter({!$0.hasKey}) + pushComposeView(to: to, cc: [], bcc: [], subject: subject, body: body, responseType: .none) + + } + + func askSenderToResendForPK <M: DisplayMail> (mail: M) { + guard let sender = mail.sender.keyRecord else { + return + } + let to = [sender.contact] + var body = NSLocalizedString("ReadView.PrefilledMail.AskForResend.Body", comment: "") + body += preparePreviousMailBody(mail: mail) + pushComposeView(to: to, cc: [], bcc: [], subject: mail.subject, body: body, responseType: .Reply) + // TODO: Add Public key! + } + + func askSenderToSendPK <M: DisplayMail>(mail: M) { + guard let sender = mail.sender.keyRecord else { + return + } + let to = [sender.contact] + let body = NSLocalizedString("ReadView.PrefilledMail.AskForPK.Body", comment: "") + let subject = NSLocalizedString("ReadView.PrefilledMail.AskForPK.Subject", comment: "") + pushComposeView(to: to, cc: [], bcc: [], subject: subject, body: body, responseType: .none) + } + + func askSenderToConfirm <M: DisplayMail>(mail: M) { + guard let sender = mail.sender.keyRecord else { + return + } + let to = [sender.contact] + let body = NSLocalizedString("didYouSendThis", comment: "Did you sent this mail?") + "\n"+preparePreviousMailBody(mail: mail) + pushComposeView(to: to, cc: [], bcc: [], subject: mail.subject, body: body, responseType: .Reply) + } + + private func preparePreviousMailBody<M: DisplayMail>(mail: M) -> String{ + var body = NSLocalizedString("mail from", comment: "describing who send the mail") + " " + body.append(mail.sender.addr) + let time = DateFormatter.init() + time.dateStyle = .short + time.timeStyle = .short + time.locale = Locale.current + body.append(" " + NSLocalizedString("sent at", comment: "describing when the mail was send") + " " + time.string(from: mail.date)) + body.append("\n" + NSLocalizedString("To", comment: "describing adressee") + ": ") + for addr in mail.tos { + body.append("\(addr.addr), ") + } + if mail.ccs.count > 0 { + body.append("\n\(NSLocalizedString("Cc", comment: "")): ") + for addr in mail.ccs { + body.append("\(addr.addr), ") } + } + body.append("\n" + NSLocalizedString("subject", comment: "describing what subject was choosen") + ": " + (mail.subject ?? "")) + body.append("\n------------------------\n\n" + (mail.body ?? "")) + body = body.components(separatedBy: "\n").map { line in + if line.hasPrefix(">") { + return ">" + line + } + return "> " + line + }.reduce("", { $0 + "\n" + $1 }) + return body + } + + private func findPersisentContact (persons: [DisplayContact]) -> [EnzevalosContact] { + var result = [EnzevalosContact] () + for p in persons { + if let contact = p.keyRecord { + result.append(contact.ezContact) + } + // TODO: Add data handler? + } + return result + } } + diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SecurityBriefingView.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SecurityBriefingView.swift index a8417597..4cd807bd 100644 --- a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SecurityBriefingView.swift +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SecurityBriefingView.swift @@ -19,9 +19,13 @@ struct SecurityBriefingView<M: DisplayMail>: View { title if mail.warnings.count > 0 && showWarning { ForEach(0..<mail.warnings.count) {index in - DialogView(option: self.mail.warnings[index], ctaAction: self.action, additionalAction: self.action, dismissAction: self.action, extend: false) + // DialogView(option: self.mail.warnings[index], ctaAction: self.action, additionalAction: self.action, dismissAction: self.action, extend: false) + WarningView(warning: self.mail.warnings[index]) + // WarningView(title: "Warning", description: "Description!", icon: Image(systemName: "xmark.octagon.fill"), color: Color(ThemeManager.troubleMessageColor())) } + } + confidentiality Divider() authenticity @@ -37,29 +41,27 @@ struct SecurityBriefingView<M: DisplayMail>: View { var title: some View { Text("ReadView.SecurityBriefing.Title") .font(.largeTitle) + .fixedSize(horizontal: false, vertical: true) } var confidentiality: some View { var stateString: LocalizedStringKey - var secure = false switch (mail.encState, mail.transportEnc) { case (.NoEncryption, true): stateString = "ReadView.SecurityBriefing.Conf.State.TransportEnc" case (.NoEncryption, false): stateString = "ReadView.SecurityBriefing.Conf.State.Plain" case (.UnableToDecrypt, _): stateString = "ReadView.SecurityBriefing.Conf.State.UnableToDecrypt" case (.ValidEncryptedWithOldKey, _), (.ValidedEncryptedWithCurrentKey, _): stateString = "ReadView.SecurityBriefing.Conf.State.Encrypted" - secure = true } return InfoView( titleString: "ReadView.SecurityBriefing.Conf.Title", descriptionString: "ReadView.SecurityBriefing.Conf.Description", stateString: stateString, - padding: padding, secure: secure) + padding: padding, rating: mail.encState.rating) } var authenticity: some View { var stateString: LocalizedStringKey - var secure = false switch mail.signedState { case .InvalidSignature: stateString = "ReadView.SecurityBriefing.Auth.State.InvalidSignature" @@ -69,26 +71,26 @@ struct SecurityBriefingView<M: DisplayMail>: View { stateString = "ReadView.SecurityBriefing.Auth.State.MissingPK" case .ValidSignature: stateString = "ReadView.SecurityBriefing.Auth.State.Signed" - secure = true } return InfoView( titleString: "ReadView.SecurityBriefing.Auth.Title", descriptionString: "ReadView.SecurityBriefing.Auth.Description", stateString: stateString, - padding: padding, secure: secure) + padding: padding, rating: mail.signedState.rating) } var actions: some View { - VStack { + VStack (alignment: .leading){ Text("ReadView.SecurityBriefing.Actions.Title") .font(.headline) .padding(padding) - Text("ReadView.SecurityBriefing.Actions.Description" ) + Text("ReadView.SecurityBriefing.Actions.Description") .fontWeight(.light) .padding(padding) - ForEach(0..<mail.buttonActions.count) {index in + .fixedSize(horizontal: false, vertical: true) + ForEach(0..<mail.buttonActions.count) {index in Button(action: { - print("Click!") + self.choseAction(action: self.mail.buttonActions[index]) }, label: { Text(self.mail.buttonActions[index].title) .frame(maxWidth: .infinity, minHeight: 50, maxHeight: 50) @@ -101,6 +103,80 @@ struct SecurityBriefingView<M: DisplayMail>: View { } } } + + func choseAction (action: ButtonAction) { + guard let coord = AppDelegate.getAppDelegate().readViewCoordinator else { + print("No coordinator!") + return + } + coord.makeAction(action: action) + } +} + +struct WarningView: View { + + let title: String + let description: String + let icon: Image + let color: Color + var ctaButton: ButtonStruct? = nil + let moreButtons: [ButtonStruct] + + init(warning: Dialog) { + title = warning.title + description = warning.body + icon = Image(systemName: "xmark.octagon.fill") //warning.img + color = warning.dialogColor + if let ctaTitle = warning.ctaButtonTitle, let ctaAction = warning.ctaButtonAction { + ctaButton = ButtonStruct(titleKey: ctaTitle, action: ctaAction, type: .CTA) + } + moreButtons = warning.moreButtons + + + } + var body: some View { + VStack { + Text(title) + .font(.headline) + .padding(10) + HStack { + icon + .resizable() + .frame(width: 80, height: 80) + .foregroundColor(color) + Text(description) + .fontWeight(.light) + .fixedSize(horizontal: false, vertical: true) + } + + if ctaButton != nil { + Button(action: { + self.choseAction(action: self.ctaButton!.action) + }, label: { + DialogButtonLabel(button: ctaButton!) + }) + } + if moreButtons.count > 0 { + ForEach(0..<moreButtons.count) {i in + Button(action: { + self.choseAction(action: self.moreButtons[i].action) + }, label: { + DialogButtonLabel(button: self.moreButtons[i])}) + } + } + } + .padding(20) + .addBorder(color, width: 3, cornerRadius: 30) + .padding(5) + } + + func choseAction (action: ButtonAction) { + guard let coord = AppDelegate.getAppDelegate().readViewCoordinator else { + print("No coordinator!") + return + } + coord.makeAction(action: action) + } } struct InfoView: View { @@ -108,7 +184,7 @@ struct InfoView: View { let descriptionString: LocalizedStringKey var stateString: LocalizedStringKey var padding: CGFloat - var secure: Bool + var rating: Rating var body: some View { VStack(alignment: .leading) { @@ -119,31 +195,62 @@ struct InfoView: View { // .fontWeight(.light) // .padding(padding) HStack { - if secure { - Image(systemName: "checkmark") - .resizable() - .frame(width: 40, height: 40) - .foregroundColor(Color(ThemeManager.encryptedMessageColor())) - .padding(.leading, padding) - } else { - Image(systemName: "xmark.octagon.fill") - .resizable() - .frame(width: 40, height: 40) - .foregroundColor(Color(ThemeManager.troubleMessageColor())) - .padding(.leading, padding) - } - + icon Text(stateString) .padding(padding) } } } + + var icon: some View { + var image: Image + var color: Color + switch rating { + case .Positiv: + image = Image(systemName: "hand.thumbsup")//"checkmark") + color = Color(ThemeManager.encryptedMessageColor()) + case .Neutral: + image = Image(systemName: "hand.thumbsdown") + color = Color(ThemeManager.unencryptedMessageColor()) + case .Negativ: + image = Image(systemName: "xmark.ocatgon.fill")//"hand.raised") + color = Color(ThemeManager.troubleMessageColor()) + } + image = image.resizable() + let view = image + .frame(width: 40, height: 40) + .padding(.leading, padding) + .foregroundColor(color) + return view + } +} + +struct DialogButtonLabel: View { + let data: ButtonStruct + let color: Color + + init(button: ButtonStruct) { + data = button + switch data.type { + case .CTA: color = .blue + case .DISMISS: color = Color(ThemeManager.troubleMessageColor()) + case .MORE: color = .white + } + } + + var body: some View { + Text(data.titleKey) + .frame(maxWidth: .infinity, minHeight: 20, maxHeight: 20) + .padding(10) + .addBorder(color, width: 1, cornerRadius: 30) + .padding(10) + + } } struct SecurityBriefingView_Previews: PreviewProvider { static var previews: some View { let sim = Simulators<SecurityBriefingView<PseuoMail>>() - return sim.previews(view: SecurityBriefingView(mail: DummyData.MissingPKMail)) - + return sim.previews(view: SecurityBriefingView(mail: DummyData.CorruptedMail)) } } diff --git a/enzevalos_iphone/en.lproj/Localizable.strings b/enzevalos_iphone/en.lproj/Localizable.strings index b082efeb..5b889ab0 100644 --- a/enzevalos_iphone/en.lproj/Localizable.strings +++ b/enzevalos_iphone/en.lproj/Localizable.strings @@ -398,3 +398,6 @@ "ReadView.SecurityBriefing.Auth.State.InvalidSignature" = "This mail has been manipulated! If you want to read it anyway, please be cautions."; "ReadView.SecurityBriefing.Actions.Title" = "Improving the security"; "ReadView.SecurityBriefing.Actions.Description" = "We can improve the security of this email and other emails in the future"; +"ReadView.PrefilledMail.AskForPK.Body" = "Hey, \nI could not verify your last email because I do not have your public key. Can you send me your public key? Thank you and best regards"; +"ReadView.PrefilledMail.AskForPK.Subject" = "Missing your public key"; +"ReadView.PrefilledMail.AskForResend.Body" = "Hey, \nI could not decrypt your last email because I do not have the secret key. Can you resend the email again and encrypt the email for the attachted secret key? Thank you and best regards"; -- GitLab