App icon, group member annotations, variable spacing
This commit is contained in:
@@ -9,16 +9,28 @@ import SwiftUI
|
||||
|
||||
struct BubbleView<Content: View>: View
|
||||
{
|
||||
let isFromMe: Bool
|
||||
let date: Date
|
||||
let sender: Display.Sender
|
||||
let content: () -> Content
|
||||
|
||||
init(isFromMe: Bool, @ViewBuilder content: @escaping () -> Content) {
|
||||
self.isFromMe = isFromMe
|
||||
private var isFromMe: Bool { sender.isMe }
|
||||
|
||||
private let tooltipDateFormatter: DateFormatter = {
|
||||
let f = DateFormatter()
|
||||
f.dateFormat = "EEEE, MMMM dd, HH:mm"
|
||||
|
||||
return f
|
||||
}()
|
||||
|
||||
|
||||
init(sender: Display.Sender, date: Date, @ViewBuilder content: @escaping () -> Content) {
|
||||
self.sender = sender
|
||||
self.content = content
|
||||
self.date = date
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
VStack(alignment: isFromMe ? .trailing : .leading) {
|
||||
HStack(alignment: .bottom) {
|
||||
if isFromMe { Spacer(minLength: .minimumBubbleHorizontalPadding) }
|
||||
|
||||
@@ -28,20 +40,24 @@ struct BubbleView<Content: View>: View
|
||||
topLeading: isFromMe ? .dominantCornerRadius : .minorCornerRadius,
|
||||
bottomLeading: .dominantCornerRadius,
|
||||
bottomTrailing: .dominantCornerRadius,
|
||||
topTrailing: isFromMe ? .minorCornerRadius : .dominantCornerRadius,
|
||||
topTrailing: isFromMe ? .minorCornerRadius : .dominantCornerRadius
|
||||
))
|
||||
}
|
||||
|
||||
if !isFromMe { Spacer(minLength: .minimumBubbleHorizontalPadding) }
|
||||
}
|
||||
}
|
||||
.help(tooltipDateFormatter.string(from: date))
|
||||
}
|
||||
}
|
||||
|
||||
struct TextBubbleItemView: View
|
||||
{
|
||||
let text: String
|
||||
let isFromMe: Bool
|
||||
let sender: Display.Sender
|
||||
let date: Date
|
||||
|
||||
private var isFromMe: Bool { sender.isMe }
|
||||
|
||||
var body: some View {
|
||||
let bubbleColor: Color = isFromMe ? .blue : Color(NSColor(name: "grayish", dynamicProvider: { appearance in
|
||||
@@ -49,7 +65,7 @@ struct TextBubbleItemView: View
|
||||
}))
|
||||
let textColor: Color = isFromMe ? .white : .primary
|
||||
|
||||
BubbleView(isFromMe: isFromMe) {
|
||||
BubbleView(sender: sender, date: date) {
|
||||
HStack {
|
||||
Text(text)
|
||||
.foregroundStyle(textColor)
|
||||
@@ -65,12 +81,14 @@ struct TextBubbleItemView: View
|
||||
|
||||
struct ImageItemView: View
|
||||
{
|
||||
let isFromMe: Bool
|
||||
let sender: Display.Sender
|
||||
let date: Date
|
||||
let attachment: Display.ImageAttachment
|
||||
|
||||
@State private var img: NSImage?
|
||||
@Environment(\.xpcClient) var xpcClient
|
||||
|
||||
private let imageMaxWidth: CGFloat = 340.0
|
||||
@State private var containerWidth: CGFloat? = nil
|
||||
|
||||
var aspectRatio: CGFloat {
|
||||
@@ -99,13 +117,13 @@ struct ImageItemView: View
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
BubbleView(isFromMe: isFromMe) {
|
||||
BubbleView(sender: sender, date: date) {
|
||||
if let img {
|
||||
Image(nsImage: img)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(
|
||||
maxWidth: containerWidth
|
||||
maxWidth: CGFloat.minimum(imageMaxWidth, containerWidth ?? imageMaxWidth)
|
||||
)
|
||||
} else {
|
||||
Rectangle()
|
||||
@@ -139,16 +157,18 @@ struct ImageItemView: View
|
||||
|
||||
struct PlaceholderImageItemView: View
|
||||
{
|
||||
let isFromMe: Bool
|
||||
let sender: Display.Sender
|
||||
let date: Date
|
||||
let size: CGSize
|
||||
|
||||
init(isFromMe: Bool, size: CGSize?) {
|
||||
self.isFromMe = isFromMe
|
||||
init(sender: Display.Sender, date: Date, size: CGSize?) {
|
||||
self.sender = sender
|
||||
self.date = date
|
||||
self.size = size ?? CGSize(width: 250.0, height: 100.0)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
BubbleView(isFromMe: isFromMe) {
|
||||
BubbleView(sender: sender, date: date) {
|
||||
Color.gray
|
||||
.frame(width: size.width, height: size.height)
|
||||
}
|
||||
@@ -180,6 +200,24 @@ struct DateItemView: View
|
||||
}
|
||||
}
|
||||
|
||||
struct SenderAttributionView: View
|
||||
{
|
||||
let sender: Display.Sender
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
if sender.isMe { Spacer() }
|
||||
|
||||
Text(sender.displayName)
|
||||
.foregroundStyle(.secondary)
|
||||
.font(.caption2)
|
||||
|
||||
if !sender.isMe { Spacer() }
|
||||
}
|
||||
.padding(.top, 10.0)
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension CGFloat {
|
||||
static let dominantCornerRadius = 16.0
|
||||
static let minorCornerRadius = 4.0
|
||||
|
||||
Reference in New Issue
Block a user