Skip to content
Snippets Groups Projects
Commit 6fc5858f authored by cruxfilm's avatar cruxfilm
Browse files

Merge branch 'dev'

Conflicts:
	enzevalos_iphone/SwiftUI/Inbox/MailListView.swift
parents 662cdf94 628b129e
Branches
No related tags found
1 merge request!76Resolve "InboxView & MailListView improvements"
//
// ContactView.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 30.10.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import SwiftUI
struct ContactTabView <C: DisplayContact, M: DisplayMail>: View {
public var contact: C
public var fromMail: M?
public var derivedFromKey: Bool = true
private var keyID: String? {
return fromMail?.signatureKey?.keyID
}
var body: some View {
VStack{
VStack(alignment: .leading, spacing: 3) {
Text(contact.name)
.font(.title)
rating
if contact.name != contact.email {
row(label: "ContactView.EMail.Name", data: contact.email, action: composeMail)
.padding(.bottom, 10)
}
key
}.padding(5)
icon
backgroundInfo
Spacer()
}
}
private var icon: some View {
contact.avatar
.resizable()
.frame(width: 130, height: 110)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
.padding(10)
}
private var key: AnyView? {
if let keyID = keyID {
var label: LocalizedStringKey = "ContactView.Key.Signature.Name"
if fromMail == nil {
label = "ContactView.Key.Primary.Name"
}
return AnyView(row(label: label, data: keyID, action: inspectKey))
} else {
return AnyView(Button("Invitation.Welcome.Try.InvitationMail", action: invite))
}
}
private var rating: some View {
HStack {
Text("ContactView.Rating.Name")
.foregroundColor(.gray)
Text(contact.rating(mail: fromMail).name)
.foregroundColor(contact.rating(mail: fromMail).color)
}
}
var backgroundInfo: some View {
VStack (alignment: .leading, spacing: 3){
if derivedFromKey, let discovery = contact.primaryKey?.discovery {
row(label: "ContactView.KnownSince", data: discovery.dateToString, action: nil) // TODO Add discovery mail?
} else if let discovery = contact.discovery {
row(label: "ContactView.KnownSince", data: discovery.dateToString, action: nil)
} else {
row(label: "ContactView.KnownSince.Unknown", data:nil, action: nil)
}
if derivedFromKey, let last = contact.primaryKey?.lastSeen {
row(label: "ContactView.LastMail.Name", data: last.dateToString, action: nil)
}
else if let last = contact.last {
row(label: "ContactView.LastMail.Name", data: last.dateToString, action: nil)
} else {
row(label: "ContactView.LastMail.No", data: nil, action: nil)
}
} .padding(10)
}
private func row(label: LocalizedStringKey, data: String?, action: ((()->Void)?)) -> some View {
HStack {
Text(label)
.foregroundColor(.gray)
if let data = data, let action = action {
Button(data, action: action)
} else if let data = data{
Text(data)
.foregroundColor(.gray)
}
}
}
private func composeMail() {
print("Compose mail!")
}
private func inspectKey() {
print("Inspect key!")
}
private func invite() {
print("Invite user!")
}
}
struct ContactTabView_Previews: PreviewProvider {
static var previews: some View {
ContactTabView<ProxyContact, ProxyMail>(contact: ProxyData.Alice)
ContactTabView<ProxyContact, ProxyMail>(contact: ProxyData.Bob)
ContactTabView<ProxyContact, ProxyMail>(contact: ProxyData.Charlie)
}
}
//
// ContactView.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 30.10.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import SwiftUI
// TODO: Add contact book, related addresses, related keys, related mails.
struct ContactView <C: DisplayContact, M: DisplayMail>: View {
public var contact: C
public var fromMail: M?
public var derivedFromKey: Bool = true
var body: some View {
TabView{
ForEach(Tabs, id: \.id ){ tab in
tab.content
.tabItem {
tab.image
Text(tab.description)
}
}
}
.navigationTitle("ContactView.Title")
}
var Tabs:[Tab] {
get {
return [
Tab(
tab: 0, image: Image(systemName: "touchid"),
description: "ContactView.Tab.Contact.Description",
content:AnyView(ContactTabView(contact: contact, fromMail: fromMail, derivedFromKey: derivedFromKey))
)
]
}
}
}
struct ContactView_Previews: PreviewProvider {
static var previews: some View {
ContactView<ProxyContact, ProxyMail>(contact: ProxyData.Alice)
ContactView<ProxyContact, ProxyMail>(contact: ProxyData.Bob)
ContactView<ProxyContact, ProxyMail>(contact: ProxyData.Charlie)
}
}
......@@ -15,10 +15,6 @@ struct ContactView <C: DisplayContact, M: DisplayMail>: View {
public var fromMail: M?
public var derivedFromKey: Bool = true
// init(contact: C, fromMail: M? = nil) {
// self.contact = contact
// }
var body: some View {
TabView{
ForEach(Tabs, id: \.id ){ tab in
......
//
// MailListView.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 16.10.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import SwiftUI
import CoreData
// TODO: Refactor to Model!
// Updating text -> Last update, updating, no connection....
struct MailListView: View {
@Environment(\.managedObjectContext) var managedObjectContext
var fetchRequest: FetchRequest<MailRecord>
var mails: FetchedResults<MailRecord>{fetchRequest.wrappedValue}
var folderpath: String
var name: String
@State var updating = false
@State var showUser = false
@State var searchText = ""
@State var searchField = 0
@State var searchNow = false
@State var composeMail = false
init(folderpath: String, name: String) {
fetchRequest = MailRecord.mailsInFolderFetchRequest(folderpath: folderpath)
self.folderpath = folderpath
self.name = name
}
var body: some View {
mainView
.navigationBarTitle(name, displayMode: .inline)
.onAppear(perform: {
self.updateMails()
})
.sheet(isPresented: $composeMail) {
ComposeView()
}
}
private var mainView: some View {
VStack (alignment: .leading){
SearchView(searchText: $searchText, searchField: $searchField, searchNow: $searchNow)
.padding(6)
mailList
.padding(-10)
// Toolbar
HStack {
self.idButton
Spacer()
self.lastUpdate
Spacer()
self.composeButton
}
.padding(6)
}
}
private var mailList: some View {
List (self.mails.filter(filterKeyRecord), id: \.self){ record in
NavigationLink(
destination: ReadMainView(model: ReadModel(mail: record))) {
MailRow(mail: record)
}
}
.resignKeyboardOnDragGesture() // hide keyboard when dragging
}
private var idButton: some View {
Button(action: {
print("Go to my id")
}, label: {
Text(NSLocalizedString("KeyID", comment: "id"))
})
}
private var composeButton: some View {
Button(action: {
composeMail = true
}, label: {
Image(systemName: "square.and.pencil").imageScale(.large)
})
}
private var lastUpdate: some View {
var text = NSLocalizedString("Updating", comment: "updating...")
if !updating {
let last = Date()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
dateFormatter.timeStyle = .medium
let dateString = dateFormatter.string(from: last)
text = NSLocalizedString("LastUpdate", comment: "") + " " + dateString
}
return Button(action: updateMails, label: {Text(text)
.font(.callout)
})
}
func updateMails() {
guard !updating else {
return
}
LetterboxModel.instance.mailHandler.updateFolder(folderpath: folderpath, completionCallback: {error in
if error == nil {
self.updating = false
}
// TODO: Add error message
})
updating = true
}
func filterKeyRecord(keyRecord: MailRecord) -> Bool {
let searchType = SearchType.findType(i: searchField)
if self.searchText.isEmpty || self.searchText == NSLocalizedString("Searchbar.Title", comment: "Search") {
return true
}
let query = self.searchText.lowercased()
if (searchType == .All || searchType == .Sender) && (containsSearchTerms(content: keyRecord.sender.displayname, searchText: query) || containsSearchTerms(content: keyRecord.sender.email, searchText: query)) {
return true
}
else if (searchType == .All || searchType == .Sender) && keyRecord.addresses.filter({containsSearchTerms(content: $0.mailAddress, searchText: query)}).count > 0 {
return true
}
else if (searchType == .All || searchType == .Subject) && containsSearchTerms(content: keyRecord.subject, searchText: query){
return true
}
else if (searchType == .All || searchType == .Body) && containsSearchTerms(content: keyRecord.body, searchText: query){
return true
}
return false
}
}
struct MailListView_Previews: PreviewProvider {
static var previews: some View {
MailListView(folderpath: "INBOX", name: "INBOX")
.environment(\.managedObjectContext, PersistentDataProvider.proxyPersistentDataProvider.persistentContainer.viewContext)
}
}
......@@ -51,6 +51,7 @@ struct MailListView: View {
.padding(-10)
// Toolbar
HStack {
self.idButton
Spacer()
self.lastUpdate
Spacer()
......
//
// PermissionRequestView.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 16.10.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import SwiftUI
struct PermissionRequestView: View {
// TODO: Text should fit to permission request.
@ObservedObject private var model = PermissionModel()
var title: LocalizedStringKey = "Permission.AccessContacts.Title"
var description: LocalizedStringKey = "Permission.AccessContacts.Description"
var body: some View {
VStack(alignment: .center){
Text(title)
.font(.largeTitle)
.padding(.all)
Text(description)
.font(.body)
.padding(.all)
Spacer()
}
}
}
struct PermissionRequestView_Previews: PreviewProvider {
static var previews: some View {
PermissionRequestView()
}
}
//
// SmallContactListView.swift
// enzevalos_iphone
//
// Created by Oliver Wiese on 06.04.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
import SwiftUI
struct SmallContactListView <C: DisplayContact>: View {
let contacts: [C]
var title: String
@State var showList = true
var body: some View {
VStack (alignment: .leading, spacing: 10){
HStack {
Text(title)
.font(.headline)
Button (action: {
self.showList.toggle()
}) {
Image(systemName: showList ? "chevron.up" : "chevron.down")
.resizable()
.frame(width: 12.0, height: 7.0)
}
Spacer()
}
if showList {
ForEach(contacts, id: \.email) {contact in
Group {
HStack {
CircleImage(image: contact.avatar, radius: 40)
VStack (alignment: .leading, spacing: 2){
Text(contact.name)
.font(.subheadline)
Text(contact.email)
.foregroundColor(.gray)
}
Spacer()
Button(action: {self.goToContact(contact: contact)}){
Image(systemName: "chevron.right")
}
}
}
.onTapGesture {
self.goToContact(contact: contact)
}
}
}
}
.padding(10)
}
private func goToContact(contact: C) {
/* TODOguard let con = contact.keyRecord else {
return
} */
return
// AppDelegate.getAppDelegate().readViewCoordinator?.pushContactView(contact: con)
}
}
struct SmallContactListView_Previews: PreviewProvider {
static let alice = ProxyData.Alice
static let bob = ProxyData.Bob
static let charlie = ProxyData.Charlie
static var previews: some View {
VStack{
SmallContactListView(contacts: [alice,bob,charlie], title: "To")
SmallContactListView(contacts: [alice,bob,charlie], title: "To", showList: false)
}
}
}
//
// SenderViewMain.swift
// enzevalos_iphone
//
// Created by fatimaaa96 on 12.03.20.
// Copyright © 2020 fu-berlin. All rights reserved.
//
// 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 CoreLocation
struct SenderViewMain <M: DisplayMail>: View {
// SEE: PersonNameComponents
@EnvironmentObject var model: ReadModel<M>
@State var selectedLandmark: Landmark? = nil
@State var showingLandmarkDetails = false
var body: some View {
ScrollView {
sender
.padding(.top, 110/2-20)
.padding()
.offset(y: (-110/2 + 20))
icon
SmallContactListView(contacts: model.mail.tos, title: NSLocalizedString("To", comment: "To"))
Divider()
SmallContactListView(contacts: model.mail.ccs, title: NSLocalizedString("Cc", comment: "CC"))
Divider()
SmallContactListView(contacts: model.mail.bccs, title: NSLocalizedString("Bcc", comment: "BCC"))
}
}
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))
]
private func selectNextLandmark() {
let landmarks = Landmarks// mail.routingStops
/// This method identifies and moves to the next selected landmark
if let selectedLandmark = selectedLandmark, let currentIndex = landmarks.firstIndex(where: { $0 == selectedLandmark }), currentIndex + 1 < landmarks.endIndex {
self.selectedLandmark = landmarks[currentIndex + 1]
} else {
selectedLandmark = landmarks.first
}
}
private func selectPrevLandmark() {
let landmarks = Landmarks //mail.routingStops
/// This method identifies and moves to the prevoius selected landmark
if let selectedLandmark = selectedLandmark, let currentIndex = landmarks.firstIndex(where: { $0 == selectedLandmark }), currentIndex + -1 >= 0 {
self.selectedLandmark = landmarks[currentIndex - 1]
} else {
selectedLandmark = landmarks.last
}
}
private var icon: some View {
model.mail.sender.avatar
.resizable()
.frame(width: 130, height: 110)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white, lineWidth: 4))
.shadow(radius: 10)
.offset(y: -110/2)
.padding(.bottom, -110/2)
.onTapGesture {
self.goToContact(contact: self.model.mail.sender)
}
}
private var sender: some View {
VStack (alignment: .leading, spacing: 10) {
HStack {
VStack (alignment: .leading) {
Text(NSLocalizedString("Sender", comment: "Sender"))
.font(.headline)
.padding(.bottom, 10)
Text(model.mail.sender.name)
.font(.subheadline)
Text(model.mail.sender.email)
.foregroundColor(.gray)
}
Spacer()
Button(action: {self.goToContact(contact: self.model.mail.sender)}){
Image(systemName: "chevron.right")
}
}
.onTapGesture {
self.goToContact(contact: self.model.mail.sender)
}
HStack{
Text(String(format: NSLocalizedString("ReadView.Sender.Previous", comment: "100 previous received mails"), model.mail.sender.previousMails))
Spacer()
Text(String(format: NSLocalizedString("ReadView.Sender.Responses", comment: "5 previous sent mails"), model.mail.sender.previousResponses))
// TODO: Add last mail date
// TODO: Go to mails?
}
}
.padding(10)
}
private var map: some View {
ZStack {
ZStack {
MapView(landmarks: Landmarks,//mail.routingStops,
selectedLandmark: $selectedLandmark, showingLandmarkDetails: $showingLandmarkDetails)
.frame(height: 300)
HStack {
Button(action: {
/// this button displays the previous selected landmark
self.selectPrevLandmark()
}) {
Text("Button.Prev")
.foregroundColor(.black)
.padding()
.background(Color.white)
.cornerRadius(6)
.shadow(radius: 3)
.padding(.top, 150)
}
Spacer()
Button(action: {
/// this button displays the next selected landmark
self.selectNextLandmark()
}) {
Text("Button.Next")
.foregroundColor(.black)
.padding()
.background(Color.white)
.cornerRadius(6)
.shadow(radius: 3)
.padding(.top, 150)
}
}
} .alert(isPresented: $showingLandmarkDetails) {
/// alert displays the landmark details and gets trigered when the user taps the information button of a landmark
Alert(title: Text("Domain for this location"), message: Text(selectedLandmark?.domain ?? "Missing place information"), dismissButton: .default(Text("OK")) )
}
}
}
private func goToContact(contact: M.C) {
/* guard let con = contact.keyRecord else {
print("No record...")
return
}
AppDelegate.getAppDelegate().readViewCoordinator?.pushContactView(contact: con) */
}
}
struct SenderView_Previews: PreviewProvider {
static var model = ReadModel(mail: ProxyData.SecureMail)
static var previews: some View {
model.currentTab = ReadPart.Header.value
let sim = Simulators<ReadMainView<ProxyMail>>()
return sim.previews(view: ReadMainView(model: model))
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment