Meshtastic-Apple/Meshtastic/Views/Nodes/Helpers/Map/MapContent/AnimatedNodePin.swift
Garth Vander Houwen 6bb880d503
Two Column Node List (#1425)
* Restore BLE State

* Log privacy

* AccessoryManager to handle restored connection

* Comment task out

* Switch the node list to a two column layout

* Keep asian translations of channel details string

* Update restore state function based on conversation with jake

* Update Meshtastic/Accessory/Transports/Bluetooth Low Energy/BLETransport.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update Meshtastic/Accessory/Transports/Bluetooth Low Energy/BLETransport.swift

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* always show node list search bar

* Update auto correct modifier

* Dont show online animations for ios 17, remove online animation from node map, remove online circle from position popover

* Work in progress.

* Update detents

* Gate the discovery process while restoring

* Use geometry reader to size weather tiles on node details

* Update BLE Transport

* Update location weather condistion styles

* Log privacy in didReceive

* Remove extra dividers from admin key config, fix onboarding typo

* Bump minimum catalyst target

* Bump mac target version

* Use @FetchRequest for UserList to try and use less memory on ios 17

* Revert change to @fetchrequest

* Stab in the dark for Devices crash

* Updated UserList (back?) to @FetchRequest

* Set mac minimum to 15

* Nil out continuation after use

* Use @FetchRequest for the node list to stop crashes on iOS 17

* Handle failed connections during restoration

---------

Co-authored-by: Jake-B <jake-b@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-24 20:55:42 -07:00

72 lines
2 KiB
Swift

import SwiftUI
import MapKit
import CoreLocation
struct AnimatedNodePin: View, Equatable {
let nodeColor: UIColor
let shortName: String?
let hasDetectionSensorMetrics: Bool
let isOnline: Bool
let calculatedDelay: Double
private let swiftUIColor: Color
init(nodeColor: UIColor, shortName: String?, hasDetectionSensorMetrics: Bool, isOnline: Bool, calculatedDelay: Double) {
self.nodeColor = nodeColor
self.shortName = shortName
self.hasDetectionSensorMetrics = hasDetectionSensorMetrics
self.isOnline = isOnline
self.calculatedDelay = calculatedDelay
self.swiftUIColor = Color(nodeColor)
}
var body: some View {
ZStack {
// Pass the calculatedDelay to the PulsingCircle view
if isOnline {
if #available(iOS 18, macOS 15, *) {
PulsingCircle(nodeColor: nodeColor, calculatedDelay: calculatedDelay)
}
}
if hasDetectionSensorMetrics {
Image(systemName: "sensor.fill")
.symbolRenderingMode(.palette)
.symbolEffect(.variableColor)
.padding()
.foregroundStyle(.white)
.background(swiftUIColor)
.clipShape(Circle())
} else {
CircleText(text: shortName ?? "?", color: swiftUIColor, circleSize: 40)
}
}
}
static func == (lhs: AnimatedNodePin, rhs: AnimatedNodePin) -> Bool {
return lhs.nodeColor == rhs.nodeColor &&
lhs.shortName == rhs.shortName &&
lhs.hasDetectionSensorMetrics == rhs.hasDetectionSensorMetrics &&
lhs.isOnline == rhs.isOnline &&
lhs.calculatedDelay == rhs.calculatedDelay // Include calculatedDelay to ensure changes in animation timing trigger UI updates
}
}
struct PulsingCircle: View {
let nodeColor: UIColor
let calculatedDelay: Double
@State private var isPulsing = false
var body: some View {
Circle()
.fill(Color(nodeColor.lighter()).opacity(0.4))
.frame(width: 55, height: 55)
.scaleEffect(isPulsing ? 1.2 : 0.8)
.animation(
.easeInOut(duration: 0.8).repeatForever(autoreverses: true).delay(calculatedDelay),
value: isPulsing
)
.onAppear {
isPulsing = true
}
}
}