another.im-ios/Monal/another.im/Views/Conversation/ConversationMessageRow.swift

79 lines
3 KiB
Swift
Raw Normal View History

2024-11-23 23:22:07 +00:00
import Foundation
import SwiftUI
struct ConversationMessageRow: View {
2024-12-02 15:50:23 +00:00
@EnvironmentObject var chatWrapper: WrapperXMPP
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)
}
}