mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Help!
This commit is contained in:
parent
7e80accfad
commit
ce3aacba63
8 changed files with 258 additions and 35 deletions
|
|
@ -4810,9 +4810,6 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Contacts" : {
|
||||
|
||||
},
|
||||
"contacts %@" : {
|
||||
"extractionState" : "migrated",
|
||||
|
|
@ -6315,6 +6312,15 @@
|
|||
},
|
||||
"Direct" : {
|
||||
|
||||
},
|
||||
"Direct Message Help" : {
|
||||
|
||||
},
|
||||
"Direct messages are using the new public key infrastructure to encrypt the message." : {
|
||||
|
||||
},
|
||||
"Direct messages are using the shared key for the channel when communicating with this node." : {
|
||||
|
||||
},
|
||||
"direct.messages" : {
|
||||
"localizations" : {
|
||||
|
|
@ -7204,7 +7210,7 @@
|
|||
"Favorites" : {
|
||||
|
||||
},
|
||||
"Favorites and nodes with recent messages show up at the top of the list. Contacts using the shared key display an open lock, nodes with a private key show a green lock and a red key with a slash will show up if a key has changed for a contact. Long press to favorite or mute the contact or delete a conversation." : {
|
||||
"Favorites and nodes with recent messages show up at the top of the contact list." : {
|
||||
|
||||
},
|
||||
"Fifteen Minutes" : {
|
||||
|
|
@ -11272,6 +11278,9 @@
|
|||
},
|
||||
"Long Name: %@" : {
|
||||
|
||||
},
|
||||
"Long press to favorite or mute the contact or delete a conversation." : {
|
||||
|
||||
},
|
||||
"Longitude" : {
|
||||
|
||||
|
|
@ -14527,6 +14536,9 @@
|
|||
},
|
||||
"Message" : {
|
||||
|
||||
},
|
||||
"Message Status Options" : {
|
||||
|
||||
},
|
||||
"message.details" : {
|
||||
"localizations" : {
|
||||
|
|
@ -15406,6 +15418,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Node Encryption Status" : {
|
||||
|
||||
},
|
||||
"Node History" : {
|
||||
|
||||
|
|
@ -16665,6 +16680,9 @@
|
|||
},
|
||||
"Public Key" : {
|
||||
|
||||
},
|
||||
"Public Key Encryption" : {
|
||||
|
||||
},
|
||||
"Public Key Mismatch" : {
|
||||
|
||||
|
|
@ -19763,6 +19781,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Shared Key" : {
|
||||
|
||||
},
|
||||
"Short Name" : {
|
||||
|
||||
|
|
@ -20995,6 +21016,9 @@
|
|||
},
|
||||
"The public key authorized to send admin messages to this node." : {
|
||||
|
||||
},
|
||||
"The public key does not match the key that was used previously, delete the node and let it negotatiate keys again. Usually the other user did a factory reset, but it could indicate a security issue." : {
|
||||
|
||||
},
|
||||
"The region where you will be using your radios." : {
|
||||
|
||||
|
|
@ -22519,6 +22543,9 @@
|
|||
},
|
||||
"Website" : {
|
||||
|
||||
},
|
||||
"What does the lock mean?" : {
|
||||
|
||||
},
|
||||
"What is Meshtastic?" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@
|
|||
DD6193792863875F00E59241 /* SerialConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6193782863875F00E59241 /* SerialConfig.swift */; };
|
||||
DD6F65722C6AB8EC0053C113 /* SecureInput.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F65712C6AB8EC0053C113 /* SecureInput.swift */; };
|
||||
DD6F65742C6CB80A0053C113 /* View.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F65732C6CB80A0053C113 /* View.swift */; };
|
||||
DD6F65762C6EA5490053C113 /* AckErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F65752C6EA5490053C113 /* AckErrors.swift */; };
|
||||
DD6F65792C6EADE60053C113 /* DirectMessagesHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F65782C6EADE60053C113 /* DirectMessagesHelp.swift */; };
|
||||
DD6F657B2C6EC2900053C113 /* LockLegend.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD6F657A2C6EC2900053C113 /* LockLegend.swift */; };
|
||||
DD73FD1128750779000852D6 /* PositionLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD73FD1028750779000852D6 /* PositionLog.swift */; };
|
||||
DD769E0328D18BF1001A3F05 /* DeviceMetricsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */; };
|
||||
DD77093B2AA1ABB8007A8BF0 /* BluetoothTips.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD77093A2AA1ABB8007A8BF0 /* BluetoothTips.swift */; };
|
||||
|
|
@ -349,6 +352,9 @@
|
|||
DD68BAE72C417A74004C01A0 /* MeshtasticDataModelV 40.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 40.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD6F65712C6AB8EC0053C113 /* SecureInput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecureInput.swift; sourceTree = "<group>"; };
|
||||
DD6F65732C6CB80A0053C113 /* View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = View.swift; sourceTree = "<group>"; };
|
||||
DD6F65752C6EA5490053C113 /* AckErrors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AckErrors.swift; sourceTree = "<group>"; };
|
||||
DD6F65782C6EADE60053C113 /* DirectMessagesHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DirectMessagesHelp.swift; sourceTree = "<group>"; };
|
||||
DD6F657A2C6EC2900053C113 /* LockLegend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockLegend.swift; sourceTree = "<group>"; };
|
||||
DD73FD1028750779000852D6 /* PositionLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionLog.swift; sourceTree = "<group>"; };
|
||||
DD769E0228D18BF0001A3F05 /* DeviceMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceMetricsLog.swift; sourceTree = "<group>"; };
|
||||
DD77093A2AA1ABB8007A8BF0 /* BluetoothTips.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BluetoothTips.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -710,6 +716,16 @@
|
|||
path = Module;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DD6F65772C6EAB860053C113 /* Help */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD6F65752C6EA5490053C113 /* AckErrors.swift */,
|
||||
DD6F65782C6EADE60053C113 /* DirectMessagesHelp.swift */,
|
||||
DD6F657A2C6EC2900053C113 /* LockLegend.swift */,
|
||||
);
|
||||
path = Help;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DD7709392AA1ABA1007A8BF0 /* Tips */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -902,6 +918,7 @@
|
|||
DDC2E18D26CE25CB0042C5E4 /* Helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DD6F65772C6EAB860053C113 /* Help */,
|
||||
DD3CC6BD28E4CD9800FA9159 /* BatteryGauge.swift */,
|
||||
DD3CC24B2C498D6C001BD3A2 /* BatteryCompact.swift */,
|
||||
DDB75A222A13CDA9006ED576 /* BatteryLevelCompact.swift */,
|
||||
|
|
@ -1300,6 +1317,7 @@
|
|||
DD3CC6BE28E4CD9800FA9159 /* BatteryGauge.swift in Sources */,
|
||||
DD6193772862F90F00E59241 /* CannedMessagesConfig.swift in Sources */,
|
||||
DD3619152B1EF9F900C41C8C /* LocationsHandler.swift in Sources */,
|
||||
DD6F65792C6EADE60053C113 /* DirectMessagesHelp.swift in Sources */,
|
||||
25F5D5C02C3F6DA6008036E3 /* Router.swift in Sources */,
|
||||
DDDB444A29F8AA3A00EE2349 /* CLLocationCoordinate2D.swift in Sources */,
|
||||
25C49D902C471AEA0024FBD1 /* Constants.swift in Sources */,
|
||||
|
|
@ -1358,6 +1376,7 @@
|
|||
251926852C3BA97800249DF5 /* FavoriteNodeButton.swift in Sources */,
|
||||
D9C983A02B79D0E800BDBE6A /* AlertButton.swift in Sources */,
|
||||
DD86D4112881D16900BAEB7A /* WriteCsvFile.swift in Sources */,
|
||||
DD6F65762C6EA5490053C113 /* AckErrors.swift in Sources */,
|
||||
DDDB445029F8AC9C00EE2349 /* UIImage.swift in Sources */,
|
||||
DD86D40F2881BE4C00BAEB7A /* CsvDocument.swift in Sources */,
|
||||
DDB75A142A0593E2006ED576 /* OfflineTileManager.swift in Sources */,
|
||||
|
|
@ -1385,6 +1404,7 @@
|
|||
DD15E4F52B8BFC8E00654F61 /* PaxCounterLog.swift in Sources */,
|
||||
25F5D5C22C3F6E4B008036E3 /* AppState.swift in Sources */,
|
||||
DD3CC6C028E7A60700FA9159 /* MessagingEnums.swift in Sources */,
|
||||
DD6F657B2C6EC2900053C113 /* LockLegend.swift in Sources */,
|
||||
DD97E96628EFD9820056DDA4 /* MeshtasticLogo.swift in Sources */,
|
||||
DDAB580D2B0DAA9E00147258 /* Routes.swift in Sources */,
|
||||
D93068D52B812B700066FBC8 /* MessageDestination.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ enum RoutingError: Int, CaseIterable, Identifiable {
|
|||
case .notAuthorized:
|
||||
return "routing.notauthorized".localized
|
||||
case .pkiFailed:
|
||||
return "routing.pkiFailed".localized
|
||||
return "routing.pkifailed".localized
|
||||
case .pkiUnknownPubkey:
|
||||
return "routing.pkiunknownpubkey".localized
|
||||
}
|
||||
|
|
@ -77,7 +77,7 @@ enum RoutingError: Int, CaseIterable, Identifiable {
|
|||
case .noChannel:
|
||||
return Color.orange
|
||||
case .tooLarge:
|
||||
return Color.red
|
||||
return Color.orange
|
||||
case .noResponse:
|
||||
return Color.orange
|
||||
case .dutyCycleLimit:
|
||||
|
|
|
|||
|
|
@ -25,22 +25,3 @@ struct MessagesTip: Tip {
|
|||
Image(systemName: "bubble.left.and.bubble.right")
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 17.0, macOS 14.0, *)
|
||||
struct ContactsTip: Tip {
|
||||
|
||||
var id: String {
|
||||
return "tip.messages.contacts"
|
||||
}
|
||||
var title: Text {
|
||||
// Text("tip.messages.contacts.title")
|
||||
Text("Contacts")
|
||||
}
|
||||
var message: Text? {
|
||||
// Text("tip.messages.contacts.message")
|
||||
Text("Favorites and nodes with recent messages show up at the top of the list. Contacts using the shared key display an open lock, nodes with a private key show a green lock and a red key with a slash will show up if a key has changed for a contact. Long press to favorite or mute the contact or delete a conversation.")
|
||||
}
|
||||
var image: Image? {
|
||||
Image(systemName: "person.circle")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
44
Meshtastic/Views/Helpers/Help/AckErrors.swift
Normal file
44
Meshtastic/Views/Helpers/Help/AckErrors.swift
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// IAQScale.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright Garth Vander Houwen 4/24/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct AckErrors: View {
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Message Status Options")
|
||||
.font(.title2)
|
||||
HStack {
|
||||
RoundedRectangle(cornerRadius: 5)
|
||||
.fill(.orange)
|
||||
.frame(width: 20, height: 12)
|
||||
Text("Acknowledged by another node")
|
||||
.font(.caption)
|
||||
.foregroundStyle(.orange)
|
||||
}
|
||||
ForEach(RoutingError.allCases) { re in
|
||||
HStack {
|
||||
RoundedRectangle(cornerRadius: 5)
|
||||
.fill(re.color)
|
||||
.frame(width: 20, height: 12)
|
||||
Text(re.display)
|
||||
.font(.caption)
|
||||
.foregroundStyle(re.color)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct AckErrorsPreviews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
VStack {
|
||||
AckErrors()
|
||||
}
|
||||
}
|
||||
}
|
||||
75
Meshtastic/Views/Helpers/Help/DirectMessagesHelp.swift
Normal file
75
Meshtastic/Views/Helpers/Help/DirectMessagesHelp.swift
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// DirectMessagesHelp.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright Garth Vander Houwen on 8/15/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct DirectMessagesHelp: View {
|
||||
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
Text("Direct Message Help")
|
||||
.font(.title)
|
||||
.padding(.vertical)
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Image(systemName: "star.fill")
|
||||
.foregroundColor(.yellow)
|
||||
.padding(.bottom)
|
||||
Text("Favorites and nodes with recent messages show up at the top of the contact list.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom)
|
||||
}
|
||||
HStack {
|
||||
Image(systemName: "hand.tap")
|
||||
.padding(.bottom)
|
||||
Text("Long press to favorite or mute the contact or delete a conversation.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
.padding(.bottom)
|
||||
}
|
||||
}
|
||||
if idiom == .phone {
|
||||
VStack(alignment: .leading) {
|
||||
LockLegend()
|
||||
AckErrors()
|
||||
}
|
||||
} else {
|
||||
HStack(alignment: .top) {
|
||||
LockLegend()
|
||||
AckErrors()
|
||||
}
|
||||
}
|
||||
#if targetEnvironment(macCatalyst)
|
||||
Spacer()
|
||||
Button {
|
||||
dismiss()
|
||||
} label: {
|
||||
Label("close", systemImage: "xmark")
|
||||
}
|
||||
.buttonStyle(.bordered)
|
||||
.buttonBorderShape(.capsule)
|
||||
.controlSize(.large)
|
||||
.padding(.bottom)
|
||||
#endif
|
||||
}
|
||||
.frame(minHeight: 0, maxHeight: .infinity, alignment: .leading)
|
||||
.padding()
|
||||
.presentationDetents([.large])
|
||||
.presentationContentInteraction(.scrolls)
|
||||
.presentationDragIndicator(.visible)
|
||||
.presentationBackgroundInteraction(.enabled(upThrough: .large))
|
||||
}
|
||||
}
|
||||
|
||||
struct DirectMessagesHelpPreviews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
VStack {
|
||||
AckErrors()
|
||||
}
|
||||
}
|
||||
}
|
||||
61
Meshtastic/Views/Helpers/Help/LockLegend.swift
Normal file
61
Meshtastic/Views/Helpers/Help/LockLegend.swift
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// LockLegend.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright Garth Vander Houwen 8/15/24.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct LockLegend: View {
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Node Encryption Status")
|
||||
.font(.title2)
|
||||
Text("What does the lock mean?")
|
||||
.padding(.bottom)
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Image(systemName: "lock.open.fill")
|
||||
.foregroundColor(.yellow)
|
||||
Text("Shared Key")
|
||||
.fontWeight(.semibold)
|
||||
}
|
||||
Text("Direct messages are using the shared key for the channel when communicating with this node.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
.padding(.bottom)
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Image(systemName: "lock.fill")
|
||||
.foregroundColor(.green)
|
||||
Text("Public Key Encryption")
|
||||
.fontWeight(.semibold)
|
||||
}
|
||||
Text("Direct messages are using the new public key infrastructure to encrypt the message.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
.padding(.bottom)
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
Image(systemName: "key.slash")
|
||||
.foregroundColor(.red)
|
||||
Text("Public Key Mismatch")
|
||||
.fontWeight(.semibold)
|
||||
}
|
||||
Text("The public key does not match the key that was used previously, delete the node and let it negotatiate keys again. Usually the other user did a factory reset, but it could indicate a security issue.")
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
.padding(.bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LockLegendPreviews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
VStack {
|
||||
LockLegend()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,9 +28,10 @@ struct UserList: View {
|
|||
@State private var hopsAway: Double = -1.0
|
||||
@State private var roleFilter = false
|
||||
@State private var deviceRoles: Set<Int> = []
|
||||
@State var isEditingFilters = false
|
||||
@State private var editingFilters = false
|
||||
@State private var showingHelp = false
|
||||
@State private var showingTrustConfirm: Bool = false
|
||||
|
||||
|
||||
var boolFilters: [Bool] {[
|
||||
isFavorite,
|
||||
isOnline,
|
||||
|
|
@ -59,9 +60,6 @@ struct UserList: View {
|
|||
let dateFormatString = (localeDateFormat ?? "MM/dd/YY")
|
||||
VStack {
|
||||
List(selection: $userSelection) {
|
||||
if #available(iOS 17.0, macOS 14.0, *) {
|
||||
TipView(ContactsTip(), arrowEdge: .bottom)
|
||||
}
|
||||
ForEach(users) { (user: UserEntity) in
|
||||
let mostRecent = user.messageList.last
|
||||
let lastMessageTime = Date(timeIntervalSince1970: TimeInterval(Int64((mostRecent?.messageTimestamp ?? 0 ))))
|
||||
|
|
@ -196,9 +194,12 @@ struct UserList: View {
|
|||
}
|
||||
.listStyle(.plain)
|
||||
.navigationTitle(String.localizedStringWithFormat("contacts %@".localized, String(users.count == 0 ? 0 : users.count)))
|
||||
.sheet(isPresented: $isEditingFilters) {
|
||||
.sheet(isPresented: $editingFilters) {
|
||||
NodeListFilter(filterTitle: "Contact Filters", viaLora: $viaLora, viaMqtt: $viaMqtt, isOnline: $isOnline, isPkiEncrypted: $isPkiEncrypted, isFavorite: $isFavorite, isEnvironment: $isEnvironment, distanceFilter: $distanceFilter, maximumDistance: $maxDistance, hopsAway: $hopsAway, roleFilter: $roleFilter, deviceRoles: $deviceRoles)
|
||||
}
|
||||
.sheet(isPresented: $showingHelp) {
|
||||
DirectMessagesHelp()
|
||||
}
|
||||
.onChange(of: searchText) { _ in
|
||||
searchUserList()
|
||||
}
|
||||
|
|
@ -229,25 +230,39 @@ struct UserList: View {
|
|||
.onFirstAppear {
|
||||
searchUserList()
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .trailing) {
|
||||
.safeAreaInset(edge: .bottom, alignment: .leading) {
|
||||
HStack {
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
isEditingFilters = !isEditingFilters
|
||||
showingHelp = !showingHelp
|
||||
}
|
||||
}) {
|
||||
Image(systemName: !isEditingFilters ? "line.3.horizontal.decrease.circle" : "line.3.horizontal.decrease.circle.fill")
|
||||
Image(systemName: !editingFilters ? "questionmark.circle" : "questionmark.circle.fill")
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
.tint(Color(UIColor.secondarySystemBackground))
|
||||
.foregroundColor(.accentColor)
|
||||
.buttonStyle(.borderedProminent)
|
||||
|
||||
Spacer()
|
||||
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
editingFilters = !editingFilters
|
||||
}
|
||||
}) {
|
||||
Image(systemName: !editingFilters ? "line.3.horizontal.decrease.circle" : "line.3.horizontal.decrease.circle.fill")
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
.tint(Color(UIColor.secondarySystemBackground))
|
||||
.foregroundColor(.accentColor)
|
||||
.buttonStyle(.borderedProminent)
|
||||
|
||||
}
|
||||
.controlSize(.regular)
|
||||
.padding(5)
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.padding(.bottom, 5)
|
||||
.searchable(text: $searchText, placement: users.count > 10 ? .navigationBarDrawer(displayMode: .always) : .automatic, prompt: "Find a contact")
|
||||
.disableAutocorrection(true)
|
||||
.scrollDismissesKeyboard(.immediately)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue