mirror of
https://github.com/yattee/yattee.git
synced 2026-02-19 17:29:45 +00:00
95 lines
3.1 KiB
Swift
95 lines
3.1 KiB
Swift
//
|
|
// CommentsPillView.swift
|
|
// Yattee
|
|
//
|
|
// A rounded pill showing a comment preview that slides in from the bottom.
|
|
// Tapping expands to full comments view.
|
|
// Collapses to just avatar when isCollapsed is true.
|
|
//
|
|
|
|
import SwiftUI
|
|
import NukeUI
|
|
|
|
struct CommentsPillView: View {
|
|
let comment: Comment
|
|
let isCollapsed: Bool
|
|
var fillWidth: Bool = false
|
|
/// When true, uses smaller sizing for the collapsed state (e.g. on narrow devices).
|
|
var compact: Bool = false
|
|
let onTap: () -> Void
|
|
|
|
var body: some View {
|
|
Button(action: onTap) {
|
|
HStack(spacing: isCollapsed ? 0 : 12) {
|
|
// Show icon when collapsed, avatar when expanded
|
|
if isCollapsed {
|
|
collapsedIconView
|
|
} else {
|
|
avatarView
|
|
}
|
|
|
|
// Text content - only in layout when expanded
|
|
if !isCollapsed {
|
|
textContent
|
|
}
|
|
}
|
|
.frame(maxWidth: (!isCollapsed && fillWidth) ? .infinity : nil, alignment: .leading)
|
|
.padding(.horizontal, isCollapsed ? (compact ? 6 : 10) : 16)
|
|
.padding(.vertical, isCollapsed ? (compact ? 6 : 10) : 12)
|
|
.contentShape(Rectangle())
|
|
}
|
|
.buttonStyle(.plain)
|
|
.contentShape(Capsule())
|
|
.glassBackground(.regular, in: .capsule, fallback: .thinMaterial)
|
|
.shadow(color: .black.opacity(0.1), radius: 8, y: 2)
|
|
}
|
|
|
|
private var collapsedIconView: some View {
|
|
let size: CGFloat = compact ? 28 : 32
|
|
return Image(systemName: "bubble.left.and.bubble.right")
|
|
.font(.system(size: compact ? 16 : 18, weight: .medium))
|
|
.foregroundStyle(.primary)
|
|
.frame(width: size, height: size)
|
|
}
|
|
|
|
private var avatarView: some View {
|
|
LazyImage(url: comment.author.thumbnailURL) { state in
|
|
if let image = state.image {
|
|
image
|
|
.resizable()
|
|
.aspectRatio(contentMode: .fill)
|
|
} else {
|
|
Circle()
|
|
.fill(.quaternary)
|
|
.overlay {
|
|
Text(String(comment.author.name.prefix(1)))
|
|
.font(.caption2)
|
|
.fontWeight(.medium)
|
|
.foregroundStyle(.secondary)
|
|
}
|
|
}
|
|
}
|
|
.frame(width: 32, height: 32)
|
|
.clipShape(Circle())
|
|
}
|
|
|
|
private var textContent: some View {
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
// Author name
|
|
Text(comment.author.name)
|
|
.font(.caption2)
|
|
.fontWeight(.semibold)
|
|
.foregroundStyle(.primary)
|
|
.lineLimit(1)
|
|
|
|
// 2-line excerpt of comment
|
|
Text(comment.content)
|
|
.font(.footnote)
|
|
.foregroundStyle(.secondary)
|
|
.lineLimit(2)
|
|
.multilineTextAlignment(.leading)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
}
|
|
}
|