Split core and TUI crates
This commit is contained in:
28
docs/IOS_CORE_REUSE.md
Normal file
28
docs/IOS_CORE_REUSE.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# iOS core reuse
|
||||
|
||||
Первый workspace split готовит код к будущему iOS-клиенту, но не добавляет
|
||||
Swift, SwiftUI, UniFFI, C ABI или XCFramework.
|
||||
|
||||
## Уже в `tele-core`
|
||||
|
||||
- Typed IDs и shared domain-типы: `types`.
|
||||
- TDLib client wrapper, auth/chats/messages/reactions/users/update handling.
|
||||
- `TdClientConfig` и `TdCredentials`: credentials передаются явно из клиента.
|
||||
- Core-neutral `IncomingMessageEvent` вместо прямой зависимости от desktop notifications.
|
||||
- Pure message grouping.
|
||||
- Pure account profile structs and validation.
|
||||
- Reusable `FakeTdClient` and TDLib test data.
|
||||
|
||||
## Остаётся TUI-only
|
||||
|
||||
- `ratatui`, `crossterm`, UI state, input handling and snapshots.
|
||||
- Runtime config loading, `.env`, `accounts.toml`, XDG/macOS paths and lock files.
|
||||
- Desktop notifications, clipboard, URL opening, terminal images and `ffplay`.
|
||||
- PTY fixture and `termwright` E2E tests.
|
||||
|
||||
## Следующий этап
|
||||
|
||||
1. Decide the iOS-facing API shape on top of `tele-core`.
|
||||
2. Add UniFFI or a C ABI only after the Rust boundary is stable.
|
||||
3. Validate TDLib linking and database paths for `aarch64-apple-ios`.
|
||||
4. Keep platform delivery concerns outside `tele-core`.
|
||||
@@ -9,22 +9,28 @@ TDLib updates -> mpsc channel -> App state -> UI render
|
||||
User input -> input handlers -> App methods -> TdClientTrait -> TDLib API
|
||||
```
|
||||
|
||||
`main.rs` держит event loop: клавиатура, TDLib updates, фоновые задачи и отрисовка по `needs_redraw`.
|
||||
`crates/tele-tui/src/main.rs` держит event loop: клавиатура, TDLib updates,
|
||||
фоновые задачи и отрисовка по `needs_redraw`.
|
||||
|
||||
## Подсистемы
|
||||
|
||||
| Путь | Назначение |
|
||||
|------|------------|
|
||||
| `src/app/` | Центральное состояние `App<T: TdClientTrait>`, экраны, режимы и modal state |
|
||||
| `src/app/methods/` | Trait-based методы navigation/messages/compose/search/modal |
|
||||
| `src/input/` | Роутинг клавиатуры и обработчики global/chat/compose/modal/search |
|
||||
| `src/tdlib/` | TDLib wrapper: auth, chats, users, reactions, updates, conversion, operations |
|
||||
| `src/ui/` | Отрисовка экранов, списка чатов, сообщений, footer, compose bar и модалок |
|
||||
| `src/config/` | TOML config, credentials, keybindings, validation |
|
||||
| `src/accounts/` | Профили, `accounts.toml`, migration, per-account lock files |
|
||||
| `src/audio/` | Голосовые сообщения через `ffplay` и `VoiceCache` |
|
||||
| `src/media/` | Inline images и modal viewer под feature `images` |
|
||||
| `src/utils/` | Форматирование, validation, retry, TDLib log helpers |
|
||||
| `crates/tele-core/src/tdlib/` | TDLib wrapper: auth, chats, users, reactions, updates, conversion, operations |
|
||||
| `crates/tele-core/src/types.rs` | Shared typed IDs |
|
||||
| `crates/tele-core/src/message_grouping.rs` | Pure message grouping |
|
||||
| `crates/tele-core/src/accounts/` | Pure account profile types and validation |
|
||||
| `crates/tele-core/src/test_support/` | Reusable `FakeTdClient` and TDLib test data |
|
||||
| `crates/tele-tui/src/app/` | Центральное состояние `App<T: TdClientTrait>`, экраны, режимы и modal state |
|
||||
| `crates/tele-tui/src/app/methods/` | Trait-based методы navigation/messages/compose/search/modal |
|
||||
| `crates/tele-tui/src/input/` | Роутинг клавиатуры и обработчики global/chat/compose/modal/search |
|
||||
| `crates/tele-tui/src/ui/` | Отрисовка экранов, списка чатов, сообщений, footer, compose bar и модалок |
|
||||
| `crates/tele-tui/src/config/` | TOML config, credentials, keybindings, validation |
|
||||
| `crates/tele-tui/src/accounts/` | `accounts.toml`, migration, account data paths, per-account lock files |
|
||||
| `crates/tele-tui/src/audio/` | Голосовые сообщения через `ffplay` и `VoiceCache` |
|
||||
| `crates/tele-tui/src/media/` | Inline images и modal viewer под feature `images` |
|
||||
| `crates/tele-tui/src/notifications.rs` | Desktop notification delivery and muted-chat syncing |
|
||||
| `crates/tele-tui/src/utils/` | Форматирование, validation, retry, TDLib log helpers |
|
||||
|
||||
## State
|
||||
|
||||
@@ -37,16 +43,20 @@ User input -> input handlers -> App methods -> TdClientTrait -> TDLib API
|
||||
- `TdClientTrait` задаёт API для приложения и тестов.
|
||||
- Реальный клиент живёт в `TdClient`, тесты используют `FakeTdClient`.
|
||||
- Updates должны фильтроваться по активному `client_id`, особенно для мультиаккаунта.
|
||||
- `TdClient` не зависит от desktop notifications. Он отдаёт входящие сообщения
|
||||
через `drain_incoming_message_events()`, а `tele-tui` решает, показывать ли
|
||||
desktop notification.
|
||||
|
||||
## Тесты
|
||||
|
||||
| Область | Где искать |
|
||||
|---------|------------|
|
||||
| Test builders и fake TDLib | `tests/helpers/` |
|
||||
| Snapshot UI | `tests/*` + `tests/snapshots/` |
|
||||
| Навигация и ввод | `tests/input_navigation.rs`, `tests/vim_mode.rs`, `tests/navigation.rs` |
|
||||
| Аккаунты | `tests/accounts.rs`, `tests/account_switcher.rs` |
|
||||
| User journeys | `tests/e2e_smoke.rs`, `tests/e2e_user_journey.rs` |
|
||||
| Core unit tests | `crates/tele-core/src/**` |
|
||||
| Test builders и fake TDLib | `crates/tele-core/src/test_support/`, `crates/tele-tui/src/test_support/`, `crates/tele-tui/tests/helpers/` |
|
||||
| Snapshot UI | `crates/tele-tui/tests/*` + `crates/tele-tui/tests/snapshots/` |
|
||||
| Навигация и ввод | `crates/tele-tui/tests/input_navigation.rs`, `crates/tele-tui/tests/vim_mode.rs`, `crates/tele-tui/tests/navigation.rs` |
|
||||
| Аккаунты | `crates/tele-tui/tests/accounts.rs`, `crates/tele-tui/tests/account_switcher.rs` |
|
||||
| User journeys | `crates/tele-tui/tests/e2e_smoke.rs`, `crates/tele-tui/tests/e2e_user_journey.rs` |
|
||||
|
||||
## Runtime-файлы
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# TDLib integration notes
|
||||
|
||||
Проект использует `tdlib-rs` с feature `download-tdlib`. Актуальные версии смотри в `Cargo.toml`.
|
||||
Проект использует `tdlib-rs` с feature `download-tdlib`. Актуальные версии смотри в `crates/tele-core/Cargo.toml` и `crates/tele-tui/Cargo.toml`.
|
||||
|
||||
## Runtime
|
||||
|
||||
@@ -23,6 +23,9 @@ UI должен показывать понятное состояние и не
|
||||
- Receive loop передаёт в UI пару `(client_id, Update)`.
|
||||
- UI применяет update только если `client_id == active_client_id`.
|
||||
- При переключении аккаунта pending updates старого клиента должны игнорироваться.
|
||||
- `tele-core` не вызывает desktop notifications напрямую. Входящие сообщения
|
||||
складываются в очередь `IncomingMessageEvent`, которую `tele-tui` drain-ит в
|
||||
main loop и передаёт в `NotificationManager`.
|
||||
|
||||
Это критично для multi-account: без фильтрации старый клиент может испортить state нового аккаунта.
|
||||
|
||||
|
||||
142
docs/superpowers/plans/2026-05-20-ios-app-roadmap.md
Normal file
142
docs/superpowers/plans/2026-05-20-ios-app-roadmap.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# 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 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`.
|
||||
Reference in New Issue
Block a user