Files
telegram-tui/docs/superpowers/plans/2026-05-20-ios-app-roadmap.md
2026-05-21 15:27:59 +03:00

10 KiB

iOS Telegram Client Roadmap

Summary

Build a full native iOS app on top of the new tele-core crate, keeping Telegram/TDLib behavior shared in Rust and implementing UI/platform concerns in SwiftUI. Target feature parity with the current TUI client: auth, chat list, folders, messages, send/edit/delete/reply/forward/copy, reactions, search, pinned/profile flows, photos/albums, voice playback, notifications, multi-account support, unread/muted/mentions, drafts, network/typing state.

Architecture default: Rust tele-core remains the source of Telegram state and operations; add a UniFFI-based bridge crate plus a SwiftUI app. Do not port ratatui, terminal image rendering, ffplay, desktop notifications, or TUI keybindings to iOS.

Phases

Phase 0: Stabilize Current Workspace

  • Finish and commit the current split: tele-core + tele-tui.
  • Confirm tele-core has no TUI/desktop deps: no ratatui, crossterm, ratatui-image, notify-rust, arboard, open, ffplay.
  • Save this roadmap at docs/superpowers/plans/2026-05-20-ios-app-roadmap.md.
  • Acceptance:
    • cargo fmt -- --check
    • cargo check -p tele-core
    • cargo test -p tele-core
    • cargo check -p tele-tui --all-targets --all-features
    • cargo test --workspace --all-features

Phase 1: iOS-Facing Core API

  • Add a platform-neutral session layer in tele-core above TdClientTrait.
  • Expose stable models for iOS: account, auth state, chat summary, folder, message, media, reactions, profile, draft, network state, typing state.
  • Add event stream types for Swift: auth changed, chat list changed, message added/updated/deleted, reaction changed, media download progress, incoming notification candidate, network changed.
  • Keep filesystem, notifications, clipboard, URL open, and audio playback out of tele-core.
  • Acceptance:
    • Core unit tests cover auth transitions, chat/message mapping, incoming event queue, folders, reactions, drafts, search results, pinned/profile data.
    • Existing tele-tui behavior remains unchanged.

Phase 2: UniFFI Bridge

  • Add crates/tele-ios-ffi using UniFFI.
  • Export a small async-safe facade:
    • create_session(config) -> SessionHandle
    • poll_events() -> Vec<IosEvent>
    • auth methods: phone/code/password
    • chat methods: load chats/folders/history/search/open profile
    • message methods: send/edit/delete/reply/forward/react/copy payload
    • media methods: download photo/download voice
  • Generate Swift bindings and wire Rust build outputs into an iOS-consumable XCFramework.
  • Acceptance:
    • Swift sample test can create a fake session, receive events, load chats, open a chat, send a message, react, and search.
    • Real TDLib linking is validated for iOS simulator and device or documented as blocked with exact linker error.

Phase 2A: Local TDLib for iOS

tdlib-rs 1.2.0 with download-tdlib downloads prebuilt TDLib archives from FedericoBruzzone/tdlib-rs releases using the pattern tdlib-{tdlib_version}-{target_os}-{target_arch}.zip. The terminal/macOS build works because the macOS archive exists. The iOS archives, for example tdlib-1.8.29-ios-aarch64.zip, are not published, so iOS real linking must not depend on download-tdlib.

  • Keep download-tdlib for the terminal/macOS build path while it remains useful there.
  • Switch the iOS FFI build path to tdlib-rs local-tdlib support.
  • Pin the local TDLib build to the TDLib version expected by tdlib-rs 1.2.0: 1.8.29.
  • Add scripts/build-tdlib-ios.sh to build TDLib locally for:
    • arm64-apple-ios
    • arm64-apple-ios-sim
    • optionally x86_64-apple-ios-sim if Intel Mac simulator support is needed.
  • Store generated TDLib artifacts outside git, for example:
    • .build/tdlib-ios/iphoneos/include
    • .build/tdlib-ios/iphoneos/lib
    • .build/tdlib-ios/iphonesimulator/include
    • .build/tdlib-ios/iphonesimulator/lib
  • Add scripts/build-ios-ffi-with-local-tdlib.sh to set LOCAL_TDLIB_PATH and build tele-ios-ffi for simulator/device targets.
  • Patch tdlib-rs through crates/vendor/tdlib-rs until upstream handles target_os = "ios" in its local-tdlib build helper.
  • Run TDLib's host-side prepare_cross_compiling target before the iOS cross-build, because TDLib 1.8.29 expects generated TL/MIME sources to exist during cross-compilation.
  • After simulator and device Rust builds link, package the Rust FFI output and TDLib dependency into an iOS-consumable XCFramework or documented adjacent native dependency.
  • Acceptance:
    • scripts/check-ios-tdlib-linking.sh no longer fails because of a missing GitHub release archive. Completed on 2026-05-21.
    • cargo build -p tele-ios-ffi --target aarch64-apple-ios-sim --release links with local TDLib. Completed on 2026-05-21 through scripts/check-ios-tdlib-linking.sh.
    • cargo build -p tele-ios-ffi --target aarch64-apple-ios --release links with local TDLib. Completed on 2026-05-21 through IOS_RUST_TARGET=aarch64-apple-ios scripts/build-ios-ffi-with-local-tdlib.sh.
    • The Xcode app can be built against the real FFI path, not only the fake bridge. Completed on 2026-05-21 through scripts/build-ios-real-ffi-xcframework.sh and TELE_IOS_USE_LOCAL_FFI=1 scripts/build-ios-simulator-app.sh.
    • Any remaining CMake/OpenSSL/zlib/linker blockers are documented with the exact command and error text.

Phase 3: iOS App Shell

  • Add native app under apps/ios/TeleTuiIOS.
  • Use SwiftUI + MVVM:
    • SessionStore
    • AuthViewModel
    • ChatListViewModel
    • ChatViewModel
    • ProfileViewModel
    • MediaViewModel
  • Implement auth screens, loading/error state, tab-free chat list, folder selector, chat screen, compose bar, profile sheet, settings/account switcher shell.
  • Store credentials and account metadata with Keychain + Application Support paths, not TUI config files.
  • Acceptance:
    • App boots on simulator using fake bridge.
    • Auth flow screens match all AuthState variants.
    • Chat list and chat detail render deterministic fake data.

Phase 4: Messaging Feature Parity

  • Implement chat list features: folders, search, unread count, mentions, muted state, pinned indicator, drafts, network footer/status equivalent.
  • Implement message features: markdown rendering, incoming/outgoing styling, date separators, sender grouping, albums, reply/forward context, edited/read state.
  • Implement actions: send, edit, delete confirmation, reply, forward, reactions picker, pinned messages, profile open/leave flow, copy message text via UIPasteboard.
  • Acceptance:
    • XCTest/UI tests cover the same user journeys as TUI: launch, open chat, send, receive incoming, switch chats, edit, reply, search, reactions, delete confirmation.
    • Snapshot tests cover chat list, message list, modals/sheets, auth screens, profile, and media placeholders.

Phase 5: iOS Media, Notifications, and Accounts

  • Replace desktop-only behavior with iOS-native services:
    • notifications: UNUserNotificationCenter
    • URL open: UIApplication.open
    • clipboard: UIPasteboard
    • voice playback: AVAudioPlayer or AVPlayer
    • photo viewing: SwiftUI image viewer with zoom/pan
  • Implement photo download/cache, albums, fullscreen viewer, voice download/cache/play/seek.
  • Implement multi-account switcher with per-account TDLib db paths and app-level account lock policy suitable for iOS.
  • Acceptance:
    • Local notifications respect muted chats and mention-only settings.
    • Voice messages play, pause, seek, and cache.
    • Photos/albums open fullscreen and reuse cache.
    • Account switching does not mix old TDLib events into the active account.

Phase 6: Real Device Hardening

  • Run against real Telegram credentials on simulator and device.
  • Add background/foreground lifecycle handling: reconnect, suspend polling, resume events, close sessions safely.
  • Add privacy and permission flows: notifications, local network/file storage if needed.
  • Add crash logging and structured Rust/Swift logs.
  • Optimize large chats: pagination, image memory pressure, voice cache limits, event batching.
  • Acceptance:
    • 30-minute manual smoke on real device: auth, load chats, open multiple chats, send/edit/delete/reply/forward/react, receive notifications, view photos, play voice, switch accounts.
    • No mixed-account updates after rapid account switch.
    • No UI freeze during chat history loads or media downloads.

Phase 7: Release Readiness

  • Add CI jobs for Rust core, FFI generation, Swift build, simulator tests, and packaging.
  • Add TestFlight configuration, app icons, launch screen, entitlements, privacy manifest, notification capability, and TDLib packaging docs.
  • Document support matrix: minimum iOS version, device architectures, TDLib version, known limitations.
  • Acceptance:
    • Clean CI from empty checkout.
    • TestFlight build installs and launches.
    • Release checklist in docs includes credentials setup, TDLib build, signing, and rollback steps.

Key Interface Decisions

  • iOS UI is native SwiftUI, not a terminal/TUI port.
  • Rust/Swift boundary is UniFFI unless TDLib iOS linking forces a lower-level C ABI.
  • tele-core owns Telegram semantics and emits events; Swift owns presentation, storage permissions, notifications, clipboard, URL opening, and media playback.
  • tele-tui remains a first-class crate and must keep passing its existing tests after every core change.

Test Plan

  • Rust:
    • cargo fmt -- --check
    • cargo clippy --workspace --all-targets --all-features -- -D warnings
    • cargo test --workspace --all-features
    • cargo tree -p tele-core | rg "ratatui|crossterm|ratatui-image|notify-rust|arboard|open|ffplay" must return no matches.
  • FFI:
    • Generated Swift bindings compile.
    • Fake-session Swift tests cover all exported methods and event variants.
  • iOS:
    • XCTest unit tests for view models.
    • SwiftUI snapshot tests for auth, chat list, chat, message actions, profile, media.
    • UI tests for auth mock flow, open chat, send, edit, reply, forward, react, search, account switch.
  • Manual:
    • Simulator fake-data smoke each phase.
    • Real-device TDLib smoke before Phase 6 completion.

Assumptions

  • "Полноценное iOS-приложение" means practical feature parity with current tele-tui, not a minimal chat reader.
  • iOS implementation should prioritize native UX over preserving Vim/TUI keybindings.
  • iOS credentials/account storage should use iOS-native secure storage and app sandbox paths.
  • The first saved plan file should be docs/superpowers/plans/2026-05-20-ios-app-roadmap.md.