mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Add missing SwiftUI #Preview blocks across 65 views (#1649)
* Add SwiftUI previews for simple helper views Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Apple/sessions/a2a43e8c-24fd-443a-8a98-13b678770edd Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> * Add previews for action buttons, ChannelForm, MetricsColumnDetail, and DeviceOnboarding Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Apple/sessions/a2a43e8c-24fd-443a-8a98-13b678770edd Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> * Add previews for config views, log views, AppLog, Firmware, AppData, and UserConfig Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Apple/sessions/a2a43e8c-24fd-443a-8a98-13b678770edd Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> * Add preview for PositionConfig Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Apple/sessions/a2a43e8c-24fd-443a-8a98-13b678770edd Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> * Fix formatting bugs in #Preview blocks: restore missing .environmentObject/.environment modifiers and add proper tab indentation Agent-Logs-Url: https://github.com/meshtastic/Meshtastic-Apple/sessions/7eeb7a54-7928-466f-8e39-b00d0012a09d Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> * Linting fixes --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: garthvh <1795163+garthvh@users.noreply.github.com> Co-authored-by: Garth Vander Houwen <garthvh@yahoo.com>
This commit is contained in:
parent
5364fdf22f
commit
c388bf9b40
76 changed files with 567 additions and 41 deletions
|
|
@ -59,8 +59,7 @@ extension MessageEntity {
|
|||
let users = try context.fetch(request)
|
||||
|
||||
// If exactly one match is found, return its name
|
||||
if users.count == 1, let name = users.first?.longName, !name.isEmpty
|
||||
{
|
||||
if users.count == 1, let name = users.first?.longName, !name.isEmpty {
|
||||
return "\(name)"
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1278,4 +1278,3 @@ actor MeshPackets {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -184,4 +184,3 @@ extension MqttClientProxyManager: CocoaMQTTDelegate {
|
|||
Logger.mqtt.debug("📲 [MQTT Client Proxy] pong")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,10 +71,7 @@ final class CoTXMLParser: NSObject, XMLParserDelegate {
|
|||
}
|
||||
|
||||
// MARK: - XMLParserDelegate
|
||||
|
||||
func parser(_ parser: XMLParser, didStartElement elementName: String,
|
||||
namespaceURI: String?, qualifiedName qName: String?,
|
||||
attributes attributeDict: [String: String] = [:]) {
|
||||
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String: String] = [:]) {
|
||||
elementStack.append(elementName)
|
||||
currentElement = elementName
|
||||
currentText = ""
|
||||
|
|
@ -138,8 +135,7 @@ final class CoTXMLParser: NSObject, XMLParserDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
func parser(_ parser: XMLParser, didEndElement elementName: String,
|
||||
namespaceURI: String?, qualifiedName qName: String?) {
|
||||
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {
|
||||
if elementName == "remarks" {
|
||||
remarksText = currentText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -494,4 +494,3 @@ enum TAKConnectionError: LocalizedError {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -565,18 +565,18 @@ struct DeviceConnectRow: View {
|
|||
}
|
||||
// Show transport type
|
||||
#if !targetEnvironment(macCatalyst)
|
||||
HStack(alignment: .center){
|
||||
HStack(alignment: .center) {
|
||||
TransportIcon(transportType: device.transportType)
|
||||
if device.isManualConnection && (device.longName != nil || device.shortName != nil) {
|
||||
VStack (alignment: .leading) {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Last seen device:")
|
||||
Text("\(String(describing: device))")
|
||||
}
|
||||
}
|
||||
}.padding(.top, 3.0)
|
||||
#else
|
||||
//Different alignment for Mac
|
||||
HStack(alignment: .firstTextBaseline){
|
||||
// Different alignment for Mac
|
||||
HStack(alignment: .firstTextBaseline) {
|
||||
TransportIcon(transportType: device.transportType)
|
||||
if device.isManualConnection && (device.longName != nil || device.shortName != nil) {
|
||||
Text("Last seen device: \(String(describing: device))")
|
||||
|
|
@ -609,4 +609,3 @@ struct DeviceConnectRow: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -62,3 +62,7 @@ struct InvalidVersion: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
InvalidVersion(minimumVersion: "2.5.4", version: "2.3.0")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,3 +94,11 @@ enum BLESignalStrength: Int {
|
|||
case normal = 1
|
||||
case strong = 2
|
||||
}
|
||||
|
||||
#Preview {
|
||||
HStack(spacing: 16) {
|
||||
SignalStrengthIndicator(signalStrength: .weak)
|
||||
SignalStrengthIndicator(signalStrength: .normal)
|
||||
SignalStrengthIndicator(signalStrength: .strong)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,3 +111,15 @@ struct BatteryCompact: View {
|
|||
} ?? "Unknown")
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
VStack(spacing: 12) {
|
||||
BatteryCompact(batteryLevel: 75, font: .caption, iconFont: .caption, color: .gray)
|
||||
BatteryCompact(batteryLevel: 50, font: .caption, iconFont: .caption, color: .gray)
|
||||
BatteryCompact(batteryLevel: 25, font: .caption, iconFont: .caption, color: .gray)
|
||||
BatteryCompact(batteryLevel: 10, font: .caption, iconFont: .caption, color: .gray)
|
||||
BatteryCompact(batteryLevel: 100, font: .caption, iconFont: .caption, color: .gray)
|
||||
BatteryCompact(batteryLevel: 101, font: .caption, iconFont: .caption, color: .gray)
|
||||
BatteryCompact(batteryLevel: nil, font: .caption, iconFont: .caption, color: .gray)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,3 +32,15 @@ struct ChannelLock: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let encryptedChannel = ChannelEntity(context: context)
|
||||
encryptedChannel.psk = Data([0x01, 0x02, 0x03, 0x04])
|
||||
let unencryptedChannel = ChannelEntity(context: context)
|
||||
unencryptedChannel.psk = Data()
|
||||
return HStack(spacing: 16) {
|
||||
ChannelLock(channel: encryptedChannel)
|
||||
ChannelLock(channel: unencryptedChannel)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ struct CompassView: View {
|
|||
}
|
||||
|
||||
// Trigger a vibration if aligned with waypoint
|
||||
private func checkAlignment(bearing: Double,heading: Double) {
|
||||
private func checkAlignment(bearing: Double, heading: Double) {
|
||||
// Compute minimal angular difference between heading and bearing in [0, 180]
|
||||
let rawDiff = abs(heading - bearing).truncatingRemainder(dividingBy: 360)
|
||||
let diff = min(rawDiff, 360 - rawDiff)
|
||||
|
|
@ -53,7 +53,6 @@ struct CompassView: View {
|
|||
inAlignment = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func distanceToWaypoint() -> CLLocationDistance? {
|
||||
guard
|
||||
|
|
@ -76,7 +75,6 @@ struct CompassView: View {
|
|||
return formatter.string(from: measurement)
|
||||
}
|
||||
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack(spacing: 15) {
|
||||
|
|
@ -88,14 +86,14 @@ struct CompassView: View {
|
|||
.foregroundColor(color)
|
||||
|
||||
if let wp = waypointLocation {
|
||||
HStack{
|
||||
HStack {
|
||||
Image(systemName: "mappin.and.ellipse")
|
||||
Text("\(String(format: "%.4f", wp.latitude)), \(String(format: "%.4f", wp.longitude))")
|
||||
.font(.subheadline)
|
||||
}
|
||||
|
||||
if let distance = distanceToWaypoint() {
|
||||
HStack{
|
||||
HStack {
|
||||
Image(systemName: "lines.measurement.horizontal")
|
||||
Text("Distance: \(formatDistance(distance))")
|
||||
.font(.subheadline)
|
||||
|
|
@ -137,7 +135,7 @@ struct CompassView: View {
|
|||
)
|
||||
// Move waypoint marker outside compass
|
||||
.onChange(of: locationsHandler.heading) { _, _ in
|
||||
checkAlignment(bearing: bearing,heading:locationsHandler.heading)
|
||||
checkAlignment(bearing: bearing, heading:locationsHandler.heading)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -159,9 +157,7 @@ struct CompassView: View {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Waypoint Marker View
|
||||
|
||||
struct WaypointMarkerView: View {
|
||||
let bearing: Double
|
||||
let compassDegrees: Double
|
||||
|
|
@ -177,9 +173,7 @@ struct WaypointMarkerView: View {
|
|||
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Bearing Calculator
|
||||
|
||||
struct BearingCalculator {
|
||||
|
||||
static func bearingBetween(
|
||||
|
|
@ -205,9 +199,7 @@ struct BearingCalculator {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Marker Model
|
||||
|
||||
struct Marker: Hashable {
|
||||
let degrees: Double
|
||||
let label: String
|
||||
|
|
@ -239,9 +231,7 @@ struct Marker: Hashable {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Compass Marker View
|
||||
|
||||
struct CompassMarkerView: View {
|
||||
let marker: Marker
|
||||
let compassDegrees: Double
|
||||
|
|
@ -281,9 +271,7 @@ struct CompassMarkerView: View {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Preview
|
||||
|
||||
struct CompassView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CompassView(
|
||||
|
|
|
|||
|
|
@ -28,3 +28,11 @@ struct DateTimeText: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
VStack {
|
||||
DateTimeText(dateTime: Date())
|
||||
DateTimeText(dateTime: Calendar.current.date(byAdding: .day, value: -1, to: Date()))
|
||||
DateTimeText(dateTime: nil)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,3 +51,8 @@ struct MeshtasticLogo: View {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
MeshtasticLogo()
|
||||
.frame(width: 200, height: 44)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,3 +36,15 @@ struct MessageTemplate: View {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test User"
|
||||
user.shortName = "TU"
|
||||
let message = MessageEntity(context: context)
|
||||
message.messagePayload = "Hello, World!"
|
||||
message.messageTimestamp = Int32(Date().timeIntervalSince1970)
|
||||
message.replyID = 0
|
||||
return MessageTemplate(user: user, message: message)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,3 +94,15 @@ struct PowerMetricCompactWidget: View {
|
|||
.background(.tertiary, in: RoundedRectangle(cornerRadius: 20, style: .continuous))
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let gridItemLayout = Array(repeating: GridItem(.flexible(), spacing: 10), count: 2)
|
||||
Form {
|
||||
LazyVGrid(columns: gridItemLayout) {
|
||||
PowerMetricCompactWidget(type: .voltage, value: 3.72, title: "Channel 1 Voltage")
|
||||
PowerMetricCompactWidget(type: .current, value: 125.3, title: "Channel 1 Current")
|
||||
PowerMetricCompactWidget(type: .voltage, value: 5.01, title: "Channel 2 Voltage")
|
||||
PowerMetricCompactWidget(type: .current, value: 42.7, title: "Channel 2 Current")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,3 +119,12 @@ struct LEDIndicator: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
HStack(spacing: 12) {
|
||||
LEDIndicator(flash: .constant(1), color: .green)
|
||||
.frame(width: 10, height: 10)
|
||||
LEDIndicator(flash: .constant(0), color: .red)
|
||||
.frame(width: 10, height: 10)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,16 @@ public struct RateLimitedButton<Content: View>: View {
|
|||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
RateLimitedButton(key: "preview", rateLimit: 30, action: { }) { rateLimitInfo in
|
||||
if let info = rateLimitInfo {
|
||||
Label("\(Int(info.secondsRemaining))s", systemImage: "clock")
|
||||
} else {
|
||||
Label("Send", systemImage: "paperplane")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To store the time an action occured (name by a key) and the time limit
|
||||
// Does not persist across app launches
|
||||
class RateLimitStorage: ObservableObject {
|
||||
|
|
|
|||
|
|
@ -69,3 +69,11 @@ struct SecureInput: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
List {
|
||||
SecureInput("Password", text: .constant("s3cretP@ss"), isValid: .constant(true))
|
||||
SecureInput("Invalid Key", text: .constant("short"), isValid: .constant(false))
|
||||
SecureInput("Empty", text: .constant(""), isValid: .constant(true))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,3 +118,7 @@ func calculateDewPoint(temp: Float, relativeHumidity: Float, convertToLocale: Bo
|
|||
}
|
||||
return dewPointUnit.converted(to: format).value
|
||||
}
|
||||
|
||||
#Preview {
|
||||
LocalWeatherConditions(location: CLLocation(latitude: 47.6062, longitude: -122.3321))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,13 @@ struct TraceRouteComponent<V: View>: View {
|
|||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
TraceRouteComponent {
|
||||
Image(systemName: "antenna.radiowaves.left.and.right")
|
||||
.font(.title)
|
||||
}
|
||||
}
|
||||
|
||||
struct TraceRoute: Layout {
|
||||
var animatableData: AnimatablePair<CGFloat, CGFloat> {
|
||||
get {
|
||||
|
|
|
|||
|
|
@ -56,8 +56,6 @@ struct MessageContextMenuItems: View {
|
|||
let sixMonthsAgo = Calendar.current.date(byAdding: .month, value: -6, to: Date())
|
||||
|
||||
// Compute a relay display string if relayNode is present
|
||||
|
||||
|
||||
VStack {
|
||||
Text("\(messageDate.formattedDate(format: MessageText.dateFormatString))")
|
||||
.foregroundColor(.gray)
|
||||
|
|
|
|||
|
|
@ -79,6 +79,12 @@ struct TapbackInputView: View {
|
|||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
TapbackInputView(text: .constant(""), isPresented: .constant(true)) { emoji in
|
||||
print("Selected: \(emoji)")
|
||||
}
|
||||
}
|
||||
|
||||
extension UIView {
|
||||
var firstResponder: UIView? {
|
||||
guard !isFirstResponder else { return self }
|
||||
|
|
@ -90,4 +96,3 @@ extension UIView {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,3 +141,16 @@ struct DetectionSensorLog: View {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return DetectionSensorLog(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -254,3 +254,16 @@ struct DeviceMetricsLog: View {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return DeviceMetricsLog(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -186,3 +186,16 @@ struct EnvironmentMetricsLog: View {
|
|||
return lower...upper
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return EnvironmentMetricsLog(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,3 +40,13 @@ struct ClientHistoryButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let connectedNode = NodeInfoEntity(context: context)
|
||||
connectedNode.num = 987654321
|
||||
return ClientHistoryButton(connectedNode: connectedNode, node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,3 +64,14 @@ struct DeleteNodeButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let connectedNode = NodeInfoEntity(context: context)
|
||||
connectedNode.num = 987654321
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
return DeleteNodeButton(connectedNode: connectedNode, node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,3 +61,13 @@ struct ExchangePositionsButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let connectedNode = NodeInfoEntity(context: context)
|
||||
connectedNode.num = 987654321
|
||||
return ExchangePositionsButton(node: node, connectedNode: connectedNode)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,3 +59,13 @@ struct ExchangeUserInfoButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let connectedNode = NodeInfoEntity(context: context)
|
||||
connectedNode.num = 987654321
|
||||
return ExchangeUserInfoButton(node: node, connectedNode: connectedNode)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,3 +79,16 @@ struct FavoriteNodeButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return FavoriteNodeButton(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,3 +51,12 @@ struct IgnoreNodeButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
return IgnoreNodeButton(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,3 +54,15 @@ struct NavigateToButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
user.num = 123456789
|
||||
node.user = user
|
||||
return NavigateToButton(node: node)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,3 +31,14 @@ struct NodeAlertsButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return NodeAlertsButton(context: context, node: node, user: user)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,3 +43,15 @@ struct TraceRouteButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return TraceRouteButton(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,14 @@ struct AnimatedNodePin: View, Equatable {
|
|||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
VStack(spacing: 20) {
|
||||
AnimatedNodePin(nodeColor: .systemBlue, shortName: "TN", hasDetectionSensorMetrics: false, isOnline: true, calculatedDelay: 0.0)
|
||||
AnimatedNodePin(nodeColor: .systemGreen, shortName: "AB", hasDetectionSensorMetrics: true, isOnline: true, calculatedDelay: 0.2)
|
||||
AnimatedNodePin(nodeColor: .systemRed, shortName: "XY", hasDetectionSensorMetrics: false, isOnline: false, calculatedDelay: 0.0)
|
||||
}
|
||||
}
|
||||
|
||||
struct PulsingCircle: View {
|
||||
let nodeColor: UIColor
|
||||
let calculatedDelay: Double
|
||||
|
|
|
|||
|
|
@ -228,3 +228,13 @@ struct MapSettingsForm: View {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
MapSettingsForm(
|
||||
traffic: .constant(false),
|
||||
pointsOfInterest: .constant(true),
|
||||
mapLayer: .constant(.standard),
|
||||
meshMap: .constant(true),
|
||||
enabledOverlayConfigs: .constant(Set<UUID>())
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,3 +99,10 @@ struct MetricsColumnDetail: View {
|
|||
.interactiveDismissDisabled(false)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
MetricsColumnDetail(
|
||||
columnList: MetricsColumnList(columns: []),
|
||||
seriesList: MetricsSeriesList()
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,3 +208,7 @@ struct NodeListFilter: View {
|
|||
.presentationBackgroundInteraction(.enabled(upThrough: .large))
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NodeListFilter(filters: NodeFilterParameters())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -224,3 +224,16 @@ struct PaxCounterLog: View {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return PaxCounterLog(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,3 +181,16 @@ struct PositionLog: View {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return PositionLog(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -297,3 +297,16 @@ struct PowerMetricsLog: View {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return PowerMetricsLog(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -287,3 +287,16 @@ func getTraceRouteHops(context: NSManagedObjectContext) -> [TraceRouteHopEntity]
|
|||
array.append(trh8)
|
||||
return array
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
let node = NodeInfoEntity(context: context)
|
||||
node.num = 123456789
|
||||
let user = UserEntity(context: context)
|
||||
user.longName = "Test Node"
|
||||
user.shortName = "TN"
|
||||
node.user = user
|
||||
return TraceRouteLog(node: node)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -454,3 +454,8 @@ struct DeviceOnboarding: View {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
#Preview {
|
||||
DeviceOnboarding()
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,3 +67,9 @@ struct AboutMeshtastic: View {
|
|||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NavigationView {
|
||||
AboutMeshtastic()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,3 +143,10 @@ struct AppData: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return AppData()
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -271,3 +271,7 @@ extension AppLog {
|
|||
}
|
||||
|
||||
extension OSLogEntry: @retroactive Identifiable { }
|
||||
|
||||
#Preview {
|
||||
AppLog()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,3 +250,21 @@ struct ChannelForm: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ChannelForm(
|
||||
channelIndex: .constant(0),
|
||||
channelName: .constant("LongFast"),
|
||||
channelKeySize: .constant(32),
|
||||
channelKey: .constant("AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE="),
|
||||
channelRole: .constant(1),
|
||||
uplink: .constant(false),
|
||||
downlink: .constant(false),
|
||||
positionPrecision: .constant(14),
|
||||
preciseLocation: .constant(false),
|
||||
positionsEnabled: .constant(true),
|
||||
hasChanges: .constant(false),
|
||||
hasValidKey: .constant(true),
|
||||
supportedVersion: .constant(true)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -147,3 +147,10 @@ struct BluetoothConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return BluetoothConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,3 +37,13 @@ struct ConfigHeader<T>: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ConfigHeader(
|
||||
title: "Bluetooth Configuration",
|
||||
config: \NodeInfoEntity.bluetoothConfig,
|
||||
node: nil,
|
||||
onAppear: { }
|
||||
)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -345,3 +345,10 @@ struct DeviceConfig: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return DeviceConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -235,3 +235,10 @@ struct DisplayConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return DisplayConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -321,3 +321,10 @@ struct LoRaConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return LoRaConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,3 +134,10 @@ struct AmbientLightingConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return AmbientLightingConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -355,3 +355,10 @@ struct CannedMessagesConfig: View {
|
|||
self.hasMessagesChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return CannedMessagesConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -261,3 +261,10 @@ struct DetectionSensorConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return DetectionSensorConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,3 +283,9 @@ struct ExternalNotificationConfig: View {
|
|||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return ExternalNotificationConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -464,3 +464,10 @@ struct MQTTConfig: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return MQTTConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -123,3 +123,10 @@ struct PaxCounterConfig: View {
|
|||
paxcounterUpdateInterval = UpdateInterval(from: Int(node?.paxCounterConfig?.updateInterval ?? 1800))
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return PaxCounterConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,3 +143,10 @@ struct RangeTestConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return RangeTestConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,3 +114,10 @@ struct RtttlConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return RtttlConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,3 +205,10 @@ struct SerialConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return SerialConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,3 +197,10 @@ struct StoreForwardConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return StoreForwardConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -241,3 +241,10 @@ struct TelemetryConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return TelemetryConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -209,3 +209,10 @@ struct NetworkConfig: View {
|
|||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return NetworkConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -562,3 +562,10 @@ struct PositionConfig: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return PositionConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,3 +226,10 @@ private struct FloatField: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return PowerConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,3 +58,8 @@ struct SaveConfigButton: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
SaveConfigButton(node: nil, hasChanges: .constant(true), onConfirmation: { })
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -428,3 +428,10 @@ struct SecurityConfig: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return SecurityConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,3 +206,10 @@ struct Firmware: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return Firmware(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,3 +65,7 @@ struct GPSStatus: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
GPSStatus()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,3 +169,7 @@ struct AppLogFilter: View {
|
|||
.presentationBackgroundInteraction(.enabled(upThrough: .medium))
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
AppLogFilter(categories: .constant(Set<Int>()), levels: .constant(Set<Int>()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -424,9 +424,7 @@ struct TAKServerConfig: View {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: - Channel Label
|
||||
|
||||
@ViewBuilder
|
||||
private func channelLabel(_ channel: ChannelEntity) -> some View {
|
||||
if channel.name?.isEmpty ?? false {
|
||||
|
|
|
|||
|
|
@ -55,3 +55,11 @@ struct UpdateIntervalPicker: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
UpdateIntervalPicker(
|
||||
config: .broadcastShort,
|
||||
pickerLabel: "Update Interval",
|
||||
selectedInterval: .constant(UpdateInterval(from: 30))
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -253,3 +253,10 @@ struct UserConfig: View {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
let context = PersistenceController.preview.container.viewContext
|
||||
return UserConfig(node: nil)
|
||||
.environmentObject(AccessoryManager.shared)
|
||||
.environment(\.managedObjectContext, context)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ struct DeviceTests {
|
|||
(-80, BLESignalStrength.normal),
|
||||
(-84, BLESignalStrength.normal),
|
||||
(-85, BLESignalStrength.weak),
|
||||
(-100, BLESignalStrength.weak),
|
||||
(-100, BLESignalStrength.weak)
|
||||
])
|
||||
func signalStrength(rssi: Int, expected: BLESignalStrength) {
|
||||
let device = Device(
|
||||
|
|
@ -209,7 +209,7 @@ struct TransportTypeTests {
|
|||
@Test(arguments: [
|
||||
(TransportType.ble, "BLE"),
|
||||
(TransportType.tcp, "TCP"),
|
||||
(TransportType.serial, "Serial"),
|
||||
(TransportType.serial, "Serial")
|
||||
])
|
||||
func rawValues(type: TransportType, expected: String) {
|
||||
#expect(type.rawValue == expected)
|
||||
|
|
@ -307,7 +307,7 @@ struct NavigationStateTests {
|
|||
NavigationState.Tab.connect,
|
||||
NavigationState.Tab.nodes,
|
||||
NavigationState.Tab.map,
|
||||
NavigationState.Tab.settings,
|
||||
NavigationState.Tab.settings
|
||||
])
|
||||
func tabRawValues(tab: NavigationState.Tab) {
|
||||
#expect(NavigationState.Tab(rawValue: tab.rawValue) == tab)
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ struct RouterTests {
|
|||
("debugLogs", SettingsNavigationState.debugLogs),
|
||||
("appFiles", SettingsNavigationState.appFiles),
|
||||
("firmwareUpdates", SettingsNavigationState.firmwareUpdates),
|
||||
("tak", SettingsNavigationState.tak),
|
||||
("tak", SettingsNavigationState.tak)
|
||||
])
|
||||
func routeSettingsPage(path: String, expected: SettingsNavigationState) async throws {
|
||||
try await assertRoute(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue