mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Try and re-connect BLE devices in the background better
This commit is contained in:
parent
b214b34d64
commit
9c4deecc36
9 changed files with 228 additions and 183 deletions
|
|
@ -38,12 +38,13 @@
|
|||
DD4C0EFA29A8735400D3316C /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD4C0EF929A8735400D3316C /* WidgetKit.framework */; };
|
||||
DD4C0EFC29A8735400D3316C /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD4C0EFB29A8735400D3316C /* SwiftUI.framework */; };
|
||||
DD4C0EFF29A8735400D3316C /* MeshtasticWidgetsBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0EFE29A8735400D3316C /* MeshtasticWidgetsBundle.swift */; };
|
||||
DD4C0F0129A8735400D3316C /* MeshtasticWidgetsLiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0F0029A8735400D3316C /* MeshtasticWidgetsLiveActivity.swift */; };
|
||||
DD4C0F0329A8735400D3316C /* MeshtasticWidgets.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0F0229A8735400D3316C /* MeshtasticWidgets.swift */; };
|
||||
DD4C0F0629A8735500D3316C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DD4C0F0529A8735500D3316C /* Assets.xcassets */; };
|
||||
DD4C0F0829A8735500D3316C /* MeshtasticWidgets.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0F0429A8735400D3316C /* MeshtasticWidgets.intentdefinition */; };
|
||||
DD4C0F0929A8735500D3316C /* MeshtasticWidgets.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0F0429A8735400D3316C /* MeshtasticWidgets.intentdefinition */; };
|
||||
DD4C0F0C29A8735500D3316C /* MeshtasticWidgetsExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = DD4C0EF829A8735400D3316C /* MeshtasticWidgetsExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
DD4C0F1329A9DDF800D3316C /* MeshActivityAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0F1229A9DDF800D3316C /* MeshActivityAttributes.swift */; };
|
||||
DD4C0F1629A9EB5000D3316C /* MeshActivityWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0F1429A9E21A00D3316C /* MeshActivityWidget.swift */; };
|
||||
DD4C0F1729A9EB6300D3316C /* MeshActivityWidget.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4C0F1429A9E21A00D3316C /* MeshActivityWidget.swift */; };
|
||||
DD4F23CD28779A3C001D37CB /* EnvironmentMetricsLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD4F23CC28779A3C001D37CB /* EnvironmentMetricsLog.swift */; };
|
||||
DD5394FC276993AD00AD86B1 /* SwiftProtobuf in Frameworks */ = {isa = PBXBuildFile; productRef = DD5394FB276993AD00AD86B1 /* SwiftProtobuf */; };
|
||||
DD5394FE276BA0EF00AD86B1 /* PositionEntityExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD5394FD276BA0EF00AD86B1 /* PositionEntityExtension.swift */; };
|
||||
|
|
@ -199,12 +200,12 @@
|
|||
DD4C0EF929A8735400D3316C /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; };
|
||||
DD4C0EFB29A8735400D3316C /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; };
|
||||
DD4C0EFE29A8735400D3316C /* MeshtasticWidgetsBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticWidgetsBundle.swift; sourceTree = "<group>"; };
|
||||
DD4C0F0029A8735400D3316C /* MeshtasticWidgetsLiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticWidgetsLiveActivity.swift; sourceTree = "<group>"; };
|
||||
DD4C0F0229A8735400D3316C /* MeshtasticWidgets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshtasticWidgets.swift; sourceTree = "<group>"; };
|
||||
DD4C0F0429A8735400D3316C /* MeshtasticWidgets.intentdefinition */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; path = MeshtasticWidgets.intentdefinition; sourceTree = "<group>"; };
|
||||
DD4C0F0529A8735500D3316C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
DD4C0F0729A8735500D3316C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
DD4C0F0D29A8735500D3316C /* MeshtasticWidgetsExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MeshtasticWidgetsExtension.entitlements; sourceTree = "<group>"; };
|
||||
DD4C0F1229A9DDF800D3316C /* MeshActivityAttributes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshActivityAttributes.swift; sourceTree = "<group>"; };
|
||||
DD4C0F1429A9E21A00D3316C /* MeshActivityWidget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MeshActivityWidget.swift; sourceTree = "<group>"; };
|
||||
DD4F23CC28779A3C001D37CB /* EnvironmentMetricsLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvironmentMetricsLog.swift; sourceTree = "<group>"; };
|
||||
DD5394FD276BA0EF00AD86B1 /* PositionEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PositionEntityExtension.swift; sourceTree = "<group>"; };
|
||||
DD58C5F12919AD3C00D5BEFB /* ChannelEntityExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChannelEntityExtension.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -401,11 +402,11 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
DD4C0EFE29A8735400D3316C /* MeshtasticWidgetsBundle.swift */,
|
||||
DD4C0F0029A8735400D3316C /* MeshtasticWidgetsLiveActivity.swift */,
|
||||
DD4C0F0229A8735400D3316C /* MeshtasticWidgets.swift */,
|
||||
DD4C0F0429A8735400D3316C /* MeshtasticWidgets.intentdefinition */,
|
||||
DD4C0F0529A8735500D3316C /* Assets.xcassets */,
|
||||
DD4C0F0729A8735500D3316C /* Info.plist */,
|
||||
DD4C0F1229A9DDF800D3316C /* MeshActivityAttributes.swift */,
|
||||
DD4C0F1429A9E21A00D3316C /* MeshActivityWidget.swift */,
|
||||
);
|
||||
path = MeshtasticWidgets;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -870,9 +871,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DD4C0F1629A9EB5000D3316C /* MeshActivityWidget.swift in Sources */,
|
||||
DD4C0EFF29A8735400D3316C /* MeshtasticWidgetsBundle.swift in Sources */,
|
||||
DD4C0F0129A8735400D3316C /* MeshtasticWidgetsLiveActivity.swift in Sources */,
|
||||
DD4C0F0329A8735400D3316C /* MeshtasticWidgets.swift in Sources */,
|
||||
DD4C0F0829A8735500D3316C /* MeshtasticWidgets.intentdefinition in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
|
@ -946,6 +946,7 @@
|
|||
DDB6ABE028B13AC700384BA1 /* DeviceRoles.swift in Sources */,
|
||||
DD86D40C287F401000BAEB7A /* SaveChannelQRCode.swift in Sources */,
|
||||
DDA1C48E28DB49D3009933EC /* ChannelRoles.swift in Sources */,
|
||||
DD4C0F1729A9EB6300D3316C /* MeshActivityWidget.swift in Sources */,
|
||||
DD8ED9C8289CE4B900B3B0AB /* RoutingError.swift in Sources */,
|
||||
DD5E5202298EE33B00D21B61 /* admin.pb.swift in Sources */,
|
||||
DD964FC62975DBFD007C176F /* QueryCoreData.swift in Sources */,
|
||||
|
|
@ -953,6 +954,7 @@
|
|||
DD8ED9C52898D51F00B3B0AB /* NetworkConfig.swift in Sources */,
|
||||
DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */,
|
||||
DD2E65262767A01F00E45FC5 /* NodeDetail.swift in Sources */,
|
||||
DD4C0F1329A9DDF800D3316C /* MeshActivityAttributes.swift in Sources */,
|
||||
DD1925B928CDA93900720036 /* SerialConfigEnums.swift in Sources */,
|
||||
DD86D4112881D16900BAEB7A /* WriteCsvFile.swift in Sources */,
|
||||
DD86D40F2881BE4C00BAEB7A /* CsvDocument.swift in Sources */,
|
||||
|
|
@ -1237,7 +1239,7 @@
|
|||
INFOPLIST_FILE = Meshtastic/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Meshtastic;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
@ -1271,7 +1273,7 @@
|
|||
INFOPLIST_FILE = Meshtastic/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Meshtastic;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 16.2;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@ class BLEManager: NSObject, CBPeripheralDelegate, ObservableObject {
|
|||
self.lastConnectionError = ""
|
||||
self.connectedVersion = "0.0.0"
|
||||
super.init()
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil)
|
||||
//centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionRestoreIdentifierKey: restoreKey])
|
||||
//centralManager = CBCentralManager(delegate: self, queue: nil)
|
||||
centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionRestoreIdentifierKey: restoreKey])
|
||||
}
|
||||
|
||||
// MARK: Scanning for BLE Devices
|
||||
|
|
@ -2018,35 +2018,19 @@ extension BLEManager: CBCentralManagerDelegate {
|
|||
}
|
||||
|
||||
if peripherals.count > 0 {
|
||||
//connectedPeripheral.peripheral = peripherals[0]
|
||||
// 5
|
||||
//connectedPeripheral.peripheral.delegate = self
|
||||
|
||||
|
||||
for peripheral in peripherals {
|
||||
print(peripheral)
|
||||
switch peripheral.state {
|
||||
case .connecting: // I've only seen this happen when
|
||||
// re-launching attached to Xcode.
|
||||
print("Xcode Restore")
|
||||
case .connecting: // I've only seen this happen when
|
||||
// re-launching attached to Xcode.
|
||||
print("Xcode Restore")
|
||||
|
||||
case .connected: // Store for connection / requesting
|
||||
// notifications when BT starts.
|
||||
disconnectPeripheral(reconnect: true)
|
||||
if connectedPeripheral?.peripheral != nil {
|
||||
self.sendWantConfig()
|
||||
} else {
|
||||
disconnectPeripheral(reconnect: true)
|
||||
case .connected:
|
||||
connectTo(peripheral: peripheral)
|
||||
print("Restore BLE State")
|
||||
default: break
|
||||
}
|
||||
print("Actual restore")
|
||||
//centralManager.connect(peripheral)
|
||||
default: break
|
||||
}
|
||||
|
||||
|
||||
|
||||
// connectedPeripheral.peripheral
|
||||
//connectedPeripheral.peripheral = peripheral
|
||||
//connectedPeripheral.peripheral.delegate = self
|
||||
}
|
||||
}
|
||||
print("willRestoreState Hit!")
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@
|
|||
<string>We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device.</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>We use your location to display it on the mesh map as well as to have GPS coordinatess to send to the connected device.</string>
|
||||
<key>NSSupportsLiveActivities</key>
|
||||
<true/>
|
||||
<key>Privacy – Bluetooth Always Usage Description</key>
|
||||
<string>We use bluetooth to connect to nearby Meshtastic Devices</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
|
|
|
|||
23
MeshtasticWidgets/MeshActivityAttributes.swift
Normal file
23
MeshtasticWidgets/MeshActivityAttributes.swift
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// MeshActivityAttributes.swift
|
||||
// Meshtastic
|
||||
//
|
||||
// Copyright(c) Garth Vander Houwen 2/24/23.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import ActivityKit
|
||||
|
||||
struct MeshActivityAttributes: ActivityAttributes {
|
||||
public typealias MyActivityStatus = ContentState
|
||||
|
||||
public struct ContentState: Codable, Hashable {
|
||||
var timerRange: ClosedRange<Date>
|
||||
}
|
||||
|
||||
var nodeNum: Int
|
||||
var nodeName: String
|
||||
var channelUtilization: Double
|
||||
var airtime: Double
|
||||
var activityName: String
|
||||
}
|
||||
172
MeshtasticWidgets/MeshActivityWidget.swift
Normal file
172
MeshtasticWidgets/MeshActivityWidget.swift
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
////
|
||||
//// MeshActivityWidget.swift
|
||||
//// Meshtastic
|
||||
////
|
||||
//// Created by Garth Vander Houwen on 2/24/23.
|
||||
////
|
||||
//
|
||||
///*
|
||||
//See LICENSE folder for this sample’s licensing information.
|
||||
//
|
||||
//Abstract:
|
||||
//Defines the live activity and dynamic island.
|
||||
//*/
|
||||
//
|
||||
//import SwiftUI
|
||||
//import WidgetKit
|
||||
//
|
||||
//
|
||||
//struct MeshActivityWidget: Widget {
|
||||
//
|
||||
// var body: some WidgetConfiguration {
|
||||
//
|
||||
// ActivityConfiguration(for: MeshActivityAttributes.self) { context in
|
||||
// LiveActivityView(orderNumber: String(context.attributes.nodeNum), timerRange: context.state.timerRange)
|
||||
// .widgetURL(URL(string: "meshtastic://node/\(context.attributes.nodeNum)"))
|
||||
// } dynamicIsland: { context in
|
||||
// DynamicIsland {
|
||||
// DynamicIslandExpandedRegion(.leading) {
|
||||
// ExpandedLeadingView()
|
||||
// }
|
||||
//
|
||||
// DynamicIslandExpandedRegion(.trailing, priority: 1) {
|
||||
// ExpandedTrailingView(orderNumber: String(context.attributes.nodeNum), timerInterval: context.state.timerRange)
|
||||
// .dynamicIsland(verticalPlacement: .belowIfTooWide)
|
||||
// }
|
||||
// } compactLeading: {
|
||||
// Image("IslandCompactIcon")
|
||||
// .padding(4)
|
||||
// .background(.indigo.gradient, in: ContainerRelativeShape())
|
||||
//
|
||||
// } compactTrailing: {
|
||||
// Text(timerInterval: context.state.timerRange, countsDown: true)
|
||||
// .monospacedDigit()
|
||||
// .foregroundColor(Color("LightIndigo"))
|
||||
// .frame(width: 40)
|
||||
// } minimal: {
|
||||
// Image("IslandCompactIcon")
|
||||
// .padding(4)
|
||||
// .background(.indigo.gradient, in: ContainerRelativeShape())
|
||||
// }
|
||||
// .contentMargins(.trailing, 32, for: .expanded)
|
||||
// .contentMargins([.leading, .top, .bottom], 6, for: .compactLeading)
|
||||
// .contentMargins(.all, 6, for: .minimal)
|
||||
// .widgetURL(URL(string: "foodtruck://order/\(context.attributes.nodeNum)"))
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//struct LiveActivityView: View {
|
||||
// @Environment(\.colorScheme) private var colorScheme
|
||||
// @Environment(\.isLuminanceReduced) var isLuminanceReduced
|
||||
//
|
||||
// var orderNumber: String
|
||||
// var timerRange: ClosedRange<Date>
|
||||
//
|
||||
// var body: some View {
|
||||
// HStack {
|
||||
// Image("IslandExpandedIcon")
|
||||
// .clipShape(ContainerRelativeShape())
|
||||
// .opacity(isLuminanceReduced ? 0.5 : 1.0)
|
||||
// OrderInfoView(orderNumber: orderNumber)
|
||||
// Spacer()
|
||||
// OrderTimerView(timerRange: timerRange)
|
||||
// }
|
||||
// .tint(.primary)
|
||||
// .padding([.leading, .top, .bottom])
|
||||
// .padding(.trailing, 32)
|
||||
// .activityBackgroundTint(colorScheme == .light ? Color("LiveActivityBackground") : Color("AccentColorDimmed"))
|
||||
// .activitySystemActionForegroundColor(.primary)
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//struct ExpandedLeadingView: View {
|
||||
// var body: some View {
|
||||
// Image("IslandExpandedIcon")
|
||||
// .clipShape(ContainerRelativeShape())
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//struct OrderInfoView: View {
|
||||
// @Environment(\.isLuminanceReduced) var isLuminanceReduced
|
||||
//
|
||||
// var orderNumber: String
|
||||
//
|
||||
// var body: some View {
|
||||
// VStack(alignment: .leading, spacing: 0) {
|
||||
// Text("Order \(orderNumber)")
|
||||
// .font(.title3)
|
||||
// .fontWeight(.semibold)
|
||||
// .foregroundStyle(.tint)
|
||||
//
|
||||
// Text("6 donuts")
|
||||
// .font(.subheadline)
|
||||
// .fontWeight(.medium)
|
||||
// .foregroundStyle(.secondary)
|
||||
// .opacity(isLuminanceReduced ? 0.5 : 1.0)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//struct OrderTimerView: View {
|
||||
// @Environment(\.isLuminanceReduced) var isLuminanceReduced
|
||||
//
|
||||
// var timerRange: ClosedRange<Date>
|
||||
//
|
||||
// var body: some View {
|
||||
// VStack(alignment: .trailing) {
|
||||
// Text(timerInterval: timerRange, countsDown: true)
|
||||
// .monospacedDigit()
|
||||
// .multilineTextAlignment(.trailing)
|
||||
// .frame(width: 80)
|
||||
// .font(.title3)
|
||||
// .fontWeight(.semibold)
|
||||
// .foregroundStyle(.tint)
|
||||
// Text("Remaining")
|
||||
// .font(.subheadline)
|
||||
// .fontWeight(.medium)
|
||||
// .foregroundStyle(.secondary)
|
||||
// .opacity(isLuminanceReduced ? 0.5 : 1.0)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//struct ExpandedTrailingView: View {
|
||||
// var orderNumber: String
|
||||
// var timerInterval: ClosedRange<Date>
|
||||
//
|
||||
// var body: some View {
|
||||
// HStack(alignment: .lastTextBaseline) {
|
||||
// OrderInfoView(orderNumber: orderNumber)
|
||||
// Spacer()
|
||||
// OrderTimerView(timerRange: timerInterval)
|
||||
// }
|
||||
// .tint(Color("LightIndigo"))
|
||||
// }
|
||||
//}
|
||||
//struct MeshActivityPreviewProvider: PreviewProvider {
|
||||
// static let activityAttributes = MeshActivityAttributes(
|
||||
// nodeNum: 666, nodeName: "Garth Hydra", channelUtilization: 45.0, airtime: 10.0, activityName: "activity name"
|
||||
// )
|
||||
//
|
||||
// static let state = MeshActivityAttributes.ContentState(
|
||||
// timerRange: Date.now...Date(timeIntervalSinceNow: 30))
|
||||
//
|
||||
// static var previews: some View {
|
||||
// activityAttributes
|
||||
// .previewContext(state, viewKind: .dynamicIsland(.compact))
|
||||
// .previewDisplayName("Compact")
|
||||
//
|
||||
// activityAttributes
|
||||
// .previewContext(state, viewKind: .dynamicIsland(.expanded))
|
||||
// .previewDisplayName("Expanded")
|
||||
//
|
||||
// activityAttributes
|
||||
// .previewContext(state, viewKind: .content)
|
||||
// .previewDisplayName("Notification")
|
||||
//
|
||||
// activityAttributes
|
||||
// .previewContext(state, viewKind: .dynamicIsland(.minimal))
|
||||
// .previewDisplayName("Minimal")
|
||||
// }
|
||||
//}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
//
|
||||
// MeshtasticWidgets.swift
|
||||
// MeshtasticWidgets
|
||||
//
|
||||
// Created by Garth Vander Houwen on 2/23/23.
|
||||
//
|
||||
|
||||
import WidgetKit
|
||||
import SwiftUI
|
||||
import Intents
|
||||
|
||||
struct Provider: IntentTimelineProvider {
|
||||
func placeholder(in context: Context) -> SimpleEntry {
|
||||
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
|
||||
}
|
||||
|
||||
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
|
||||
let entry = SimpleEntry(date: Date(), configuration: configuration)
|
||||
completion(entry)
|
||||
}
|
||||
|
||||
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
|
||||
var entries: [SimpleEntry] = []
|
||||
|
||||
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
|
||||
let currentDate = Date()
|
||||
for hourOffset in 0 ..< 5 {
|
||||
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
|
||||
let entry = SimpleEntry(date: entryDate, configuration: configuration)
|
||||
entries.append(entry)
|
||||
}
|
||||
|
||||
let timeline = Timeline(entries: entries, policy: .atEnd)
|
||||
completion(timeline)
|
||||
}
|
||||
}
|
||||
|
||||
struct SimpleEntry: TimelineEntry {
|
||||
let date: Date
|
||||
let configuration: ConfigurationIntent
|
||||
}
|
||||
|
||||
struct MeshtasticWidgetsEntryView : View {
|
||||
var entry: Provider.Entry
|
||||
|
||||
var body: some View {
|
||||
Text(entry.date, style: .time)
|
||||
}
|
||||
}
|
||||
|
||||
struct MeshtasticWidgets: Widget {
|
||||
let kind: String = "MeshtasticWidgets"
|
||||
|
||||
var body: some WidgetConfiguration {
|
||||
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
|
||||
MeshtasticWidgetsEntryView(entry: entry)
|
||||
}
|
||||
.configurationDisplayName("My Widget")
|
||||
.description("This is an example widget.")
|
||||
}
|
||||
}
|
||||
|
||||
struct MeshtasticWidgets_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
MeshtasticWidgetsEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
|
||||
.previewContext(WidgetPreviewContext(family: .systemSmall))
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,10 @@ import SwiftUI
|
|||
@main
|
||||
struct MeshtasticWidgetsBundle: WidgetBundle {
|
||||
var body: some Widget {
|
||||
MeshtasticWidgets()
|
||||
MeshtasticWidgetsLiveActivity()
|
||||
|
||||
// MARK: - Live Activity Widgets
|
||||
#if canImport(ActivityKit)
|
||||
//MeshActivityWidget()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
//
|
||||
// MeshtasticWidgetsLiveActivity.swift
|
||||
// MeshtasticWidgets
|
||||
//
|
||||
// Created by Garth Vander Houwen on 2/23/23.
|
||||
//
|
||||
|
||||
import ActivityKit
|
||||
import WidgetKit
|
||||
import SwiftUI
|
||||
|
||||
struct MeshtasticWidgetsAttributes: ActivityAttributes {
|
||||
public struct ContentState: Codable, Hashable {
|
||||
// Dynamic stateful properties about your activity go here!
|
||||
var value: Int
|
||||
}
|
||||
|
||||
// Fixed non-changing properties about your activity go here!
|
||||
var name: String
|
||||
}
|
||||
|
||||
struct MeshtasticWidgetsLiveActivity: Widget {
|
||||
var body: some WidgetConfiguration {
|
||||
ActivityConfiguration(for: MeshtasticWidgetsAttributes.self) { context in
|
||||
// Lock screen/banner UI goes here
|
||||
VStack {
|
||||
Text("Hello")
|
||||
}
|
||||
.activityBackgroundTint(Color.cyan)
|
||||
.activitySystemActionForegroundColor(Color.black)
|
||||
|
||||
} dynamicIsland: { context in
|
||||
DynamicIsland {
|
||||
// Expanded UI goes here. Compose the expanded UI through
|
||||
// various regions, like leading/trailing/center/bottom
|
||||
DynamicIslandExpandedRegion(.leading) {
|
||||
Text("Leading")
|
||||
}
|
||||
DynamicIslandExpandedRegion(.trailing) {
|
||||
Text("Trailing")
|
||||
}
|
||||
DynamicIslandExpandedRegion(.bottom) {
|
||||
Text("Bottom")
|
||||
// more content
|
||||
}
|
||||
} compactLeading: {
|
||||
Text("L")
|
||||
} compactTrailing: {
|
||||
Text("T")
|
||||
} minimal: {
|
||||
Text("Min")
|
||||
}
|
||||
.widgetURL(URL(string: "http://www.apple.com"))
|
||||
.keylineTint(Color.red)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct MeshtasticWidgetsLiveActivity_Previews: PreviewProvider {
|
||||
static let attributes = MeshtasticWidgetsAttributes(name: "Me")
|
||||
static let contentState = MeshtasticWidgetsAttributes.ContentState(value: 3)
|
||||
|
||||
static var previews: some View {
|
||||
attributes
|
||||
.previewContext(contentState, viewKind: .dynamicIsland(.compact))
|
||||
.previewDisplayName("Island Compact")
|
||||
attributes
|
||||
.previewContext(contentState, viewKind: .dynamicIsland(.expanded))
|
||||
.previewDisplayName("Island Expanded")
|
||||
attributes
|
||||
.previewContext(contentState, viewKind: .dynamicIsland(.minimal))
|
||||
.previewDisplayName("Minimal")
|
||||
attributes
|
||||
.previewContext(contentState, viewKind: .content)
|
||||
.previewDisplayName("Notification")
|
||||
}
|
||||
}
|
||||
|
|
@ -140,6 +140,10 @@
|
|||
"map.centering"="Centering";
|
||||
"map.recentering"="Automatic Re-centering";
|
||||
"map.type"="地图类型";
|
||||
"map.usertrackingmode"="User tracking mode";
|
||||
"map.usertrackingmode.none"="None";
|
||||
"map.usertrackingmode.follow"="Follow";
|
||||
"map.usertrackingmode.followwithheading"="Follow with heading";
|
||||
"mesh.log"="Mesh 日志";
|
||||
"mesh.log.bluetooth.config %@"="Bluetooth config received: %@";
|
||||
"mesh.log.cannedmessage.config %@"="Canned Message module config received: %@";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue