diff --git a/Thunderbird/Thunderbird/EmailDisplay/EmailCellView.swift b/Thunderbird/Thunderbird/EmailDisplay/EmailCellView.swift
index 9acbc3d9..b66eb875 100644
--- a/Thunderbird/Thunderbird/EmailDisplay/EmailCellView.swift
+++ b/Thunderbird/Thunderbird/EmailDisplay/EmailCellView.swift
@@ -6,6 +6,7 @@
//
import SwiftUI
+import EmailAddress
struct EmailCellView: View {
@Environment(FeatureFlags.self) private var flags: FeatureFlags
@@ -22,7 +23,7 @@ struct EmailCellView: View {
let isThread: Bool
init(email: TempEmail) {
- self.senderText = email.senderText
+ self.senderText = email.from[0].label ?? email.from[0].value
self.headerText = email.headerText
self.bodyText = email.bodyText
self.dateSent = email.dateSent
@@ -45,9 +46,10 @@ struct EmailCellView: View {
.font(.headline)
.fontWeight(unread ? .semibold : .regular)
Spacer()
- Text(SmartDateFormatter()
- .dateFormatter(date: dateSent, isSmartDate: !flags.flagForKey(key: Flag.fullDate.rawValue))
-)
+ Text(
+ SmartDateFormatter()
+ .dateFormatter(date: dateSent, isSmartDate: !flags.flagForKey(key: Flag.fullDate.rawValue))
+ )
}.padding(.leading, pinned ? 0 : 20)
HStack {
if newEmail {
@@ -95,16 +97,260 @@ struct EmailCellView: View {
}
#Preview("Email Cell") {
- let tempEmail = TempEmail(
- sender: "Sender5",
- recipients: ["Rhea"],
- headerText: "Email four with a longer set of text",
- bodyText: "This is some nice long text",
+ var tempEmail = TempEmail(
+ from: [EmailAddress("sender1@test.com", label: "Sender1")],
+ sender: [EmailAddress("sender1@test.com", label: "Sender1")],
+ reply: [EmailAddress("sender1@test.com", label: "Sender1")],
+ to: [EmailAddress("rheaThun@thundermail.com", label: "Rhea Thunderbird")],
+ cc: [],
+ bcc: [],
+ headerText: "This is the subject line of the email",
+ bodyText: """
+
+
+
+
+
+
+
+
+
+

+
+
+
Appr=
+ oval requested
+
+ Laurel has requested an approval from you for a group of screen=
+ s.
+
+
+
+
+
+
+ i=
+ OS Alpha screens
+
+
+
+ Pending
+ review
+
+
+
+ 16 screens =E2=80=A2 7 PM UTC, Dec 3, 2025
+
+
+
+
+ |
+ manual set up combined |
+
+
+ |
+ manual set up complete |
+
+
+ |
+ manual set up protocol |
+
+
+ |
+ lrg/WelcomeiOS_v01 |
+
+
+ |
+ manual set up complete (dark mode) |
+
+
+ |
+ lrg/WelcomeiOS_v01 (dark mode) |
+
+
+ |
+ manual set up combined (dark mode) |
+
+
+ |
+ manual set up protocol (dark mode) |
+
+
+ |
+ message-view-threaded v01 |
+
+
+ |
+ message-view v01 |
+
+
+ |
+ message-list-v01 |
+
+
+ |
+ account-drawer-v01 |
+
+
+ |
+ manual set up: email & password |
+ (with 2
+ variants) |
+
+
+ |
+ manual set up: email & password |
+ (with 2
+ variants) |
+
+
+
+
+
+

+
+
+ Let us know if you have any questions:
+ support@zeplin.io
+
+
+ Zeplin Crew
+
+
+
+
+
+
+
+
+
+ """,
dateSent: Date(),
- unread: true,
+ unread: false,
newEmail: false,
- attachments: nil,
- isThread: true,
+ attachments: [Data(), Data()],
+ isThread: false,
pinned: true
)
EmailCellView(email: tempEmail)
diff --git a/Thunderbird/Thunderbird/EmailDisplay/ReadEmailView.swift b/Thunderbird/Thunderbird/EmailDisplay/ReadEmailView.swift
index e0601177..24250ef1 100644
--- a/Thunderbird/Thunderbird/EmailDisplay/ReadEmailView.swift
+++ b/Thunderbird/Thunderbird/EmailDisplay/ReadEmailView.swift
@@ -7,45 +7,32 @@
import SwiftUI
import WebKit
+import EmailAddress
struct ReadEmailView: View {
init(_ email: TempEmail) {
-
self.email = email
-
- self.emailBody = email.bodyText
- self.sender = email.senderText
- self.subject = email.headerText
- self.sentDate = email.dateSent
- self.recipients = email.recipients
- self.attachments = email.attachments
}
private var email: TempEmail
- private var emailBody: String
- private var sender: String
- private var recipients: [String]
- private var subject: String
- private var sentDate: Date
- private var attachments: [Data]!
var body: some View {
NavigationView {
VStack(alignment: .leading, spacing: 20) {
HStack {
- Text(subject)
+ Text(email.headerText)
.font(.title3)
Spacer()
- if attachments != nil {
+ if email.attachments != nil {
Image(systemName: "paperclip").font(.caption)
}
}
ScrollView {
VStack(alignment: .leading) {
- SenderView(sender, sentDate, recipients)
- WebView(htmlString: emailBody).scaledToFill()
- if attachments != nil {
- AttachmentBlockView(attachments)
+ SenderView(email: email)
+ WebView(htmlString: email.bodyText).scaledToFill()
+ if email.attachments != nil {
+ AttachmentBlockView(email.attachments)
}
}
}
@@ -168,31 +155,41 @@ struct WebView: UIViewRepresentable {
}
struct SenderView: View {
- init(_ sender: String, _ sentDate: Date, _ recipients: [String]) {
- self.sender = sender
- self.date = sentDate
- self.recipients = recipients
+ init(email: TempEmail) {
+ from = email.from
+ sender = email.sender
+ recipients = email.cc
+ toText = email.to
+ date = email.dateSent
+ replyTo = email.reply
}
- private var sender: String
- private var recipients: [String]
+ private var from: [EmailAddress]
+ private var sender: [EmailAddress]
+ private var replyTo: [EmailAddress]
+ private var recipients: [EmailAddress]
+ private var toText: [EmailAddress]
private var date: Date
@State private var showingAlert = false
@State private var unimplementedFeatureName: String = ""
+ @State private var showSenderRecipientInfo = false
var body: some View {
HStack {
VStack(alignment: .leading) {
HStack {
- Text(sender).font(.title3)
+ Text(from[0].value).font(.title3)
}
HStack {
- Text("To: \(recipients[0])")
- if recipients.count > 1 {
- Text("+\(recipients.count-1)")
+ Text("To: \(toText[0].label ?? toText[0].value)")
+ if recipients.count > 0 {
+ Text("+\(recipients.count)")
}
}
.font(.subheadline)
.foregroundStyle(.accent)
+ .onTapGesture {
+ showSenderRecipientInfo = true
+ }
}
Spacer()
@@ -211,13 +208,79 @@ struct SenderView: View {
}
}
+ .sheet(isPresented: $showSenderRecipientInfo) {
+ VStack {
+ Text(date.formatted(.dateTime.hour().minute().second().month(.abbreviated).day().year()))
+ .font(.caption2)
+ .frame(maxWidth: .infinity, alignment: .trailing)
+ .padding([.top, .trailing])
+
+ List {
+ Section(header: Text("from_header")) {
+ ForEach(from) { person in
+ ContactCellView(contact: person)
+ }
+ }.listRowSeparator(.hidden)
+
+ if !sender.isEmpty {
+ Section(header: Text("sender_header")) {
+ ForEach(sender) { person in
+ ContactCellView(contact: person)
+ }
+ }.listRowSeparator(.hidden)
+ }
+ if !replyTo.isEmpty {
+ Section(header: Text("reply_to_header")) {
+ ForEach(replyTo) { person in
+ ContactCellView(contact: person)
+ }
+ }.listRowSeparator(.hidden)
+ }
+ Section(header: Text("to_header")) {
+ ForEach(toText) { person in
+ ContactCellView(contact: person)
+ }
+ if !recipients.isEmpty {
+ ForEach(recipients) { person in
+ ContactCellView(contact: person)
+ }
+ }
+ }.listRowSeparator(.hidden)
+
+ }
+ .listSectionSpacing(.compact)
+ }
+ .presentationDetents([.medium])
+
+ }
+ }
+}
+
+struct ContactCellView: View {
+ let contact: EmailAddress
+ init(contact: EmailAddress) {
+ self.contact = contact
+ }
+ var body: some View {
+ HStack {
+ //TODO: Avatar with initials/icon
+ VStack(alignment: .leading) {
+ if contact.label != nil { Text(contact.label!) }
+ Text(contact.value)
+ }.font(.caption)
+ //TODO: button for interaction
+ }
}
}
#Preview {
var tempEmail = TempEmail(
- sender: "Sender@sender.com",
- recipients: ["Rhea Thunderbird", "Roc"],
+ from: [EmailAddress("sender1@test.com", label: "Sender1")],
+ sender: [EmailAddress("sender1@test.com", label: "Sender1")],
+ reply: [EmailAddress("sender1@test.com", label: "Sender1")],
+ to: [EmailAddress("rheaThun@thundermail.com", label: "Rhea Thunderbird")],
+ cc: [],
+ bcc: [],
headerText: "This is the subject line of the email",
bodyText: """
diff --git a/Thunderbird/Thunderbird/Localization/en.lproj/Localizable.strings b/Thunderbird/Thunderbird/Localization/en.lproj/Localizable.strings
index 9fadb14f..608e2ef0 100644
--- a/Thunderbird/Thunderbird/Localization/en.lproj/Localizable.strings
+++ b/Thunderbird/Thunderbird/Localization/en.lproj/Localizable.strings
@@ -47,6 +47,17 @@
"feature_not_implemented" = "This feature has not been implemented yet";
"demo_button" = "Demo";
+//Headers
+"to_header" = "To";
+"from_header" = "From";
+"reply_to_header" = "Reply To";
+"sender_header" = "Sender";
+"cc_header" = "CC";
+"bcc_header" = "BCC";
+"copy_header" = "Copy";
+"blind_copy_header" = "Blind Copy";
+
+
// Other
"next_button" = "Next";
"donation_support" = "Donate";
diff --git a/Thunderbird/Thunderbird/Util/TempEmailModel.swift b/Thunderbird/Thunderbird/Util/TempEmailModel.swift
index eafcf755..7d09d206 100644
--- a/Thunderbird/Thunderbird/Util/TempEmailModel.swift
+++ b/Thunderbird/Thunderbird/Util/TempEmailModel.swift
@@ -8,15 +8,20 @@
import Foundation
import SwiftData
+import EmailAddress
@Model
class TempEmail {
-
- var senderText: String
var headerText: String
var bodyText: String
var dateSent: Date
var uuid: UUID
- var recipients: [String]
+
+ var from: [EmailAddress]
+ var sender: [EmailAddress]
+ var reply: [EmailAddress]
+ var to: [EmailAddress]
+ var cc: [EmailAddress]
+ var bcc: [EmailAddress]
var attachments: [Data]!
// For alignment, bool check likely not final
@@ -26,8 +31,12 @@ class TempEmail {
var pinned: Bool
init(
- sender: String,
- recipients: [String],
+ from: [EmailAddress],
+ sender: [EmailAddress],
+ reply: [EmailAddress],
+ to: [EmailAddress],
+ cc: [EmailAddress],
+ bcc: [EmailAddress],
headerText: String,
bodyText: String,
dateSent: Date,
@@ -37,7 +46,12 @@ class TempEmail {
isThread: Bool,
pinned: Bool
) {
- self.senderText = sender
+ self.from = from
+ self.sender = sender
+ self.reply = reply
+ self.to = to
+ self.cc = cc
+ self.bcc = bcc
self.headerText = headerText
self.bodyText = bodyText
self.dateSent = dateSent
@@ -46,14 +60,17 @@ class TempEmail {
self.attachments = attachments
self.isThread = isThread
self.uuid = UUID()
- self.recipients = recipients
self.pinned = pinned
}
@MainActor static let sampleData = [
TempEmail(
- sender: "Sender1",
- recipients: ["Rhea Thunderbird"],
+ from: [EmailAddress("sender1@test.com", label: "Sender1")],
+ sender: [EmailAddress("sender1@test.com", label: "Sender1")],
+ reply: [EmailAddress("sender1@test.com", label: "Sender1")],
+ to: [EmailAddress("rheaThun@thundermail.com", label: "Rhea Thunderbird")],
+ cc: [],
+ bcc: [],
headerText: "Email one",
bodyText: "This is some nice long text",
dateSent: Date(),
@@ -64,8 +81,12 @@ class TempEmail {
pinned: false
),
TempEmail(
- sender: "Sender1",
- recipients: ["Rhea Thunderbird"],
+ from: [EmailAddress("sender1@test.com", label: "Sender1")],
+ sender: [EmailAddress("sender1@test.com", label: "Sender1")],
+ reply: [EmailAddress("sender1@test.com", label: "Sender1")],
+ to: [EmailAddress("rheaThun@thundermail.com", label: "Rhea Thunderbird")],
+ cc: [],
+ bcc: [],
headerText: "Email two",
bodyText: "This is some nice long text",
dateSent: Date(timeIntervalSinceNow: -6000),
@@ -76,8 +97,12 @@ class TempEmail {
pinned: true
),
TempEmail(
- sender: "Sender2",
- recipients: ["Rhea Thunderbird"],
+ from: [EmailAddress("sendera@test.com", label: "Sendera")],
+ sender: [],
+ reply: [EmailAddress("sender2replyto@test.com", label: "Sender2")],
+ to: [EmailAddress("rheaThun@thundermail.com", label: "Rhea Thunderbird")],
+ cc: [],
+ bcc: [],
headerText: "Email three with a longer set of text",
bodyText: "This is some nice long text",
dateSent: Date(timeIntervalSinceNow: -6200),
@@ -88,8 +113,12 @@ class TempEmail {
pinned: false
),
TempEmail(
- sender: "Sender5",
- recipients: ["Rhea Thunderbird", "Roc Thunderbird Jr", "Roc Thunderbird", "Roc Thunderbird Sr"],
+ from: [EmailAddress("sender3@test.com", label: "Sender3")],
+ sender: [EmailAddress("sender3@test.com", label: "Sender3")],
+ reply: [EmailAddress("sender2@test.com", label: "Sender2")],
+ to: [EmailAddress("rheaThun@thundermail.com", label: "Rhea Thunderbird")],
+ cc: [EmailAddress("rocThun@thundermail.com", label: "Roc Thunderbird"), EmailAddress("rocjrThun@thundermail.com"), EmailAddress("rocsrThun@thundermail.com", label: "Dad")],
+ bcc: [],
headerText: "Email four with a longer set of text",
bodyText: "This is some nice long text",
dateSent: Date(timeIntervalSinceNow: -100000),
@@ -100,8 +129,12 @@ class TempEmail {
pinned: false
),
TempEmail(
- sender: "Sender5",
- recipients: ["Rhea Thunderbird", "Roc Thunderbird"],
+ from: [EmailAddress("sender2@test.com", label: "Sender2")],
+ sender: [EmailAddress("sender2@test.com", label: "Sender2")],
+ reply: [EmailAddress("sender2@test.com", label: "Sender2")],
+ to: [EmailAddress("rheaThun@thundermail.com", label: "Rhea Thunderbird")],
+ cc: [],
+ bcc: [],
headerText: "Email four with a longer set of text",
bodyText: "This is some nice long text",
dateSent: Date(timeIntervalSinceNow: -257000),
@@ -110,18 +143,6 @@ class TempEmail {
attachments: [Data()],
isThread: false,
pinned: false
- ),
- TempEmail(
- sender: "Sender6",
- recipients: ["Rhea Thunderbird", "Roc Thunderbird"],
- headerText: "Email four with a longer set of text",
- bodyText: "This is some nice long text",
- dateSent: Date(timeIntervalSinceReferenceDate: 51_556_900),
- unread: false,
- newEmail: false,
- attachments: [Data()],
- isThread: false,
- pinned: false
)
]