chore: Rebrand auf ev.mana.cardecky
Apple-Developer-Portal-App-ID lautet ev.mana.cardecky (analog zur Domain cardecky.mana.how). Alle Bundle-IDs, App-Group, Keychain- Group, OSLog-Subsysteme, URL-Schemes, Widget-Kind, App-Intent-Phrases, Marketing-Texte und Doku nachgezogen. Bundle-IDs neu: - Main: ev.mana.cardecky - Widget: ev.mana.cardecky.widget - Share: ev.mana.cardecky.share - Tests: ev.mana.cardecky.tests / .uitests App-Group: group.ev.mana.cardecky Keychain-Access-Group: $(AppIdentifierPrefix)ev.mana.cardecky OSLog-Subsystem: ev.mana.cardecky AASA gleichzeitig in cards-Repo angepasst (Commit 21ec535) und auf mana-server redeployed — Probe liefert appID "QP3GLU8PH3.ev.mana.cardecky". Plus: ShareExtension/Resources/Info.plist + entitlements werden jetzt analog zu Widget-Resources gitignored (sind XcodeGen-generated). 35 Unit-Tests + 1 UI-Test grün, alle drei Targets bauen. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
468ef291f5
commit
4dfb32ba25
17 changed files with 203 additions and 94 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -11,3 +11,5 @@ Sources/Resources/Info.plist
|
|||
Sources/Resources/CardsNative.entitlements
|
||||
Widgets/CardsWidget/Resources/Info.plist
|
||||
Widgets/CardsWidget/Resources/CardsWidgetExtension.entitlements
|
||||
ShareExtension/Resources/Info.plist
|
||||
ShareExtension/Resources/CardsShareExtension.entitlements
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ Affordances (Widgets, Notifications, Universal-Links, Pencil).
|
|||
HTTPS/JWT ┌──────────────────┐
|
||||
cards-api ◄───────────── │ cards-native │ SwiftUI
|
||||
cardecky-api.mana.how │ (this repo) │ SwiftData (Cache)
|
||||
│ ev.mana.cards │ WidgetKit (β-6)
|
||||
│ ev.mana.cardecky │ WidgetKit (β-6)
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ Beschlossen. Nicht ohne explizite Diskussion antasten.
|
|||
Auth-Implementierung ist verboten.
|
||||
4. **Pure SwiftUI.** Keine externen UI-Libraries. AppKit/UIKit nur
|
||||
als Bridge wenn zwingend (z.B. `PencilKit` für Image-Occlusion).
|
||||
5. **Bundle-ID `ev.mana.cards`.** Reverse-Domain mana-ev.ch.
|
||||
5. **Bundle-ID `ev.mana.cardecky`.** Reverse-Domain mana-ev.ch.
|
||||
Universal-Link-Domain: `cardecky.mana.how`.
|
||||
6. **Cards-Domain-Logik bleibt am Server.** SubIndex-Berechnung für
|
||||
Cloze, Image-Occlusion-Mask-Validation, Content-Hash — alles
|
||||
|
|
@ -74,7 +74,7 @@ Beschlossen. Nicht ohne explizite Diskussion antasten.
|
|||
sind **nicht** im Git
|
||||
- **SwiftFormat** mit `.swiftformat` (4-space, 120-col, sorted imports)
|
||||
- **SwiftLint** mit `.swiftlint.yml`
|
||||
- **Logging:** App-Subsystem `ev.mana.cards` via
|
||||
- **Logging:** App-Subsystem `ev.mana.cardecky` via
|
||||
`Sources/Core/Telemetry/Log.swift`. ManaCore loggt parallel unter
|
||||
`ev.mana.core`
|
||||
- **Persistenz:** SwiftData für Deck/Card-Cache (ab β-1), JWT im
|
||||
|
|
@ -117,7 +117,7 @@ cards-native/
|
|||
│ │ ├── Domain/ (Card-Type-Enums, Rating-Enum — ab β-2)
|
||||
│ │ ├── Storage/ (SwiftData-Models — ab β-1)
|
||||
│ │ ├── Sync/ (ReviewQueue, MediaCache — ab β-2/β-4)
|
||||
│ │ ├── Telemetry/ OSLog (Subsystem ev.mana.cards)
|
||||
│ │ ├── Telemetry/ OSLog (Subsystem ev.mana.cardecky)
|
||||
│ │ └── Theme/ CardsTheme (forest-Werte)
|
||||
│ ├── Widgets/ (WidgetKit-Extension — ab β-6)
|
||||
│ ├── ShareExtension/ (Save-as-Card — ab β-6)
|
||||
|
|
|
|||
8
PLAN.md
8
PLAN.md
|
|
@ -17,12 +17,12 @@ mit Flugmodus zwischendurch) steht aus — Aufgabe für Till.
|
|||
|
||||
✅ **β-0 — Setup (2026-05-12, Tag `v0.1.0`)**
|
||||
- Repo-Skelett unter `git.mana.how/till/cards-native`
|
||||
- `project.yml` mit Bundle-ID `ev.mana.cards`, ManaSwiftCore via
|
||||
- `project.yml` mit Bundle-ID `ev.mana.cardecky`, ManaSwiftCore via
|
||||
`path: ../mana-swift-core`
|
||||
- `AppConfig` als `ManaAppConfig`-Provider:
|
||||
- Auth: `https://auth.mana.how`
|
||||
- API: `https://cardecky-api.mana.how`
|
||||
- Keychain-Service: `ev.mana.cards`
|
||||
- Keychain-Service: `ev.mana.cardecky`
|
||||
- `CardsTheme.swift` mit forest-Werten (lokal nachgebaut aus
|
||||
`mana/packages/themes/src/variants/forest.css`)
|
||||
- `LoginView` (Email/PW gegen mana-auth)
|
||||
|
|
@ -63,7 +63,7 @@ mit Flugmodus zwischendurch) steht aus — Aufgabe für Till.
|
|||
- `WidgetSnapshot` Codable mit `topDecks` (Top-3 nach dueCount)
|
||||
und `totalDueCount`
|
||||
- `WidgetSnapshotStore` schreibt in App-Group-Container
|
||||
`group.ev.mana.cards`
|
||||
`group.ev.mana.cardecky`
|
||||
- `DeckListStore.refresh` ruft `updateWidgetSnapshot()` und
|
||||
`WidgetCenter.shared.reloadAllTimelines()` nach jedem Pull
|
||||
- `CardsWidgetExtension`-Target (eigenes app-extension-Bundle):
|
||||
|
|
@ -73,7 +73,7 @@ mit Flugmodus zwischendurch) steht aus — Aufgabe für Till.
|
|||
- `DueProvider` als `TimelineProvider`: liest Snapshot, plant
|
||||
Refresh alle 30 min (plus instant-Refresh via Haupt-App)
|
||||
- `DueWidgetView` mit Family-Switch, alle 5 Family-Layouts
|
||||
- `com.apple.security.application-groups: group.ev.mana.cards`
|
||||
- `com.apple.security.application-groups: group.ev.mana.cardecky`
|
||||
im Haupt- und Widget-Entitlement
|
||||
- `WidgetSnapshot.swift` in beiden Targets via XcodeGen-source-array
|
||||
(single-source-of-truth)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ Reachability-Check. Vollständiger Phasen-Plan in
|
|||
```
|
||||
HTTPS/JWT ┌──────────────────┐
|
||||
cards-api ◄───────────── │ cards-native │ SwiftUI
|
||||
cardecky-api.mana.how │ ev.mana.cards │ WidgetKit (β-6)
|
||||
cardecky-api.mana.how │ ev.mana.cardecky │ WidgetKit (β-6)
|
||||
└──────────────────┘
|
||||
│
|
||||
┌─────────────────────────────────────────┐
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
<?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>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.ev.mana.cards</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
<?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>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Als Karte speichern</string>
|
||||
<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>XPC!</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionAttributes</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationRule</key>
|
||||
<dict>
|
||||
<key>NSExtensionActivationSupportsText</key>
|
||||
<true/>
|
||||
<key>NSExtensionActivationSupportsWebURLWithMaxCount</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.share-services</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).ShareViewController</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
@ -72,7 +72,7 @@ final class ShareViewController: UIViewController {
|
|||
|
||||
private func cancel() {
|
||||
dismiss(animated: true) { [weak self] in
|
||||
self?.extensionContext?.cancelRequest(withError: NSError(domain: "ev.mana.cards.share", code: 0))
|
||||
self?.extensionContext?.cancelRequest(withError: NSError(domain: "ev.mana.cardecky.share", code: 0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import ManaCore
|
|||
enum AppConfig {
|
||||
static let manaAppConfig: ManaAppConfig = DefaultManaAppConfig(
|
||||
authBaseURL: URL(string: "https://auth.mana.how")!,
|
||||
keychainService: "ev.mana.cards",
|
||||
keychainService: "ev.mana.cardecky",
|
||||
keychainAccessGroup: nil
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ final class NotificationManager {
|
|||
}
|
||||
|
||||
private(set) var authorization: AuthorizationStatus = .unknown
|
||||
private let identifier = "ev.mana.cards.dailyReminder"
|
||||
private let identifier = "ev.mana.cardecky.dailyReminder"
|
||||
private let store = UserDefaults.standard
|
||||
|
||||
/// Persistiert User-Pref. Format: ISO-Stunde:Minute (default 18:00).
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ struct PendingShare: Codable, Identifiable, Hashable, Sendable {
|
|||
}
|
||||
|
||||
enum PendingShareStore {
|
||||
static let appGroupID = "group.ev.mana.cards"
|
||||
static let appGroupID = "group.ev.mana.cardecky"
|
||||
static let filename = "pending-shares.json"
|
||||
|
||||
static var url: URL? {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ struct WidgetSnapshot: Codable, Sendable {
|
|||
/// Liest und schreibt WidgetSnapshot in den shared App-Group-Container.
|
||||
enum WidgetSnapshotStore {
|
||||
/// App-Group-ID — muss exakt mit dem Entitlement-Eintrag matchen.
|
||||
static let appGroupID = "group.ev.mana.cards"
|
||||
static let appGroupID = "group.ev.mana.cardecky"
|
||||
static let snapshotFilename = "widget-snapshot.json"
|
||||
|
||||
static var snapshotURL: URL? {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import Foundation
|
||||
import OSLog
|
||||
|
||||
/// App-eigene OSLog-Logger unter Subsystem `ev.mana.cards`.
|
||||
/// App-eigene OSLog-Logger unter Subsystem `ev.mana.cardecky`.
|
||||
/// ManaCore loggt unter `ev.mana.core` parallel — siehe
|
||||
/// `mana-swift-core/Sources/ManaCore/Telemetry/CoreLog.swift`.
|
||||
enum Log {
|
||||
static let app = Logger(subsystem: "ev.mana.cards", category: "app")
|
||||
static let auth = Logger(subsystem: "ev.mana.cards", category: "auth")
|
||||
static let api = Logger(subsystem: "ev.mana.cards", category: "api")
|
||||
static let study = Logger(subsystem: "ev.mana.cards", category: "study")
|
||||
static let sync = Logger(subsystem: "ev.mana.cards", category: "sync")
|
||||
static let app = Logger(subsystem: "ev.mana.cardecky", category: "app")
|
||||
static let auth = Logger(subsystem: "ev.mana.cardecky", category: "auth")
|
||||
static let api = Logger(subsystem: "ev.mana.cardecky", category: "api")
|
||||
static let study = Logger(subsystem: "ev.mana.cardecky", category: "study")
|
||||
static let sync = Logger(subsystem: "ev.mana.cardecky", category: "sync")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ struct AppConfigTests {
|
|||
#expect(AppConfig.manaAppConfig.authBaseURL.absoluteString == "https://auth.mana.how")
|
||||
}
|
||||
|
||||
@Test("Keychain-Service ist ev.mana.cards")
|
||||
@Test("Keychain-Service ist ev.mana.cardecky")
|
||||
func keychainServiceIsAppSpecific() {
|
||||
#expect(AppConfig.manaAppConfig.keychainService == "ev.mana.cards")
|
||||
#expect(AppConfig.manaAppConfig.keychainService == "ev.mana.cardecky")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import SwiftUI
|
|||
import WidgetKit
|
||||
|
||||
struct CardsDueWidget: Widget {
|
||||
let kind: String = "ev.mana.cards.due"
|
||||
let kind: String = "ev.mana.cardecky.due"
|
||||
|
||||
var body: some WidgetConfiguration {
|
||||
StaticConfiguration(kind: kind, provider: DueProvider()) { entry in
|
||||
|
|
|
|||
155
docs/MARKETING_COPY.md
Normal file
155
docs/MARKETING_COPY.md
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
# MARKETING_COPY — cards-native
|
||||
|
||||
Vorschläge für App-Store-Description (de + en). Zum Eintragen in
|
||||
App-Store-Connect. **Nicht final** — vor Submission durch dich
|
||||
gegenlesen, Tonalität an Vereins-Stil schärfen (siehe `mana/docs/BRAND.md`,
|
||||
`mana/docs/MISSION.md`).
|
||||
|
||||
## Name + Subtitle
|
||||
|
||||
**App-Name:** `Cards`
|
||||
**Subtitle (max 30 Zeichen):** `Karteikarten — mana e.V.`
|
||||
|
||||
## Keywords (max 100 Zeichen, comma-separated)
|
||||
|
||||
```
|
||||
Karteikarten,Spaced Repetition,Lernen,Vokabeln,Anki,Flashcards,FSRS,mana,Verein,Open Source
|
||||
```
|
||||
|
||||
(95 Zeichen)
|
||||
|
||||
## Description — DE (max 4000 Zeichen)
|
||||
|
||||
```
|
||||
Cards ist die Karteikarten-App des Vereins mana e.V. — Spaced
|
||||
Repetition wie es sein soll: ohne Werbung, ohne Tracking, ohne
|
||||
Abo-Zwang.
|
||||
|
||||
KARTEN, WIE DU SIE BRAUCHST
|
||||
- Klassische Vorder-/Rückseite, beidseitig, Lückentext (Cloze),
|
||||
Eintippen, Multiple Choice
|
||||
- Bild-Verdeckung mit selbst gesetzten Masken — für Anatomie, Karten,
|
||||
Diagramme
|
||||
- Audio-Karten für Sprachen und Aussprache
|
||||
|
||||
MODERNER LERN-ALGORITHMUS
|
||||
Cards nutzt FSRS (Free Spaced Repetition Scheduler), den genauesten
|
||||
offenen Algorithmus für Karteikarten. Karten kommen wieder, wenn du
|
||||
sie wirklich brauchst — nicht nach willkürlichen Intervallen.
|
||||
|
||||
OFFLINE LERNEN
|
||||
Karten cachen lokal auf deinem Gerät. Im Flugzeug, in der U-Bahn,
|
||||
ohne WLAN — Cards funktioniert. Deine Bewertungen werden gequeued
|
||||
und beim nächsten Online-Moment automatisch hochgeladen.
|
||||
|
||||
WIDGETS UND NOTIFICATIONS
|
||||
Zeige dir die heute fälligen Karten direkt auf dem Home-Bildschirm
|
||||
oder Lock-Screen. Erinnerung zur Lieblings-Lern-Uhrzeit — lokal, ohne
|
||||
externe Push-Server.
|
||||
|
||||
CARDECKY — MARKETPLACE FÜR LERN-DECKS
|
||||
Stöbere durch öffentliche Decks aus der Cardecky-Community: Geografie,
|
||||
Sprachen, Wissenschaft. Abonnieren = Karten landen direkt in deiner
|
||||
Bibliothek, du kannst sie nach Belieben anpassen.
|
||||
|
||||
VEREIN, NICHT FIRMA
|
||||
Cards wird vom Verein mana e.V. (Schweiz, in Gründung) betrieben.
|
||||
Kein Tracking, kein Werbe-Anbieter, kein Crash-Reporter. Wenn du dem
|
||||
Verein etwas zurückgeben willst: mana-ev.ch/spende.
|
||||
|
||||
NATIV
|
||||
Geschrieben in SwiftUI, optimiert für iPhone, iPad und Mac. Apple-
|
||||
Pencil, Magic-Keyboard und Universal-Links sind voll unterstützt.
|
||||
Teile aus Safari oder Mail direkt eine neue Karte.
|
||||
|
||||
DSGVO-EHRLICH
|
||||
Deine Daten gehören dir. Export jederzeit als JSON, Lösch-Knopf
|
||||
löscht alles. Wir hosten in Europa, sprechen Deutsch, und antworten
|
||||
selbst.
|
||||
```
|
||||
|
||||
## Description — EN (max 4000 Zeichen)
|
||||
|
||||
```
|
||||
Cards is the flashcard app from mana e.V. — spaced repetition the
|
||||
way it should be: no ads, no tracking, no subscription pressure.
|
||||
|
||||
THE CARDS YOU NEED
|
||||
- Classic front/back, two-sided, cloze, type-in, multiple-choice
|
||||
- Image occlusion with hand-drawn masks — for anatomy, maps, diagrams
|
||||
- Audio cards for languages and pronunciation
|
||||
|
||||
MODERN SPACED-REPETITION
|
||||
Cards uses FSRS (Free Spaced Repetition Scheduler), the most accurate
|
||||
open algorithm available. Cards come back when you actually need them.
|
||||
|
||||
OFFLINE-FIRST
|
||||
Decks cache locally on your device. On a plane, in the subway, off
|
||||
the grid — Cards keeps working. Your reviews queue up and sync on
|
||||
the next online moment.
|
||||
|
||||
WIDGETS AND REMINDERS
|
||||
See today's due cards on your Home Screen or Lock Screen. Daily
|
||||
reminder at your preferred time — local, no push servers.
|
||||
|
||||
CARDECKY MARKETPLACE
|
||||
Browse public decks from the Cardecky community: geography, languages,
|
||||
science. Subscribe = decks land in your library, ready to be edited.
|
||||
|
||||
ASSOCIATION, NOT CORPORATION
|
||||
Cards is operated by mana e.V. (Switzerland, formation in progress).
|
||||
No tracking, no ad networks, no crash reporters. Want to give back?
|
||||
mana-ev.ch/donate.
|
||||
|
||||
NATIVE
|
||||
Built in SwiftUI for iPhone, iPad, and Mac. Apple Pencil,
|
||||
Magic Keyboard, and Universal Links are first-class. Share from
|
||||
Safari or Mail to create a card.
|
||||
|
||||
GDPR-HONEST
|
||||
Your data, your call. Full JSON export, single-button delete.
|
||||
Hosted in Europe, German-speaking support, replies from real humans.
|
||||
```
|
||||
|
||||
## Privacy-Declaration (App-Store-Connect)
|
||||
|
||||
| Datentyp | Gesammelt | Zweck | Verlinkt mit User | Tracking |
|
||||
|---|---|---|---|---|
|
||||
| Email | Ja | App-Functionality (Login) | Ja | Nein |
|
||||
| User Content (Cards, Decks) | Ja | App-Functionality | Ja | Nein |
|
||||
| Usage Data (FSRS Reviews) | Ja | App-Functionality | Ja | Nein |
|
||||
|
||||
Keine weiteren Kategorien. Insbesondere: keine `Identifiers`,
|
||||
keine `Diagnostics`, keine `Location`, keine `Contacts`.
|
||||
|
||||
## Privacy-Policy- + Support-URLs
|
||||
|
||||
Vor Submission setzen — vermutlich:
|
||||
- Privacy-Policy: `https://cardecky.mana.how/privacy` (existiert? prüfen)
|
||||
- Support: `https://cardecky.mana.how/help` oder `kontakt@mana-ev.ch`
|
||||
- Marketing: `https://cardecky.mana.how`
|
||||
|
||||
Falls die URLs noch nicht live sind, vor Submission in cards-web
|
||||
ergänzen (Routes `/privacy`, `/help`).
|
||||
|
||||
## Screenshot-Skizzen
|
||||
|
||||
Pro Locale (de, en) jeweils 3–5 Screenshots zeigen:
|
||||
|
||||
1. **DeckListView mit fälligen Karten** — Hauptbildschirm, "X Karten fällig" sichtbar
|
||||
2. **Study mit gefliptem Cloze** — Markierte Antwort, RatingBar unten
|
||||
3. **Image-Occlusion** — Bild mit aktiver Maske + Reveal-Hover
|
||||
4. **Marketplace Explore** — Featured-Carousel
|
||||
5. **Widget auf Home-Screen** (optional, via Simulator-Screenshot komponiert)
|
||||
|
||||
iPhone-Größen (mindestens):
|
||||
- 6.7" (iPhone 16 Pro Max)
|
||||
- 6.5" (iPhone XS Max / 11 Pro Max / 14 Plus)
|
||||
- 5.5" (iPhone 8 Plus — wenn ältere Support-Tier)
|
||||
|
||||
Plus iPad:
|
||||
- 12.9" (iPad Pro)
|
||||
|
||||
Apple skaliert die größere Auflösung auf kleinere Slots, wenn keine
|
||||
spezifischen Screenshots vorhanden — Mindest-Set ist daher Größe 6.7"
|
||||
für iPhone + 12.9" für iPad. Reicht zur Submission.
|
||||
|
|
@ -11,14 +11,14 @@ AASA) und über Xcode (für Build + Sign).
|
|||
|
||||
- [x] **Team-ID gesetzt** (`QP3GLU8PH3`, mana e.V.) — `DEVELOPMENT_TEAM`
|
||||
in `project.yml > settings > base`. Greift bei Archive automatisch.
|
||||
- [ ] **App-ID `ev.mana.cards`** im Developer-Portal anlegen, falls
|
||||
- [ ] **App-ID `ev.mana.cardecky`** im Developer-Portal anlegen, falls
|
||||
noch nicht da. Mit Capabilities: App Groups, Keychain Sharing,
|
||||
Associated Domains.
|
||||
- [ ] **App-ID `ev.mana.cards.share`** + **`ev.mana.cards.widget`** für
|
||||
- [ ] **App-ID `ev.mana.cardecky.share`** + **`ev.mana.cardecky.widget`** für
|
||||
die Extensions analog anlegen, ebenfalls mit App Groups.
|
||||
- [ ] **App-Group `group.ev.mana.cards`** im Portal anlegen und allen
|
||||
- [ ] **App-Group `group.ev.mana.cardecky`** im Portal anlegen und allen
|
||||
drei App-IDs zuweisen.
|
||||
- [ ] **Keychain-Access-Group**: heute `ev.mana.cards`. Wenn
|
||||
- [ ] **Keychain-Access-Group**: heute `ev.mana.cardecky`. Wenn
|
||||
Shared-Keychain mit `memoro-native` gewünscht (siehe
|
||||
`mana/docs/MANA_SWIFT.md` Phase γ), auf
|
||||
`$(AppIdentifierPrefix)ev.mana.shared` umstellen und
|
||||
|
|
@ -49,9 +49,11 @@ AASA) und über Xcode (für Build + Sign).
|
|||
`cards/infrastructure/docker-compose.production.yml` hinterlegt
|
||||
(Commit folgt). Wird zur Runtime von `$env/dynamic/public`
|
||||
aufgelöst und in den AASA-Response geschrieben.
|
||||
- [ ] **Production-Deploy von cards-web** mit dem neuen Compose-Stand:
|
||||
`cd ~/projects/cards/infrastructure && docker compose -f docker-compose.production.yml up -d cards-web` auf mana-server.
|
||||
Erst danach liefert die AASA die echte Team-ID statt Platzhalter.
|
||||
- [x] **Production-Deploy von cards-web** durchgeführt 2026-05-13.
|
||||
Probe von außen: `curl https://cardecky.mana.how/.well-known/apple-app-site-association`
|
||||
liefert `application/json` mit `"appID":"QP3GLU8PH3.ev.mana.cardecky"`.
|
||||
Cloudflare-Tunnel reicht den Endpoint sauber durch (kein
|
||||
HTML-Captive, kein Redirect).
|
||||
- [ ] **cardecky-api.mana.how** muss erreichbar bleiben — die App
|
||||
ist 100% Online-write. Health-Probe verifizieren.
|
||||
|
||||
|
|
@ -84,12 +86,13 @@ AASA) und über Xcode (für Build + Sign).
|
|||
### App-Store-Connect
|
||||
|
||||
- [ ] **App-Eintrag erstellen** unter https://appstoreconnect.apple.com
|
||||
mit Bundle-ID `ev.mana.cards`.
|
||||
mit Bundle-ID `ev.mana.cardecky`.
|
||||
- [ ] **App-Name** + **Subtitle** (max 30 Zeichen):
|
||||
- Name: "Cards"
|
||||
- Subtitle: "Karteikarten — Verein mana"
|
||||
- [ ] **Description** (de + en, max 4000 Zeichen). Vorschlag siehe
|
||||
`docs/MARKETING_COPY.md` (existiert noch nicht — TODO).
|
||||
- [ ] **Description** (de + en, max 4000 Zeichen). Vorschlag in
|
||||
[`docs/MARKETING_COPY.md`](MARKETING_COPY.md) — vor Submission
|
||||
gegenlesen und Vereins-Tonalität schärfen.
|
||||
- [ ] **Keywords** (max 100 Zeichen, comma-separated):
|
||||
"Karteikarten,Spaced Repetition,Lernen,Vokabeln,Anki,Flashcards,FSRS,mana,Verein,Open Source"
|
||||
- [ ] **Screenshots** für iPhone 16 Pro Max + iPhone SE-3 + iPad Pro.
|
||||
|
|
|
|||
20
project.yml
20
project.yml
|
|
@ -60,7 +60,7 @@ targets:
|
|||
LSApplicationCategoryType: "public.app-category.education"
|
||||
UILaunchScreen: {}
|
||||
CFBundleURLTypes:
|
||||
- CFBundleURLName: ev.mana.cards
|
||||
- CFBundleURLName: ev.mana.cardecky
|
||||
CFBundleURLSchemes:
|
||||
- cards
|
||||
NSUserActivityTypes:
|
||||
|
|
@ -74,14 +74,14 @@ targets:
|
|||
com.apple.security.network.client: true
|
||||
com.apple.security.files.user-selected.read-write: true
|
||||
keychain-access-groups:
|
||||
- $(AppIdentifierPrefix)ev.mana.cards
|
||||
- $(AppIdentifierPrefix)ev.mana.cardecky
|
||||
com.apple.developer.associated-domains:
|
||||
- applinks:cardecky.mana.how
|
||||
com.apple.security.application-groups:
|
||||
- group.ev.mana.cards
|
||||
- group.ev.mana.cardecky
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cards
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cardecky
|
||||
CODE_SIGN_STYLE: Automatic
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME: AccentColor
|
||||
|
|
@ -111,10 +111,10 @@ targets:
|
|||
path: ShareExtension/Resources/CardsShareExtension.entitlements
|
||||
properties:
|
||||
com.apple.security.application-groups:
|
||||
- group.ev.mana.cards
|
||||
- group.ev.mana.cardecky
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cards.share
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cardecky.share
|
||||
CODE_SIGN_STYLE: Automatic
|
||||
SKIP_INSTALL: "YES"
|
||||
|
||||
|
|
@ -137,13 +137,13 @@ targets:
|
|||
path: Widgets/CardsWidget/Resources/CardsWidgetExtension.entitlements
|
||||
properties:
|
||||
com.apple.security.application-groups:
|
||||
- group.ev.mana.cards
|
||||
- group.ev.mana.cardecky
|
||||
dependencies:
|
||||
- sdk: WidgetKit.framework
|
||||
- sdk: SwiftUI.framework
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cards.widget
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cardecky.widget
|
||||
CODE_SIGN_STYLE: Automatic
|
||||
SKIP_INSTALL: "YES"
|
||||
INFOPLIST_KEY_CFBundleDisplayName: Cards Widget
|
||||
|
|
@ -157,7 +157,7 @@ targets:
|
|||
- target: CardsNative
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cards.tests
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cardecky.tests
|
||||
GENERATE_INFOPLIST_FILE: "YES"
|
||||
|
||||
CardsNativeUITests:
|
||||
|
|
@ -169,7 +169,7 @@ targets:
|
|||
- target: CardsNative
|
||||
settings:
|
||||
base:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cards.uitests
|
||||
PRODUCT_BUNDLE_IDENTIFIER: ev.mana.cardecky.uitests
|
||||
GENERATE_INFOPLIST_FILE: "YES"
|
||||
|
||||
schemes:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue