Private
Public Access
1
0

App icon, group member annotations, variable spacing

This commit is contained in:
2025-08-29 21:47:51 -06:00
parent 5f37f82a33
commit 7992c03fb6
7 changed files with 116 additions and 31 deletions

View File

@@ -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