* core, ui: plan per-server roles for self-hosted servers * core: add per-server roles field to UserServer * core: add nullable role columns to protocol_servers * core: persist per-server roles * core: validate server coverage using per-server roles * test: cover per-server roles resolution and coverage * multiplatform: per-server role toggles for self-hosted servers * ios: per-server role toggles for self-hosted servers * core: per-server role overrides with per-role defaults * test: cover three-state per-server role resolution * fix: derive Eq for ServerRolesOverride * multiplatform: three-state role dropdowns on saved servers * ios: three-state role pickers on saved servers * test: per-server roles independent across two servers * test: enable names role in name-resolution tests * style: trim comments in per-server roles code * chore: rename server_roles migration to 20260716 (last) * core: per-server roles override operator roles, inherit when unset * multiplatform: per-server role default inherits from operator * ios: per-server role default inherits from operator * refactor(servers): tidy per-server roles per review - dedup no-operator default into ServerRoles.noOperatorDefault (Kotlin/Swift) - iOS: move roles-section control flow to the call site via a named gate, and parse the server address once instead of up to three times - Kotlin: collapse redundant derivedState; revert defaultOn->default rename for cross-platform parity - drop unused Hashable conformance on Swift ServerRoles - add agentServerCfgs test for names inheritance from an operator - remove no-op enableNamesRole calls from dormant DirectoryTests - fix ChatClient import ordering * chore(migration): date server_roles migration 20260720 * only show roles when server is enabled, move section above QR code --------- Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
SimpleX Chat iOS app
This file provides guidance when working with code in this repository.
iOS App Overview
The iOS app is a SwiftUI application that interfaces with the Haskell core library via FFI. It shares the SimpleXChat framework with two extensions: Notification Service Extension (NSE) for push notifications and Share Extension (SE) for sharing content from other apps.
Build & Development
Open SimpleX.xcodeproj in Xcode. The project has five targets:
- SimpleX (iOS) - Main app (Bundle ID:
chat.simplex.app) - SimpleXChat - Framework containing FFI bridge and shared types
- SimpleX NSE - Notification Service Extension
- SimpleX SE - Share Extension
- Tests iOS - UI tests
Build and run via Xcode (Product > Build/Run). Tests run via Product > Test or:
xcodebuild test -scheme "SimpleX (iOS)" -destination 'platform=iOS Simulator,name=iPhone 15'
Deployment target: iOS 15.0+, Swift 5.0.
Architecture
Haskell Core Integration
The app calls the Haskell core library through C FFI defined in SimpleXChat/SimpleX.h:
chat_migrate_init_key()- Initialize/migrate databasechat_send_cmd_retry()- Send command to chat controllerchat_recv_msg_wait()- Receive messages from controller
Swift wrappers in SimpleXChat/API.swift:
chatMigrateInit()- Initialize chat controllersendSimpleXCmd<R>()- Send typed commands and parse responsesrecvSimpleXMsg<R>()- Receive typed messages
Haskell runtime initialization (SimpleXChat/hs_init.c) uses different memory configurations:
- Main app: 64MB heap
- NSE: 512KB heap (minimal footprint for background processing)
- SE: 1MB heap
Pre-compiled Haskell libraries are in Libraries/{ios,mac,sim}/.
State Management
- ChatModel (
Shared/Model/ChatModel.swift) - Main singletonObservableObjectfor app-wide state (chat list, active chat, users) - ItemsModel - Manages chat items within a selected chat (similar to Kotlin's ChatsContext)
- AppTheme - Theme management and customization
App Structure
Entry point: Shared/SimpleXApp.swift
Key directories in Shared/:
Model/- Data models and API layer (ChatModel.swift,SimpleXAPI.swift)Views/- SwiftUI views organized by feature:ChatList/- Chat list and user pickerChat/- Message display and compositionCall/- VoIP call UIUserSettings/- App settingsLocalAuth/- Passcode and biometric authenticationDatabase/- Database initialization and migration
Shared Data Between Targets
All three targets share data via App Group (group.chat.simplex.app):
SimpleXChat/AppGroup.swift- GroupDefaults wrapper for typed shared preferences- Keychain for sensitive data:
kcDatabasePassword,kcAppPassword,kcSelfDestructPassword
Key Types
Types are defined in SimpleXChat/:
ChatTypes.swift- User, Chat, Message, Group typesAPITypes.swift- API request/response types
Commands follow ChatCmdProtocol (has cmdString property), sent as JSON through FFI.
Localization
31 languages supported. Localization files in SimpleX Localizations/.
Workflow:
Product > Export Localizations- Export XLIFF filesProduct > Import Localizations- Import updated translations
SimpleX Assets
The app includes optional assets behind the SIMPLEX_ASSETS Swift compilation flag. Without setup, the app builds normally without them.
Setup
Create Local.xcconfig (gitignored) in the apps/ios/ directory:
SIMPLEX_ASSETS_DIR = /path/to/assets
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) SIMPLEX_ASSETS
The copy script (scripts/ios/copy-assets.sh) runs as a build phase on each build but exits immediately if SIMPLEX_ASSETS is not set.
Updating assets
When source images change, regenerate resized images (requires ImageMagick):
cd path/to/assets && ./resize.sh
Background Capabilities
Configured in Info.plist:
- Background modes: audio, fetch, remote-notification, voip
- URL scheme:
simplex://for deep linking - BGTaskScheduler:
chat.simplex.app.receive