From 066e6b864e4d721429f244818ff74dc960608e81 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Mon, 28 Aug 2023 21:46:04 -0700 Subject: [PATCH] Mock up message improvements --- Meshtastic.xcodeproj/project.pbxproj | 2 +- Meshtastic/Helpers/BLEManager.swift | 2 - .../contents | 4 + .../Persistence/UserEntityExtension.swift | 5 + Meshtastic/Views/ContentView.swift | 3 + Meshtastic/Views/Messages/Contacts.swift | 202 +++++++++--------- pl.lproj/Localizable.strings | 8 +- 7 files changed, 123 insertions(+), 103 deletions(-) diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index 6ff8c283..40e9c479 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -674,8 +674,8 @@ C9483F6B2773016700998F6B /* Map */, DDC2E18D26CE25CB0042C5E4 /* Helpers */, DD47E3D726F2F21A00029299 /* Bluetooth */, - DD47E3CA26F0E50300029299 /* Nodes */, DDC2E18B26CE25A70042C5E4 /* Messages */, + DD47E3CA26F0E50300029299 /* Nodes */, DD4A911C2708C57100501B7E /* Settings */, DDC2E18E26CE25FE0042C5E4 /* ContentView.swift */, ); diff --git a/Meshtastic/Helpers/BLEManager.swift b/Meshtastic/Helpers/BLEManager.swift index ade1b866..375bf513 100644 --- a/Meshtastic/Helpers/BLEManager.swift +++ b/Meshtastic/Helpers/BLEManager.swift @@ -656,8 +656,6 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate } } - - public func sendMessage(message: String, toUserNum: Int64, channel: Int32, isEmoji: Bool, replyID: Int64) -> Bool { var success = false diff --git a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV17.xcdatamodel/contents b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV17.xcdatamodel/contents index 2f6acb17..4a6286e4 100644 --- a/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV17.xcdatamodel/contents +++ b/Meshtastic/Meshtastic.xcdatamodeld/MeshtasticDataModelV17.xcdatamodel/contents @@ -142,6 +142,7 @@ + @@ -202,6 +203,8 @@ + + @@ -325,6 +328,7 @@ + diff --git a/Meshtastic/Persistence/UserEntityExtension.swift b/Meshtastic/Persistence/UserEntityExtension.swift index 6d9f5699..79324752 100644 --- a/Meshtastic/Persistence/UserEntityExtension.swift +++ b/Meshtastic/Persistence/UserEntityExtension.swift @@ -18,4 +18,9 @@ extension UserEntity { self.value(forKey: "adminMessages") as? [MessageEntity] ?? [MessageEntity]() } + + var unreadMessages: Int { + self.receivedMessages?.count ?? 0 + } } + diff --git a/Meshtastic/Views/ContentView.swift b/Meshtastic/Views/ContentView.swift index 146badc1..cb294a23 100644 --- a/Meshtastic/Views/ContentView.swift +++ b/Meshtastic/Views/ContentView.swift @@ -13,6 +13,7 @@ struct ContentView: View { Label("messages", systemImage: "message") } .tag(Tab.contacts) + .badge(42) Connect() .tabItem { Label("bluetooth", systemImage: "antenna.radiowaves.left.and.right") @@ -23,11 +24,13 @@ struct ContentView: View { Label("nodes", systemImage: "flipphone") } .tag(Tab.nodes) + .badge(11) NodeMap() .tabItem { Label("map", systemImage: "map") } .tag(Tab.map) + .badge(4) Settings() .tabItem { Label("settings", systemImage: "gear") diff --git a/Meshtastic/Views/Messages/Contacts.swift b/Meshtastic/Views/Messages/Contacts.swift index 72cfc3de..41b99876 100644 --- a/Meshtastic/Views/Messages/Contacts.swift +++ b/Meshtastic/Views/Messages/Contacts.swift @@ -14,7 +14,7 @@ struct Contacts: View { @EnvironmentObject var bleManager: BLEManager @FetchRequest( - sortDescriptors: [NSSortDescriptor(key: "longName", ascending: true)], + sortDescriptors: [NSSortDescriptor(key: "lastMessage", ascending: true)], animation: .default) private var users: FetchedResults @@ -139,107 +139,116 @@ struct Contacts: View { } Section(header: Text("direct.messages")) { ForEach(users) { (user: UserEntity) in + + let mostRecent = user.messageList.last + 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 if user.num != bleManager.connectedPeripheral?.num ?? 0 { + NavigationLink(destination: UserMessageList(user: user)) { - let mostRecent = user.messageList.last - 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 - HStack { - VStack { - HStack { - CircleText(text: user.shortName ?? "???", color: Color(UIColor(hex: UInt32(user.num))), circleSize: 60, fontSize: (user.shortName ?? "???").isEmoji() ? 42 : 20, textColor: UIColor(hex: UInt32(user.num)).isLight() ? .black : .white) - .padding(.trailing, 5) - VStack { - HStack { - Text(user.longName ?? "unknown".localized).font(.headline) - Spacer() - if user.messageList.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: dateFormatString)) - .font(.subheadline) - } else if lastMessageDay < (currentDay - 1800) { - Text(lastMessageTime.formattedDate(format: dateFormatString)) - .font(.subheadline) - } - } - .brightness(-0.2) - } + ZStack { + Image(systemName: "circle.fill") + .opacity(user.unreadMessages > 0 ? 1 : 0) + .font(.system(size: 10)) + .foregroundColor(.accentColor) + } + + CircleText(text: user.shortName ?? "???", color: Color(UIColor(hex: UInt32(user.num))), circleSize: 45, fontSize: (user.shortName ?? "???").isEmoji() ? 32 : (user.shortName?.count ?? 0 == 4 ? 14 : (user.shortName?.count ?? 0 == 3 ? 18 : 22)), brightness: 0.0, textColor: UIColor(hex: UInt32(user.num)).isLight() ? .black : .white) + + VStack(alignment: .leading){ + HStack{ + Text(user.longName ?? "unknown".localized) + + Spacer() + + if user.messageList.count > 0 { + if lastMessageDay == currentDay { + Text(lastMessageTime, style: .time ) + .font(.system(size: 16)) + .foregroundColor(.secondary) + } else if lastMessageDay == (currentDay - 1) { + Text("Yesterday") + .font(.system(size: 16)) + .foregroundColor(.secondary) + } else if lastMessageDay < (currentDay - 1) && lastMessageDay > (currentDay - 5) { + Text(lastMessageTime.formattedDate(format: dateFormatString)) + .font(.system(size: 16)) + .foregroundColor(.secondary) + } else if lastMessageDay < (currentDay - 1800) { + Text(lastMessageTime.formattedDate(format: dateFormatString)) + .font(.system(size: 16)) + .foregroundColor(.secondary) } - if user.messageList.count > 0 { - HStack(alignment: .top) { - Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")") - .truncationMode(.tail) - .font(.body) - .frame(maxWidth: .infinity, alignment: .leading) - .brightness(-0.2) - } - } - } - .frame(maxWidth: .infinity, maxHeight: 80, alignment: .leading) - .contextMenu { - Button { - user.mute = !user.mute - do { - try context.save() - } catch { - context.rollback() - print("💥 Save User Mute Error") - } - } label: { - Label(user.mute ? "Show Alerts" : "Hide Alerts", systemImage: user.mute ? "bell" : "bell.slash") - } - Button { - let success = bleManager.sendTraceRouteRequest(destNum: user.num, wantResponse: true) - if success { - isPresentingTraceRouteSentAlert = true - } - } label: { - Label("Trace Route", systemImage: "signpost.right.and.left") - } - if user.messageList.count > 0 { - Button(role: .destructive) { - isPresentingDeleteUserMessagesConfirm = true - userSelection = user - } label: { - Label("Delete Messages", systemImage: "trash") - } - } - } - .alert( - "Trace Route Sent", - isPresented: $isPresentingTraceRouteSentAlert - ) { - Button("OK", role: .cancel) { } - } - message: { - Text("This could take a while, response will appear in the mesh log.") - } - .confirmationDialog( - "This conversation will be deleted.", - isPresented: $isPresentingDeleteUserMessagesConfirm, - titleVisibility: .visible - ) { - Button(role: .destructive) { - deleteUserMessages(user: userSelection!, context: context) - context.refresh(node!.user!, mergeChanges: true) - } label: { - Text("delete") - } - } } + +// Image(systemName: "chevron.forward") +// .font(.caption) +// .foregroundColor(.secondary) + } + + if user.messageList.count > 0 { + HStack(alignment: .top) { + Text("\(mostRecent != nil ? mostRecent!.messagePayload! : " ")") + .font(.system(size: 16)) + .foregroundColor(.secondary) + } + } + + } + + } + .frame(height: 90) + .contextMenu { + Button { + user.mute = !user.mute + do { + try context.save() + } catch { + context.rollback() + print("💥 Save User Mute Error") + } + } label: { + Label(user.mute ? "Show Alerts" : "Hide Alerts", systemImage: user.mute ? "bell" : "bell.slash") + } + Button { + let success = bleManager.sendTraceRouteRequest(destNum: user.num, wantResponse: true) + if success { + isPresentingTraceRouteSentAlert = true + } + } label: { + Label("Trace Route", systemImage: "signpost.right.and.left") + } + if user.messageList.count > 0 { + Button(role: .destructive) { + isPresentingDeleteUserMessagesConfirm = true + userSelection = user + } label: { + Label("Delete Messages", systemImage: "trash") } } } - .padding(.top, 10) - .padding(.bottom, 10) + .alert( + "Trace Route Sent", + isPresented: $isPresentingTraceRouteSentAlert + ) { + Button("OK", role: .cancel) { } + } + message: { + Text("This could take a while, response will appear in the mesh log.") + } + .confirmationDialog( + "This conversation will be deleted.", + isPresented: $isPresentingDeleteUserMessagesConfirm, + titleVisibility: .visible + ) { + Button(role: .destructive) { + deleteUserMessages(user: userSelection!, context: context) + context.refresh(node!.user!, mergeChanges: true) + } label: { + Text("delete") + } + } } } } @@ -266,8 +275,7 @@ struct Contacts: View { } } } - } - detail: { + } detail: { if let user = userSelection { UserMessageList(user: user) diff --git a/pl.lproj/Localizable.strings b/pl.lproj/Localizable.strings index c8cf4de8..da664afb 100644 --- a/pl.lproj/Localizable.strings +++ b/pl.lproj/Localizable.strings @@ -1,8 +1,10 @@ /* - Localizable.strings - Meshtastic + Localizable.strings + Meshtastic - Created by Shiv Kokroo ( @kokroo ) on 27/08/23, with contributions from @Marek_SP5ISZ + Copyright(r) Garth Vander Houwen 12/12/22. + + Created by Shiv Kokroo ( @kokroo ) on 27/08/23, with contributions from @Marek_SP5ISZ */ "about"="O programie";