Commit dc93fb51 authored by Oliver Wiese's avatar Oliver Wiese

add dialogView and improve message read view

parent e8599065
......@@ -145,7 +145,7 @@
47C22281218AFD6300BD2C2B /* AutocryptTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C22280218AFD6300BD2C2B /* AutocryptTest.swift */; };
47C22283218B02C700BD2C2B /* autocryptSimpleExample1.eml in Resources */ = {isa = PBXBuildFile; fileRef = 47C22282218B02C700BD2C2B /* autocryptSimpleExample1.eml */; };
47C8225324379EAE005BCE73 /* AttachmentsViewMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224324379EAE005BCE73 /* AttachmentsViewMain.swift */; };
47C8225724379EAE005BCE73 /* Warning_MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224924379EAE005BCE73 /* Warning_MessageView.swift */; };
47C8225724379EAE005BCE73 /* DialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224924379EAE005BCE73 /* DialogView.swift */; };
47C8225824379EAE005BCE73 /* FloatingActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224A24379EAE005BCE73 /* FloatingActionButton.swift */; };
47C8225924379EAE005BCE73 /* AttPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224C24379EAE005BCE73 /* AttPreview.swift */; };
47C8225A24379EAE005BCE73 /* CardWithTitle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224D24379EAE005BCE73 /* CardWithTitle.swift */; };
......@@ -592,7 +592,7 @@
47C22280218AFD6300BD2C2B /* AutocryptTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutocryptTest.swift; sourceTree = "<group>"; };
47C22282218B02C700BD2C2B /* autocryptSimpleExample1.eml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = autocryptSimpleExample1.eml; sourceTree = "<group>"; };
47C8224324379EAE005BCE73 /* AttachmentsViewMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttachmentsViewMain.swift; sourceTree = "<group>"; };
47C8224924379EAE005BCE73 /* Warning_MessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Warning_MessageView.swift; sourceTree = "<group>"; };
47C8224924379EAE005BCE73 /* DialogView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DialogView.swift; sourceTree = "<group>"; };
47C8224A24379EAE005BCE73 /* FloatingActionButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FloatingActionButton.swift; sourceTree = "<group>"; };
47C8224C24379EAE005BCE73 /* AttPreview.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AttPreview.swift; sourceTree = "<group>"; };
47C8224D24379EAE005BCE73 /* CardWithTitle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CardWithTitle.swift; sourceTree = "<group>"; };
......@@ -1259,8 +1259,6 @@
children = (
47C8224224379EAE005BCE73 /* Tabbed Views */,
47C8225124379EAE005BCE73 /* ReadViewCoordinator.swift */,
47C8226A2438A86A005BCE73 /* SenderViewMain.swift */,
47C8224324379EAE005BCE73 /* AttachmentsViewMain.swift */,
47C8225224379EAE005BCE73 /* ReadMainView.swift */,
47C8226C2438C2CF005BCE73 /* ReadViewModel.swift */,
);
......@@ -1270,10 +1268,12 @@
47C8224224379EAE005BCE73 /* Tabbed Views */ = {
isa = PBXGroup;
children = (
47C8224E24379EAE005BCE73 /* MessageViewMain.swift */,
47C8226A2438A86A005BCE73 /* SenderViewMain.swift */,
47C8224324379EAE005BCE73 /* AttachmentsViewMain.swift */,
47C822632438A84C005BCE73 /* SenderViewChildren */,
47C8224824379EAE005BCE73 /* MessageViewChildren */,
47C8224B24379EAE005BCE73 /* AttachmentChildren */,
47C8224E24379EAE005BCE73 /* MessageViewMain.swift */,
);
path = "Tabbed Views";
sourceTree = "<group>";
......@@ -1281,7 +1281,7 @@
47C8224824379EAE005BCE73 /* MessageViewChildren */ = {
isa = PBXGroup;
children = (
47C8224924379EAE005BCE73 /* Warning_MessageView.swift */,
47C8224924379EAE005BCE73 /* DialogView.swift */,
47C8224A24379EAE005BCE73 /* FloatingActionButton.swift */,
);
path = MessageViewChildren;
......@@ -2387,7 +2387,7 @@
F1984D741E1E92B300804E1E /* LabelStyleKit.swift in Sources */,
A1FA44A721E10E1400DB02AC /* TravelHandler.swift in Sources */,
47E7376E22845EC400972401 /* SecretKeyTableViewController.swift in Sources */,
47C8225724379EAE005BCE73 /* Warning_MessageView.swift in Sources */,
47C8225724379EAE005BCE73 /* DialogView.swift in Sources */,
478154A721FF3F0900A931EC /* Warning.swift in Sources */,
4764069F2416B5A600C7D426 /* NewOnboardingView.swift in Sources */,
0EF73F4324237E6500932FA0 /* SMIMEHelpers.swift in Sources */,
......
......@@ -19,6 +19,75 @@
//
import UIKit
import SwiftUI
/* TODO: MORE DIALOGS
if mail.trouble{
Text(NSLocalizedString("corruptedHeadline", comment: "corrupted mail"))
.font(.system(size: 25))
.frame(maxWidth: .infinity)
.background(Color.yellow)
HStack{
Text("!")
.foregroundColor(Color.red)
.font(.system(size: 60))
.padding([.leading, .top, .bottom])
Text(NSLocalizedString("corruptedText", comment: "corrupted mail"))
.padding()
}
}
else if mail.isEncrypted && mail.unableToDecrypt{
if TravelHandler.instance().mode != .atHome{
Text(NSLocalizedString("couldNotDecryptTravelHeadline", comment: "couldn't decrypt message"))
.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("couldNotDecryptTravelText", comment: "couldn't decrypt message"))
.padding()
}
}
else {
Text(NSLocalizedString("couldNotDecryptHeadline", comment: "couldn't decrypt message"))
.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("couldNotDecryptText", comment: "couldn't decrypt message"))
.padding()
}
}
}
//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()
}
}
//else if mail.deleteWhileTravel{}
// message not readable while traveling
}.background(Color(UIColor.systemGray5)).padding()
}
*/
enum DialogOption {
......@@ -28,17 +97,63 @@ enum DialogOption {
case invitationStep
case invitationHelp
case travelInfo
case corrupted
case couldNotDecrypt
case couldNotDecryptTravel
case encryptedBefore
var color: UIColor {
switch self {
case .postcard : return .yellow
case .postcard : return ThemeManager.unencryptedMessageColor()
case .invitationCode : return UIColor.Invitation.orange
case .invitationWelcome : return UIColor.Invitation.orange
case .invitationStep : return UIColor.Invitation.orange
case .invitationHelp : return UIColor.Invitation.orange
case .travelInfo : return UIColor.Invitation.orange
case .corrupted : return ThemeManager.troubleMessageColor()
case .couldNotDecrypt : return ThemeManager.unencryptedMessageColor()
case .couldNotDecryptTravel : return ThemeManager.unencryptedMessageColor()
case .encryptedBefore : return ThemeManager.unencryptedMessageColor()
}
}
var messageImage: Image? {
switch self {
case .postcard : return nil
case .invitationCode : return nil
case .invitationWelcome, .invitationHelp :
switch StudySettings.invitationsmode {
case .Censorship:
var images = [UIImage]()
if let sender = UIImage(named: "bg_inviation_censor_sender"), let receiver = UIImage(named: "bg_inviation_censor_receiver") {
images.append(sender)
images.append(receiver)
if let img = UIImage.animatedImage(with: images, duration: 4) {
return Image(uiImage: img)
}
}
return nil
case .PasswordEnc:
if let img = UIImage(named: "bg_inviation"){
return Image(uiImage: img)
}
return nil
case .FreeText,
.InviteMail:
if let img = UIImage(named: "postcard") {
return Image(uiImage: img)
}
return nil
}
case .invitationStep : return nil
case .travelInfo : return nil
case .corrupted : return Image(systemName: "exclamationmark.triangle.fill")
case .couldNotDecrypt : return nil
case .couldNotDecryptTravel : return nil
case .encryptedBefore : return nil
}
}
var titleImage: UIImage? {
switch self {
......@@ -62,6 +177,14 @@ enum DialogOption {
}
case .invitationStep : return nil
case .travelInfo : return nil
case .corrupted :
let icon = UIImage(systemName: "exclamationmark.triangle.fill")?
.tint(color: self.color)
return icon
case .couldNotDecrypt : return nil
case .couldNotDecryptTravel : return nil
case .encryptedBefore : return nil
}
}
......@@ -73,23 +196,33 @@ enum DialogOption {
.invitationHelp : return nil
case .invitationStep : return UIImage(named: "ic_secure_card")
case .travelInfo : return TravelHandler.planeIcon
case .corrupted : return nil
case .couldNotDecrypt : return nil
case .couldNotDecryptTravel : return nil
case .encryptedBefore : return nil
}
}
var title: String? {
var title: String {
switch self {
case .postcard : return "Welcome"
case .postcard : return NSLocalizedString("Postcard", comment: "")
case .invitationCode : return NSLocalizedString("Invitation.Code.Title", comment: "")
case .invitationWelcome,
.invitationHelp : return NSLocalizedString("Invitation.Welcome.Title", comment: "")
case .invitationStep : return NSLocalizedString("Invitation.Step.Title", comment: "")
case .travelInfo : return NSLocalizedString("TravelInfo.Title", comment: "")
case .corrupted : return NSLocalizedString("corruptedHeadline", comment: "corrupted mail")
case .couldNotDecrypt : return NSLocalizedString("couldNotDecryptHeadline", comment: "couldn't decrypt message")
case .couldNotDecryptTravel : return NSLocalizedString("couldNotDecryptTravelHeadline", comment: "couldn't decrypt message")
case .encryptedBefore : return NSLocalizedString("encryptedBeforeHeadline", comment: "encrypted by sender before")
}
}
var message: String? {
var message: String {
switch self {
case .postcard : return "Message\nMultiline and long texts are allowed, btw second button is hidden"
case .postcard : return NSLocalizedString("ReceiveInsecureInfo", comment: "")
case .invitationWelcome,
.invitationHelp :
switch StudySettings.invitationsmode {
......@@ -109,6 +242,10 @@ enum DialogOption {
}
return String(format: NSLocalizedString("Invitation.Code.Message", comment: ""), code)
case .travelInfo : return NSLocalizedString("TravelInfo.Message", comment: "")
case .corrupted : return NSLocalizedString("corruptedText", comment: "corrupted mail")
case .couldNotDecrypt : return NSLocalizedString("couldNotDecryptText", comment: "couldn't decrypt message")
case .couldNotDecryptTravel : return NSLocalizedString("couldNotDecryptTravelText", comment: "couldn't decrypt message")
case .encryptedBefore : return NSLocalizedString("encryptedBeforeText", comment: "encrypted by sender before")
}
}
......@@ -126,6 +263,10 @@ enum DialogOption {
case .invitationStep : return NSLocalizedString("Invitation.Step.CTA", comment: "")
case .invitationHelp : return NSLocalizedString("Done", comment: "")
case .travelInfo : return NSLocalizedString("TravelInfo.Remember", comment: "")
case .corrupted : return nil
case .couldNotDecrypt : return nil
case .couldNotDecryptTravel : return nil
case .encryptedBefore : return nil
}
}
......@@ -137,6 +278,10 @@ enum DialogOption {
case .invitationStep : return nil
case .invitationHelp : return nil
case .travelInfo : return NSLocalizedString("MoreInformation", comment: "")
case .corrupted : return nil
case .couldNotDecrypt : return nil
case .couldNotDecryptTravel : return nil
case .encryptedBefore : return nil
}
}
......@@ -148,6 +293,11 @@ enum DialogOption {
case .invitationStep : return NSLocalizedString("Invitation.Step.Undo", comment: "")
case .invitationHelp : return nil
case .travelInfo : return NSLocalizedString("OK", comment: "")
case .corrupted : return nil
case .couldNotDecrypt : return nil
case .couldNotDecryptTravel : return nil
case .encryptedBefore : return nil
}
}
}
......@@ -86,9 +86,7 @@ extension DialogViewController {
}
func layout(for option: DialogOption) {
self.titleLabel?.isHidden = (option.title == nil)
self.titleLabel?.text = option.title
self.messageLabel?.isHidden = (option.message == nil)
self.messageLabel?.text = option.message
self.ctaButton?.isHidden = (option.ctaButtonTitle == nil)
self.ctaButton?.setTitle(option.ctaButtonTitle, for: .normal)
......
......@@ -450,5 +450,24 @@ extension PersistentMail: DisplayMail {
return self
}
var folderType: FolderType {
return .Other // TODO FIX
}
var warnings: [DialogOption] {
var result = [DialogOption]()
if self.unableToDecrypt {
result.append(.couldNotDecrypt)
}
else if self.trouble {
result.append(.corrupted)
}
return result
}
func markAsRead(isRead: Bool) {
self.isRead = isRead
}
}
......@@ -61,7 +61,7 @@ struct ReadMainView: View {
Tab(
image: Image(systemName: "text.bubble.fill"),
description: "message",
content: AnyView(MessageViewMain(coord: coord, mail: mail))
content: AnyView(MessageViewMain<PersistentMail>(mail: mail))
),
Tab(
image: Image(systemName: "rectangle.and.paperclip"),
......
......@@ -62,10 +62,15 @@ class ReadViewCoordinator {
AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendArchiveFolderPath)
}
func pushComposeView() {
func pushComposeView(to: [EnzevalosContact], cc: [EnzevalosContact], bcc: [EnzevalosContact], subject: String?, body: String?, responseType: ResponseType?) {
let vc = mainStoryboard.instantiateViewController(identifier: ViewID.ComposeView.rawValue)
var prefilledMail: EphemeralMail?
if let subject = subject, let body = body, let responseType = responseType {
prefilledMail = EphemeralMail(to: NSSet(object: to), cc: NSSet(object: cc), bcc: NSSet(object: bcc), date: Date(), subject: responseType.addPrefix(subject: subject), body: body, uid: 0, predecessor: nil)
}
if let vc = vc as? SendViewController {
vc.wasPushed = true
vc.prefilledMail = prefilledMail
}
root.isToolbarHidden = false
root.pushViewController(vc, animated: true)
......
......@@ -9,15 +9,36 @@
import Foundation
import SwiftUI
enum FolderType {
case Archive, Trash, Inbox, Sent, Draft, Other
}
enum ResponseType {
case Reply, Forward, Draft
func addPrefix(subject: String) -> String {
switch self {
case .Reply:
return "Re: " + subject
case .Forward:
return "Fwd: " + subject
case .Draft:
return subject
}
}
}
let alice = PseudoContact(name: "Alice", addr: "alice@example.com", myImage: PseudoContact.makeImg("Alice", color: .blue))
let bob = PseudoContact(name: "Bob", addr: "Bob.lord.of.kingsbridge.and.king.of.england@huge.subdomain.with. a.long.long.long.domain.example.com", myImage: PseudoContact.makeImg("Bob", color: .red))
let bob = PseudoContact(name: "Bob", addr: "Bob.lord.of.kingsbridge.and.king.of.england@huge.subdomain.with. a.long.long.long.domain.example.com", myImage: PseudoContact.makeImg("Bob", color: .red))
let charlie = PseudoContact(name: "Charlie", addr: "charlie@example.com", myImage: PseudoContact.makeImg("Charlie", color: .green))
let landmarks = [
Landmark(name: "Berlin", domain: "exampledomain.de", location: .init(latitude: 52.520008, longitude: 13.404954)),
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(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: .ValidSignature, encState: .ValidedEncryptedWithCurrentKey)
protocol DisplayContact {
// General
......@@ -39,7 +60,6 @@ protocol DisplayContact {
var keyRecord: KeyRecord? { get }
}
protocol DisplayMail {
associatedtype C: DisplayContact
......@@ -51,11 +71,20 @@ protocol DisplayMail {
var bccs: [C] { get }
var routingStops: [Landmark] { get }
var isRead: Bool {get set}
var folderType: FolderType { get }
// Crypto
var signedState: SignatureState { get }
var encState: EncryptionState { get }
var warnings: [DialogOption] { get }
var persistentMail: PersistentMail? { get }
func markAsRead(isRead: Bool)
}
class ReadViewModel: ObservableObject {
......@@ -155,6 +184,17 @@ struct PseudoContact: DisplayContact {
}
struct PseuoMail: DisplayMail {
func markAsRead(isRead: Bool) {
print("Mail is marked as read: \(isRead)")
}
var folderType: FolderType
var isRead: Bool = false
var warnings: [DialogOption] = [DialogOption.corrupted, DialogOption.postcard]
typealias U = PseudoContact
var subject: String? = "Hello World"
......
//
// WarningMessageView.swift
// enzevalos_iphone
//
// Created by melicoa97 on 11.03.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import SwiftUI
struct DialogView: View {
let option: DialogOption
var ctaAction: (() -> Void)?
var additionalAction: (() -> Void)?
var dismissAction: (() -> Void)?
private let color = Color(UIColor.systemGray6)
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)
.frame(maxWidth: .infinity)
.padding(.bottom, 20)
.addBorder(Color(option.color), 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)
.fontWeight(.light)
}
.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))
.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)
}
}
if option.dismissButtonTitle != nil && dismissAction != nil {
Button(action: dismissAction!) {
Text(option.dismissButtonTitle!)
.foregroundColor(.red)
.frame(maxWidth: .infinity,maxHeight: 50)
.background(RoundedCorners(color: color, radius: 30))
.padding(.vertical, 10)
.padding(.horizontal, 20)
}
}
}
.background(RoundedCorners(color: color, radius: 30))
.padding(10)
}
}
struct WarningMessageView_Previews: PreviewProvider {
static var previews: some View {
VStack{
DialogView(option: .postcard, ctaAction: action, additionalAction: action, dismissAction: action)
DialogView(option: .corrupted, ctaAction: action)
} .padding(20)
}
static func action() {
print("Button click!")
}
}
extension View {
public func addBorder<S>(_ content: S, width: CGFloat = 1, cornerRadius: CGFloat) -> some View where S : ShapeStyle {
return overlay(RoundedRectangle(cornerRadius: cornerRadius).strokeBorder(content, lineWidth: width))
}
}
......@@ -8,158 +8,93 @@
import SwiftUI
struct MessageViewMain: View {
struct MessageViewMain <M: DisplayMail>: View {
var mail: M
let coord:ReadViewCoordinator
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
let mail:PersistentMail
let innerPadding:CGFloat = 20 // button radius
let outerPadding:CGFloat = 5
let extraButtonFactor: CGFloat = 0.8
@State var showExtraButtons:Bool = false
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
func action() {
print("Click!")
}
var body: some View {
ZStack{
ScrollView{
VStack{
Subjectbar
VStack{Stroke(offsetY:-15)}.frame(height: 3)//workaround
if mail.isEncrypted || mail.trouble || mail.containsSecretKey || mail.deleteWhileTravel || mail.isNewPubKey {
WarnMsg
Divider()
if mail.warnings.count > 0 {
ForEach(0..<mail.warnings.count) { index in
DialogView(option: self.mail.warnings[index], ctaAction: self.action, additionalAction: self.action, dismissAction: self.action)
}
Divider()
MessageBody.padding(.horizontal)
}
else{