diff --git a/SodaLive/Sources/Chat/Talk/Room/Message/TypingIndicatorItemView.swift b/SodaLive/Sources/Chat/Talk/Room/Message/TypingIndicatorItemView.swift index 621ae8e..21e54cd 100644 --- a/SodaLive/Sources/Chat/Talk/Room/Message/TypingIndicatorItemView.swift +++ b/SodaLive/Sources/Chat/Talk/Room/Message/TypingIndicatorItemView.swift @@ -6,13 +6,79 @@ // import SwiftUI +import Kingfisher 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 { - 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.. 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 { - TypingIndicatorItemView() + TypingIndicatorItemView( + characterName: "보라", + characterProfileUrl: "https://picsum.photos/1000" + ) + .padding() + .background(Color.black) }