- Updated the application namespace and ID from "net.ypchat.app" to "de.ypchat.android" for better alignment with branding. - Increased Gradle heap size settings to optimize build performance. - Disabled dependency constraints to simplify dependency management. - Removed obsolete files related to the previous application structure, including MainActivity, YpChatApp, and various core components, streamlining the codebase. These changes collectively enhance the application's configuration and structure, improving maintainability and performance.
13 KiB
iOS-App für YpChat – Umsetzungsplan
Dieses Dokument beschreibt die komplette Planung einer nativen iOS-App mit Feature-Parität zur bestehenden Android-App (android/app, Paket de.ypchat.android). Die Android-Implementierung dient als fachliche und API-Referenz.
1. Ziele und Abgrenzung
1.1 Produktziel
- Nutzer können sich wie in der Android-App anmelden, chatten, suchen, Posteingang/Verlauf nutzen, Konsole-Befehle senden, Feedback und Partner-Links einsehen sowie Bilder hochladen und versenden.
- Gleiche Backend-URLs, REST-Endpunkte und Socket.IO-Ereignisse wie auf Android.
1.2 Nicht-Ziele (optional später)
- WatchOS, iPad-spezifisches Layout (erst iPhone-first).
- Eigener Push-Benachrichtigungsdienst (nur falls das Backend später APNs unterstützt).
2. Referenz: Android-Architektur (zu spiegeln)
| Schicht | Android | iOS-Empfehlung |
|---|---|---|
| Konfiguration | BuildConfig.BASE_URL / local.properties |
Xcode Build-Konfiguration + xcconfig oder Info-Key BASE_URL |
| DI / Container | AppContainer |
Eigene AppServices-Klasse oder schlankes Factory-Pattern beim App-Start |
| HTTP + Cookies | OkHttp + SessionCookieJar |
URLSession mit HTTPCookieStorage (shared oder app-group bei Bedarf) |
| REST | Retrofit + Gson | URLSession + Codable (oder optional Alamofire) |
| Echtzeit | io.socket (Socket.IO) |
socket.io-client-swift (oder vergleichbare aktive Library) |
| Zustand | ChatRepository + StateFlow |
ObservableObject / @Observable + async oder Combine |
| UI | Jetpack Compose | SwiftUI (empfohlen) |
| Profil lokal | ProfileStore (SharedPreferences) |
UserDefaults oder kleines Keychain-Wrapper nur wenn sensibel |
Wichtige Dateien zum Abgleich: AppContainer.kt, RestApi.kt, SocketClient.kt, ChatRepository.kt, ChatViewModel.kt, YpChatRoot.kt, Models.kt, SocketEvent.kt.
3. Technologie- und Projektentscheidungen
3.1 Sprache und UI
- Swift 5.10+, Deployment iOS 17+ (oder 16, wenn Gerätebindung es erfordert – dann API prüfen).
- SwiftUI für alle Screens; Navigation:
TabView+ eingebettete Unternavigation für „Mehr“.
3.2 Abhängigkeiten
- Socket.IO-Client (Swift-Paket via SPM): muss dieselben Transporte unterstützen wie Android (
websocket+polling); Verbindungsoptionen anSocketClient.ktanlehnen (Reconnect, Timeout). - Kein Retrofit – native
URLSessionreicht für die überschaubare REST-Oberfläche. - Bilder: PhotosUI (
PhotosPicker/PHPicker) für die Bildauswahl; Upload alsmultipart/form-datawie Android.
3.3 Bundle-ID und Naming
- Vorschlag:
de.ypchat.iosoder konsistent mit Androidde.ypchat.android→ z. B.de.ypchat.app(einheitlich mit Marketing/Store). - Anzeigename: wie
R.string.app_nameauf Android.
4. Konfiguration und Build-Varianten
4.1 Base-URL
- Standard wie Android:
https://www.ypchat.net(siehedefaultBaseUrlinandroid/app/build.gradle.kts). - Pro Build-Konfiguration überschreibbar:
- Debug: lokale
Config/Debug.xcconfigmitBASE_URL = https://…(oder Staging). - Release: feste Produktions-URL.
- Debug: lokale
- Zur Laufzeit:
Bundle/ generierteInfo-Keys auslesen, trailing slash wieAppConfig.ktentfernen.
4.2 App Transport Security (ATS)
- Produktion: HTTPS wie Android Release (
usesCleartextTrafficfalse). - Debug: nur bei Bedarf
NSAppTransportSecurityfür HTTP-Testserver – dokumentieren und nicht in Release aktiv lassen.
4.3 Berechtigungen (Info.plist)
- Foto-Bibliothek (Lesen):
NSPhotoLibraryUsageDescriptionmit klarer Begründung (Bild im Chat senden). - Keine Kamera zwingend nötig, wenn nur Galerie wie Android
PickVisualMedia.
5. Datenmodell (Codable)
Alle DTOs aus Models.kt 1:1 als struct mit Codable abbilden, inkl. Sonderfall CountriesResponse: auf Android ein LinkedHashMap<String, String> – auf iOS als [String: String] decodieren oder eigener Decodable-Wrapper.
PartnerLinkDto: JSON-Feld "Page Name" → CodingKeys mit case pageName = "Page Name".
6. REST-API
Basis-URL + Pfad wie RestApi.kt:
| Methode | Pfad | Zweck |
|---|---|---|
| GET | api/session |
Session / eingeloggter User |
| POST | api/logout |
Logout |
| GET | api/countries |
Länderliste |
| GET | api/feedback |
Feedback-Liste |
| GET | api/feedback/admin-status |
Admin-Session-Status |
| POST | api/feedback |
Feedback senden |
| POST | api/feedback/admin-login |
Admin-Login |
| POST | api/feedback/admin-logout |
Admin-Logout |
| DELETE | api/feedback/{id} |
Eintrag löschen (Admin) |
| GET | api/partners |
Partner-Links |
| POST | api/upload-image |
Multipart-Feld image |
Cookie-Handling: Nach session-Call und weiteren Requests müssen Cookies wie im Browser/OkHttp mitgeführt werden – URLSessionConfiguration.default mit httpCookieStorage und httpShouldSetCookies / httpCookieAcceptPolicy prüfen; bei Problemen explizit Cookie-Header aus Storage für die Domain setzen.
Fehlerbehandlung: HTTP-Status und Body auswerten; Fehlermeldungen in den UI-State wie ChatState.errorMessage / feedbackMessage.
7. Socket.IO-Client
7.1 Verbindung
- URL: gleiche
baseUrlwie REST (ohne zusätzlichen Pfad, sofern Server Root nutzt – mit Android-Verhalten abgleichen). - Optionen analog
SocketClient.kt: Reconnect,reconnectionAttempts, Delays, Timeout; Transports WebSocket + Polling falls die Swift-Library das abbildet.
7.2 Authentifizierung / Session
- Beim Connect bzw. nach Connect:
setSessionIdmit Payload{ "expressSessionId": "<id>" }– identisch zu Android. pendingExpressSessionIdbei erneutem Connect erneut senden.
7.3 Client → Server (emit)
| Event | Payload-Felder (Kern) |
|---|---|
login |
userName, gender, age, country, expressSessionId |
message |
message, messageId, optional toUserName; für Bild: toUserName, isImage, imageUrl |
requestConversation |
withUserName |
userSearch |
nameIncludes, minAge, maxAge, countries[], genders[] |
requestHistory |
(leer) |
requestOpenConversations |
(leer) |
blockUser / unblockUser |
userName |
7.4 Server → Client (on)
Alle Events aus SocketClient.kt abbilden und in ein internes enum / sealed Äquivalent übersetzen: connected, loginSuccess, userList, message, messageSent, conversation, searchResults, historyResults, inboxResults, unreadChats, userBlocked, userUnblocked, commandResult, commandTable, error, sowie Verbindungsmetadaten (connect, disconnect, connect_error).
JSON-Parsing: Foundation JSONSerialization oder JSONDecoder mit [String: Any]-Hilfstypen – Feldnamen und Typen strikt an Android-Mapper (toUserDto, toMessageDto, …) halten.
7.5 HTTP-Stack und Socket
- Android nutzt dieselbe
OkHttpClient-Instanz für Socket und REST. Auf iOS: wo möglich eine gemeinsame Cookie-Quelle; falls die Socket-Library keinenURLSessionteilt, nach dem Connect sicherstellen, dassexpressSessionIdpersetSessionIdgesetzt ist (wie Android bei getrenntem Transport).
8. Repository- und App-Logik (ChatRepository)
Die Reducer-Logik aus ChatRepository.reduce und die Methoden funktional kopieren:
- restoreSession: Profil laden, Länder laden,
feedbackAdminStatus,GET api/session, dann Socket connect +setSessionId. - login: Profil speichern, Session-ID beschaffen, Socket ggf. verbinden,
loginemit. - logout:
POST api/logout, Socket trennen, Cookies löschen, State reset mit erhaltenemsavedProfileundcountries. - Timeout: 30 Minuten (
1800s) – Ticker jede Sekunde, bei 0 automatischlogout(wiestartTimeoutTicker/resetTimeout). - openConversation / closeConversation, sendMessage (inkl. Konsolen-Befehle mit
/), search, inbox/history, block/unblock. - Bild: Upload REST → bei Erfolg
sendImagemit absoluter URL (Basis-URL voranstellen wenn relativ).
Zustand als eine ChatState-Struktur (alle Properties aus ChatRepository.kt).
9. Präsentationsschicht (SwiftUI)
9.1 ViewModel
@MainActorViewModel (oder Repository auf MainActor publizieren), dasChatStatepublished und User-Aktionen an das Repository delegiert.task { await repository.restoreSession() }beim Erscheinen der Root-View.
9.2 Bildschirme (Parität zu YpChatRoot)
- Login: Landing-Karte, Profilfelder, Gender/Country-Picker, Validierung (Nickname ≥ 3 Zeichen), Socket-Status.
- Haupt-Shell: Top-Bar (App-Name, User, Online-Status, Timeout-Countdown, Logout).
- Tabs: Online | Suche | Posteingang | Verlauf | Konsole | Mehr – wie Android; Posteingang-Badge mit
unreadChatsCount. - Chat: Zurück, Blockieren/Entblocken, Nachrichtenliste, Eingabe, Smiley-Leiste (gleiche Tokens wie
SmileyItems), Bild wählen, Senden, Upload-Banner. - Suche / Inbox / Verlauf: Listen wie Android.
- Konsole: Eingabe, Senden, Ausgabezeilen + Tabelle (
CommandTableState). - Mehr: Unterseiten Feedback (inkl. Admin-Login), Partner (Safari öffnen), FAQ, Regeln, Sicherheit, Impressum – Texte aus lokalisierten Strings (siehe
res/values/strings.xmlauf Android als Quelle für DE/EN).
9.3 Design
- Farben und Abstände an die Android-Farbkonstanten in
YpChatRoot.ktanlehnen für ein konsistentes Erscheinungsbild. - Bilder in Chat: AsyncImage / Kingfisher nur falls nötig; Caching beachten.
9.4 Lokalisierung
Localizable.xcstrings(oder.strings) – mindestens Deutsch; Android-strings.xmlals Master-Liste.
10. Sicherheit und Datenschutz
- Passwörter (Feedback-Admin) nur im Speicher, nicht loggen.
- TLS in Release erzwingen.
- Keychain nur nötig, wenn sensible Tokens dauerhaft ohne Cookies gespeichert werden sollen (aktuell: Session eher cookie-basiert wie Web).
11. Qualitätssicherung
11.1 Tests
- Unit-Tests: JSON-Decodierung der REST- und Socket-Payloads (Fixtures aus echten Server-Responses erfassen).
- Integration: Manuell gegen Staging/Produktion: Login, Nachricht, Suche, Feedback, Bild-Upload, Logout, Timeout.
11.2 Edge Cases
- App in den Hintergrund: Socket-Verhalten (Disconnect/Reconnect) und Timeout-Reset gemäß Produktregel klären (Android tickt weiter – iOS analog umsetzen).
- Schlechte Netzwerke: Fehlermeldungen aus
SocketEvent.Errorund REST anzeigen.
12. App Store / Vertrieb
- Apple Developer Program, App-ID, Provisioning Profiles.
- Datenschutzerklärung und App-Privacy-Labels (Netzwerk, Fotos, ggf. Nutzerinhalt).
- TestFlight für interne Tester vor Release.
- Versionierung: an
versionName/versionCodeder Android-App angleichen oder eigenes Schema dokumentieren.
13. Repository-Struktur (Vorschlag)
ios/
YpChat.xcodeproj oder YpChat.xcworkspace
YpChat/
App/
Core/ # AppConfig, Cookie/Session storage, ProfileStore
Data/ # APIClient, SocketClient, DTOs
Features/ # Login, Chat, Tabs, More, …
Resources/ # Assets, Localizable
Config/
Debug.xcconfig
Release.xcconfig
Root-README oder dieses Dokument verlinken, wie man BASE_URL setzt.
14. Phasenplan (Meilensteine)
| Phase | Inhalt | Ergebnis |
|---|---|---|
| P0 | Xcode-Projekt, Konfiguration, leere SwiftUI-App, BASE_URL | Laufende Shell-App |
| P1 | REST-Client + Cookie-Speicher, session / countries / logout |
Session funktioniert |
| P2 | Socket-Client, setSessionId, login, userList, message |
Minimaler Chat |
| P3 | Vollständiger ChatRepository-State, alle Socket-Events, Timeout |
Parität Kernlogik |
| P4 | SwiftUI: Login + Tabs + Chat + Suche/Inbox/Verlauf | UI-Hauptteil |
| P5 | Bild-Upload + Anzeige, Smileys | Medien-Parität |
| P6 | Mehr: Feedback, Partner, statische Seiten | Rest-UI |
| P7 | Lokalisierung, Feinschliff, Dark Mode optional | Polish |
| P8 | TestFlight, Store-Metadaten, Screenshots | Release |
15. Risiken und Abhängigkeiten
- Socket.IO-Swift-Version muss zum Server-Socket.IO passen; bei Protokoll-Mismatch Verbindungsfehler – mit Server-Version abgleichen.
- Cookie-Domain / Pfad: muss mit dem Backend identisch sein, sonst wirkt
sessionwie „nicht eingeloggt“. - Bildgröße: 5 MB-Limit clientseitig wie Android (
MAX_IMAGE_BYTES).
16. Nächster konkreter Schritt
- Im Repo Ordner
ios/anlegen und Xcode-Projekt (SwiftUI App) hinzufügen. - SPM: Socket.IO-Client einbinden, minimales
SocketClient-Swift gegen Staging testen. GET api/sessionmit gemeinsamem Cookie-Storage verifizieren.- Danach schrittweise
ChatRepositoryportieren und UI anbinden.
Stand: Abgleich mit Android-Codebase (Compose-App, Mai 2026). Bei Backend-Änderungen diesen Plan und die Event-Liste aktualisieren.