Replaces the full sentence ("Heck steht höher, links steht höher") in
the .small activity family with a compact "H ↑ L" style readout: a
direction letter per axis (only shown when outside tolerance) around a
single up arrow, since only the higher side is ever named anyway. Text
now shares the same green/orange/red scale as the bubble glyph (factored
into one levelColour helper instead of two duplicated thresholds), and
uses a scalable font style with minimumScaleFactor so it fits whatever
size CarPlay actually grants the card - there's no API to query the
physical display size from Live Activity content.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
CarPlay renders Live Activities through the .small activity family
(shared with the Watch Smart Stack), not the lock-screen content view.
Without it, CarPlay fell back to the Dynamic Island's compactLeading/
compactTrailing, which only had the generic "level" SF Symbol and an
empty trailing view — hence the wrong icon and missing text.
Adds .supplementalActivityFamilies([.small]) and a compact layout that
reuses the real LevelBubbleGlyph plus a one-line instruction for that
family, while the lock screen keeps its existing two-line view.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Dynamic Island now shows only the level icon (compact/minimal); the
bubble, instruction text, and numbers move to the shared lock
screen/CarPlay ActivityView, which iOS renders identically on both
surfaces (no separate CarPlay layout API exists for this).
- Replace +/- signs with a leading direction letter (H/F for Heck-
Front, R/L for rechts-links) via a new shared LevelDirectionFormatting
helper, used by the level screen, alignment assistant, and dashboard
card. The generic "Messwerte" list keeps raw signed values.
- Live Activity's instruction now reads as two lines ("Heck steht
höher 1.8°" / "links steht höher 0.9°") instead of a sentence plus a
separate number column.
- Fix the bubble level graphic's pitch axis being inverted (front/rear
reversed) in all three copies (app, watch, Live Activity widget) —
confirmed against the known-correct VehicleTiltView orientation.
- Dashboard card shows pitch and roll side by side, large, without the
"Längsneigung"/"Querneigung" labels, for the leveling device.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- Assign the shared development team to the widget extension and watch
complication targets, and correct the watch app's companion bundle
identifier so on-device installs succeed after the bundle ID rename
to de.s0.fototeddy.VanAligneiOS.
- Guard against two ConfiguredDevices sharing a peripheralID (e.g. a
double-tapped "Sichern"), which crashed BluetoothManager's
Dictionary(uniqueKeysWithValues:) on launch.
- Keep Bluetooth running in the background while a Live Activity is
active, so lock screen/CarPlay keep receiving fresh readings instead
of freezing at the last value before backgrounding.
- Render the actual bubble-level graphic (not just a static icon) in
the Live Activity's lock screen view and expanded Dynamic Island.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the ActivityKit boilerplate with a real lock screen/Dynamic
Island UI driven by live pitch/roll readings, toggled from the
leveling device's detail screen. Since iOS 17 shows any running Live
Activity on CarPlay's dashboard without a dedicated CarPlay app entitlement,
this covers the requested CarPlay use case without one.
Also fixes the widget extension never being embedded into the app
(missing Embed Foundation Extensions build phase and target
dependency), which meant no widget or Live Activity could ever have
rendered regardless of code changes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>