Die App zeigte "Bald ablaufend" nur beim Oeffnen. Jetzt erinnert sie aktiv vor dem Ablauf - mit frei zusammenstellbaren Regeln, pro Server getrennt. Eine Regel ist "X Tage/Wochen vor Ablauf", optional nur fuer eine Kategorie (inklusive deren Unterkategorien), einmalig oder taeglich wiederkehrend. Eine Kategorie-Regel ersetzt fuer ihre Produkte die allgemeine - so kann Molkerei frueher warnen als Chips. Dazu am Ablauftag eine letzte, deutliche Warnung fuer alle Produkte (eigener Schalter). Die Meldungen kommen als Tages-Sammelmeldung, je Server eine, zur pro Server eingestellten Uhrzeit. Weil Vorrania im Heimnetz laeuft und von unterwegs oft nicht erreichbar ist, kann die App nicht zuverlaessig im Hintergrund abfragen - und iOS verlangt ohnehin, dass lokale Benachrichtigungen im Voraus geplant werden. Also: aus den Ablaufdaten kuenftige Termine berechnen und einplanen; aufgefrischt beim Oeffnen, im Vordergrund und best-effort per Hintergrund-Aktualisierung. Geplant wird fuer alle eingerichteten Server, jeder mit seinem Token aus dem Keychain; unerreichbare werden uebersprungen. iOS erlaubt 64 ausstehende Meldungen je App, deshalb die naechstliegenden zuerst und bei 60 gekappt. Einstellungen sitzen hinter der Glocke je Server in der Server-Verwaltung (nicht admin-beschraenkt, es ist eine Geraete-Einstellung). Getippt wechselt die Meldung auf den betroffenen Server und oeffnet "Bald ablaufend". Keine Backend-Aenderung: die Kategorie kommt aus /products, der Ablauf aus /expiring. Die Rechenlogik (ExpiryPlanner) ist bewusst netz- und iOS-frei und mit einem eigenstaendigen Swift-Harnisch geprueft: Kategorie-Vorrang, Unterkategorien, Rueckfall auf die allgemeine Regel, einmalig vs. wiederkehrend und die letzte Warnung. Modelle gegen echte /expiring- und /products-Antworten abgeglichen, App startet ohne Absturz (auch die BGTask-Registrierung). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
107 lines
3.7 KiB
Plaintext
107 lines
3.7 KiB
Plaintext
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
<plist version="1.0">
|
|
<dict>
|
|
<!-- Von Xcode aus den Build-Einstellungen gefuellt -->
|
|
<!-- Deutsch als Sprache der App: Sonst zeichnet iOS DatePicker und
|
|
Monatsnamen auf Englisch ("10. Dec 2027"). -->
|
|
<key>CFBundleDevelopmentRegion</key>
|
|
<string>de</string>
|
|
<key>CFBundleLocalizations</key>
|
|
<array>
|
|
<string>de</string>
|
|
</array>
|
|
<key>CFBundleExecutable</key>
|
|
<string>$(EXECUTABLE_NAME)</string>
|
|
<key>CFBundleIdentifier</key>
|
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
|
<key>CFBundleInfoDictionaryVersion</key>
|
|
<string>6.0</string>
|
|
<key>CFBundleName</key>
|
|
<string>$(PRODUCT_NAME)</string>
|
|
<key>CFBundlePackageType</key>
|
|
<string>APPL</string>
|
|
|
|
<key>CFBundleDisplayName</key>
|
|
<string>Vorrania</string>
|
|
<key>CFBundleShortVersionString</key>
|
|
<string>1.0</string>
|
|
<key>CFBundleVersion</key>
|
|
<string>1</string>
|
|
<key>UILaunchScreen</key>
|
|
<dict/>
|
|
|
|
<!-- Am iPad verlangt das System alle Ausrichtungen, solange die App nicht
|
|
auf Vollbild besteht. Am iPhone bleibt Hochkant plus Querformat. -->
|
|
<key>UISupportedInterfaceOrientations</key>
|
|
<array>
|
|
<string>UIInterfaceOrientationPortrait</string>
|
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
</array>
|
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
|
<array>
|
|
<string>UIInterfaceOrientationPortrait</string>
|
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
|
</array>
|
|
|
|
<!-- Kamera für den Barcode-Scan -->
|
|
<key>NSCameraUsageDescription</key>
|
|
<string>Die Kamera wird zum Scannen von Barcodes beim Ein- und Auslagern verwendet.</string>
|
|
|
|
<!-- Lokaler Server ohne HTTPS (Heimnetz) -->
|
|
<key>NSAppTransportSecurity</key>
|
|
<dict>
|
|
<key>NSAllowsLocalNetworking</key>
|
|
<true/>
|
|
</dict>
|
|
|
|
<!-- Hintergrund-Aktualisierung: die App frischt gelegentlich den Plan der
|
|
Ablauf-Benachrichtigungen auf. Zeitpunkt bestimmt iOS. -->
|
|
<key>UIBackgroundModes</key>
|
|
<array>
|
|
<string>fetch</string>
|
|
</array>
|
|
<key>BGTaskSchedulerPermittedIdentifiers</key>
|
|
<array>
|
|
<string>com.scarriffle.vorrania.refresh</string>
|
|
</array>
|
|
|
|
<!-- Schnellaktionen beim langen Druck auf das App-Symbol -->
|
|
<key>UIApplicationShortcutItems</key>
|
|
<array>
|
|
<dict>
|
|
<key>UIApplicationShortcutItemType</key>
|
|
<string>com.scarriffle.vorrania.checkin</string>
|
|
<key>UIApplicationShortcutItemTitle</key>
|
|
<string>Einlagern</string>
|
|
<key>UIApplicationShortcutItemIconType</key>
|
|
<string>UIApplicationShortcutIconTypeAdd</string>
|
|
</dict>
|
|
<dict>
|
|
<key>UIApplicationShortcutItemType</key>
|
|
<string>com.scarriffle.vorrania.checkout</string>
|
|
<key>UIApplicationShortcutItemTitle</key>
|
|
<string>Auslagern</string>
|
|
<key>UIApplicationShortcutItemIconType</key>
|
|
<string>UIApplicationShortcutIconTypeRemove</string>
|
|
</dict>
|
|
</array>
|
|
|
|
<!-- vorrania://checkin bzw. vorrania://checkout -->
|
|
<key>CFBundleURLTypes</key>
|
|
<array>
|
|
<dict>
|
|
<key>CFBundleURLName</key>
|
|
<string>com.scarriffle.vorrania</string>
|
|
<key>CFBundleURLSchemes</key>
|
|
<array>
|
|
<string>vorrania</string>
|
|
</array>
|
|
</dict>
|
|
</array>
|
|
</dict>
|
|
</plist>
|