diff --git a/enzevalos_iphone.xcodeproj/project.pbxproj b/enzevalos_iphone.xcodeproj/project.pbxproj index f61999812a8366b6ac15cb5ad4d095fee93ca7b8..e9942f4f93a42f2a5b5df9c0fd8c6cd7da31d6c7 100644 --- a/enzevalos_iphone.xcodeproj/project.pbxproj +++ b/enzevalos_iphone.xcodeproj/project.pbxproj @@ -143,6 +143,17 @@ 47C037032347D4D1006295E8 /* PasteKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C037022347D4D1006295E8 /* PasteKeyViewController.swift */; }; 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 */; }; + 47C8225424379EAE005BCE73 /* SenderViewMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224424379EAE005BCE73 /* SenderViewMain.swift */; }; + 47C8225524379EAE005BCE73 /* ProfileEmoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224624379EAE005BCE73 /* ProfileEmoji.swift */; }; + 47C8225624379EAE005BCE73 /* MapView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224724379EAE005BCE73 /* MapView.swift */; }; + 47C8225724379EAE005BCE73 /* Warning_MessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224924379EAE005BCE73 /* Warning_MessageView.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 */; }; + 47C8225B24379EAE005BCE73 /* MessageViewMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8224E24379EAE005BCE73 /* MessageViewMain.swift */; }; + 47C8225D24379EAE005BCE73 /* ReadViewCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8225124379EAE005BCE73 /* ReadViewCoordinator.swift */; }; + 47C8225E24379EAE005BCE73 /* ReadMainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47C8225224379EAE005BCE73 /* ReadMainView.swift */; }; 47CD5AAA2012368D00E771A1 /* logging_pk.asc in Resources */ = {isa = PBXBuildFile; fileRef = 47CD5AA82012368D00E771A1 /* logging_pk.asc */; }; 47CD5AAD2012369400E771A1 /* support_pk2.asc in Resources */ = {isa = PBXBuildFile; fileRef = 47CD5AAC2012369300E771A1 /* support_pk2.asc */; }; 47CEAC98222541B40075B7DC /* MailSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 47CEAC97222541B40075B7DC /* MailSession.swift */; }; @@ -575,6 +586,17 @@ 47C037022347D4D1006295E8 /* PasteKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasteKeyViewController.swift; sourceTree = "<group>"; }; 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>"; }; + 47C8224424379EAE005BCE73 /* SenderViewMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SenderViewMain.swift; sourceTree = "<group>"; }; + 47C8224624379EAE005BCE73 /* ProfileEmoji.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileEmoji.swift; sourceTree = "<group>"; }; + 47C8224724379EAE005BCE73 /* MapView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapView.swift; sourceTree = "<group>"; }; + 47C8224924379EAE005BCE73 /* Warning_MessageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Warning_MessageView.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>"; }; + 47C8224E24379EAE005BCE73 /* MessageViewMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessageViewMain.swift; sourceTree = "<group>"; }; + 47C8225124379EAE005BCE73 /* ReadViewCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadViewCoordinator.swift; sourceTree = "<group>"; }; + 47C8225224379EAE005BCE73 /* ReadMainView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReadMainView.swift; sourceTree = "<group>"; }; 47CD5AA82012368D00E771A1 /* logging_pk.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = logging_pk.asc; path = keys/logging_pk.asc; sourceTree = "<group>"; }; 47CD5AAC2012369300E771A1 /* support_pk2.asc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = support_pk2.asc; path = keys/support_pk2.asc; sourceTree = "<group>"; }; 47CEAC97222541B40075B7DC /* MailSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailSession.swift; sourceTree = "<group>"; }; @@ -1071,6 +1093,7 @@ 476406872416B54D00C7D426 /* SwiftUI */ = { isa = PBXGroup; children = ( + 47C8224124379EAE005BCE73 /* Read */, 47EABF2E24240BA400774A93 /* AccountSetup */, 476406882416B54D00C7D426 /* Inbox */, 4764068C2416B54D00C7D426 /* SupportingViews */, @@ -1221,6 +1244,56 @@ name = data; sourceTree = "<group>"; }; + 47C8224124379EAE005BCE73 /* Read */ = { + isa = PBXGroup; + children = ( + 47C8224224379EAE005BCE73 /* Tabbed Views */, + 47C8225124379EAE005BCE73 /* ReadViewCoordinator.swift */, + 47C8225224379EAE005BCE73 /* ReadMainView.swift */, + ); + path = Read; + sourceTree = "<group>"; + }; + 47C8224224379EAE005BCE73 /* Tabbed Views */ = { + isa = PBXGroup; + children = ( + 47C8224324379EAE005BCE73 /* AttachmentsViewMain.swift */, + 47C8224424379EAE005BCE73 /* SenderViewMain.swift */, + 47C8224524379EAE005BCE73 /* SenderViewChildren */, + 47C8224824379EAE005BCE73 /* MessageViewChildren */, + 47C8224B24379EAE005BCE73 /* AttachmentChildren */, + 47C8224E24379EAE005BCE73 /* MessageViewMain.swift */, + ); + path = "Tabbed Views"; + sourceTree = "<group>"; + }; + 47C8224524379EAE005BCE73 /* SenderViewChildren */ = { + isa = PBXGroup; + children = ( + 47C8224624379EAE005BCE73 /* ProfileEmoji.swift */, + 47C8224724379EAE005BCE73 /* MapView.swift */, + ); + path = SenderViewChildren; + sourceTree = "<group>"; + }; + 47C8224824379EAE005BCE73 /* MessageViewChildren */ = { + isa = PBXGroup; + children = ( + 47C8224924379EAE005BCE73 /* Warning_MessageView.swift */, + 47C8224A24379EAE005BCE73 /* FloatingActionButton.swift */, + ); + path = MessageViewChildren; + sourceTree = "<group>"; + }; + 47C8224B24379EAE005BCE73 /* AttachmentChildren */ = { + isa = PBXGroup; + children = ( + 47C8224C24379EAE005BCE73 /* AttPreview.swift */, + 47C8224D24379EAE005BCE73 /* CardWithTitle.swift */, + ); + path = AttachmentChildren; + sourceTree = "<group>"; + }; 47EABF04241A9C6400774A93 /* Recovered References */ = { isa = PBXGroup; children = ( @@ -1480,7 +1553,7 @@ isa = PBXGroup; children = ( 0ED9072F24338E3C008CF9D0 /* SMIMETests.swift */, - 71DF0896242151E200162B74 /* phishing */, + 71DF0896242151E200162B74 /* phishing */, 97C5279D241A9F690030BBC9 /* authentication */, 47F0376C22A7278A0005C9DE /* private */, 470709202189C24800DF71A3 /* testKeys */, @@ -1996,7 +2069,6 @@ "${PODS_ROOT}/Target Support Files/Pods-enzevalos_iphone/Pods-enzevalos_iphone-frameworks.sh", "${BUILT_PRODUCTS_DIR}/AppAuth/AppAuth.framework", "${BUILT_PRODUCTS_DIR}/BZipCompression/BZipCompression.framework", - "${BUILT_PRODUCTS_DIR}/Cuckoo/Cuckoo.framework", "${BUILT_PRODUCTS_DIR}/FrameAccessor/FrameAccessor.framework", "${BUILT_PRODUCTS_DIR}/GTMAppAuth/GTMAppAuth.framework", "${BUILT_PRODUCTS_DIR}/GTMSessionFetcher/GTMSessionFetcher.framework", @@ -2012,7 +2084,6 @@ outputPaths = ( "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AppAuth.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BZipCompression.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Cuckoo.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FrameAccessor.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMAppAuth.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GTMSessionFetcher.framework", @@ -2156,11 +2227,13 @@ A1EB05941D956931008659C1 /* InboxCellDelegator.swift in Sources */, 8428A85D1F436A05007649A5 /* Badges.swift in Sources */, 971D404A2428C87E002FCD31 /* BadgeCaseView.swift in Sources */, + 47C8225B24379EAE005BCE73 /* MessageViewMain.swift in Sources */, 8428A8651F436A11007649A5 /* BadgeCaseCollectionViewCell.swift in Sources */, 472F39811E1E5347009260FB /* Mail_Address+CoreDataClass.swift in Sources */, A1EB05821D95685B008659C1 /* CollectionDataDelegate.swift in Sources */, 47A5D6E22294BF3B0084F81D /* TempKey.swift in Sources */, 4751C7012344D37C006B2A4D /* SecretKey+CoreDataProperties.swift in Sources */, + 47C8225624379EAE005BCE73 /* MapView.swift in Sources */, 476406992416B54D00C7D426 /* SearchView.swift in Sources */, 47D1302B1F7CEE6D007B14DF /* DebugSettings.swift in Sources */, A1EB05801D956851008659C1 /* SendViewController.swift in Sources */, @@ -2173,6 +2246,8 @@ F1984D721E1D327200804E1E /* IconsStyleKit.swift in Sources */, F1737ACB2031D7D70000312B /* StudySettings.swift in Sources */, 0ECA5798240D496800B0F231 /* SMIME.swift in Sources */, + 47C8225A24379EAE005BCE73 /* CardWithTitle.swift in Sources */, + 47C8225524379EAE005BCE73 /* ProfileEmoji.swift in Sources */, 6789425F2430C3B300C746D1 /* MailComparison.swift in Sources */, 8428A8691F436A11007649A5 /* UserNameGamificationTableViewCell.swift in Sources */, A114E4321FACB23000E40243 /* StringExtension.swift in Sources */, @@ -2183,6 +2258,7 @@ F113C3851F30D06800E7F1D6 /* QRScannerView.swift in Sources */, 97BDE0432429188500B0BF03 /* BadgeProgressView.swift in Sources */, 477670C6228454F700043604 /* ButtonCell.swift in Sources */, + 47C8225824379EAE005BCE73 /* FloatingActionButton.swift in Sources */, F18B44601E704C550080C041 /* ReplaceSegue.swift in Sources */, 8428A8661F436A11007649A5 /* ArrowTableViewCell.swift in Sources */, F1ACF21C1E0C1C6800C1B843 /* ContactViewController.swift in Sources */, @@ -2195,6 +2271,7 @@ 8428A86F1F436A1E007649A5 /* InviteFriendViewController.swift in Sources */, A1735DFA205AB88500B336DB /* SendViewState.swift in Sources */, 475B00331F7B9565006CDD41 /* SwiftPGP.swift in Sources */, + 47C8225D24379EAE005BCE73 /* ReadViewCoordinator.swift in Sources */, 477548E421F77BA0000B22A8 /* StudyParameterProtocol.swift in Sources */, 47A5D6E42294BFF50084F81D /* Logger.swift in Sources */, 3EB4FAA420120096001D0625 /* DialogOption.swift in Sources */, @@ -2245,6 +2322,7 @@ 8428A85E1F436A05007649A5 /* CircleView.swift in Sources */, A182182C21E5072200918A29 /* IntroDescriptionViewController.swift in Sources */, F1C7AC821FED6473007629DB /* AboutViewController.swift in Sources */, + 47C8225324379EAE005BCE73 /* AttachmentsViewMain.swift in Sources */, A182183421E51DD200918A29 /* IntroContactCell.swift in Sources */, 678942612430C3D600C746D1 /* Typosquatting.swift in Sources */, 472F397C1E1D0B0B009260FB /* PersistentMail +CoreDataProperties.swift in Sources */, @@ -2265,8 +2343,10 @@ 4706D65F225B7B6B00B3F1D3 /* ItunesHandler.swift in Sources */, 3EC35F2D200376A1008BDF95 /* SendViewController+Invitation.swift in Sources */, 47EABF0A241A9C8700774A93 /* AuthenticationViewModel.swift in Sources */, + 47C8225924379EAE005BCE73 /* AttPreview.swift in Sources */, 475B00341F7B9565006CDD41 /* Cryptography.swift in Sources */, A1EB057C1D956838008659C1 /* MailHandler.swift in Sources */, + 47C8225424379EAE005BCE73 /* SenderViewMain.swift in Sources */, A182182E21E50D8D00918A29 /* IntroButtonViewController.swift in Sources */, 0EFEF0952417C0B400BB2FF7 /* CHelpers.swift in Sources */, 4764069D2416B54D00C7D426 /* Stroke.swift in Sources */, @@ -2291,14 +2371,15 @@ F1984D741E1E92B300804E1E /* LabelStyleKit.swift in Sources */, A1FA44A721E10E1400DB02AC /* TravelHandler.swift in Sources */, 47E7376E22845EC400972401 /* SecretKeyTableViewController.swift in Sources */, + 47C8225724379EAE005BCE73 /* Warning_MessageView.swift in Sources */, 478154A721FF3F0900A931EC /* Warning.swift in Sources */, 4764069F2416B5A600C7D426 /* NewOnboardingView.swift in Sources */, 0EF73F4324237E6500932FA0 /* SMIMEHelpers.swift in Sources */, - 47EABF0B241A9C8700774A93 /* AuthenticationScreen.swift in Sources */, 8428A8681F436A11007649A5 /* SubBadgeTableViewCell.swift in Sources */, A1EB05861D956872008659C1 /* FrequentCell.swift in Sources */, F12041FB1DA3FBF7002E4940 /* ListViewController.swift in Sources */, F18B445E1E7044B70080C041 /* FlipTransition.swift in Sources */, + 47C8225E24379EAE005BCE73 /* ReadMainView.swift in Sources */, 472F397E1E1D0B0B009260FB /* EnzevalosContact+CoreDataProperties.swift in Sources */, 4751C6FA23449699006B2A4D /* CryptoManagementViewController.swift in Sources */, 478154AC21FF6A9600A931EC /* Mailbot.swift in Sources */, @@ -2321,7 +2402,7 @@ 479B5977206914BE00B3944D /* CryptoTests.swift in Sources */, A15D215F223BE6E4003E0CE0 /* MailTest.swift in Sources */, 0ED9073024338E3C008CF9D0 /* SMIMETests.swift in Sources */, - 47EABF0F2420C63600774A93 /* AuthenticationTests.swift in Sources */, + 47EABF0F2420C63600774A93 /* AuthenticationTests.swift in Sources */, 988C9C5D240D507A006213F0 /* UrlStringExtensionTests.swift in Sources */, 4715F637202A0248001BFFD0 /* CoreDataTests.swift in Sources */, 47C22281218AFD6300BD2C2B /* AutocryptTest.swift in Sources */, diff --git a/enzevalos_iphone/Settings.bundle/Acknowledgements.plist b/enzevalos_iphone/Settings.bundle/Acknowledgements.plist index 41fc4f8b65bcafeade28b7a17e46dc5d359d9925..16268961ca57ca847876ca686ed570e46006c51f 100644 --- a/enzevalos_iphone/Settings.bundle/Acknowledgements.plist +++ b/enzevalos_iphone/Settings.bundle/Acknowledgements.plist @@ -425,37 +425,6 @@ third-party archives. <key>Type</key> <string>PSGroupSpecifier</string> </dict> - <dict> - <key>FooterText</key> - <string>The MIT License (MIT) - -Copyright (c) 2016 Brightify.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -</string> - <key>License</key> - <string>MIT</string> - <key>Title</key> - <string>Cuckoo</string> - <key>Type</key> - <string>PSGroupSpecifier</string> - </dict> <dict> <key>FooterText</key> <string>Copyright (c) 2012 Alexey Denisov diff --git a/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift b/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift new file mode 100644 index 0000000000000000000000000000000000000000..cb1b7eefd92b184107e7b113897810646100294c --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/ReadMainView.swift @@ -0,0 +1,245 @@ +// +// ReadMainView.swift +// enzevalos_iphone +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +import SwiftUI + +struct ReadMainView: View { + + public var mail:PersistentMail + + public var coord: ReadViewCoordinator + + @State var currentScreen: Int = 1 //doesnt work + + @State var isSecIndExpanded:Bool=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) + } + } + } + .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 + var Tabs:[Tab] { + get { + return [ + Tab( + image: Image(systemName: "person.fill"), + description: "sender", + content: AnyView(SenderViewMain(mail: mail)) + ), + Tab( + image: Image(systemName: "text.bubble.fill"), + description: "message", + content: AnyView(MessageViewMain(coord: coord, mail: mail)) + ), + Tab( + image: Image(systemName: "rectangle.and.paperclip"), + description: "attachments", + content: AnyView(AttachmentsViewMain(mail: mail, coord: coord)) + ) + ] + } + } + + var moreInfoButton: some View{ + return Button(action: {self.isSecIndExpanded.toggle()}){ + 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()))) + } + + + else{ + + return AnyView(SecInd(secNum:3,isExpanded: $isSecIndExpanded,color:Color(ThemeManager.unencryptedMessageColor()))) + + } + } + } +} + + +struct Tab{ + let id = UUID() + + var image : Image = Image(systemName: "tag.fill") + var description : String = "---" + var content : AnyView = AnyView(Text("Still in development")) +} + + +struct SecInd:View{ + + var secNum:UInt8=0 //1: trouble ; 2:safe ; 3 not safe + + @Binding var isExpanded:Bool + + var color:Color + @State private var pullInfo:Bool = true; + + var body : some View { + VStack(spacing:0){ + Rectangle() + .fill(color) + .frame(height: 2) + .frame(height: 2) + if isExpanded { + expandedSecInd(secNum: secNum).onTapGesture { + self.isExpanded = false + } + .padding(/*[.leading, .bottom, .trailing],*/20) + .background(RoundedCorners(color: color, tl: 0, tr: 0, bl: 30, br: 30)) + } + if pullInfo {Text("tap info-icon to get more info").font(.system(size: 8)).padding(.vertical,4)} + } + .padding(0) + .background((isExpanded || !pullInfo) ? RoundedCorners(color: color, tl: 0, tr: 0, bl: 30, br: 30) : nil) + .animation(.easeInOut(duration: 1)) + .onAppear(perform:{ + DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) { + self.pullInfo=false + }} + ) + } +} + + +struct expandedSecInd: View { + + var secNum:UInt8 //1: trouble ; 2:safe ; 3 not safe & subcases of unsecure(4,5,6) + + var icon = LogData.IndicatorButton.self + + var body: some View { + VStack(){ + if secNum == 1 { + layout( + title: NSLocalizedString("LetterDamaged", comment: "Modified email received")/*"Angerissener Brief"*/, + text: NSLocalizedString("ReceiveDamagedInfo", comment: "Modified email infotext"), + icon: Image(icon.error.name)//TODO: ask oli how to do this correctly + ) + } else if secNum == 2 { + layout( + title: NSLocalizedString("Letter", comment: "letter label"), + text: NSLocalizedString("ReceiveSecureInfo", comment: "Letter infotext"), + icon: Image(icon.confidential.name)//TODO: ask oli how to do this correctly + ) + + }else if secNum==4 { + layout( + title: NSLocalizedString("Postcard", comment: "postcard label"), + text: NSLocalizedString("ReceiveInsecureInfoVerified", comment: "Postcard infotext"), + icon: Image(icon.signedOnly.name)//TODO: ask oli how to do this correctly + ) + } else if secNum==5 { + layout( + title: NSLocalizedString("Postcard", comment: "postcard label"), + text: NSLocalizedString("ReceiveInsecureInfoEncrypted", comment: "Postcard infotext"), + icon: Image(icon.encryptedOnly.name)//TODO: ask oli how to do this correctly + ) + } else if secNum==6 { + layout( + title: NSLocalizedString("Postcard", comment: "postcard label"), + text: NSLocalizedString("ReceiveInsecureInfoDecryptionFailed", comment: "Postcard infotext"), + icon: Image(icon.unableToDecrypt.name)//TODO: ask oli how to do this correctly + ) + }else if secNum == 3 { + layout( + title: NSLocalizedString("Postcard", comment: "postcard label"), + text: NSLocalizedString("ReceiveInsecureInfo", comment: "Postcard infotext"), + icon: Image("work")//Image(icon.notConfidential.name)//TODO: ask oli how to do this correctly + ) + } + } + } + + func layout(title:String, text:String, icon:Image)->some View{ + + //TODO: add a cool layout + return VStack{ + HStack{ + Spacer() + icon.resizable() + .scaledToFit() + .frame(width:30,height: 30) + Text(title).font(.system(size:22)).fontWeight(.light) + Spacer() + } + Text(text).font(.caption).multilineTextAlignment(.center) + } + } +} + +#if DEBUG +struct Layout_Previews: PreviewProvider { + static var previews: some View { + Group { + expandedSecInd(secNum: 2) + } + } +} +#endif + diff --git a/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift new file mode 100644 index 0000000000000000000000000000000000000000..1bb93740978f9aa89660eaac862bc9ac058a7ca1 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/ReadViewCoordinator.swift @@ -0,0 +1,134 @@ +// +// ReadViewCoordinator.swift +// enzevalos_iphone +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +import Foundation +import SwiftUI + +class ReadViewCoordinator { + let root: UINavigationController + + private let mainStoryboardName = "Main" + private let mainStoryboard: UIStoryboard + private var readView: UIViewController? + + private var mail:PersistentMail + + + init(root: UINavigationController, mail:PersistentMail) { + self.mail = mail + self.root = root + mainStoryboard = UIStoryboard(name: self.mainStoryboardName, bundle: nil) + } + + func pushReadView(){ + + root.isToolbarHidden = true + + try? AppDelegate.getAppDelegate().mailHandler.startIMAPIdleIfSupported() + AppDelegate.getAppDelegate().mailHandler.updateFolder(folder: Folder.inbox, completionCallback: {_ in + }) + + + if let vc = readView { + if root.viewControllers.contains(vc) { + while root.topViewController != vc { + root.popViewController(animated: true) + } + } else { + root.pushViewController(vc, animated: true) + } + } + else { + let context = DataHandler.handler.managedObjectContext + let vc = UIHostingController(rootView: ReadMainView(mail: mail, coord: self).environment(\.managedObjectContext,context)) + readView = vc + root.pushViewController(vc, animated: true) + } + } + + func delete(){ + //TODO: make this work + Logger.log(delete: mail, toTrash: true) + AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendTrashFolderPath) + } + + func archive(){ + //TODO: make this work + Logger.log(archive: mail) + AppDelegate.getAppDelegate().mailHandler.move(mails: [mail], from: mail.folder.path, to: UserManager.backendArchiveFolderPath) + } + + func pushComposeView() { + let vc = mainStoryboard.instantiateViewController(identifier: ViewID.ComposeView.rawValue) + if let vc = vc as? SendViewController { + vc.wasPushed = true + } + root.isToolbarHidden = false + root.pushViewController(vc, animated: true) + } + + func pushExportKeyView() { + //TODO: make this work + let vc = mainStoryboard.instantiateViewController(identifier: "exportKeyFromReadView") + if let vc = vc as? ImportKeyOverviewController { + //vc.wasPushed = true + } + root.isToolbarHidden = false + root.pushViewController(vc, animated: true) + } + + func shareData(_ data:NSData){ + //let shareText = "Hello, world!" + + //let data:NSData = data + + let vc = UIActivityViewController(activityItems: [data], applicationActivities: []) + root.present(vc, animated: true) + } + + func setup(){ + hideUIKitToolbar() + setupNavigationbar() + } + + func reset(){ + animateBarColor(ThemeManager.defaultColor) + } + + func hideUIKitToolbar(){ + root.isToolbarHidden = true + } + + func setupNavigationbar(){ + + ///those dont work + //root.isNavigationBarHidden=true + //root.navigationBar.isHidden=true + //root.navigationBar.isTranslucent=true + + /*if mail.trouble{animateBarColor(ThemeManager.troubleMessageColor()) } + else{animateBarColor(mail.isSecure ? ThemeManager.encryptedMessageColor() : ThemeManager.unencryptedMessageColor())}*/ + } + + private func animateBarColor(_ c:UIColor){ + + //TODO: why desnt it work? it just jumps + UIView.animate(withDuration: 0.3, animations: { + self.root.navigationBar.barTintColor = c }) + } +} + diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentChildren/AttPreview.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentChildren/AttPreview.swift new file mode 100644 index 0000000000000000000000000000000000000000..682adb3b42b85caffe488f4c252fa58101a2c37c --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentChildren/AttPreview.swift @@ -0,0 +1,94 @@ +// +// AttPreview.swift +// enzevalos_iphone +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +import SwiftUI +import QuickLook + +//To use the QuickLook in SwiftUI +struct QuickLookView: UIViewControllerRepresentable { + var name: String + var data: Data? + + //if it should download the data as a file if not yet downloaded + var shallDL: Bool = true + + var allowScaling: Bool = true + + func makeCoordinator() -> QuickLookView.Coordinator { + Coordinator(self) + } + + func makeUIViewController(context: Context) -> QLPreviewController { + let controller = QLPreviewController() + //the coordinator provides the real preview data as a NSURL + controller.dataSource = context.coordinator + return controller + } + + func updateUIViewController(_ controller: QLPreviewController, + context: Context) { + print("updated") + controller.reloadData()//not beautiful but works + } + + class Coordinator: NSObject, QLPreviewControllerDataSource { + let parent: QuickLookView + + init(_ parent: QuickLookView) { + self.parent = parent + super.init() + } + + // The QLPreviewController asks its delegate how many items it has: + func numberOfPreviewItems(in controller: QLPreviewController) -> Int { + return 1 + } + + // For each item (see method above), the QLPreviewController asks for + // a QLPreviewItem instance describing that item: + func previewController( + _ controller: QLPreviewController, + previewItemAt index: Int + ) -> QLPreviewItem { + + func getDocumentsDirectory() -> URL { + let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) + return paths[0] + } + + let str = parent.data! + + //This is where the file is stored + let filename = getDocumentsDirectory().appendingPathComponent(parent.name) + + if parent.shallDL{ + do { + try str.write(to: filename) + } catch { + // failed to write file – bad permissions, bad filename, missing permissions + } + } + + _ = parent.name.components(separatedBy: ".") + let path = filename + + return path as NSURL + + } + } +} + diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentChildren/CardWithTitle.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentChildren/CardWithTitle.swift new file mode 100644 index 0000000000000000000000000000000000000000..703ae6aa688a742eb91f8ce4091d981fafca0828 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentChildren/CardWithTitle.swift @@ -0,0 +1,112 @@ +// +// CardWithTitle.swift +// enzevalos_iphone +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +import SwiftUI + +// MARK: a CardView with title +struct CardV<Content:View>: View{ + var elevation:CGFloat = 3 + var title:String? + + var actions:[AnyView]? + var actionsVertical:Bool=false + + var content: () -> Content + + @State private var isAdvancedVisable:Bool = false + @/*Gesture*/State private var isTapDownB:Bool = false + + + private let colo=Color(red:0.85,green:0.85,blue:0.88) + + var body: some View{ + ZStack { + VStack{ + VStack{ + content() + .background(Color.white) + .clipShape( + RoundedRectangle(cornerRadius: 15) + ) + .padding(3) + .opacity(isTapDownB ? 0.7 : 1) + if title != nil { + Text(title!).padding(7) + } + } + .background(isTapDownB ? colo : Color.white) + .clipShape( + RoundedRectangle(cornerRadius: 15) + ) + .gesture ( + TapGesture() + /*.updating($isTapDownB, body: { (currentState, state, transaction) in + //sadly doesnt work ; iwant to make it visable if a user touches + self.isTapDown=state + })*/ + .onEnded{ _ in + self.isTapDownB.toggle() + self.isAdvancedVisable.toggle() + } + ) + + if isAdvancedVisable{ + Advanced.padding(.horizontal,10) + } + } + .shadow(color: isTapDownB ? Color.clear : colo , radius: 2*elevation, x: elevation, y:elevation) + } + .padding(.leading, 10) + .padding(2*elevation) + .padding(.bottom,isTapDownB ? elevation : 2*elevation) + .animation(.easeIn(duration: 0.2)) + .scaleEffect(isTapDownB ? 0.82 : 1) + .opacity(isTapDownB ? 0.9 : 1) + } + + private func Actions(_ nr:Int)-> some View{ + self.actions![nr] + .padding(10) + .background(Color.white) + .clipShape( + RoundedRectangle(cornerRadius: 15) + ) + .shadow(color: colo , radius: 2*elevation, x: elevation, y:elevation) + } + + //the button section beneath + private var Advanced: AnyView{ + if actions != nil{ + if actionsVertical{ + return AnyView(VStack{ + ForEach(0..<actions!.count){ i in + self.Actions(i) + } + }) + }else{ + return AnyView(HStack{ + ForEach(0..<actions!.count){ i in + self.Actions(i) + } + }) + } + } + return AnyView(EmptyView()) + } + +} + diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentsViewMain.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentsViewMain.swift new file mode 100644 index 0000000000000000000000000000000000000000..80a5701edd24e4b742632c1c52c1037738220502 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/AttachmentsViewMain.swift @@ -0,0 +1,246 @@ +// +// AttachmentsViewMain.swift +// enzevalos_iphone +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +import SwiftUI + +struct AttachmentsViewMain: View { + + let mail:PersistentMail + + let coord:ReadViewCoordinator + + //gets the attachments as attachments not as nsElemets + @State var Attachments:[Attachment]? = nil + func attachmentList()->[Attachment]{ + if Attachments != nil { return Attachments!}//if we already converted the attachments + print((mail.attachments ?? []).count) + var atts:[Attachment]=[] + for at in mail.attachments ?? []{ + atts.append(at as! Attachment) + } + Attachments=atts + return atts + } + + var body: some View { + VStack{ + Spacer() + Spacer() + linkSection + attachmentSection + } + } + + @State var dlAll=false;//whether the Download all button was clicked + var attachments: some View { + return VStack(alignment: .leading, spacing: 5){ + + //headline + HStack{ + Text(NSLocalizedString("attachmentsHeadline", comment: "attachments:")) + .font(.system(size:24)).fontWeight(.light) + Spacer() + FloatingActionButton( + radius:10, + onShortPress:{ + self.dlAll=true + }){ + HStack{ + Image(systemName: dlAll ? "arrow.down" : "arrow.down.circle") + Text(dlAll ? NSLocalizedString("download again", comment: "") : NSLocalizedString("download all", comment: "")).font(.footnote) + } + } + } + .padding(.horizontal , 15) + .padding(3) + + //main attachment view + ScrollView(.horizontal, showsIndicators: false) { + HStack(spacing: 5) { + ForEach(0..<attachmentList().count) { i in + AttPrev( + attachment: self.attachmentList()[i], + preload: self.dlAll, + + //needed to pop over sharing functionality + coord: self.coord + ) + } + }.onAppear(perform: { + print("appeaer") + print(self.mail.attachments!.count) + }) + } + }.padding(.top, 30) + .padding(.bottom,10) + } + + var noAttachments: some View { + return Text(NSLocalizedString("no attachments", comment: "")).font(.footnote).padding(30) + } + + var attachmentSection : AnyView { + //check if there even are attachments to be displayed + if !mail.hasAttachment && mail.attachments!.count==0{ + return AnyView(noAttachments) + } + + return AnyView(attachments) + } + + //TODO + var linkSection: some View { + return Text(NSLocalizedString("linksFuture", comment: "")).font(.footnote).padding(20) + } + +} + +/*struct AttachmentsViewMain_Previews: PreviewProvider { + static var previews: some View { + AttachmentsViewMain() + } +}*/ + + +// MARK: one AttachmentPreview +struct AttPrev:View{ + + var attachment:Attachment + var preload = false + + let coord:ReadViewCoordinator + + @State var isDownloaded:Bool = false + @State var isFullScreen:Bool = false + + func download(){ + func getDocumentsDirectory() -> URL { + let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) + return paths[0] + } + let filename = getDocumentsDirectory().appendingPathComponent(self.attachment.name!) + + do { + try self.attachment.data!.write(to: filename) + } catch let error as NSError { + print("Error: \(error)") + } + self.isDownloaded = true + } + + //is the file already downloaded? + func getDownloadedState(){ + func getDocumentsDirectory() -> URL { + let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) + return paths[0] + } + let filename = getDocumentsDirectory().appendingPathComponent(self.attachment.name!) + + if FileManager.default.fileExists(atPath: filename.path){self.isDownloaded = true} + } + + var body: some View{ + if preload {self.download()} + + //this QuickLookView has to be defined here so it reloads on every state-change + var QLV = QuickLookView(name: self.attachment.name!, data: self.attachment.data!, shallDL: self.isDownloaded) + return VStack{ + Group{ + CardV(title: self.attachment.name ?? "", + + //those are the actions visable under the cklicked preview + actions: self.isDownloaded||self.preload ? + [ + self.ActionView(NSLocalizedString("delete", comment: ""), + icon: AnyView(Image(systemName: "trash")), + onClick: { + func getDocumentsDirectory() -> URL { + let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) + return paths[0] + } + let filename = getDocumentsDirectory().appendingPathComponent(self.attachment.name!) + + do { + try FileManager.default.removeItem(at: filename) + } catch let error as NSError { + print("Error: \(error)") + } + self.isDownloaded = false + } + + ), + self.ActionView(NSLocalizedString("open", comment: ""), + icon: AnyView(Image(systemName: "arrow.up.and.down").rotationEffect(.degrees(45))), + onClick: {self.isFullScreen.toggle()} + ), + AnyView(VStack{ + shareButton + Text(NSLocalizedString("share", comment: "")).font(.system(size: 12)).foregroundColor(.blue) + }) + ] + : + [ + self.ActionView(NSLocalizedString("download", comment: ""), + icon: AnyView(Image(systemName: "arrow.down.circle")), + onClick: { + self.download() + } + ), + //odd but both lists need same length + AnyView(EmptyView()), + AnyView(EmptyView()) + ] + ){ + QLV/*TODO: + .allowsHitTesting(false).disabled(true)*/ //this should make the whole view scrollable averywhere not just on the title + + } + } + .frame(width: UIScreen.main.bounds.width*2/3)//, maxHeight: 500) + + //an invisable NavigationLink to open the preview in fullscreen + NavigationLink(destination: QuickLookView(name: self.attachment.name!, data: self.attachment.data!) + .navigationBarItems(trailing: shareButton), isActive: self.$isFullScreen){Text("loi")}.hidden() + + } + .onAppear(perform:{ + self.getDownloadedState() + + //download all functionality + if self.preload {self.isDownloaded=true; self.download()} + }) + } + + var shareButton: some View { + return Button(action:{ + //popover the standart apple sharing stuff + self.coord.shareData(self.attachment.data! as NSData) + }){ + Image(systemName: "square.and.arrow.up") + } + } + + //each of those buttons under the card + func ActionView( _ text:String,icon: AnyView, onClick:@escaping ()->Void={})-> AnyView{ + return AnyView(Button( + action: onClick + ){VStack{ + icon + Text(text).font(.system(size: 12)) + }}) + } +} diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewChildren/FloatingActionButton.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewChildren/FloatingActionButton.swift new file mode 100644 index 0000000000000000000000000000000000000000..967d8cee21713994b0e466bcd38830e297e25723 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewChildren/FloatingActionButton.swift @@ -0,0 +1,56 @@ +// +// FloatingActionButton.swift +// enzevalos_iphone +// +// Created by hanneh00 on 12.03.20. +// Copyright © 2020 fu-berlin. All rights reserved. +// + +import SwiftUI + +struct FloatingActionButton<Content: View>: View{ + + var innerPadding:CGFloat, onLongPress:()->Void, onShortPress:()->Void = {}, color: Color, pressColor: Color + + let content: Content + + @GestureState var tapDown: Bool = false + + init(color:Color = Color.accentColor, pressColor:Color = Color.init(red: 0.5, green: 0.5, blue: 1), radius:CGFloat = 15, onLongPress:@escaping ()->Void = {}, onShortPress:@escaping ()->Void = {}, @ViewBuilder content: () -> Content) { + self.onLongPress = onLongPress + self.onShortPress = onShortPress + self.innerPadding = radius + self.content = content() + + self.color = color + self.pressColor = pressColor + } + + + var body: some View { + VStack{ + content + } + .foregroundColor(.white) + .padding(innerPadding) + .background(self.tapDown ? pressColor : color) + .clipShape(Capsule()) + .shadow(radius: self.tapDown ? 0 : 3) + .gesture ( + TapGesture() + .onEnded{ _ in + self.onShortPress() + } + .simultaneously(with: + LongPressGesture(minimumDuration: 0.5) + .updating($tapDown, body: { (currentState, state, transaction) in + state = currentState + }) + .onEnded({ _ in + self.onLongPress() + }) + ) + ) + } +} + diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewChildren/Warning_MessageView.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewChildren/Warning_MessageView.swift new file mode 100644 index 0000000000000000000000000000000000000000..dcf396493007fbdbe207d15796efc995f5225119 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewChildren/Warning_MessageView.swift @@ -0,0 +1,24 @@ +// +// Warning_MessageView.swift +// enzevalos_iphone +// +// Created by melicoa97 on 11.03.20. +// Copyright © 2020 fu-berlin. All rights reserved. +// + +import SwiftUI + +struct Warning_MessageView: View { + + + + var body: some View { + Text(/*@START_MENU_TOKEN@*/"Hello World!"/*@END_MENU_TOKEN@*/) + } +} + +struct Warning_MessageView_Previews: PreviewProvider { + static var previews: some View { + Warning_MessageView() + } +} diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewMain.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewMain.swift new file mode 100644 index 0000000000000000000000000000000000000000..a0798b7e78fb322d79ea952e051f2fc1e74dace2 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/MessageViewMain.swift @@ -0,0 +1,278 @@ +// +// MessageViewMain.swift +// enzevalos_iphone +// +// Created by melicoa97 on 10.03.20. +// Copyright © 2020 fu-berlin. All rights reserved. +// + +import SwiftUI + +struct MessageViewMain: View { + + let coord:ReadViewCoordinator + + let mail:PersistentMail + + @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode> + + 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 + } + else{ + MessageBody.padding(.horizontal) + } + } + } + .onTapGesture { + self.showExtraButtons=false + } + FloatingReplyButtons + }.onAppear(perform: {self.mail.isRead = true}) + } + + + var Subjectbar: some View{ + return + VStack(alignment: .leading){ + Text(mail.subject ?? "--no-subject--").font(.system(size: 23)).fontWeight(.light) + }.padding() + } + + func actionButton(image:Image , description:String, action:@escaping ()->Void)->some View{ + return Button(action: action){ + VStack{ + image + Text(description).font(.system(size: 10)).fontWeight(.none) + } + } + } + + + var WarnMsg: some View{ + return VStack{ + 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() + } + + + var MessageBody : some View { + return Text(self.mail.body!).padding(.bottom, 2*innerPadding+outerPadding) + } + + + let innerPadding:CGFloat = 15 //buttonRadius + let outerPadding:CGFloat = 5 + let extraButtonFactor: CGFloat = 0.8 + + @State var showExtraButtons:Bool = false + + var FloatingReplyButtons: some View{ + return VStack{ + Spacer() + HStack{ + Spacer() + ZStack{ + + if mail.folder.path.hasPrefix(UserManager.backendArchiveFolderPath){ + forwardButton.offset(y: showExtraButtons ? -innerPadding*9 : 0) + replyAllButton.offset(y: showExtraButtons ? -innerPadding*4.5 : 0) + replyButton + unreadButton.offset(x: showExtraButtons ? -innerPadding*4.5 : 0) + deleteButton.offset(x: showExtraButtons ? -innerPadding*9 : 0) + } + else if mail.folder.path.hasPrefix(UserManager.backendTrashFolderPath){ + forwardButton.offset(y: showExtraButtons ? -innerPadding*9 : 0) + replyAllButton.offset(y: showExtraButtons ? -innerPadding*4.5 : 0) + replyButton + unreadButton.offset(x: showExtraButtons ? -innerPadding*4.5 : 0) + archiveButton.offset(x: showExtraButtons ? -innerPadding*9 : 0) + } + else if mail.folder.path.hasPrefix(UserManager.backendSentFolderPath){ + forwardButton.offset(y: showExtraButtons ? -innerPadding*4.5 : 0) + deleteButton.offset(x: showExtraButtons ? -innerPadding*4.5 : 0) + } + else if mail.folder.path.hasPrefix(UserManager.backendDraftFolderPath){ + deleteButton.offset(x: showExtraButtons ? -innerPadding*4.5 :0) + } + else{ + forwardButton.offset(y: showExtraButtons ? -innerPadding*9 : 0) + replyAllButton.offset(y: showExtraButtons ? -innerPadding*4.5 : 0) + replyButton + unreadButton.offset(x: showExtraButtons ? -innerPadding*4.5 : 0) + deleteButton.offset(x: showExtraButtons ? -innerPadding*9 : 0) + archiveButton.offset(x: showExtraButtons ? -innerPadding*13.5 : 0) + } + + //options + FloatingActionButton( + //radius: innerPadding, + onShortPress: {self.showExtraButtons.toggle()}/*TODO: fill in stuff*/ + ){ + VStack{ + Image(systemName: "arrowshape.turn.up.left.fill") + Text("options").font(.system(size: 7)).fontWeight(.none) + } + }.opacity(showExtraButtons ? 0 : 1) + }.animation(.easeInOut(duration: 0.2)) + }.padding(outerPadding) + }.padding(outerPadding) + } + + var forwardButton: some View { + FloatingActionButton( + radius: innerPadding*extraButtonFactor, + onShortPress: self.coord.pushComposeView/*TODO: fill in stuff*/ + ){ + VStack{ + Image(systemName: "arrowshape.turn.up.right.fill") + Text("forward").font(.system(size: 7)).fontWeight(.none) + } + } + + } + + var replyAllButton: some View{ + FloatingActionButton( + radius: innerPadding*extraButtonFactor, + onShortPress: self.coord.pushComposeView/*TODO: fill in stuff*/ + ){ + VStack{ + Image(systemName: "arrowshape.turn.up.left.2.fill") + Text("reply all").font(.system(size: 7)).fontWeight(.none) + } + } + } + + var unreadButton: some View{ + FloatingActionButton( + radius: innerPadding*extraButtonFactor, + onShortPress: { + self.mail.isRead = false + self.presentationMode.wrappedValue.dismiss() + }/*TODO: fill in stuff*/ + ){ + VStack{ + Image(systemName: "envelope.badge") + Text("unread").font(.system(size: 7)).fontWeight(.none) + } + } + } + + var deleteButton: some View{ + FloatingActionButton( + radius: innerPadding*extraButtonFactor, + onShortPress: { + self.coord.delete(); + self.presentationMode.wrappedValue.dismiss()}/*TODO: fill in stuff*/ + ){ + VStack{ + Image(systemName: "trash") + Text("delete").font(.system(size: 7)).fontWeight(.none) + } + } + + } + + var archiveButton: some View { + FloatingActionButton( + radius: innerPadding*extraButtonFactor, + onShortPress: { + self.presentationMode.wrappedValue.dismiss() + } + ){ + VStack{ + Image(systemName: "folder") + Text("archive").font(.system(size: 7)).fontWeight(.none) + } + } + } + + var replyButton: some View{ + FloatingActionButton( + //radius: innerPadding, + onShortPress: self.coord.pushComposeView/*TODO: fill in stuff*/ + ){ + VStack{ + Image(systemName: "arrowshape.turn.up.left.fill") + Text("reply").font(.system(size: 7)).fontWeight(.none) + } + } + } +} + + +/*struct MessageViewMain_Previews: PreviewProvider { + static var previews: some View { + MessageViewMain() + } +}*/ + + diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/MapView.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/MapView.swift new file mode 100644 index 0000000000000000000000000000000000000000..bf632f12ab02cd0ac1ed373bd8c8e5c5d3f02e7b --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/MapView.swift @@ -0,0 +1,30 @@ +// +// MapView.swift +// enzevalos_iphone +// +// Created by Sabina on 16.03.20. +// Copyright © 2020 fu-berlin. All rights reserved. +// + +import SwiftUI +import MapKit + +struct MapView: UIViewRepresentable { + func makeUIView(context: Context) -> MKMapView { + MKMapView(frame: .zero) + } + + func updateUIView(_ uiView: MKMapView, context: Context) { + let coordinate = CLLocationCoordinate2D( + latitude: 52.5065116, longitude: 13.1438676) + let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0) + let region = MKCoordinateRegion(center: coordinate, span: span) + uiView.setRegion(region, animated: true) + } +} + +struct MapView_Previews: PreviewProvider { + static var previews: some View { + MapView() + } +} diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/ProfileEmoji.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/ProfileEmoji.swift new file mode 100644 index 0000000000000000000000000000000000000000..3192fa32e5e53cc574502d245b2c89741eeb8957 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewChildren/ProfileEmoji.swift @@ -0,0 +1,29 @@ +// +// SwiftUIView.swift +// enzevalos_iphone +// +// Created by Fatima on 16/03/2020. +// Copyright © 2020 fu-berlin. All rights reserved. +// + +import SwiftUI +/* +struct ProfileEmoji: View { + var body: some View { + Image("profileEmoji") + .resizable() + .frame(width: 130.0, height: 110.0) + .clipShape(Circle()) + .overlay( + Circle().stroke(Color.white, lineWidth: 2)) + .shadow(radius: 8) + } +} + +struct ProfileEmoji_Previews: PreviewProvider { + static var previews: some View { + ProfileEmoji() + } +} + */ + diff --git a/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewMain.swift b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewMain.swift new file mode 100644 index 0000000000000000000000000000000000000000..015dd2246855c9fa3ad057a9810f995ea6ced912 --- /dev/null +++ b/enzevalos_iphone/SwiftUI/Read/Tabbed Views/SenderViewMain.swift @@ -0,0 +1,192 @@ +// +// SenderViewMain.swift +// enzevalos_iphone +// +// Created by fatimaaa96 on 12.03.20. +// Copyright © 2020 fu-berlin. All rights reserved. +// + + + +import SwiftUI + +//map, Memoji picture, sender information and phishing detail +struct SenderViewMain: View { + + + let mail:PersistentMail + + + var body: some View { + VStack { + ZStack { + MapView() + .frame(height: 250) + HStack (spacing: -5) { + Spacer() + .frame(width: 60) + // ProfileEmoji() + //.offset(y: 105) + .padding(.bottom, -270) + Button (action: { + print ("Edit activated") + }) { + + Text("Edit") + .font(.system(size: 9)) + + }.padding(.top, 190) + + }.offset(y: 60) + + + } + + Spacer() + + VStack(alignment: .leading) { + + Spacer() + .frame(height: 70) + + // TODO: add reference about sender information (additionally to be done: link update to data base ?!) + Text("Sender:") + .font(.subheadline) + .padding(.bottom, 5) + + MoreDetailsSender() + + Divider() + + VStack (alignment: .leading){ + + Text("CC:") + .font(.subheadline) + .padding(.bottom, 8) + + HStack (spacing: 20){ + + Text("Email 1") + Text("Email 2") + Text("Email 3") + + }.font(.system(size: 12)) + + }.padding([.top, .bottom], 5) + + Divider() + + VStack (alignment: .leading){ + + Text("BCC:") + .font(.subheadline) + .padding(.bottom, 8) + + HStack (spacing: 20){ + + Text("Email 1") + Text("Email 2") + Text("Email 3") + + }.font(.system(size: 12)) + + }.padding([.top, .bottom], 5) + + Divider() + + DropDown() + + Spacer() + + }.padding() + + Spacer() + + } + } +} + +/* +struct SenderViewMain_Previews: PreviewProvider { + static var previews: some View { + SenderViewMain() + } +} + */ + +struct MoreDetailsSender: View { + @State private var moreDetails = false + var body: some View { + VStack (alignment: .leading, spacing: 20) { + + HStack(alignment: .top) { + Text("Details") + .foregroundColor(.blue) + .font(.system(size: 10)) + + Button (action: { + self.moreDetails.toggle() + }) { + + Image(systemName: moreDetails ? "chevron.up" : "chevron.down") + .resizable() + .frame(width: 12.0, height: 7.0) + } + } + + if moreDetails { + + HStack { + + Spacer() + .frame(width: 40) + + VStack(alignment: .leading){ + Text("Last message received on:") + Text("Last message sent on:") + Text("Total number of messages sent:") + + } .font(.system(size: 10)) + + } + + } + } + } +} + +// important TODO: add phishing elements +struct DropDown: View { + @State private var clicked = false + var body: some View { + VStack (alignment: .leading, spacing: 20) { + + HStack(alignment: .top) { + Text("Phishing:") + .font(.subheadline) + + Button (action: { + self.clicked.toggle() + }) { + + Image(systemName: clicked ? "chevron.up" : "chevron.down") + } + } + + if clicked { + + HStack { + + Spacer() + .frame(width: 70) + + Text ("Here comes the text with phishing details.") //TODO: Add content for phishing details + .font(.system(size: 12)) + } + + + } + }.padding([.top, .bottom], 5) + } +} +