another.im-ios/Monal/another.im/Views/Conversation/ConversationMessageRow.swift
2024-12-02 16:50:23 +01:00

79 lines
3 KiB
Swift

import Foundation
import SwiftUI
struct ConversationMessageRow: View {
@EnvironmentObject var chatWrapper: WrapperXMPP
let message: Message
@State private var offset: CGSize = .zero
var body: some View {
VStack(spacing: 0) {
HStack(spacing: 0) {
if !message.isInbound {
Spacer()
MessageAttr(message: message)
.padding(.trailing, 4)
}
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)
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)
}
}