another.im-ios/ConversationsClassic/View/Screens/Conversation/ConversationMessageRow.swift
2024-07-01 14:14:20 +02:00

75 lines
2.7 KiB
Swift

import Foundation
import SwiftUI
struct ConversationMessageRow: View {
@EnvironmentObject var store: AppStore
let message: Message
@State private var offset: CGSize = .zero
var body: some View {
VStack(spacing: 0) {
HStack(spacing: 0) {
if isOutgoing() {
Spacer()
MessageAttr(message: message)
.padding(.trailing, 4)
}
ConversationMessageContainer(message: message, isOutgoing: isOutgoing())
.background(isOutgoing() ? Color.Material.greenDark100 : Color.Main.white)
.clipShape(ConversationMessageBubble(isOutgoing: isOutgoing()))
if !isOutgoing() {
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
withAnimation(.easeOut(duration: 0.1)) {
if value.translation.width <= -90 {
Vibration.success.vibrate()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
store.dispatch(.conversationAction(.setReplyText(message.body ?? "")))
withAnimation(.easeOut(duration: 0.1)) {
offset = .zero
}
}
} else {
offset = .zero
}
}
}
)
}
.sharedListRow()
}
private func isOutgoing() -> Bool {
message.from == store.state.conversationsState.currentChat?.account
}
}
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)
}
}