Files
simplex-chat/apps/ios/spec
Narasimha-sc 2a7eb7eed2 fix the review's findings and cut the remaining API surface
Correctness.

The one-time link picker's profile list was keyed on the active user as well as the
count. That defeats the "don't change order after a user was selected" behaviour its own
comment protects - changeActiveUser_ sets currentUser first and only then reloads chats,
so the list visibly re-sorted and stayed re-sorted for the whole of getUserChatData - and
it was redundant: the count alone covers a profile being created from the picker.

iOS, compose picker: the old-core fallback relied on the user switch tearing this view
down, which only happens when the switch succeeded. If it threw, the form was left open
over a profile that already existed, and the only way out was to swipe it away. It is now
dismissed unconditionally.

iOS: alerts raised right after a sheet is dismissed are presented on a controller that is
going away and are dropped. The 0.5s wait was applied only to the old-core path, while the
ordinary reassignment failures - the ones that actually happen - went unguarded.
alertAfterDismissal now covers all of them, in one place.

iOS: dropped the chatId write that Kotlin removed for the same reason two commits ago. It
is a no-op on the happy path, but not if something legitimately closed the chat meanwhile
- SimpleX lock re-auth clears it, and this would reopen the chat behind the lock screen.

iOS: the create-profile row is now gated on profileChangeProhibited, as every other row on
both platforms already was.

Surface.

apiCreateActiveUser takes keepActiveUser as a defaulted argument, exactly as it already
takes pastTimestamp, instead of a public wrapper plus a private helper. Two symbols fewer
on each platform, and every existing call site passes its arguments by name, so none of
them changes.

Reverted the activeOrder sort flip in the compose picker: it changes the order of an
existing screen for every user, is not needed for this feature, and with active_order 0
would push a newly created profile to the bottom. It deserves its own commit if wanted.

Also: apps/ios/spec/api.md tracks the command enum and had gone stale; the plan records
the two limits of the flag the review surfaced - it is ignored when there is no active
user, and active_order 0 ties rather than sorts last on migrated databases.
2026-08-06 17:27:35 +00:00
..
2026-02-19 10:58:16 +00:00
2026-02-19 10:58:16 +00:00
2026-05-18 09:06:25 +00:00

SimpleX Chat iOS -- Specification Overview

Technical specification suite for the SimpleX Chat iOS application. Each document provides bidirectional links to product documentation and source code.

Executive Summary

The SimpleX Chat iOS app is a native SwiftUI frontend that communicates with a Haskell core library via C FFI. All chat logic, encryption, protocol handling, and database operations happen in the Haskell core (chat_ctrl). The iOS layer handles UI rendering, system integration (CallKit, Push Notifications, Background Tasks), local preferences, and theming. The app shares its database with a Notification Service Extension (NSE) for decrypting push payloads while the main app is inactive.

Dependency Graph

SimpleXApp (root entry point)
├── ChatModel (ObservableObject state) <-> SimpleXAPI (FFI bridge) <-> Haskell Core (chat_ctrl)
├── Views (SwiftUI)
│   ├── ChatListView -> ChatView -> ComposeView
│   ├── ChatItemView (renders individual messages)
│   ├── Settings, UserProfiles, Onboarding
│   └── ActiveCallView (WebRTC + CallKit)
├── Models
│   ├── ChatModel (global app state -- singleton)
│   ├── ItemsModel (per-chat message list state -- singleton + secondary instances)
│   ├── ChatTagsModel (tag filtering state)
│   └── Chat (per-conversation observable state)
├── Services
│   ├── NtfManager (push notification coordination)
│   ├── BGManager (background task scheduling)
│   ├── CallController (CallKit + VoIP push)
│   └── ThemeManager (theme resolution engine)
└── Extensions
    ├── SimpleX NSE (Notification Service Extension -- decrypts push payloads)
    └── SimpleX SE (Share Extension)

Specification Documents

Document Description
Architecture System architecture, FFI bridge, app lifecycle, extension model
Chat API Reference Complete ChatCommand, ChatResponse, ChatEvent, ChatError type reference
State Management ChatModel, ItemsModel, Chat, ChatInfo, preference storage
Database & Storage SQLite databases, encryption, file storage, export/import
Chat View Message rendering, chat item types, context menu actions
Chat List Conversation list, filtering, search, swipe actions
Message Composition Compose bar, attachments, reply/edit/forward modes, voice recording
Navigation Navigation stack, deep linking, sheet presentation, call overlay
Push Notifications NtfManager, NSE, notification modes, token lifecycle
WebRTC Calling CallController, WebRTCClient, CallKit, signaling via SMP
File Transfer Inline/XFTP transfer, auto-receive, CryptoFile, file constants
Theme Engine ThemeManager, default themes, customization layers, wallpapers
Impact Graph Source file → product concept mapping, risk levels

Source Code Entry Points

File Role
Shared/SimpleXApp.swift App entry point, Haskell init, lifecycle management
Shared/AppDelegate.swift UIApplicationDelegate for push token registration
Shared/ContentView.swift Root view -- authentication gate, call overlay, navigation
Shared/Model/ChatModel.swift Primary observable state (ChatModel, ItemsModel, Chat)
Shared/Model/SimpleXAPI.swift FFI bridge -- chatSendCmd, chatApiSendCmd, sendSimpleXCmd
Shared/Model/AppAPITypes.swift ChatCommand, ChatResponse, ChatEvent enums (iOS app layer)
SimpleXChat/APITypes.swift APIResult, ChatError, ChatCmdProtocol (shared framework)
SimpleXChat/ChatTypes.swift User, ChatInfo, Contact, GroupInfo, ChatItem data types
SimpleXChat/SimpleX.h C header for Haskell FFI functions