feat(chat-room) 타이핑 중인 것을 알려주는 애니메이션 아이템 추가

This commit is contained in:
Yu Sung
2025-09-04 00:10:12 +09:00
parent 3ca85b248e
commit b74ec15de4

View File

@@ -6,13 +6,79 @@
// //
import SwiftUI import SwiftUI
import Kingfisher
struct TypingIndicatorItemView: View { struct TypingIndicatorItemView: View {
var dotCount: Int = 3
var size: CGFloat = 6
var spacing: CGFloat = 6
var color: Color = .secondary
var period: Double = 1.2 //
let characterName: String
let characterProfileUrl: String
var body: some View { var body: some View {
Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) HStack(alignment: .top, spacing: 9) {
KFImage(URL(string: characterProfileUrl))
.placeholder {
Image(systemName: "person.crop.circle")
.resizable()
.scaledToFit()
}
.resizable()
.frame(width: 30, height: 30)
.clipShape(Circle())
VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 4) {
Text(characterName)
.font(.custom(Font.preRegular.rawValue, size: 12))
.foregroundColor(.white)
}
HStack(spacing: 10) {
TimelineView(.animation) { context in
let t = context.date.timeIntervalSinceReferenceDate
HStack(spacing: spacing) {
ForEach(0..<dotCount, id: \.self) { i in
Circle()
.fill(color)
.frame(width: size, height: size)
.opacity(opacity(for: i, time: t))
}
}
//
.animation(.easeInOut(duration: period / Double(dotCount)).repeatForever(autoreverses: true), value: context.date)
}
}
.padding(.horizontal, 10)
.padding(.vertical, 8)
.background(
Color.black.opacity(0.1)
)
.clipShape(AiMessageBubbleShape())
}
}
.frame(maxWidth: .infinity, alignment: .leading)
}
/// (phase)
private func opacity(for index: Int, time t: TimeInterval) -> Double {
// 0...1 ( )
let base = (t.truncatingRemainder(dividingBy: period)) / period
let phase = base + Double(index) / Double(max(1, dotCount))
let wave = 0.5 + 0.5 * sin(2 * .pi * phase)
// /
return 0.25 + 0.75 * wave
} }
} }
#Preview { #Preview {
TypingIndicatorItemView() TypingIndicatorItemView(
characterName: "보라",
characterProfileUrl: "https://picsum.photos/1000"
)
.padding()
.background(Color.black)
} }