121 lines
2.7 KiB
Swift
121 lines
2.7 KiB
Swift
import SwiftUI
|
|
import Models
|
|
|
|
struct ThreadDetailView: View {
|
|
let thread: ThreadSummary?
|
|
let messages: [MessageSummary]
|
|
@Binding var composeMode: ComposeMode?
|
|
|
|
var body: some View {
|
|
Group {
|
|
if let thread {
|
|
ScrollView {
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
Text(thread.subject ?? "(No Subject)")
|
|
.font(.title2)
|
|
.fontWeight(.semibold)
|
|
.padding()
|
|
|
|
Divider()
|
|
|
|
ForEach(messages) { message in
|
|
MessageView(message: message)
|
|
Divider()
|
|
}
|
|
}
|
|
}
|
|
.toolbar {
|
|
ToolbarItemGroup(placement: .automatic) {
|
|
Button {
|
|
if let last = messages.last {
|
|
composeMode = .reply(to: last)
|
|
}
|
|
} label: {
|
|
Label("Reply", systemImage: "arrowshape.turn.up.left")
|
|
}
|
|
.keyboardShortcut("r", modifiers: .command)
|
|
.help("Reply (⌘R)")
|
|
|
|
Button {
|
|
if let last = messages.last {
|
|
composeMode = .replyAll(to: last)
|
|
}
|
|
} label: {
|
|
Label("Reply All", systemImage: "arrowshape.turn.up.left.2")
|
|
}
|
|
.keyboardShortcut("r", modifiers: [.shift, .command])
|
|
.help("Reply All (⇧⌘R)")
|
|
|
|
Button {
|
|
if let last = messages.last {
|
|
composeMode = .forward(of: last)
|
|
}
|
|
} label: {
|
|
Label("Forward", systemImage: "arrowshape.turn.up.right")
|
|
}
|
|
.keyboardShortcut("f", modifiers: .command)
|
|
.help("Forward (⌘F)")
|
|
}
|
|
}
|
|
} else {
|
|
ContentUnavailableView(
|
|
"No Thread Selected",
|
|
systemImage: "envelope",
|
|
description: Text("Select a thread to read")
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct MessageView: View {
|
|
let message: MessageSummary
|
|
@State private var showHTML = false
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
HStack {
|
|
Text(message.from?.displayName ?? "Unknown")
|
|
.fontWeight(.semibold)
|
|
Spacer()
|
|
if message.bodyHtml != nil {
|
|
Toggle(isOn: $showHTML) {
|
|
Text("HTML")
|
|
.font(.caption)
|
|
}
|
|
.toggleStyle(.button)
|
|
.controlSize(.small)
|
|
}
|
|
Text(message.date, style: .date)
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
|
|
if !message.to.isEmpty {
|
|
Text("To: \(message.to.map(\.displayName).joined(separator: ", "))")
|
|
.font(.caption)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
|
|
if showHTML, let html = message.bodyHtml {
|
|
MessageWebView(html: html)
|
|
.frame(minHeight: 200)
|
|
} else if let bodyText = message.bodyText {
|
|
Text(bodyText)
|
|
.font(.body)
|
|
.textSelection(.enabled)
|
|
} else if let snippet = message.snippet {
|
|
Text(snippet)
|
|
.font(.body)
|
|
.foregroundStyle(.secondary)
|
|
.italic()
|
|
} else {
|
|
Text("Loading body…")
|
|
.font(.body)
|
|
.foregroundStyle(.tertiary)
|
|
}
|
|
}
|
|
.padding()
|
|
}
|
|
}
|