Add MailRootView and related components for mail functionality
- Implement MailRootView with navigation and sidebar for mail management. - Create MailSidebarView, ThreadListView, and ThreadDetailView for displaying mail content. - Introduce ComposeView for composing new messages. - Add MailTheme for consistent styling across mail components. - Implement adaptive layouts for iOS and macOS. - Create unit tests for AppNavigationCommand and AppViewModel to ensure correct functionality.
This commit is contained in:
123
swift/Sources/Core/Models/MailModels.swift
Normal file
123
swift/Sources/Core/Models/MailModels.swift
Normal file
@@ -0,0 +1,123 @@
|
||||
import Foundation
|
||||
|
||||
enum Mailbox: String, CaseIterable, Identifiable, Codable {
|
||||
case inbox
|
||||
case starred
|
||||
case sent
|
||||
case drafts
|
||||
case archive
|
||||
|
||||
var id: String { rawValue }
|
||||
|
||||
var title: String {
|
||||
switch self {
|
||||
case .inbox: "Inbox"
|
||||
case .starred: "Starred"
|
||||
case .sent: "Sent"
|
||||
case .drafts: "Drafts"
|
||||
case .archive: "Archive"
|
||||
}
|
||||
}
|
||||
|
||||
var systemImage: String {
|
||||
switch self {
|
||||
case .inbox: "tray.full"
|
||||
case .starred: "star"
|
||||
case .sent: "paperplane"
|
||||
case .drafts: "doc.text"
|
||||
case .archive: "archivebox"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MailPerson: Identifiable, Hashable, Codable {
|
||||
let id: UUID
|
||||
let name: String
|
||||
let email: String
|
||||
|
||||
init(id: UUID = UUID(), name: String, email: String) {
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.email = email
|
||||
}
|
||||
}
|
||||
|
||||
struct MailMessage: Identifiable, Hashable, Codable {
|
||||
let id: UUID
|
||||
let routeID: String
|
||||
let sender: MailPerson
|
||||
let recipients: [MailPerson]
|
||||
let sentAt: Date
|
||||
let body: String
|
||||
let isDraft: Bool
|
||||
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
routeID: String = UUID().uuidString.lowercased(),
|
||||
sender: MailPerson,
|
||||
recipients: [MailPerson],
|
||||
sentAt: Date,
|
||||
body: String,
|
||||
isDraft: Bool = false
|
||||
) {
|
||||
self.id = id
|
||||
self.routeID = routeID
|
||||
self.sender = sender
|
||||
self.recipients = recipients
|
||||
self.sentAt = sentAt
|
||||
self.body = body
|
||||
self.isDraft = isDraft
|
||||
}
|
||||
}
|
||||
|
||||
struct MailThread: Identifiable, Hashable, Codable {
|
||||
let id: UUID
|
||||
let routeID: String
|
||||
var mailbox: Mailbox
|
||||
var subject: String
|
||||
var participants: [MailPerson]
|
||||
var messages: [MailMessage]
|
||||
var isUnread: Bool
|
||||
var isStarred: Bool
|
||||
var tags: [String]
|
||||
|
||||
init(
|
||||
id: UUID = UUID(),
|
||||
routeID: String = UUID().uuidString.lowercased(),
|
||||
mailbox: Mailbox,
|
||||
subject: String,
|
||||
participants: [MailPerson],
|
||||
messages: [MailMessage],
|
||||
isUnread: Bool,
|
||||
isStarred: Bool,
|
||||
tags: [String] = []
|
||||
) {
|
||||
self.id = id
|
||||
self.routeID = routeID
|
||||
self.mailbox = mailbox
|
||||
self.subject = subject
|
||||
self.participants = participants
|
||||
self.messages = messages.sorted { $0.sentAt < $1.sentAt }
|
||||
self.isUnread = isUnread
|
||||
self.isStarred = isStarred
|
||||
self.tags = tags
|
||||
}
|
||||
|
||||
var latestMessage: MailMessage? {
|
||||
messages.max(by: { $0.sentAt < $1.sentAt })
|
||||
}
|
||||
|
||||
var previewText: String {
|
||||
latestMessage?.body.replacingOccurrences(of: "\n", with: " ") ?? ""
|
||||
}
|
||||
|
||||
var lastUpdated: Date {
|
||||
latestMessage?.sentAt ?? .distantPast
|
||||
}
|
||||
}
|
||||
|
||||
struct ComposeDraft: Equatable {
|
||||
var to = ""
|
||||
var subject = ""
|
||||
var body = ""
|
||||
}
|
||||
Reference in New Issue
Block a user