2024-11-23 23:22:07 +00:00
|
|
|
import Foundation
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
struct ConversationMessageRow: View {
|
2024-11-25 12:02:36 +00:00
|
|
|
@EnvironmentObject var chatWrapper: MonalChatWrapper
|
2024-11-24 18:42:46 +00:00
|
|
|
let message: Message
|
2024-11-25 12:02:36 +00:00
|
|
|
|
2024-11-23 23:22:07 +00:00
|
|
|
@State private var offset: CGSize = .zero
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
VStack(spacing: 0) {
|
|
|
|
HStack(spacing: 0) {
|
2024-11-25 12:02:36 +00:00
|
|
|
if !message.isInbound {
|
2024-11-23 23:22:07 +00:00
|
|
|
Spacer()
|
2024-11-25 12:02:36 +00:00
|
|
|
MessageAttr(message: message)
|
|
|
|
.padding(.trailing, 4)
|
2024-11-23 23:22:07 +00:00
|
|
|
}
|
2024-11-25 12:02:36 +00:00
|
|
|
ConversationMessageContainer(message: message)
|
|
|
|
.background(message.isInbound ? Color.Material.Shape.white : Color.Material.Shape.alternate)
|
|
|
|
.clipShape(ConversationMessageBubble(isOutgoing: !message.isInbound))
|
|
|
|
if message.isInbound {
|
|
|
|
MessageAttr(message: message)
|
|
|
|
.padding(.leading, 4)
|
2024-11-23 23:22:07 +00:00
|
|
|
Spacer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.padding(.vertical, 10)
|
|
|
|
.padding(.horizontal, 16)
|
|
|
|
.background(Color.clearTappable)
|
|
|
|
.offset(offset)
|
|
|
|
.gesture(
|
|
|
|
DragGesture(minimumDistance: 30, coordinateSpace: .local)
|
|
|
|
.onChanged { value in
|
|
|
|
var width = value.translation.width
|
|
|
|
width = width > 0 ? 0 : width
|
|
|
|
offset = CGSize(width: width, height: 0)
|
|
|
|
}
|
|
|
|
.onEnded { value in
|
|
|
|
let targetWidth: CGFloat = -90
|
|
|
|
withAnimation(.easeOut(duration: 0.1)) {
|
|
|
|
if value.translation.width <= targetWidth {
|
|
|
|
Vibration.success.vibrate()
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
|
|
|
|
withAnimation(.easeOut(duration: 0.1)) {
|
|
|
|
offset = .zero
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
offset = .zero
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if value.translation.width <= targetWidth {
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.02) {
|
|
|
|
// messages.replyText = message.body ?? ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
.listRowInsets(.zero)
|
|
|
|
.listRowSeparator(.hidden)
|
|
|
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
|
|
|
.background(Color.Material.Background.light)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ConversationMessageBubble: Shape {
|
|
|
|
let isOutgoing: Bool
|
|
|
|
|
|
|
|
func path(in rect: CGRect) -> Path {
|
|
|
|
let path = UIBezierPath(
|
|
|
|
roundedRect: rect,
|
|
|
|
byRoundingCorners: isOutgoing ? [.topLeft, .bottomLeft, .bottomRight] : [.topRight, .bottomLeft, .bottomRight],
|
|
|
|
cornerRadii: CGSize(width: 8, height: 10)
|
|
|
|
)
|
|
|
|
return Path(path.cgPath)
|
|
|
|
}
|
|
|
|
}
|