mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
extend map into the notch, get rid of little annoying white space on … (#1386)
* extend map into the notch, get rid of little annoying white space on connect * Add message action to node details, restrict contact sharing to our own node * Fix text area background colors * Use primary for text * Us primary background
This commit is contained in:
parent
8b4ebf4645
commit
7c4d55219c
5 changed files with 112 additions and 101 deletions
|
|
@ -30,7 +30,7 @@ struct Connect: View {
|
|||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
VStack(spacing: 0) {
|
||||
List {
|
||||
Section {
|
||||
if let connectedDevice = accessoryManager.activeConnection?.device,
|
||||
|
|
@ -338,6 +338,7 @@ struct Connect: View {
|
|||
Spacer()
|
||||
}
|
||||
.padding(.bottom, 10)
|
||||
.background(Color(.tertiarySystemGroupedBackground))
|
||||
}
|
||||
.navigationTitle("Connect")
|
||||
.navigationBarItems(
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ struct TextMessageField: View {
|
|||
.background(
|
||||
Capsule()
|
||||
.strokeBorder(.tertiary, lineWidth: 1)
|
||||
.background(Capsule().fill(Color.white))
|
||||
.background(Capsule().fill(Color(.systemBackground)))
|
||||
)
|
||||
.clipShape(Capsule())
|
||||
.onChange(of: typingMessage) { _, value in
|
||||
|
|
@ -58,6 +58,7 @@ struct TextMessageField: View {
|
|||
sendMessage()
|
||||
#endif
|
||||
}
|
||||
.foregroundColor(.primary)
|
||||
if !typingMessage.isEmpty {
|
||||
Button(action: sendMessage) {
|
||||
Image(systemName: "arrow.up.circle.fill")
|
||||
|
|
|
|||
|
|
@ -448,6 +448,15 @@ struct NodeDetail: View {
|
|||
node: node
|
||||
)
|
||||
if connectedNode.num != node.num {
|
||||
if !(node.user?.unmessagable ?? true) {
|
||||
Button(action: {
|
||||
if let url = URL(string: "meshtastic:///messages?userNum=\(node.num)") {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
}) {
|
||||
Label("Message", systemImage: "message")
|
||||
}
|
||||
}
|
||||
ExchangePositionsButton(
|
||||
node: node
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
//
|
||||
// MeshMap.swift
|
||||
// Meshtastic
|
||||
// MeshMap.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 11/7/23.
|
||||
// Copyright(c) Garth Vander Houwen 11/7/23.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
|
@ -45,7 +45,6 @@ struct MeshMap: View {
|
|||
@StateObject var filters = NodeFilterParameters()
|
||||
|
||||
var body: some View {
|
||||
|
||||
NavigationStack {
|
||||
ZStack {
|
||||
MapReader { reader in
|
||||
|
|
@ -79,110 +78,111 @@ struct MeshMap: View {
|
|||
distance = context.camera.distance
|
||||
})
|
||||
.onTapGesture(count: 1, perform: { position in
|
||||
newWaypointCoord = reader.convert(position, from: .local) ?? CLLocationCoordinate2D.init()
|
||||
newWaypointCoord = reader.convert(position, from: .local) ?? CLLocationCoordinate2D.init()
|
||||
})
|
||||
.gesture(
|
||||
LongPressGesture(minimumDuration: 0.5)
|
||||
.sequenced(before: SpatialTapGesture(coordinateSpace: .local))
|
||||
.onEnded { value in
|
||||
switch value {
|
||||
case let .second(_, tapValue):
|
||||
guard let point = tapValue?.location else {
|
||||
Logger.services.error("Unable to retreive tap location from gesture data.")
|
||||
return
|
||||
}
|
||||
switch value {
|
||||
case let .second(_, tapValue):
|
||||
guard let point = tapValue?.location else {
|
||||
Logger.services.error("Unable to retreive tap location from gesture data.")
|
||||
return
|
||||
}
|
||||
|
||||
guard let coordinate = reader.convert(point, from: .local) else {
|
||||
Logger.services.error("Unable to convert local point to coordinate on map.")
|
||||
return
|
||||
}
|
||||
centerMapAt(coordinate: coordinate)
|
||||
guard let coordinate = reader.convert(point, from: .local) else {
|
||||
Logger.services.error("Unable to convert local point to coordinate on map.")
|
||||
return
|
||||
}
|
||||
centerMapAt(coordinate: coordinate)
|
||||
|
||||
newWaypointCoord = coordinate
|
||||
editingWaypoint = WaypointEntity(context: context)
|
||||
editingWaypoint!.name = "Waypoint Pin"
|
||||
editingWaypoint!.expire = Date.now.addingTimeInterval(60 * 480)
|
||||
editingWaypoint!.latitudeI = Int32((newWaypointCoord?.latitude ?? 0) * 1e7)
|
||||
editingWaypoint!.longitudeI = Int32((newWaypointCoord?.longitude ?? 0) * 1e7)
|
||||
editingWaypoint!.expire = Date.now.addingTimeInterval(60 * 480)
|
||||
editingWaypoint!.id = 0
|
||||
Logger.services.debug("Long press occured at Lat: \(coordinate.latitude, privacy: .public) Long: \(coordinate.longitude, privacy: .public)")
|
||||
default: return
|
||||
newWaypointCoord = coordinate
|
||||
editingWaypoint = WaypointEntity(context: context)
|
||||
editingWaypoint!.name = "Waypoint Pin"
|
||||
editingWaypoint!.expire = Date.now.addingTimeInterval(60 * 480)
|
||||
editingWaypoint!.latitudeI = Int32((newWaypointCoord?.latitude ?? 0) * 1e7)
|
||||
editingWaypoint!.longitudeI = Int32((newWaypointCoord?.longitude ?? 0) * 1e7)
|
||||
editingWaypoint!.expire = Date.now.addingTimeInterval(60 * 480)
|
||||
editingWaypoint!.id = 0
|
||||
Logger.services.debug("Long press occured at Lat: \(coordinate.latitude, privacy: .public) Long: \(coordinate.longitude, privacy: .public)")
|
||||
default: return
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
.ignoresSafeArea()
|
||||
}
|
||||
}
|
||||
.sheet(item: $selectedPosition) { selection in
|
||||
PositionPopover(position: selection, popover: false)
|
||||
.padding()
|
||||
}
|
||||
.sheet(item: $selectedWaypoint) { selection in
|
||||
WaypointForm(waypoint: selection)
|
||||
.padding()
|
||||
}
|
||||
.sheet(item: $editingWaypoint) { selection in
|
||||
WaypointForm(waypoint: selection, editMode: true)
|
||||
.padding()
|
||||
}
|
||||
.sheet(isPresented: $editingSettings) {
|
||||
MapSettingsForm(traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap, enabledOverlayConfigs: $enabledOverlayConfigs)
|
||||
}
|
||||
.onChange(of: router.navigationState) {
|
||||
guard case .map = router.navigationState.selectedTab else { return }
|
||||
// TODO: handle deep link for waypoints
|
||||
}
|
||||
.onChange(of: selectedMapLayer) { _, newMapLayer in
|
||||
switch selectedMapLayer {
|
||||
case .standard:
|
||||
UserDefaults.mapLayer = newMapLayer
|
||||
mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic)
|
||||
case .hybrid:
|
||||
UserDefaults.mapLayer = newMapLayer
|
||||
mapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic)
|
||||
case .satellite:
|
||||
UserDefaults.mapLayer = newMapLayer
|
||||
mapStyle = MapStyle.imagery(elevation: .realistic)
|
||||
case .offline:
|
||||
return
|
||||
.sheet(item: $selectedPosition) { selection in
|
||||
PositionPopover(position: selection, popover: false)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $editingFilters) {
|
||||
NodeListFilter(
|
||||
filters: filters
|
||||
)
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .trailing) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
editingSettings = !editingSettings
|
||||
}
|
||||
}) {
|
||||
Image(systemName: editingSettings ? "info.circle.fill" : "info.circle")
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
.tint(Color(UIColor.secondarySystemBackground))
|
||||
.foregroundColor(.accentColor)
|
||||
.buttonStyle(.borderedProminent)
|
||||
.sheet(item: $selectedWaypoint) { selection in
|
||||
WaypointForm(waypoint: selection)
|
||||
.padding()
|
||||
}
|
||||
.controlSize(.regular)
|
||||
.padding(5)
|
||||
}
|
||||
}
|
||||
.navigationBarItems(leading: MeshtasticLogo(), trailing: ZStack {
|
||||
ConnectedDevice(deviceConnected: accessoryManager.isConnected, name: accessoryManager.activeConnection?.device.shortName ?? "?")
|
||||
})
|
||||
.onFirstAppear {
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
.sheet(item: $editingWaypoint) { selection in
|
||||
WaypointForm(waypoint: selection, editMode: true)
|
||||
.padding()
|
||||
}
|
||||
.sheet(isPresented: $editingSettings) {
|
||||
MapSettingsForm(traffic: $showTraffic, pointsOfInterest: $showPointsOfInterest, mapLayer: $selectedMapLayer, meshMap: $isMeshMap, enabledOverlayConfigs: $enabledOverlayConfigs)
|
||||
.presentationDetents([.fraction(0.85), .large])
|
||||
|
||||
}
|
||||
.onChange(of: router.navigationState) {
|
||||
guard case .map = router.navigationState.selectedTab else { return }
|
||||
// TODO: handle deep link for waypoints
|
||||
}
|
||||
.onChange(of: selectedMapLayer) { _, newMapLayer in
|
||||
switch selectedMapLayer {
|
||||
case .standard:
|
||||
UserDefaults.mapLayer = newMapLayer
|
||||
mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic)
|
||||
case .hybrid:
|
||||
UserDefaults.mapLayer = newMapLayer
|
||||
mapStyle = MapStyle.hybrid(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic)
|
||||
case .satellite:
|
||||
UserDefaults.mapLayer = newMapLayer
|
||||
mapStyle = MapStyle.imagery(elevation: .realistic)
|
||||
case .offline:
|
||||
return
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $editingFilters) {
|
||||
NodeListFilter(
|
||||
filters: filters
|
||||
)
|
||||
}
|
||||
.safeAreaInset(edge: .bottom, alignment: .trailing) {
|
||||
HStack {
|
||||
Spacer()
|
||||
Button(action: {
|
||||
withAnimation {
|
||||
editingSettings = !editingSettings
|
||||
}
|
||||
}) {
|
||||
Image(systemName: editingSettings ? "info.circle.fill" : "info.circle")
|
||||
.padding(.vertical, 5)
|
||||
}
|
||||
.tint(Color(UIColor.secondarySystemBackground))
|
||||
.foregroundColor(.accentColor)
|
||||
.buttonStyle(.borderedProminent)
|
||||
}
|
||||
.controlSize(.regular)
|
||||
.padding(5)
|
||||
}
|
||||
}
|
||||
.navigationBarItems(leading: MeshtasticLogo(), trailing: ZStack {
|
||||
ConnectedDevice(deviceConnected: accessoryManager.isConnected, name: accessoryManager.activeConnection?.device.shortName ?? "?")
|
||||
})
|
||||
.toolbarBackground(.hidden, for: .navigationBar)
|
||||
}
|
||||
.onAppear {
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
// Initialize enabled overlay configs with all active files
|
||||
let activeFiles = GeoJSONOverlayManager.shared.getUploadedFilesWithState().filter { $0.isActive }
|
||||
enabledOverlayConfigs = Set(activeFiles.map { $0.id })
|
||||
|
||||
// let wayPointEntity = getWaypoint(id: Int64(deepLinkManager.waypointId) ?? -1, context: context)
|
||||
// if wayPointEntity.id > 0 {
|
||||
// position = .camera(MapCamera(centerCoordinate: wayPointEntity.coordinate, distance: 1000, heading: 0, pitch: 60))
|
||||
switch selectedMapLayer {
|
||||
case .standard:
|
||||
mapStyle = MapStyle.standard(elevation: .realistic, pointsOfInterest: showPointsOfInterest ? .all : .excludingAll, showsTraffic: showTraffic)
|
||||
|
|
@ -210,9 +210,9 @@ struct MeshMap: View {
|
|||
position = .camera(
|
||||
MapCamera(
|
||||
centerCoordinate: coordinate, // Set new center
|
||||
distance: distance, // Preserve current zoom distance
|
||||
heading: 0, // align north
|
||||
pitch: 0 // set view to top down
|
||||
distance: distance, // Preserve current zoom distance
|
||||
heading: 0, // align north
|
||||
pitch: 0 // set view to top down
|
||||
)
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ struct NodeList: View {
|
|||
/// Allow users to mute notifications for a node even if they are not connected
|
||||
if let user = node.user {
|
||||
NodeAlertsButton(context: context, node: node, user: user)
|
||||
if !user.unmessagable {
|
||||
if !user.unmessagable && user.num == UserDefaults.preferredPeripheralNum {
|
||||
Button(action: {
|
||||
shareContactNode = node
|
||||
}) {
|
||||
|
|
@ -80,9 +80,6 @@ struct NodeList: View {
|
|||
Label("Message", systemImage: "message")
|
||||
}
|
||||
}
|
||||
TraceRouteButton(
|
||||
node: node
|
||||
)
|
||||
Button {
|
||||
Task {
|
||||
do {
|
||||
|
|
@ -104,6 +101,9 @@ struct NodeList: View {
|
|||
} label: {
|
||||
Label("Exchange Positions", systemImage: "arrow.triangle.2.circlepath")
|
||||
}
|
||||
TraceRouteButton(
|
||||
node: node
|
||||
)
|
||||
IgnoreNodeButton(
|
||||
node: node
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue