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

Send button enables/disables now, solved with very inelegant hack.

Should be revised later with architecture changes.
Fixed a typo in LetterboxModel.
parent 31ceb411
Branches
No related tags found
1 merge request!76Resolve "InboxView & MailListView improvements"
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
3FB75DC525FFA75C00919925 /* ComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FB75DC425FFA75B00919925 /* ComposeView.swift */; }; 3FB75DC525FFA75C00919925 /* ComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FB75DC425FFA75B00919925 /* ComposeView.swift */; };
3FB75DC925FFA77800919925 /* RecipientRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FB75DC825FFA77800919925 /* RecipientRowView.swift */; }; 3FB75DC925FFA77800919925 /* RecipientRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FB75DC825FFA77800919925 /* RecipientRowView.swift */; };
3FB75DCD25FFD37400919925 /* RecipientListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FB75DCC25FFD37400919925 /* RecipientListView.swift */; }; 3FB75DCD25FFD37400919925 /* RecipientListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FB75DCC25FFD37400919925 /* RecipientListView.swift */; };
3FEFF41E260A899100A7F9CC /* ComposeHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FEFF41D260A899100A7F9CC /* ComposeHeaderView.swift */; };
4705E31A25AE36710065FF90 /* SMIMEMailTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4705E31925AE36710065FF90 /* SMIMEMailTest.swift */; }; 4705E31A25AE36710065FF90 /* SMIMEMailTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4705E31925AE36710065FF90 /* SMIMEMailTest.swift */; };
4706D65F225B7B6B00B3F1D3 /* ItunesHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4706D65E225B7B6B00B3F1D3 /* ItunesHandler.swift */; }; 4706D65F225B7B6B00B3F1D3 /* ItunesHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4706D65E225B7B6B00B3F1D3 /* ItunesHandler.swift */; };
4706D661225CD21D00B3F1D3 /* ExportKeyHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4706D660225CD21D00B3F1D3 /* ExportKeyHelper.swift */; }; 4706D661225CD21D00B3F1D3 /* ExportKeyHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4706D660225CD21D00B3F1D3 /* ExportKeyHelper.swift */; };
...@@ -304,6 +305,7 @@ ...@@ -304,6 +305,7 @@
3FB75DC425FFA75B00919925 /* ComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeView.swift; sourceTree = "<group>"; }; 3FB75DC425FFA75B00919925 /* ComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeView.swift; sourceTree = "<group>"; };
3FB75DC825FFA77800919925 /* RecipientRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientRowView.swift; sourceTree = "<group>"; }; 3FB75DC825FFA77800919925 /* RecipientRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecipientRowView.swift; sourceTree = "<group>"; };
3FB75DCC25FFD37400919925 /* RecipientListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipientListView.swift; sourceTree = "<group>"; }; 3FB75DCC25FFD37400919925 /* RecipientListView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecipientListView.swift; sourceTree = "<group>"; };
3FEFF41D260A899100A7F9CC /* ComposeHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeHeaderView.swift; sourceTree = "<group>"; };
434D0E988CDFB6D2D46C1EA8 /* Pods_enzevalos_iphoneUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_enzevalos_iphoneUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 434D0E988CDFB6D2D46C1EA8 /* Pods_enzevalos_iphoneUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_enzevalos_iphoneUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
4705E31925AE36710065FF90 /* SMIMEMailTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMIMEMailTest.swift; sourceTree = "<group>"; }; 4705E31925AE36710065FF90 /* SMIMEMailTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMIMEMailTest.swift; sourceTree = "<group>"; };
4706D65E225B7B6B00B3F1D3 /* ItunesHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItunesHandler.swift; sourceTree = "<group>"; }; 4706D65E225B7B6B00B3F1D3 /* ItunesHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ItunesHandler.swift; sourceTree = "<group>"; };
...@@ -1230,6 +1232,7 @@ ...@@ -1230,6 +1232,7 @@
3FB75DCC25FFD37400919925 /* RecipientListView.swift */, 3FB75DCC25FFD37400919925 /* RecipientListView.swift */,
47E04DDE255D3CF600189320 /* ComposeModel.swift */, 47E04DDE255D3CF600189320 /* ComposeModel.swift */,
3FB75DC425FFA75B00919925 /* ComposeView.swift */, 3FB75DC425FFA75B00919925 /* ComposeView.swift */,
3FEFF41D260A899100A7F9CC /* ComposeHeaderView.swift */,
); );
path = Compose; path = Compose;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -1908,6 +1911,7 @@ ...@@ -1908,6 +1911,7 @@
97BDE0432429188500B0BF03 /* BadgeProgressView.swift in Sources */, 97BDE0432429188500B0BF03 /* BadgeProgressView.swift in Sources */,
47C822682438A85C005BCE73 /* SenderDetails.swift in Sources */, 47C822682438A85C005BCE73 /* SenderDetails.swift in Sources */,
47C8225824379EAE005BCE73 /* FloatingActionButton.swift in Sources */, 47C8225824379EAE005BCE73 /* FloatingActionButton.swift in Sources */,
3FEFF41E260A899100A7F9CC /* ComposeHeaderView.swift in Sources */,
47B71AAD2538354A00CA87C6 /* NewOnboardingView.swift in Sources */, 47B71AAD2538354A00CA87C6 /* NewOnboardingView.swift in Sources */,
AD97DFBE241F97A300C35B95 /* OnboardingIntroInfoSection.swift in Sources */, AD97DFBE241F97A300C35B95 /* OnboardingIntroInfoSection.swift in Sources */,
47BCAF40259CFE110008FE4B /* AddButton.swift in Sources */, 47BCAF40259CFE110008FE4B /* AddButton.swift in Sources */,
......
//
// ComposeHeaderView.swift
// enzevalos_iphone
//
// Created by Chris Offner on 23.03.21.
// Copyright © 2021 fu-berlin. All rights reserved.
//
import SwiftUI
/// A view that contains the Cancel and Send buttons for an email.
struct ComposeViewHeader: View {
@Environment(\.presentationMode) var presentationMode
@ObservedObject var model: ComposeModel
@State private var encryptionOn = true
var body: some View {
VStack {
// Grab handle in top center
Capsule()
.fill(Color(.lightGray))
.frame(width: 70, height: 5)
ZStack {
HStack {
// Cancel button
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}
Spacer()
Button("Send") {
model.sendMail()
presentationMode.wrappedValue.dismiss()
}
.disabled(model.recipientsModel.hasNoRecipients)
}
Toggle("", isOn: $encryptionOn)
.toggleStyle(EncryptionToggleStyle())
.labelsHidden()
}
}
}
/// Custom styling for the encryption toggle in ComposeViewHeader.
struct EncryptionToggleStyle: ToggleStyle {
func makeBody(configuration: Configuration) -> some View {
Button {
configuration.isOn.toggle()
} label: {
// Separate labels required for desired scaling transition between states
if configuration.isOn {
encryptedButtonLabel
} else {
unencryptedButtonLabel
}
}
.frame(width: 40, height: 40)
}
/// Label style for encryption button when encryption is activated.
private var encryptedButtonLabel: some View {
ZStack {
Circle()
.stroke(Color.blue, lineWidth: 2)
Image(systemName: "lock.fill")
.font(Font.system(size: 24, weight: Font.Weight.light))
.foregroundColor(.blue)
}
.transition(AnyTransition.opacity.combined(with: .scale))
}
/// Label style for encryption button when encryption is deactivated.
private var unencryptedButtonLabel: some View {
ZStack {
Circle()
.fill(Color(UIColor.tertiaryLabel))
Image(systemName: "lock.slash.fill")
.font(Font.system(size: 24, weight: Font.Weight.light))
.foregroundColor(.white)
}
.transition(AnyTransition.opacity.combined(with: .scale))
}
}
}
...@@ -13,7 +13,7 @@ class ComposeModel: ObservableObject { ...@@ -13,7 +13,7 @@ class ComposeModel: ObservableObject {
@Published var subject = "" @Published var subject = ""
@Published var body = "" @Published var body = ""
@Published var encryptionOff = false @Published var encryptionOff = false
var recipientsModel: RecipientsModel = RecipientsModel() @Published var recipientsModel: RecipientsModel = RecipientsModel()
init(preData: PreMailData?) { init(preData: PreMailData?) {
if let preData = preData { if let preData = preData {
...@@ -23,6 +23,7 @@ class ComposeModel: ObservableObject { ...@@ -23,6 +23,7 @@ class ComposeModel: ObservableObject {
addAddresses(preData.cc, model: recipientsModel.ccModel) addAddresses(preData.cc, model: recipientsModel.ccModel)
addAddresses(preData.bcc, model: recipientsModel.bccModel) addAddresses(preData.bcc, model: recipientsModel.bccModel)
} }
recipientsModel.parentComposeModel = self
} }
// TODO: Add security state // TODO: Add security state
......
...@@ -20,13 +20,13 @@ struct ComposeView: View { ...@@ -20,13 +20,13 @@ struct ComposeView: View {
var body: some View { var body: some View {
VStack { VStack {
// Top bar with Cancel and Send button // Top bar with Cancel and Send button
ComposeViewHeader() ComposeViewHeader(model: model)
.environmentObject(model)
Divider() Divider()
// "To" recipients // "To" recipients
RecipientField(model: model.recipientsModel.toModel) RecipientField(model: model.recipientsModel.toModel)
Divider() Divider()
// "Cc/Bcc" recipients // "Cc/Bcc" recipients
...@@ -38,7 +38,6 @@ struct ComposeView: View { ...@@ -38,7 +38,6 @@ struct ComposeView: View {
.foregroundColor(Color(UIColor.tertiaryLabel)) .foregroundColor(Color(UIColor.tertiaryLabel))
TextField("", text: $model.subject) TextField("", text: $model.subject)
.autocapitalization(.none) .autocapitalization(.none)
.frame(minWidth: 0, maxWidth: .infinity)
} }
Divider() Divider()
...@@ -47,90 +46,7 @@ struct ComposeView: View { ...@@ -47,90 +46,7 @@ struct ComposeView: View {
TextEditor(text: $model.body) TextEditor(text: $model.body)
} }
.padding() .padding()
.animation(.default) .animation(.easeInOut)
}
}
/// A view that contains the Cancel and Send buttons for an email.
struct ComposeViewHeader: View {
@Environment(\.presentationMode) var presentationMode
@EnvironmentObject var model: ComposeModel
@State var encryptionOn = true
var body: some View {
VStack {
// Grab handle in top center
Capsule()
.fill(Color(.lightGray))
.frame(width: 70, height: 5)
HStack {
// Cancel button
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}
Spacer()
// Toggle("Use Encryption", isOn: $encryptionOn)
// .foregroundColor(.accentColor)
// .labelsHidden()
// .position(x: geometry.size.width / 3)
//
// Spacer()
// Send button
Button {
model.sendMail()
presentationMode.wrappedValue.dismiss()
} label: {
if model.encryptionOff {
UnencryptedSendButton(grayedOut: model.recipientsModel.hasNoRecipients)
} else {
EncryptedSendButton(grayedOut: model.recipientsModel.hasNoRecipients)
}
}
.disabled(model.recipientsModel.hasNoRecipients)
}
}
}
}
/// Styling for Send button if email gets sent encrypted.
struct EncryptedSendButton: View {
var grayedOut: Bool
var body: some View {
HStack {
Image(systemName: "lock")
.foregroundColor(Color.white)
Spacer()
Text("Send")
.foregroundColor(Color.white)
}
.padding(.horizontal)
.padding(.vertical, 5)
.background(Capsule().fill(grayedOut ? Color(UIColor.tertiaryLabel) : Color.blue))
.frame(width: 101, height: 40)
}
}
/// Styling for Send button if email gets sent unencrypted.
struct UnencryptedSendButton: View {
var grayedOut: Bool
var body: some View {
HStack {
Image(systemName: "lock.open")
.foregroundColor(Color.blue)
Spacer()
Text("Send")
.foregroundColor(Color.blue)
}
.padding(.horizontal)
.padding(.vertical, 5)
.background(Capsule().stroke())
.frame(width: 101, height: 40)
} }
} }
...@@ -169,7 +85,6 @@ struct RecipientField: View { ...@@ -169,7 +85,6 @@ struct RecipientField: View {
if showList || !model.suggestions.isEmpty { if showList || !model.suggestions.isEmpty {
Divider() Divider()
RecipientListView() RecipientListView()
.frame(maxHeight: .infinity)
.environmentObject(model) .environmentObject(model)
} }
} }
...@@ -189,12 +104,17 @@ struct RecipientField: View { ...@@ -189,12 +104,17 @@ struct RecipientField: View {
.firstIndex(of: recipient) .firstIndex(of: recipient)
} }
} }
.padding(2)
} }
/// A TextField into which new recipients can be entered. /// A TextField into which new recipients can be entered.
var NewRecipientTextField: some View { var NewRecipientTextField: some View {
TextField("", text: $model.text) { isEditing in TextField("", text: $model.text) { isEditing in
model.parent?.isEditingCcOrBcc = isEditing if model.type != .to,
let parent = model.parentRecipientModel {
parent.isEditingCcOrBcc = isEditing
}
} onCommit: { } onCommit: {
model.commitText() model.commitText()
// TODO: Fix bug on first Cc or Bcc recipient commit // TODO: Fix bug on first Cc or Bcc recipient commit
...@@ -237,20 +157,32 @@ struct RecipientCapsule: View { ...@@ -237,20 +157,32 @@ struct RecipientCapsule: View {
@Binding var indexOfSelected: Int? @Binding var indexOfSelected: Int?
var body: some View { var body: some View {
ZStack {
Capsule()
.stroke(isSelected ? Color.accentColor : .secondary,
lineWidth: isSelected ? 2 : 1)
HStack { HStack {
Text(name) Text(name)
.fixedSize(horizontal: true, vertical: false)
// Deletion button shown if recipient capsule is selected
if isSelected { if isSelected {
Button(action: removeRecipient) { Button(action: removeRecipient) {
Image(systemName: "xmark") Image(systemName: "xmark")
.font(.caption2)
} }
.transition(.asymmetric(
insertion: AnyTransition
.opacity.combined(with: .slide),
removal: AnyTransition
.opacity.combined(with: .move(edge: .leading)))
)
} }
} }
.foregroundColor(isSelected ? .white : .accentColor) .padding(.horizontal, 8)
.padding(.horizontal, 12)
.padding(.vertical, 2) .padding(.vertical, 2)
.background(Capsule().fill(isSelected ? Color.accentColor : Color(UIColor.tertiaryLabel))) .foregroundColor(isSelected ? .accentColor : .secondary)
}
} }
// TODO: Use actual displayname once it's implemented. // TODO: Use actual displayname once it's implemented.
......
...@@ -15,7 +15,7 @@ class RecipientFieldModel: ObservableObject { ...@@ -15,7 +15,7 @@ class RecipientFieldModel: ObservableObject {
@Published var selectedContacts = [AddressRecord]() @Published var selectedContacts = [AddressRecord]()
@Published var type: RecipientType @Published var type: RecipientType
private var dataprovider: PersistentDataProvider private var dataprovider: PersistentDataProvider
var parent: RecipientsModel? var parentRecipientModel: RecipientsModel?
init(type: RecipientType, dataprovider: PersistentDataProvider) { init(type: RecipientType, dataprovider: PersistentDataProvider) {
self.type = type self.type = type
...@@ -79,6 +79,13 @@ class RecipientFieldModel: ObservableObject { ...@@ -79,6 +79,13 @@ class RecipientFieldModel: ObservableObject {
selectedContacts.append(addr) selectedContacts.append(addr)
text = "" text = ""
suggestions = [] suggestions = []
// TODO: Find better way to manage state and UI updates!
// This is a horrible hack to get UI to refresh for Send button enable/disable state.
// Please fix wherever you find the following line of code. May require architecture
// changes because state changes (currently ) don't propagate through nested models.
// Read: https://rhonabwy.com/2021/02/13/nested-observable-objects-in-swiftui/
parentRecipientModel?.parentComposeModel?.subject += ""
} }
/// Removes contact at index from recipients. /// Removes contact at index from recipients.
...@@ -88,6 +95,7 @@ class RecipientFieldModel: ObservableObject { ...@@ -88,6 +95,7 @@ class RecipientFieldModel: ObservableObject {
} else { } else {
print("ERROR wrong index! \(index) but \(selectedContacts.count)") print("ERROR wrong index! \(index) but \(selectedContacts.count)")
} }
parentRecipientModel?.parentComposeModel?.subject += ""
} }
/// Commits text to addresses. /// Commits text to addresses.
...@@ -96,7 +104,7 @@ class RecipientFieldModel: ObservableObject { ...@@ -96,7 +104,7 @@ class RecipientFieldModel: ObservableObject {
addNewAddress(text) addNewAddress(text)
text = "" text = ""
} }
print(selectedContacts.count) parentRecipientModel?.parentComposeModel?.subject += ""
} }
func addNewAddress(_ address: String) { func addNewAddress(_ address: String) {
......
...@@ -13,6 +13,13 @@ struct RecipientRowView: View { ...@@ -13,6 +13,13 @@ struct RecipientRowView: View {
@EnvironmentObject var model: RecipientFieldModel @EnvironmentObject var model: RecipientFieldModel
var body: some View { var body: some View {
Button {
if let index = model.selectedContacts.firstIndex(where: { $0.email == contact.email }) {
model.deselectContact(at: index)
} else {
model.selectContact(addr: contact)
}
} label: {
HStack { HStack {
// Profile picture // Profile picture
contact.avatar contact.avatar
...@@ -20,8 +27,8 @@ struct RecipientRowView: View { ...@@ -20,8 +27,8 @@ struct RecipientRowView: View {
.frame(width: 30, height: 30) .frame(width: 30, height: 30)
.aspectRatio(contentMode: .fit) .aspectRatio(contentMode: .fit)
.clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/) .clipShape(/*@START_MENU_TOKEN@*/Circle()/*@END_MENU_TOKEN@*/)
.shadow(radius: 3) .shadow(radius: 2)
.padding(.trailing, 8) .padding(EdgeInsets(top: 0, leading: 3, bottom: 0, trailing: 8))
VStack(alignment: .leading) { VStack(alignment: .leading) {
HStack { HStack {
...@@ -29,10 +36,10 @@ struct RecipientRowView: View { ...@@ -29,10 +36,10 @@ struct RecipientRowView: View {
// Currently for debugging purposes we show the email // Currently for debugging purposes we show the email
// before "@" as name because displaynames are all nil. // before "@" as name because displaynames are all nil.
Text(contact.displayname ?? contact.email.components(separatedBy: "@")[0]) Text(contact.displayname ?? contact.email.components(separatedBy: "@")[0])
.foregroundColor(.primary)
Spacer() Spacer()
Text(contact.lastHeardFrom) Text(contact.lastHeardFrom)
.font(.caption) .font(.caption)
.foregroundColor(.secondary)
.padding(.trailing, 16) .padding(.trailing, 16)
} }
...@@ -40,21 +47,15 @@ struct RecipientRowView: View { ...@@ -40,21 +47,15 @@ struct RecipientRowView: View {
// TODO: Decide which email address(es) to show. // TODO: Decide which email address(es) to show.
Text(contact.email) Text(contact.email)
.font(.caption) .font(.caption)
.foregroundColor(.secondary)
} }
.foregroundColor(.secondary)
Spacer() Spacer()
// Adds or removes contact from recipients.
Button(action: {
if let index = model.selectedContacts.firstIndex(where: { $0.email == contact.email }) {
model.deselectContact(at: index)
} else {
model.selectContact(addr: contact)
}
}) {
// TODO: Maybe use more robust identifier (Identifiable + UUID?) // TODO: Maybe use more robust identifier (Identifiable + UUID?)
Image(systemName: model.selectedContacts.contains(where: { $0.email == contact.email }) ? "checkmark.circle.fill" : "circle") Image(systemName: model.selectedContacts.contains {
$0.email == contact.email
} ? "checkmark.circle.fill" : "circle")
.foregroundColor(.accentColor) .foregroundColor(.accentColor)
} }
} }
......
...@@ -37,6 +37,7 @@ class RecipientsModel: ObservableObject { ...@@ -37,6 +37,7 @@ class RecipientsModel: ObservableObject {
let ccModel: RecipientFieldModel let ccModel: RecipientFieldModel
let bccModel: RecipientFieldModel let bccModel: RecipientFieldModel
@Published var showBccField = false @Published var showBccField = false
var parentComposeModel: ComposeModel?
/// Initializes models for "To", "Cc", and "Bcc" fields. /// Initializes models for "To", "Cc", and "Bcc" fields.
init() { init() {
...@@ -44,8 +45,9 @@ class RecipientsModel: ObservableObject { ...@@ -44,8 +45,9 @@ class RecipientsModel: ObservableObject {
toModel = RecipientFieldModel(type: .to, dataprovider: dataprovider) toModel = RecipientFieldModel(type: .to, dataprovider: dataprovider)
ccModel = RecipientFieldModel(type: .ccBcc, dataprovider: dataprovider) ccModel = RecipientFieldModel(type: .ccBcc, dataprovider: dataprovider)
bccModel = RecipientFieldModel(type: .bcc, dataprovider: dataprovider) bccModel = RecipientFieldModel(type: .bcc, dataprovider: dataprovider)
ccModel.parent = self toModel.parentRecipientModel = self
bccModel.parent = self ccModel.parentRecipientModel = self
bccModel.parentRecipientModel = self
} }
/// Used to show or hide Bcc field /// Used to show or hide Bcc field
...@@ -59,9 +61,9 @@ class RecipientsModel: ObservableObject { ...@@ -59,9 +61,9 @@ class RecipientsModel: ObservableObject {
/// Used to deactivate Send button if email has no recipients. /// Used to deactivate Send button if email has no recipients.
var hasNoRecipients: Bool { var hasNoRecipients: Bool {
toModel.selectedContacts.isEmpty && toModel.selectedContacts.isEmpty
ccModel.selectedContacts.isEmpty && && ccModel.selectedContacts.isEmpty
bccModel.selectedContacts.isEmpty && bccModel.selectedContacts.isEmpty
} }
/// String array of email addresses in "To" field. /// String array of email addresses in "To" field.
......
...@@ -45,13 +45,13 @@ enum UIState { ...@@ -45,13 +45,13 @@ enum UIState {
class LetterboxModel: ObservableObject { class LetterboxModel: ObservableObject {
static var instance: LetterboxModel { static var instance: LetterboxModel {
get { get {
if let instance = currentIntstance { if let instance = currentInstance {
return instance return instance
} }
return LetterboxModel() return LetterboxModel()
} }
} }
private static var currentIntstance: LetterboxModel? private static var currentInstance: LetterboxModel?
let mailHandler = MailHandler() let mailHandler = MailHandler()
let dataProvider = PersistentDataProvider.dataProvider let dataProvider = PersistentDataProvider.dataProvider
...@@ -82,20 +82,16 @@ class LetterboxModel: ObservableObject { ...@@ -82,20 +82,16 @@ class LetterboxModel: ObservableObject {
if flags.contains(.reachable) == false { if flags.contains(.reachable) == false {
// The target host is not reachable. // The target host is not reachable.
return .notReachable return .notReachable
} } else if flags.contains(.isWWAN) == true {
else if flags.contains(.isWWAN) == true {
// WWAN connections are OK if the calling application is using the CFNetwork APIs. // WWAN connections are OK if the calling application is using the CFNetwork APIs.
return .reachableViaWWAN return .reachableViaWWAN
} } else if flags.contains(.connectionRequired) == false {
else if flags.contains(.connectionRequired) == false {
// If the target host is reachable and no connection is required then we'll assume that you're on Wi-Fi... // If the target host is reachable and no connection is required then we'll assume that you're on Wi-Fi...
return .reachableViaWiFi return .reachableViaWiFi
} } else if (flags.contains(.connectionOnDemand) == true || flags.contains(.connectionOnTraffic) == true) && flags.contains(.interventionRequired) == false {
else if (flags.contains(.connectionOnDemand) == true || flags.contains(.connectionOnTraffic) == true) && flags.contains(.interventionRequired) == false {
// The connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs and no [user] intervention is needed // The connection is on-demand (or on-traffic) if the calling application is using the CFSocketStream or higher APIs and no [user] intervention is needed
return .reachableViaWiFi return .reachableViaWiFi
} } else {
else {
return .notReachable return .notReachable
} }
} }
...@@ -132,7 +128,7 @@ class LetterboxModel: ObservableObject { ...@@ -132,7 +128,7 @@ class LetterboxModel: ObservableObject {
UserDefaults.standard.register(defaults: ["Signature.Switch": false]) UserDefaults.standard.register(defaults: ["Signature.Switch": false])
UserDefaults.standard.register(defaults: ["Signature.Text": "Verfasst mit Letterbox. Mehr Informationen: http://letterbox-app.org"]) UserDefaults.standard.register(defaults: ["Signature.Text": "Verfasst mit Letterbox. Mehr Informationen: http://letterbox-app.org"])
} }
LetterboxModel.currentIntstance = self LetterboxModel.currentInstance = self
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment