Meshtastic-Apple/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift

152 lines
3.9 KiB
Swift
Raw Normal View History

import SwiftUI
struct TextMessageField: View {
static let maxbytes = 228
@EnvironmentObject var bleManager: BLEManager
2024-02-17 13:26:09 -07:00
let destination: MessageDestination
@Binding var replyMessageId: Int64
@FocusState.Binding var isFocused: Bool
let onSubmit: () -> Void
@State private var typingMessage: String = ""
@State private var totalBytes = 0
@State private var sendPositionWithMessage = false
var body: some View {
#if targetEnvironment(macCatalyst)
HStack {
if destination.showAlertButton {
Spacer()
AlertButton { typingMessage += "🔔 Alert Bell Character! \u{7}" }
}
Spacer()
RequestPositionButton(action: requestPosition)
TextMessageSize(maxbytes: Self.maxbytes, totalBytes: totalBytes).padding(.trailing)
}
#endif
HStack(alignment: .top) {
ZStack {
TextField("message", text: $typingMessage, axis: .vertical)
.onChange(of: typingMessage, perform: { value in
totalBytes = value.utf8.count
// Only mess with the value if it is too big
if totalBytes > Self.maxbytes {
let firstNBytes = Data(typingMessage.utf8.prefix(Self.maxbytes))
if let maxBytesString = String(data: firstNBytes, encoding: String.Encoding.utf8) {
// Set the message back to the last place where it was the right size
typingMessage = maxBytesString
} else {
print("not a valid UTF-8 sequence")
}
}
})
.keyboardType(.default)
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Button("dismiss.keyboard") {
isFocused = false
}
.font(.subheadline)
if destination.showAlertButton {
Spacer()
AlertButton { typingMessage += "🔔 Alert Bell Character! \u{7}" }
}
Spacer()
RequestPositionButton(action: requestPosition)
TextMessageSize(maxbytes: Self.maxbytes, totalBytes: totalBytes)
}
}
.padding(.horizontal, 8)
.focused($isFocused)
.multilineTextAlignment(.leading)
.frame(minHeight: 50)
.keyboardShortcut(.defaultAction)
.onSubmit {
#if targetEnvironment(macCatalyst)
sendMessage()
#endif
}
Text(typingMessage)
.opacity(0)
.padding(.all, 0)
}
.overlay(RoundedRectangle(cornerRadius: 20).stroke(.tertiary, lineWidth: 1))
.padding(.bottom, 15)
Button(action: sendMessage) {
Image(systemName: "arrow.up.circle.fill")
.font(.largeTitle)
.foregroundColor(.accentColor)
}
}
.padding(.all, 15)
}
private func requestPosition() {
let userLongName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown"
sendPositionWithMessage = true
typingMessage = "📍 " + userLongName + " \(destination.positionShareMessage)."
}
private func sendMessage() {
let messageSent = bleManager.sendMessage(
message: typingMessage,
toUserNum: destination.userNum,
channel: destination.channelNum,
isEmoji: false,
replyID: replyMessageId
)
if messageSent {
typingMessage = ""
isFocused = false
replyMessageId = 0
onSubmit()
if sendPositionWithMessage {
let positionSent = bleManager.sendPosition(
channel: destination.channelNum,
destNum: destination.positionDestNum,
wantResponse: destination.wantPositionResponse
)
if positionSent {
print("Location Sent")
}
}
}
}
}
2024-02-17 13:26:09 -07:00
private extension MessageDestination {
var positionShareMessage: String {
switch self {
case .user: return "has shared their position and requested a response with your position"
case .channel: return "has shared their position with you"
}
}
var positionDestNum: Int64 {
switch self {
2024-02-17 13:26:09 -07:00
case let .user(user): return user.num
case .channel: return Int64(BLEManager.emptyNodeNum)
}
}
var showAlertButton: Bool {
switch self {
case .user: return false
case .channel: return true
}
}
var wantPositionResponse: Bool {
switch self {
case .user: return true
case .channel: return false
}
}
}