From 2a2c74ca784c5a9795a5efeee519997be4649ac0 Mon Sep 17 00:00:00 2001
From: Oliver Wiese <oliver.wiese@fu-berlin.de>
Date: Wed, 8 Apr 2020 17:29:30 +0200
Subject: [PATCH] working on user actions after receiving a mail

---
 enzevalos_iphone/Base.lproj/Main.storyboard   | 10 +--
 enzevalos_iphone/CryptoObject.swift           | 44 +++++++++-
 enzevalos_iphone/Dialog/DialogOption.swift    | 21 -----
 .../SwiftUI/Read/ReadMainView.swift           | 85 +++++-------------
 .../SwiftUI/Read/ReadViewCoordinator.swift    |  5 +-
 .../SwiftUI/Read/ReadViewModel.swift          | 17 ++--
 .../Read/Tabbed Views/SenderViewMain.swift    |  2 +-
 .../SwiftUI/SupportingViews/DialogView.swift  | 87 ++++++++-----------
 8 files changed, 126 insertions(+), 145 deletions(-)

diff --git a/enzevalos_iphone/Base.lproj/Main.storyboard b/enzevalos_iphone/Base.lproj/Main.storyboard
index f5182e68..3770628f 100644
--- a/enzevalos_iphone/Base.lproj/Main.storyboard
+++ b/enzevalos_iphone/Base.lproj/Main.storyboard
@@ -1792,7 +1792,7 @@ Um deine sicheren E-Mails auch auf einem anderen Gerät lesen zu können, muss d
                                 <rect key="frame" x="0.0" y="0.0" width="414" height="32"/>
                                 <subviews>
                                     <button opaque="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="w9U-eC-Koh">
-                                        <rect key="frame" x="8" y="-8.3333333333333357" width="30" height="38.333333333333336"/>
+                                        <rect key="frame" x="8" y="-8.3333333333333339" width="30" height="38.333333333333336"/>
                                         <fontDescription key="fontDescription" type="system" weight="heavy" pointSize="21"/>
                                         <state key="normal" title="✕">
                                             <color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@@ -1802,7 +1802,7 @@ Um deine sicheren E-Mails auch auf einem anderen Gerät lesen zu können, muss d
                                         </connections>
                                     </button>
                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" insetsLayoutMarginsFromSafeArea="NO" text="Kontakt verifizieren" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="25l-XT-PFo">
-                                        <rect key="frame" x="116.33333333333333" y="-2.3333333333333357" width="181.66666666666669" height="26.333333333333336"/>
+                                        <rect key="frame" x="116.33333333333333" y="-2.3333333333333339" width="181.66666666666669" height="26.333333333333336"/>
                                         <fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
                                         <color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                                         <nil key="highlightedColor"/>
@@ -2221,9 +2221,9 @@ Um deine sicheren E-Mails auch auf einem anderen Gerät lesen zu können, muss d
         </scene>
     </scenes>
     <inferredMetricsTieBreakers>
-        <segue reference="3Wb-uL-BB5"/>
-        <segue reference="td8-VW-Wrt"/>
-        <segue reference="DcR-GX-scc"/>
+        <segue reference="rhW-cI-4c4"/>
+        <segue reference="hSn-Um-hji"/>
+        <segue reference="btx-4o-o0r"/>
         <segue reference="TgN-rB-esa"/>
         <segue reference="Fv4-FT-5gV"/>
         <segue reference="ecN-Wn-7S0"/>
diff --git a/enzevalos_iphone/CryptoObject.swift b/enzevalos_iphone/CryptoObject.swift
index 6a3d2964..9a2a0cad 100644
--- a/enzevalos_iphone/CryptoObject.swift
+++ b/enzevalos_iphone/CryptoObject.swift
@@ -15,7 +15,12 @@ struct SecurityState <M: DisplayMail> {
     
     let mail: M
         
-    // TODO: Handling new key attack
+    /* TODO: MORE DIALOGS
+       //else if (mail.isNewPubKey) && !(mail.deleteWhileTravel){}
+           // message contained new public key
+       }
+       
+    */
     
     var title: String {
         get {
@@ -47,6 +52,19 @@ struct SecurityState <M: DisplayMail> {
         }
     }
     
+    var titleIcon: UIImage {
+        get {
+            switch evaluateSecurity() {
+            case (_, .EncValidSign):
+                return StudySettings.securityIndicator.imageOfSecureIndicator()
+            case (_, .UnableToDecrypt), (_, .InvalidSignature):
+                return StudySettings.securityIndicator.imageOfCorruptedIndicator()
+            case (_, .NoCrypto), (_, .PlainMissingPublicKeyToVerify), (_, .PlainButValidSignature), (_, .EncNoSignature), (_, .EncButMissingPublicKeyToVerify):
+                return StudySettings.securityIndicator.imageOfInsecureIndicator()
+            }
+        }
+    }
+    
     var dialog: DialogStruct {
         get {
             // TODO: Do we add new public key stuff?
@@ -154,7 +172,29 @@ struct SecurityState <M: DisplayMail> {
     
     var warnings: [DialogStruct] {
         get {
-            return []
+            var result = [DialogStruct] ()
+            switch evaluateSecurity() {
+                case (_, .EncValidSign), (_, .NoCrypto), (_, .PlainButValidSignature), (_, .EncNoSignature):
+                    break // No warning required
+                case (_, .UnableToDecrypt), (_, .InvalidSignature) , (_, .PlainMissingPublicKeyToVerify), (_, .EncButMissingPublicKeyToVerify):
+                    result.append(dialog) // warning required
+            }
+            if mail.sender.keys.count > 0 && mail.signedState == .NoSignature  {
+                let icon = Image(systemName: "exclamationmark.triangl.fill")
+                let missingSignature = DialogStruct(dialogColor: Color(ThemeManager.unencryptedMessageColor()),
+                                                    title: NSLocalizedString("encryptedBeforeHeadline",
+                                                    comment: "encrypted by sender before"),
+                                                    body: NSLocalizedString("encryptedBeforeText", comment: "encrypted by sender before"),
+                                                    img: icon, messageImage: icon,
+                                                    ctaButtonTitle: NSLocalizedString("Security.Dialog.Button.Title.Confirmation", comment: ""),
+                                                    ctaButtonAction: .AskSenderToConfirm,
+                                                    infoButtonTitle: NSLocalizedString("Security.Dialog.Button.Title.MoreInfo", comment: ""),
+                                                    moreButtons: [],
+                                                    dismissButtonTitle: NSLocalizedString("Security.Dialog.Button.Title.OK", comment: ""),
+                                                    dismissButtonAction: .IgnoreWarning)
+                result.append(missingSignature)
+            }
+            return result
         }
     }
     
diff --git a/enzevalos_iphone/Dialog/DialogOption.swift b/enzevalos_iphone/Dialog/DialogOption.swift
index 0ff9b70d..e6b13a20 100644
--- a/enzevalos_iphone/Dialog/DialogOption.swift
+++ b/enzevalos_iphone/Dialog/DialogOption.swift
@@ -21,27 +21,6 @@
 import UIKit
 import SwiftUI
 
-/* TODO: MORE DIALOGS
-     
-   //else if (mail.isNewPubKey) && !(mail.deleteWhileTravel){}
-       // message contained new public key
-   else if mail.from.hasKey && !mail.isSecure{
-       Text(NSLocalizedString("encryptedBeforeHeadline", comment: "encrypted by sender before"))
-           .font(.system(size: 25))
-           .frame(maxWidth: .infinity)
-           .background(Color.yellow)
-       HStack{
-           Text("?")
-           .foregroundColor(Color.orange)
-           .font(.system(size: 60))
-           .padding([.leading, .top, .bottom])
-           Text(NSLocalizedString("encryptedBeforeText", comment: "encrypted by sender before"))
-           .padding()
-       }
-   }
-   
-*/
-
 protocol Dialog {
     var dialogColor: Color { get }
     var title: String { get }
diff --git a/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift b/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift
index b8be6ac8..a3b03991 100644
--- a/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift
+++ b/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift
@@ -21,30 +21,19 @@ struct ReadMainView <M: DisplayMail>: View {
     
     public var mail: M
         
-    @State private var currentScreen: Int = 1 //doesnt work
-    
-    @State private var isSecIndExpanded:Bool = false
+    @State private var isSecIndExpanded = false
     
     var body: some View {
-        //TODO: put into zstack instead
-        VStack(spacing:0){
-            //SecIndicator //TODO: Why the hell does expanding it reset the whole tabview
-            TabView{
-                ForEach(Tabs, id: \.id ){ tab in
-                    tab.content
-                        .tabItem {
-                            tab.image
-                            Text(tab.description)
-                    }
+        TabView{
+            ForEach(Tabs, id: \.id ){ tab in
+                tab.content
+                    .tabItem {
+                        tab.image
+                        Text(tab.description)
                 }
             }
-            .animation(.easeInOut(duration: 0.4))
         }
-       // .navigationBarTitle(Text((mail.trouble ? "❌" :( mail.isSecure ? "🔒" : "👀" )) + " " + (mail.subject ?? ""))
-      //  , displayMode: .inline) //TODO: make smooth or find better solution
         .navigationBarItems(trailing: moreInfoButton)
-        //.onAppear(perform: self.coord.setup)
-        //.onDisappear(perform: self.coord.reset)
     }
     
     //TODO: not use AnyView-workaround
@@ -71,53 +60,27 @@ struct ReadMainView <M: DisplayMail>: View {
     }
     
     var moreInfoButton: some View{
-        return Button(action: {self.isSecIndExpanded.toggle()}){
+       /* NavigationLink(destination: DialogView(option: SecurityState(mail: mail).dialog, ctaAction: nil, additionalAction: nil, dismissAction: nil), label: {
             Image(systemName: isSecIndExpanded ? "arrow.up.circle" : "info.circle")
-        }
-    }
-    /*
-    //securityIndicator
-    var SecIndicator:some View{
-        get{
-            
-            if mail.trouble{
-                
-                return AnyView(SecInd(secNum:1,isExpanded: $isSecIndExpanded, color:Color(ThemeManager.troubleMessageColor())))
-
-            }else if mail.isSecure{
-                
-                return AnyView(VStack{
-                    SecInd(secNum:2,isExpanded: $isSecIndExpanded,color:Color(ThemeManager.encryptedMessageColor()))
-                    //TODO: Design and test
-                    Button(action: {
-                        self.coord.pushExportKeyView()
-                        //let duration = Date().timeIntervalSince(opening)
-                        //Logger.log(close: icon, mail: m, action: .exportKey, duration: duration)
-                        //self.performSegue(withIdentifier: "exportKeyFromReadView", sender: nil)
-                    }){
-                        Text(NSLocalizedString("ReadMailOnOtherDevice", comment: "email is not readable on other devices"))
-                    }
-                })
-            }
-            
-            //special subcases of unsecure mail
-            else if mail.isCorrectlySigned {
-                 return AnyView(SecInd(secNum:4,isExpanded: $isSecIndExpanded,color:Color(ThemeManager.unencryptedMessageColor())))
-            } else if mail.isEncrypted && !mail.unableToDecrypt {
-                 return AnyView(SecInd(secNum:5,isExpanded: $isSecIndExpanded,color:Color(ThemeManager.unencryptedMessageColor())))
-            } else if mail.isEncrypted && mail.unableToDecrypt {
-                 return AnyView(SecInd(secNum:6,isExpanded: $isSecIndExpanded,color:Color(ThemeManager.unencryptedMessageColor())))
-            }
-            
+            })
+        .isDetailLink(false)*/
+        Button(action: {
+            self.isSecIndExpanded.toggle()
             
-            else{
-                
-                return AnyView(SecInd(secNum:3,isExpanded: $isSecIndExpanded,color:Color(ThemeManager.unencryptedMessageColor())))
-
-            }
+        }){
+            Image(systemName: isSecIndExpanded ? "arrow.up.circle" : "info.circle")
         }
     }
- */
+    var naviTitle: String {
+        return mail.subject ?? ""
+    }
+    
+    var detailInfo: some View {
+        let dialog = SecurityState(mail: mail).dialog
+        return DialogView(option: dialog, ctaAction: {
+            self.isSecIndExpanded = false
+        }, additionalAction: nil, dismissAction: nil)
+    }
 }
 
 
diff --git a/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift
index 487bb441..4a350010 100644
--- a/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift
+++ b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift
@@ -43,9 +43,12 @@ class ReadViewCoordinator {
         try? AppDelegate.getAppDelegate().mailHandler.startIMAPIdleIfSupported()
         AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: Folder.inbox, completionCallback: {_ in
         })
-        
+        let secState = SecurityState.init(mail: mail)
+        let icon = secState.titleIcon
+        let view = UIImageView(image: icon)
         let vc = UIHostingController(rootView: ReadMainView(mail: mail))
         readView = vc
+        vc.navigationItem.titleView = view
         root.pushViewController(vc, animated: true)
     }
     
diff --git a/enzevalos_iphone/SwiftUI/Read/ReadViewModel.swift b/enzevalos_iphone/SwiftUI/Read/ReadViewModel.swift
index d0ad4135..6053b8ab 100644
--- a/enzevalos_iphone/SwiftUI/Read/ReadViewModel.swift
+++ b/enzevalos_iphone/SwiftUI/Read/ReadViewModel.swift
@@ -36,7 +36,7 @@ let bob = PseudoContact(name: "Bob", addr: "Bob.lord.of.kingsbridge.and.king.of.
      Landmark(name: "New York", domain: "secondexampledomain.de", location: .init(latitude: 40.730610, longitude: -73.935242)),
      Landmark(name: "Sydney", domain: "thirdexampledomain.de", location: .init(latitude: -33.865143, longitude: 151.209900))
  ]
-let mail = PseuoMail(folderType: .Inbox, sender: alice,  tos: [bob,charlie], ccs: [bob, charlie,bob, charlie,bob], bccs: [], routingStops: landmarks, signedState: .ValidSignature, encState: .ValidedEncryptedWithCurrentKey)
+let mail = PseuoMail(folderType: .Inbox, sender: alice,  tos: [bob,charlie], ccs: [bob, charlie,bob, charlie,bob], bccs: [], routingStops: landmarks, signedState: SignatureState.NoSignature, encState: .ValidedEncryptedWithCurrentKey)
 
 protocol DisplayAttachment {
     var myName: String { get }
@@ -65,6 +65,7 @@ protocol DisplayContact {
 
 protocol DisplayMail {
     associatedtype C: DisplayContact
+    associatedtype D: Dialog
     
     var subject: String? { get }
     var sender: C { get }
@@ -83,7 +84,7 @@ protocol DisplayMail {
     var signedState: SignatureState { get }
     var encState: EncryptionState { get }
     
-    var warnings: [DialogOption] { get }
+    var warnings: [D] { get }
     
     var persistentMail: PersistentMail? { get }
     
@@ -129,7 +130,7 @@ struct PseudoContact: DisplayContact {
     
     var otherAddresses: [String] = []
     
-    var keys: [String] = []
+    var keys: [String] = ["ABC"]
     
     var hasPreviousMails: Bool = false
     
@@ -189,6 +190,9 @@ struct PseudoContact: DisplayContact {
 }
 
 struct PseuoMail: DisplayMail {
+    typealias U = PseudoContact
+    typealias D = DialogStruct
+
     var displayAttachments: [DisplayAttachment] = []
         
     func markAsRead(isRead: Bool) {
@@ -200,9 +204,12 @@ struct PseuoMail: DisplayMail {
     var isRead: Bool = false
     
     
-    var warnings: [DialogOption] = [DialogOption.corrupted, DialogOption.postcard]
+    var warnings: [D] {
+        get {
+            return SecurityState.init(mail: self).warnings
+        }
+    }
     
-    typealias U = PseudoContact
     
     var subject: String? = "Hello World"
     
diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewMain.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewMain.swift
index 72d9d5e6..f711db6b 100644
--- a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewMain.swift	
+++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewMain.swift	
@@ -78,7 +78,7 @@ struct SenderViewMain <M: DisplayMail>: View {
             .padding(.bottom, -110/2)
             .onTapGesture {
                 self.goToContact(contact: self.mail.sender)
-            }
+        }
     }
     
     private var sender: some View {
diff --git a/enzevalos_iphone/SwiftUI/SupportingViews/DialogView.swift b/enzevalos_iphone/SwiftUI/SupportingViews/DialogView.swift
index 2c93e4ed..9149d513 100644
--- a/enzevalos_iphone/SwiftUI/SupportingViews/DialogView.swift
+++ b/enzevalos_iphone/SwiftUI/SupportingViews/DialogView.swift
@@ -8,9 +8,9 @@
 
 import SwiftUI
 
-struct DialogView : View {
+struct DialogView <D: Dialog> : View {
 
-    let option: DialogOption
+    let option: D
     var ctaAction: (() -> Void)?
     var additionalAction: (() -> Void)?
     var dismissAction: (() -> Void)?
@@ -21,67 +21,55 @@ struct DialogView : View {
     var body: some View {
         simpleUI
     }
-    
-    var alternativeUI: some View {
-        VStack {
-            Text(option.title)
-            .font(.largeTitle)
-            .frame(maxWidth: .infinity, maxHeight: 100)
-            .cornerRadius(20)
-                .background(color)
-            .border(Color.red, width: 2)
-            if option.messageImage != nil {
-                CircleImage(image: option.messageImage!, radius: 60)
-                 .foregroundColor(Color(option.color))
-                .background(Color(.white))
-                .padding(10)
-            }
-        }
-    .padding(10)
-    }
-   
+      
     var simpleUI: some View {
          VStack {
             Text(option.title)
-                .font(.largeTitle)
+                .font(.headline)
+                .lineLimit(3)
                 .frame(maxWidth: .infinity)
-                .padding(.bottom, 20)
-                .addBorder(Color(option.color), width: 2, cornerRadius: 30)
+                .padding(.vertical, 20)
+                .addBorder(option.dialogColor, width: 2, cornerRadius: 30)
             HStack{
-                if option.messageImage != nil {
-                    option.messageImage!
-                        .resizable()
-                        .frame(width: 60, height: 60)
-                     .foregroundColor(Color(option.color))
-                        .padding(.trailing, 20)
-                }
-                Text(option.message)
+                option.img
+                    .resizable()
+                    .frame(width: 60, height: 60)
+                    .foregroundColor(option.dialogColor)
+                    .padding(.trailing, 20)
+                Text(option.body)
                     .fontWeight(.light)
+                    .font(.body)
+                .lineLimit(10)
+                .fixedSize(horizontal: false, vertical: true)
             }
             .padding(20)
             if option.ctaButtonTitle != nil && ctaAction != nil {
                 Button(action: ctaAction!) {
                     Text(option.ctaButtonTitle!)
-                        .frame(maxWidth: .infinity,maxHeight: 50)
-                        .background(RoundedCorners(color: Color(option.color), radius: 30))
+                        .frame(maxWidth: .infinity, minHeight: 50, maxHeight: 50)
+                        .background(RoundedCorners(color: .white, radius: 30))
                         .padding(.vertical, 10)
                         .padding(.horizontal, 20)
                 }
             }
-            if option.additionActionButtonTitle != nil && additionalAction != nil {
-                Button(action: additionalAction!) {
-                    Text(option.additionActionButtonTitle!)
-                       .frame(maxWidth: .infinity,maxHeight: 50)
-                       .background(RoundedCorners(color: color, radius: 30))
-                       .padding(.vertical, 10)
-                       .padding(.horizontal, 20)
-                }
+            ForEach(0..<option.moreButtons.count) { index in
+                Button(action: {
+                    if let action = self.additionalAction {
+                        action()
+                    }
+                }) {
+                    Text(self.option.moreButtons[index].title)
+                      .frame(maxWidth: .infinity,  minHeight: 50, maxHeight: 50)
+                        .background(RoundedCorners(color: self.color, radius: 30))
+                      .padding(.vertical, 10)
+                      .padding(.horizontal, 20)
+               }
             }
             if option.dismissButtonTitle != nil && dismissAction != nil {
                Button(action: dismissAction!) {
                    Text(option.dismissButtonTitle!)
                     .foregroundColor(.red)
-                      .frame(maxWidth: .infinity,maxHeight: 50)
+                      .frame(maxWidth: .infinity, minHeight: 50, maxHeight: 50)
                       .background(RoundedCorners(color: color, radius: 30))
                       .padding(.vertical, 10)
                       .padding(.horizontal, 20)
@@ -93,21 +81,22 @@ struct DialogView : View {
     }
 
 }
-/*
+
 struct DialogView_Previews: PreviewProvider {
+    static let options  = SecurityState.init(mail: mail)
     static var previews: some View {
         VStack{
-            DialogView(option: .postcard, ctaAction: action, additionalAction: action, dismissAction: action)
-            DialogView(option: .corrupted, ctaAction: action)
-
-            } .padding(20)
+            DialogView(option: options.dialog, ctaAction: action, additionalAction: action, dismissAction: action)
+            //DialogView(option: DialogOption.corrupted, ctaAction: action, additionalAction: action, dismissAction: action)
+           // DialogView(option: DialogOption.couldNotDecrypt, ctaAction: action, additionalAction: action, dismissAction: action)
+        }
     }
     
     static func action() {
         print("Button click!")
     }
 }
- */
+ 
 
 extension View {
     public func addBorder<S>(_ content: S, width: CGFloat = 1, cornerRadius: CGFloat) -> some View where S : ShapeStyle {
-- 
GitLab