forked from fritob/Camper-Monitor
CamperMonitor (Haupt-Repo) und VanAligneiOS (aus dem gemergten solar-integration-Branch) liefen unter zwei verschiedenen internen Namen, obwohl die App nach aussen längst einheitlich "VanControl Pro" heisst. Jetzt durchgängig VanControl: - Ordner: CamperMonitor/, CamperMonitorWatch/, CamperMonitorComplication/, VanAligneiOSWidget/ → VanControl/, VanControlWatch/, VanControlComplication/, VanControlWidget/ - Xcode-Projekt: CamperMonitor.xcodeproj → VanControl.xcodeproj, alle Targets/Schemes/Produktnamen entsprechend umbenannt - Bundle-Identifier auf Wunsch mitgeändert: de.s0.fototeddy.VanControl* (App noch nicht veröffentlicht); dabei auch die WKCompanionAppBundleIdentifier-Werte korrigiert, die noch das alte de.fritob-Präfix statt des tatsächlichen de.s0.fototeddy-Präfixes trugen - Swift-Dateien/Typen: CamperMonitorApp → VanControlApp, VanAligneiOSWidget* → VanControlWidget* - Config/*-Info.plist umbenannt, README.md/Tools/README.md/run-tests.sh auf die neuen Pfade angepasst Bewusst unverändert: firmware/vanalign und alle Bezüge auf "VanAlign" als Namen der Neigungsmesser-Hardware (eigenständiges Produkt, kein App-Name) sowie der komplette Android/-Ordner. Build (App, Watch, Debug) und Protokoll-Testlauf grün. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
93 lines
3.4 KiB
Swift
93 lines
3.4 KiB
Swift
import SwiftUI
|
||
import WidgetKit
|
||
|
||
/// Komplikation fürs Zifferblatt: ein Tipp, und die Nivellierung steht da.
|
||
///
|
||
/// Bewusst **ohne Messwert**. Eine Komplikation läuft in einem eigenen Prozess
|
||
/// und käme an die Werte nur über eine App-Gruppe – die verlangt eine bezahlte
|
||
/// Entwicklermitgliedschaft. Ein Wert, der beim Blick aufs Zifferblatt
|
||
/// womöglich Stunden alt ist, wäre ausserdem schlimmer als keiner: Man würde
|
||
/// ihm glauben.
|
||
///
|
||
/// Die Komplikation tut deshalb genau eine Sache, und die zuverlässig: Sie
|
||
/// öffnet die App auf der Nivellierung. Von dort sind die Werte live, weil die
|
||
/// Uhr den Sensor selbst anfunkt.
|
||
struct LevelComplicationEntry: TimelineEntry {
|
||
let date: Date
|
||
}
|
||
|
||
/// Nichts zu planen: Die Anzeige ändert sich nie, also ein einziger Eintrag
|
||
/// ohne Nachschub. Das kostet die Uhr auch nichts.
|
||
struct LevelComplicationProvider: TimelineProvider {
|
||
func placeholder(in context: Context) -> LevelComplicationEntry {
|
||
LevelComplicationEntry(date: .now)
|
||
}
|
||
|
||
func getSnapshot(in context: Context,
|
||
completion: @escaping (LevelComplicationEntry) -> Void) {
|
||
completion(LevelComplicationEntry(date: .now))
|
||
}
|
||
|
||
func getTimeline(in context: Context,
|
||
completion: @escaping (Timeline<LevelComplicationEntry>) -> Void) {
|
||
completion(Timeline(entries: [LevelComplicationEntry(date: .now)], policy: .never))
|
||
}
|
||
}
|
||
|
||
struct LevelComplicationView: View {
|
||
@Environment(\.widgetFamily) private var family
|
||
|
||
var body: some View {
|
||
switch family {
|
||
case .accessoryInline:
|
||
// Eine Zeile Text, mehr lässt diese Familie nicht zu.
|
||
Label("Nivellierung", systemImage: "level")
|
||
|
||
case .accessoryCorner:
|
||
Image(systemName: "level")
|
||
.font(.title2)
|
||
.widgetLabel("Nivellieren")
|
||
|
||
case .accessoryRectangular:
|
||
HStack(spacing: 6) {
|
||
Image(systemName: "level")
|
||
.font(.title3)
|
||
VStack(alignment: .leading, spacing: 0) {
|
||
Text("Nivellierung")
|
||
.font(.headline)
|
||
Text("Antippen zum Ausrichten")
|
||
.font(.caption2)
|
||
.foregroundStyle(.secondary)
|
||
}
|
||
}
|
||
|
||
default:
|
||
// Rund – auf dem Zifferblatt der knappste Platz, also nur das
|
||
// Symbol, gross genug zum Treffen.
|
||
ZStack {
|
||
AccessoryWidgetBackground()
|
||
Image(systemName: "level")
|
||
.font(.title2)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
@main
|
||
struct LevelComplication: Widget {
|
||
var body: some WidgetConfiguration {
|
||
StaticConfiguration(kind: "de.fritob.VanControl.complication.level",
|
||
provider: LevelComplicationProvider()) { _ in
|
||
LevelComplicationView()
|
||
// Der Tipp landet nicht irgendwo in der App, sondern auf der
|
||
// Nivellierung – dafür wertet die App diese Adresse aus.
|
||
.widgetURL(WatchDeepLink.level)
|
||
.containerBackground(.clear, for: .widget)
|
||
}
|
||
.configurationDisplayName("Nivellierung")
|
||
.description("Öffnet die Nivellierung direkt vom Zifferblatt.")
|
||
.supportedFamilies([.accessoryCircular, .accessoryCorner,
|
||
.accessoryInline, .accessoryRectangular])
|
||
}
|
||
}
|