mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Import Contact App Shortcut and add a share url button to the page
This commit is contained in:
parent
d5ce82347e
commit
be36dc6a30
4 changed files with 132 additions and 46 deletions
|
|
@ -7201,6 +7201,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Contact URL" : {
|
||||
|
||||
},
|
||||
"Contacts (%@)" : {
|
||||
"localizations" : {
|
||||
|
|
@ -9994,6 +9997,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Done" : {
|
||||
|
||||
},
|
||||
"Double Tap as Button" : {
|
||||
"localizations" : {
|
||||
|
|
@ -15082,6 +15088,12 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Import Contact" : {
|
||||
|
||||
},
|
||||
"Import Meshtastic Node %@ as a contact" : {
|
||||
|
||||
},
|
||||
"Import Route" : {
|
||||
"localizations" : {
|
||||
|
|
@ -22193,6 +22205,52 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"Position config received: %@" : {
|
||||
"localizations" : {
|
||||
"de" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Positionskonfiguration empfangen: %@"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Configuration de la position reçue : %@"
|
||||
}
|
||||
},
|
||||
"he" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "הגדרות מיקום התקבלו: %@"
|
||||
}
|
||||
},
|
||||
"it" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Configurazione della posizione ricevuta: %@"
|
||||
}
|
||||
},
|
||||
"pl" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Odebrano konfigurację pozycji: %@"
|
||||
}
|
||||
},
|
||||
"se" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Positionskonfiguration mottagen: %@"
|
||||
}
|
||||
},
|
||||
"sr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Конфигурација позиције примљена: %@"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Position Exchange Failed" : {
|
||||
"localizations" : {
|
||||
"it" : {
|
||||
|
|
@ -22467,52 +22525,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"Position config received: %@" : {
|
||||
"localizations" : {
|
||||
"de" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Positionskonfiguration empfangen: %@"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Configuration de la position reçue : %@"
|
||||
}
|
||||
},
|
||||
"he" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "הגדרות מיקום התקבלו: %@"
|
||||
}
|
||||
},
|
||||
"it" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Configurazione della posizione ricevuta: %@"
|
||||
}
|
||||
},
|
||||
"pl" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Odebrano konfigurację pozycji: %@"
|
||||
}
|
||||
},
|
||||
"se" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Positionskonfiguration mottagen: %@"
|
||||
}
|
||||
},
|
||||
"sr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Конфигурација позиције примљена: %@"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Power" : {
|
||||
"localizations" : {
|
||||
"de" : {
|
||||
|
|
@ -26021,6 +26033,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Scan this QR code to add %@ to another device." : {
|
||||
|
||||
},
|
||||
"Screen on for" : {
|
||||
"localizations" : {
|
||||
|
|
@ -28033,6 +28048,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Share Contact QR" : {
|
||||
|
||||
},
|
||||
"Share QR Code" : {
|
||||
"localizations" : {
|
||||
|
|
@ -29711,6 +29729,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Takes a Meshtastic contact URL and saves it to the nodes database" : {
|
||||
|
||||
},
|
||||
"Tapback" : {
|
||||
"localizations" : {
|
||||
|
|
@ -30891,6 +30912,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"The URL for the node to import" : {
|
||||
|
||||
},
|
||||
"There has been no response to a request for device metadata over the admin channel for this node." : {
|
||||
"localizations" : {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
8D3F8A412D44C2A6009EAAA4 /* PowerMetricsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D3F8A402D44C2A6009EAAA4 /* PowerMetricsLog.swift */; };
|
||||
B399E8A42B6F486400E4488E /* RetryButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B399E8A32B6F486400E4488E /* RetryButton.swift */; };
|
||||
B3E905B12B71F7F300654D07 /* TextMessageField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3E905B02B71F7F300654D07 /* TextMessageField.swift */; };
|
||||
BC10380F2DD4334400B00BFA /* AddContactIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC10380E2DD4333C00B00BFA /* AddContactIntent.swift */; };
|
||||
BC47C2EF2CE0017D008245CA /* MessageNodeIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC47C2EE2CE0017D008245CA /* MessageNodeIntent.swift */; };
|
||||
BC6B45FF2CB2F98900723CEB /* SaveChannelSettingsIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BC6B45FE2CB2F98900723CEB /* SaveChannelSettingsIntent.swift */; };
|
||||
BCB613812C67290800485544 /* SendWaypointIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = BCB613802C67290800485544 /* SendWaypointIntent.swift */; };
|
||||
|
|
@ -322,6 +323,7 @@
|
|||
8D3F8A402D44C2A6009EAAA4 /* PowerMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PowerMetricsLog.swift; sourceTree = "<group>"; };
|
||||
B399E8A32B6F486400E4488E /* RetryButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetryButton.swift; sourceTree = "<group>"; };
|
||||
B3E905B02B71F7F300654D07 /* TextMessageField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextMessageField.swift; sourceTree = "<group>"; };
|
||||
BC10380E2DD4333C00B00BFA /* AddContactIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddContactIntent.swift; sourceTree = "<group>"; };
|
||||
BC47C2EE2CE0017D008245CA /* MessageNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageNodeIntent.swift; sourceTree = "<group>"; };
|
||||
BC5EBA3B2D002A2000C442FF /* MessageNodeIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageNodeIntent.swift; sourceTree = "<group>"; };
|
||||
BC6B45FE2CB2F98900723CEB /* SaveChannelSettingsIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SaveChannelSettingsIntent.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -676,6 +678,7 @@
|
|||
BCB6137F2C6728E700485544 /* AppIntents */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
BC10380E2DD4333C00B00BFA /* AddContactIntent.swift */,
|
||||
BC5EBA3B2D002A2000C442FF /* MessageNodeIntent.swift */,
|
||||
BCB613802C67290800485544 /* SendWaypointIntent.swift */,
|
||||
BCB613822C672A2600485544 /* MessageChannelIntent.swift */,
|
||||
|
|
@ -1551,6 +1554,7 @@
|
|||
2344A2AB2D66974300170A77 /* ManagedAttributePropertyWrapper.swift in Sources */,
|
||||
BCB613832C672A2600485544 /* MessageChannelIntent.swift in Sources */,
|
||||
D93068D52B812B700066FBC8 /* MessageDestination.swift in Sources */,
|
||||
BC10380F2DD4334400B00BFA /* AddContactIntent.swift in Sources */,
|
||||
DDA9515E2BC6F56F00CEA535 /* IndoorAirQuality.swift in Sources */,
|
||||
DDDB444E29F8AB0E00EE2349 /* Int.swift in Sources */,
|
||||
DD3CC6BC28E366DF00FA9159 /* Meshtastic.xcdatamodeld in Sources */,
|
||||
|
|
|
|||
51
Meshtastic/AppIntents/AddContactIntent.swift
Normal file
51
Meshtastic/AppIntents/AddContactIntent.swift
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// AddContactIntent.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Created by Benjamin Faershtein on 5/13/25.
|
||||
//
|
||||
|
||||
import AppIntents
|
||||
import MeshtasticProtobufs
|
||||
|
||||
struct AddContactIntent: AppIntent {
|
||||
static var title: LocalizedStringResource = "Import Contact"
|
||||
static var description: IntentDescription = "Takes a Meshtastic contact URL and saves it to the nodes database"
|
||||
|
||||
@Parameter(title: "Contact URL", description: "The URL for the node to import")
|
||||
var contactUrl: URL
|
||||
|
||||
// Define the function that performs the main logic
|
||||
func perform() async throws -> some IntentResult {
|
||||
// Ensure the BLE Manager is connected
|
||||
if !BLEManager.shared.isConnected {
|
||||
throw AppIntentErrors.AppIntentError.notConnected
|
||||
}
|
||||
|
||||
if contactUrl.absoluteString.lowercased().contains("meshtastic.org/v/#") {
|
||||
|
||||
let components = self.contactUrl.absoluteString.components(separatedBy: "#")
|
||||
// Extract contact information from the URL
|
||||
if let contactData = components.last {
|
||||
|
||||
let decodedString = contactData.base64urlToBase64()
|
||||
if let decodedData = Data(base64Encoded: decodedString) {
|
||||
do {
|
||||
let success = BLEManager.shared.addContactFromURL(base64UrlString: contactData)
|
||||
if !success {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to import contact")
|
||||
}
|
||||
|
||||
} catch {
|
||||
throw AppIntentErrors.AppIntentError.message("Failed to parse contact data: \(error.localizedDescription)")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// Return a success result
|
||||
return .result()
|
||||
} else {
|
||||
throw AppIntentErrors.AppIntentError.message("The URL is not a valid Meshtastic contact link")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -61,6 +61,13 @@ struct ShareContactQRDialog: View {
|
|||
.font(.subheadline)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.secondary)
|
||||
ShareLink("Share QR Code & Link",
|
||||
item: Image(uiImage: qrImage),
|
||||
subject: Text("Import Meshtastic Node \(node.user.shortName) as a contact"),
|
||||
message: Text(qrString),
|
||||
preview: SharePreview("Import Meshtastic Node \(node.user.shortName) as a contact",
|
||||
image: Image(uiImage: qrImage))
|
||||
)
|
||||
Button("Done") { dismiss() }
|
||||
.buttonStyle(.borderedProminent)
|
||||
.padding(.bottom)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue