mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Merge pull request #1137 from meshtastic/emoji-improvements
Improvements to emoji handling for node names
This commit is contained in:
commit
2fdaed2650
8 changed files with 60 additions and 19 deletions
|
|
@ -93,12 +93,51 @@ extension String {
|
|||
|
||||
// Filter out variation selectors from the string
|
||||
var withoutVariationSelectors: String {
|
||||
return self.unicodeScalars
|
||||
.filter { scalar in
|
||||
return !scalar.properties.isVariationSelector
|
||||
var scalars: [UnicodeScalar] = []
|
||||
var previousWasASCII = false
|
||||
|
||||
for scalar in self.unicodeScalars {
|
||||
if scalar.properties.isVariationSelector {
|
||||
// Only keep variation selector if the previous character was ASCII
|
||||
if previousWasASCII {
|
||||
scalars.append(scalar)
|
||||
}
|
||||
// No need to update previousWasASCII since variation selectors aren't characters
|
||||
// Shouldn't have 2 in a row
|
||||
} else {
|
||||
scalars.append(scalar)
|
||||
previousWasASCII = scalar.isASCII
|
||||
}
|
||||
.compactMap { UnicodeScalar($0) }
|
||||
}
|
||||
|
||||
return scalars.compactMap { UnicodeScalar($0) }
|
||||
.map { String($0) }
|
||||
.joined()
|
||||
}
|
||||
|
||||
// Adds variation selectors to prefer the graphical form of emoji.
|
||||
// Looks ahead to make sure that the variation selector is not already applied.
|
||||
var addingVariationSelectors: String {
|
||||
var result = ""
|
||||
let scalars = self.unicodeScalars
|
||||
var index = scalars.startIndex
|
||||
while index < scalars.endIndex {
|
||||
let currentScalar = scalars[index]
|
||||
result += String(currentScalar)
|
||||
if currentScalar.properties.isEmoji && !currentScalar.properties.isEmojiPresentation && !currentScalar.isASCII {
|
||||
// Check if the next scalar is U+FE0F
|
||||
let nextIndex = scalars.index(after: index)
|
||||
if nextIndex < scalars.endIndex && scalars[nextIndex].value == 0xFE0F {
|
||||
// Already has variation selector; skip the next scalar
|
||||
index = nextIndex
|
||||
} else {
|
||||
// Append variation selector
|
||||
result += String(UnicodeScalar(0xFE0F)!)
|
||||
}
|
||||
}
|
||||
// Move to the next scalar
|
||||
index = scalars.index(after: index)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,9 +61,9 @@ struct Connect: View {
|
|||
.padding(.trailing)
|
||||
VStack(alignment: .leading) {
|
||||
if node != nil {
|
||||
Text(connectedPeripheral.longName).font(.title2)
|
||||
Text(connectedPeripheral.longName.addingVariationSelectors).font(.title2)
|
||||
}
|
||||
Text("BLE Name").font(.callout)+Text(": \(bleManager.connectedPeripheral?.peripheral.name ?? "unknown".localized)")
|
||||
Text("BLE Name").font(.callout)+Text(": \(bleManager.connectedPeripheral?.peripheral.name?.addingVariationSelectors ?? "unknown".localized)")
|
||||
.font(.callout).foregroundColor(Color.gray)
|
||||
if node != nil {
|
||||
Text("firmware.version").font(.callout)+Text(": \(node?.metadata?.firmwareVersion ?? "unknown".localized)")
|
||||
|
|
@ -120,7 +120,7 @@ struct Connect: View {
|
|||
#endif
|
||||
Text("Num: \(String(node!.num))")
|
||||
Text("Short Name: \(node?.user?.shortName ?? "?")")
|
||||
Text("Long Name: \(node?.user?.longName ?? "unknown".localized)")
|
||||
Text("Long Name: \(node?.user?.longName?.addingVariationSelectors ?? "unknown".localized)")
|
||||
Text("BLE RSSI: \(connectedPeripheral.rssi)")
|
||||
|
||||
Button {
|
||||
|
|
@ -333,7 +333,7 @@ struct Connect: View {
|
|||
let localStats = node?.telemetries?.filtered(using: NSPredicate(format: "metricsType == 4"))
|
||||
let mostRecent = localStats?.lastObject as? TelemetryEntity
|
||||
|
||||
let activityAttributes = MeshActivityAttributes(nodeNum: Int(node?.num ?? 0), name: node?.user?.longName ?? "unknown")
|
||||
let activityAttributes = MeshActivityAttributes(nodeNum: Int(node?.num ?? 0), name: node?.user?.longName?.addingVariationSelectors ?? "unknown")
|
||||
|
||||
let future = Date(timeIntervalSinceNow: Double(timerSeconds))
|
||||
let initialContentState = MeshActivityAttributes.ContentState(uptimeSeconds: UInt32(mostRecent?.uptimeSeconds ?? 0),
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ struct CircleText: View {
|
|||
Circle()
|
||||
.fill(color)
|
||||
.frame(width: circleSize, height: circleSize)
|
||||
Text(text)
|
||||
Text(text.addingVariationSelectors)
|
||||
.frame(width: circleSize * 0.9, height: circleSize * 0.9, alignment: .center)
|
||||
.foregroundColor(color.isLight() ? .black : .white)
|
||||
.minimumScaleFactor(0.001)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ struct ConnectedDevice: View {
|
|||
.imageScale(.large)
|
||||
.foregroundColor(.green)
|
||||
.symbolRenderingMode(.hierarchical)
|
||||
Text(name).font(name.isEmoji() ? .title : .callout).foregroundColor(.gray)
|
||||
Text(name.addingVariationSelectors).font(name.isEmoji() ? .title : .callout).foregroundColor(.gray)
|
||||
} else {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right.slash")
|
||||
.imageScale(.medium)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ struct NodeListItem: View {
|
|||
let (image, color) = userKeyStatus
|
||||
IconAndText(systemName: image,
|
||||
imageColor: color,
|
||||
text: node.user?.longName ?? "unknown".localized,
|
||||
text: node.user?.longName?.addingVariationSelectors ?? "unknown".localized,
|
||||
textColor: .primary)
|
||||
if node.favorite {
|
||||
Spacer()
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ struct NodeList: View {
|
|||
columnVisibility: columnVisibility
|
||||
)
|
||||
.edgesIgnoringSafeArea([.leading, .trailing])
|
||||
.navigationBarTitle(String(node.user?.longName ?? "unknown".localized), displayMode: .inline)
|
||||
.navigationBarTitle(String(node.user?.longName?.addingVariationSelectors ?? "unknown".localized), displayMode: .inline)
|
||||
.navigationBarItems(
|
||||
trailing: ZStack {
|
||||
if UIDevice.current.userInterfaceIdiom != .phone {
|
||||
|
|
|
|||
|
|
@ -341,7 +341,7 @@ struct Settings: View {
|
|||
/// Connected Node
|
||||
if node.num == bleManager.connectedPeripheral?.num ?? 0 {
|
||||
Label {
|
||||
Text("BLE: \(node.user?.longName ?? "unknown".localized)")
|
||||
Text("BLE: \(node.user?.longName?.addingVariationSelectors ?? "unknown".localized)")
|
||||
} icon: {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right")
|
||||
}
|
||||
|
|
@ -363,14 +363,14 @@ struct Settings: View {
|
|||
.tag(Int(node.num))
|
||||
} else if UserDefaults.enableAdministration && node.user?.pkiEncrypted ?? false {
|
||||
Label {
|
||||
Text("Request PKI Admin: \(node.user?.longName ?? "unknown".localized)")
|
||||
Text("Request PKI Admin: \(node.user?.longName?.addingVariationSelectors ?? "unknown".localized)")
|
||||
} icon: {
|
||||
Image(systemName: "rectangle.and.hand.point.up.left")
|
||||
}
|
||||
.tag(Int(node.num))
|
||||
} else if !UserDefaults.enableAdministration {
|
||||
Label {
|
||||
Text("Request Legacy Admin: \(node.user?.longName ?? "unknown".localized)")
|
||||
Text("Request Legacy Admin: \(node.user?.longName?.addingVariationSelectors ?? "unknown".localized)")
|
||||
} icon: {
|
||||
Image(systemName: "rectangle.and.hand.point.up.left")
|
||||
}
|
||||
|
|
@ -395,7 +395,7 @@ struct Settings: View {
|
|||
TipView(AdminChannelTip(), arrowEdge: .top)
|
||||
} else {
|
||||
if bleManager.connectedPeripheral != nil {
|
||||
Text("Connected Node \(node?.user?.longName ?? "unknown".localized)")
|
||||
Text("Connected Node \(node?.user?.longName?.addingVariationSelectors ?? "unknown".localized)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,12 +50,14 @@ struct UserConfig: View {
|
|||
|
||||
TextField("Long Name", text: $longName)
|
||||
.onChange(of: longName) {
|
||||
var totalBytes = longName.utf8.count
|
||||
var newValue = longName.withoutVariationSelectors
|
||||
var totalBytes = newValue.utf8.count
|
||||
// Only mess with the value if it is too big
|
||||
while totalBytes > (isLicensed ? 6 : 36) {
|
||||
longName = String(longName.dropLast())
|
||||
totalBytes = longName.utf8.count
|
||||
newValue = String(newValue.dropLast())
|
||||
totalBytes = newValue.utf8.count
|
||||
}
|
||||
longName = newValue
|
||||
}
|
||||
}
|
||||
.keyboardType(.default)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue