Enter for submit on mac

This commit is contained in:
Garth Vander Houwen 2022-12-17 23:53:06 -08:00
parent 464b74a118
commit ca0b9e66d3
7 changed files with 133 additions and 126 deletions

View file

@ -957,7 +957,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
fetchedMyInfo[0].channels = mutableChannels
do {
try context!.save()
} catch {
print("Failed to clear existing channels from local app database")
}

View file

@ -756,6 +756,7 @@ func channelPacket (channel: Channel, fromNum: Int64, context: NSManagedObjectCo
if fetchedMyInfo.count == 1 {
let newChannel = ChannelEntity(context: context)
newChannel.id = Int32(channel.index)
newChannel.index = Int32(channel.index)
newChannel.uplinkEnabled = channel.settings.uplinkEnabled
newChannel.downlinkEnabled = channel.settings.downlinkEnabled

View file

@ -60,9 +60,9 @@ public func clearTelemetry(destNum: Int64, metricsType: Int32, context: NSManage
}
}
public func deleteChannelMessages(channelIndex: Int32, context: NSManagedObjectContext) {
public func deleteChannelMessages(channel: ChannelEntity, context: NSManagedObjectContext) {
let fetchChannelMessagesRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "MessageEntity")
fetchChannelMessagesRequest.predicate = NSPredicate(format: "channel == %i AND toUser == nil AND admin == false", Int32(channelIndex))
fetchChannelMessagesRequest.predicate = NSPredicate(format: "channel == %i AND toUser == nil AND admin == false", Int32(channel.id))
fetchChannelMessagesRequest.includesPropertyValues = false
do {
let objects = try context.fetch(fetchChannelMessagesRequest) as! [NSManagedObject]
@ -70,7 +70,6 @@ public func deleteChannelMessages(channelIndex: Int32, context: NSManagedObjectC
context.delete(object)
}
try context.save()
context.refreshAllObjects()
} catch let error as NSError {
print("Error: \(error.localizedDescription)")
}

View file

@ -311,9 +311,22 @@ struct ChannelMessageList: View {
.focused($focusedField, equals: .messageText)
.multilineTextAlignment(.leading)
.frame(minHeight: 50)
.keyboardShortcut(.defaultAction)
.onSubmit {
#if targetEnvironment(macCatalyst)
if bleManager.sendMessage(message: typingMessage, toUserNum: 0, channel: channel.index, isEmoji: false, replyID: replyMessageId) {
typingMessage = ""
focusedField = nil
replyMessageId = 0
if sendPositionWithMessage {
if bleManager.sendPosition(destNum: Int64(channel.index), wantAck: true) {
print("Location Sent")
}
}
}
#endif
}
Text(typingMessage).opacity(0).padding(.all, 0)
}
.overlay(RoundedRectangle(cornerRadius: 20).stroke(.tertiary, lineWidth: 1))
.padding(.bottom, 15)

View file

@ -33,82 +33,79 @@ struct Contacts: View {
if node != nil && node!.myInfo != nil && node!.myInfo!.channels != nil {
ForEach(node!.myInfo!.channels!.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in
if channel.name?.lowercased() ?? "" != "admin" && channel.name?.lowercased() ?? "" != "gpio" && channel.name?.lowercased() ?? "" != "serial" {
VStack {
NavigationLink(destination: ChannelMessageList(channel: channel)) {
let mostRecent = channel.allPrivateMessages.last(where: { $0.channel == channel.index })
let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 ))))
let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0
let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0
VStack(alignment: .leading) {
HStack {
CircleText(text: String(channel.index), color: .accentColor, circleSize: 52, fontSize: 40, brightness: 0.1)
.padding(.trailing, 5)
VStack {
HStack {
if channel.name?.isEmpty ?? false {
if channel.role == 1 {
Text(String("PrimaryChannel").camelCaseToWords()).font(.headline)
} else {
Text(String("Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
NavigationLink(destination: ChannelMessageList(channel: channel)) {
let mostRecent = channel.allPrivateMessages.last(where: { $0.channel == channel.index })
let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 ))))
let lastMessageDay = Calendar.current.dateComponents([.day], from: lastMessageTime).day ?? 0
let currentDay = Calendar.current.dateComponents([.day], from: Date()).day ?? 0
VStack(alignment: .leading) {
HStack {
CircleText(text: String(channel.index), color: .accentColor, circleSize: 52, fontSize: 40, brightness: 0.1)
.padding(.trailing, 5)
VStack {
HStack {
if channel.name?.isEmpty ?? false {
if channel.role == 1 {
Text(String("PrimaryChannel").camelCaseToWords()).font(.headline)
} else {
Text(String(channel.name ?? "Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
Spacer()
if channel.allPrivateMessages.count > 0 {
VStack (alignment: .trailing) {
if lastMessageDay == currentDay {
Text(lastMessageTime, style: .time )
.font(.subheadline)
} else if lastMessageDay == (currentDay - 1) {
Text("Yesterday")
.font(.subheadline)
} else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) {
Text(lastMessageTime.formattedDate(format: "MM/dd/yy"))
.font(.subheadline)
} else if lastMessageDay < (currentDay - 1800) {
Text(lastMessageTime.formattedDate(format: "MM/dd/yy"))
.font(.subheadline)
}
}
.brightness(-0.20)
Text(String("Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
} else {
Text(String(channel.name ?? "Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
Spacer()
if channel.allPrivateMessages.count > 0 {
HStack(alignment: .top) {
Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")")
.truncationMode(.tail)
.frame(maxWidth: .infinity, alignment: .leading)
.brightness(-0.20)
.font(.body)
VStack (alignment: .trailing) {
if lastMessageDay == currentDay {
Text(lastMessageTime, style: .time )
.font(.subheadline)
} else if lastMessageDay == (currentDay - 1) {
Text("Yesterday")
.font(.subheadline)
} else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) {
Text(lastMessageTime.formattedDate(format: "MM/dd/yy"))
.font(.subheadline)
} else if lastMessageDay < (currentDay - 1800) {
Text(lastMessageTime.formattedDate(format: "MM/dd/yy"))
.font(.subheadline)
}
}
.brightness(-0.20)
}
}
if channel.allPrivateMessages.count > 0 {
HStack(alignment: .top) {
Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")")
.truncationMode(.tail)
.frame(maxWidth: .infinity, alignment: .leading)
.brightness(-0.20)
.font(.body)
}
}
.frame(maxWidth: .infinity, alignment: .leading)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
.frame(maxWidth: .infinity, maxHeight: 80, alignment: .leading)
.contextMenu {
// Hide mute channel menu item until I can check it in notifications
// Button {
// channel.mute = !channel.mute
//
// do {
// try context.save()
// // Would rather not do this but the merge changes on
// // A single object is only working on mac GVH
// context.refreshAllObjects()
// //context.refresh(channel, mergeChanges: true)
// } catch {
// context.rollback()
// print("💥 Save Channel Mute Error")
// }
// } label: {
// Label(channel.mute ? "Show Alerts" : "Hide Alerts", systemImage: channel.mute ? "bell" : "bell.slash")
// }
Button {
channel.mute = !channel.mute
do {
try context.save()
// Would rather not do this but the merge changes on
// A single object is only working on mac GVH
context.refreshAllObjects()
//context.refresh(channel, mergeChanges: true)
} catch {
context.rollback()
print("💥 Save Channel Mute Error")
}
} label: {
Label(channel.mute ? "Show Alerts" : "Hide Alerts", systemImage: channel.mute ? "bell" : "bell.slash")
}
if channel.allPrivateMessages.count > 0 {
Button(role: .destructive) {
@ -121,12 +118,13 @@ struct Contacts: View {
.confirmationDialog(
"This conversation will be deleted.",
isPresented: $isPresentingDeleteChannelMessagesConfirm,
titleVisibility: .visible
) {
Button(role: .destructive) {
deleteChannelMessages(channelIndex: channel.index, context: context)
context.refreshAllObjects()
deleteChannelMessages(channel: channel, context: context)
} label: {
Text("delete")
}

View file

@ -308,6 +308,21 @@ struct UserMessageList: View {
.focused($focusedField, equals: .messageText)
.multilineTextAlignment(.leading)
.frame(minHeight: 50)
.keyboardShortcut(.defaultAction)
.onSubmit {
#if targetEnvironment(macCatalyst)
if bleManager.sendMessage(message: typingMessage, toUserNum: user.num, channel: 0, isEmoji: false, replyID: replyMessageId) {
typingMessage = ""
focusedField = nil
replyMessageId = 0
if sendPositionWithMessage {
if bleManager.sendPosition(destNum: user.num, wantAck: true) {
print("Location Sent")
}
}
}
#endif
}
Text(typingMessage).opacity(0).padding(.all, 0)
}
.overlay(RoundedRectangle(cornerRadius: 20).stroke(.tertiary, lineWidth: 1))

View file

@ -9,7 +9,7 @@ import CoreData
func generateChannelKey(size: Int) -> String {
var keyData = Data(count: size)
let result = keyData.withUnsafeMutableBytes {
_ = keyData.withUnsafeMutableBytes {
SecRandomCopyBytes(kSecRandomDefault, size, $0.baseAddress!)
}
return keyData.base64EncodedString()
@ -25,73 +25,55 @@ struct Channels: View {
var node: NodeInfoEntity?
@State private var isPresentingEditView = false
@State private var selectedIndex: Int32 = -1
var body: some View {
ScrollView {
if node != nil && node?.myInfo != nil {
Grid() {
GridRow {
Text("Index")
.font(.caption2)
Text("name")
.font(.caption2)
if sizeCategory <= ContentSizeCategory.extraExtraLarge {
Text("Up/down link")
.font(.caption2)
}
Text("Edit")
.font(.caption2)
Text("Delete")
.font(.caption2)
}
NavigationStack {
List {
if node != nil && node?.myInfo != nil {
ForEach(node!.myInfo!.channels?.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in
GridRow {
CircleText(text: String(channel.index), color: .accentColor, circleSize: 32)
Text(((channel.name!.isEmpty ? "Primary" : channel.name) ?? "Primary").camelCaseToWords())
if sizeCategory <= ContentSizeCategory.extraExtraLarge {
Button(action: {
selectedIndex = channel.index
isPresentingEditView = true
print("Tapity tap")
}) {
VStack(alignment: .leading) {
HStack {
if channel.uplinkEnabled {
Image(systemName: "checkmark.square")
} else {
Image(systemName: "square")
}
if channel.downlinkEnabled {
Image(systemName: "checkmark.square")
} else {
Image(systemName: "square")
CircleText(text: String(channel.index), color: .accentColor, circleSize: 45, fontSize: 36, brightness: 0.1)
.padding(.trailing, 5)
VStack {
HStack {
if channel.name?.isEmpty ?? false {
if channel.role == 1 {
Text(String("PrimaryChannel").camelCaseToWords()).font(.headline)
} else {
Text(String("Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
} else {
Text(String(channel.name ?? "Channel \(channel.index)").camelCaseToWords()).font(.headline)
}
}
}
}
}
Button {
print("Edit Channel")
} label: {
Label("", systemImage: "square.and.pencil")
}
Button(role: .destructive) {
print("Delete Channel")
} label: {
Label("", systemImage: "trash")
}
.disabled(channel.role == 1)
}
}
}
if node!.myInfo!.channels?.array.count ?? 0 < 8 {
}
if node?.myInfo?.channels?.array.count ?? 0 < 8 {
Button {
let key = generateChannelKey(size: 32)
print("Add Channel Key \(key) ")
Button {
print("Add Channel")
} label: {
Label("Add Channel", systemImage: "plus.square")
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
} label: {
Label("Add Channel", systemImage: "plus.square")
}
.buttonStyle(.bordered)
.buttonBorderShape(.capsule)
.controlSize(.large)
.padding()
}
}
.navigationTitle("Channels")