Files
Messenger/android/CHANGELOG.md
Codex f7b9753c2e
Some checks failed
Android CI / android (push) Has been cancelled
Android Release / release (push) Has been cancelled
CI / test (push) Has been cancelled
android: fix AppCompat theme crash on launch
2026-03-10 09:12:14 +03:00

1007 lines
60 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Android Changelog
## 2026-03-08
### Step 1 - Build and app wiring
- Added Android project plugin configuration for Hilt and Kotlin serialization.
- Added dependency repositories and explicit app module include in settings.
- Added app dependencies for Retrofit/OkHttp, DataStore, coroutines, Hilt, and unit testing.
- Enabled INTERNET permission and registered MessengerApplication in manifest.
- Added MessengerApplication with HiltAndroidApp.
### Step 2 - Network/data core + DI
- Fixed DTO/Auth API serialization annotations and endpoint declarations for `/api/v1/auth/login`, `/api/v1/auth/refresh`, `/api/v1/auth/me`.
- Implemented DataStore-based token persistence with a corrected `getTokens()` read path.
- Added auth network stack: bearer interceptor, 401 authenticator with refresh flow and retry guard.
- Added clean-layer contracts and implementations: `domain/common`, `domain/auth`, `data/auth/repository`.
- Wired dependencies with Hilt modules for DataStore, OkHttp/Retrofit, and repository bindings.
### Step 3 - Minimal auth UI and navigation
- Replaced Phase 0 placeholder UI with Compose auth flow (`AuthViewModel` + login screen).
- Added loading/error states for login and startup session restore.
- Added navigation graph: `AuthGraph (login)` to placeholder `Chats` screen after successful auth.
- Implemented automatic session restore on app start using stored tokens.
### Step 4 - Unit tests
- Added `DataStoreTokenRepositoryTest` for token save/read and clear behavior.
- Added `NetworkAuthRepositoryTest` for login success path and 401 -> `InvalidCredentials` error mapping.
### Step 5 - Chat Room models and persistence core
- Added domain chat model (`ChatItem`) for chat list rendering concerns.
- Added Room entities: `chats`, `users_short` with sort-friendly indices.
- Added `ChatDao` with `observeChats()`, `upsertChats()`, and transactional `clearAndReplaceChats()`.
- Added `MessengerDatabase` and Hilt database wiring (`DatabaseModule`).
### Step 6 - Chat API and repository sync
- Added chat REST API client for `/api/v1/chats` and `/api/v1/chats/{chat_id}`.
- Added chat DTOs and remote/local mappers (`ChatReadDto -> ChatEntity/UserShortEntity -> ChatItem`).
- Implemented `NetworkChatRepository` with cache-first flow strategy (Room first, then server sync).
- Added chat domain contracts/use-cases (`ChatRepository`, observe/refresh use-cases).
- Wired chat API/repository via Hilt modules.
### Step 7 - Realtime manager and chat list updates
- Added a unified realtime manager abstraction and WebSocket implementation for `/api/v1/realtime/ws?token=...`.
- Implemented auto-reconnect with exponential backoff and max cap.
- Added realtime event parser for `receive_message`, `message_updated`, `message_deleted`, `chat_updated`, `chat_deleted`, `user_online`, `user_offline`.
- Added use-case level realtime event handling that updates Room and triggers repository refreshes when needed.
- Wired realtime manager into DI.
### Step 8 - Chat list UI and navigation
- Added Chat List screen with tabs (`All` / `Archived`), local search filter, pull-to-refresh, and state handling (loading/empty/error).
- Added chat row rendering for unread badge, mention badge (`@`), pinned/muted marks, and message preview by media type.
- Added private chat presence display (`online` / `last seen recently` fallback).
- Connected Chat List to ViewModel/use-cases with no business logic inside composables.
- Added chat click navigation to placeholder `ChatScreen(chatId)`.
### Step 9 - Tests and checklist updates
- Added unit test for chat cache-first sync strategy (`NetworkChatRepositoryTest`).
- Added unit test for realtime event parsing (`RealtimeEventParserTest`).
- Added DAO test (`ChatDaoTest`) using in-memory Room + Robolectric.
- Updated Android checklist status in `docs/android-checklist.md`.
### Step 10 - Build stabilization fixes
- Switched Android API base URL to `https://chat.daemonlord.ru/`.
- Added cleartext traffic flag in manifest for local/dev compatibility.
- Fixed Hilt dependency cycle by separating refresh `AuthApiService` with a dedicated qualifier.
- Added `CoroutineDispatcher` DI provider and qualifier for repositories.
- Fixed Material3 experimental API opt-in and removed deprecated `StateFlow.distinctUntilChanged()` usage.
### Step 11 - Sprint A / 1) Message Room + models
- Added message domain model (`MessageItem`) for chat screen rendering.
- Added Room entities `messages` and `message_attachments` with chat-history indexes.
- Added `MessageDao` with observe/pagination/upsert/delete APIs.
- Updated `MessengerDatabase` schema to include message tables and DAO.
- Added Hilt DI provider for `MessageDao`.
### Step 12 - Sprint A / 2) Message API + repository
- Added message REST API client for history/send/edit/delete endpoints.
- Added message DTOs and mappers (`MessageReadDto -> MessageEntity -> MessageItem`).
- Added `MessageRepository` contracts/use-cases for observe/sync/pagination/send/edit/delete.
- Implemented `NetworkMessageRepository` with cache-first observation and optimistic text send.
- Wired message API and repository into Hilt modules.
### Step 13 - Sprint A / 3) Message realtime integration
- Extended realtime event model/parser with message-focused events (`message_delivered`, `message_read`, `typing_start`, `typing_stop`) and richer message payload mapping.
- Updated unified realtime handler to write `receive_message`, `message_updated`, `message_deleted` into `messages` Room state.
- Added delivery/read status updates in Room for message status events.
- Kept chat list sync updates in the same manager/use-case pipeline for consistency.
### Step 14 - Sprint A / 4) Message UI core
- Replaced chat placeholder with a real message screen route + ViewModel.
- Added message list rendering with Telegram-like bubble alignment and status hints.
- Added input composer with send flow, reply/edit modes, and inline action cancellation.
- Added long-press actions (`reply`, `edit`, `delete`) for baseline message operations.
- Added manual "load older" pagination trigger and chat back navigation integration.
### Step 15 - Sprint A / 5) Message tests and docs
- Added unit tests for `NetworkMessageRepository` sync/send flows.
- Added DAO test for message scoped replace behavior in Room.
- Expanded realtime parser tests with rich `receive_message` mapping coverage.
- Updated `docs/android-checklist.md` for completed message-core items.
### Step 16 - Sprint B / 1-2) Media data layer + chat integration
- Added media API/DTO layer for upload URL and attachment creation.
- Added `MediaRepository` + `UploadAndAttachMediaUseCase` and network implementation with presigned PUT upload.
- Extended `MessageRepository` with media send flow (`sendMediaMessage`) and optimistic local update behavior.
- Wired media API/repository through Hilt modules.
- Integrated file picking and media sending into Android `ChatScreen`/`ChatViewModel` with upload state handling.
### Step 17 - Sprint B / media tests
- Added `NetworkMediaRepositoryTest` for successful upload+attach flow.
- Added error-path coverage for failed presigned upload handling.
## 2026-03-09
### Step 18 - Sprint P0 / 1) Message core completion
- Extended message API/data contracts with `messages/status`, `forward`, and reaction endpoints.
- Added message domain support for forwarded message metadata and attachment waveform payload.
- Implemented repository operations for delivery/read acknowledgements, forward, and reactions.
- Updated Chat ViewModel/UI with forward flow, reaction toggle, and edit/delete-for-all edge-case guards.
- Added automatic delivered/read acknowledgement for latest incoming message in active chat.
- Fixed outgoing message detection by resolving current user id from JWT `sub` claim.
### Step 19 - Sprint P0 / 2) Media UX after send
- Added media endpoint mapping for chat attachments (`GET /api/v1/media/chats/{chat_id}/attachments`).
- Extended Room message observation to include attachment relations via `MessageLocalModel`.
- Synced and persisted message attachments during message refresh/pagination and after media send.
- Extended message domain model with attachment list payload.
- Added message attachment rendering in Chat UI: inline image preview, minimal image viewer overlay, and basic audio play/pause control.
### Step 20 - Sprint P0 / 3) Roles/permissions baseline
- Extended chat data/domain models with `my_role` and added `observeChatById` stream in Room/repository.
- Added `ObserveChatUseCase` to expose per-chat permission state to message screen.
- Implemented channel send restrictions in `ChatViewModel`: sending/attach disabled for `member` role in `channel` chats.
- Added composer-level restriction hint in Chat UI to explain blocked actions.
### Step 21 - Sprint P0 / 4) Invite join flow (minimum)
- Added chat API contracts for invite actions: `POST /api/v1/chats/{chat_id}/invite-link` and `POST /api/v1/chats/join-by-invite`.
- Added domain model/use-cases for invite-link creation and join-by-invite.
- Extended chat repository with invite operations and local chat upsert on successful join.
- Added minimal Chat List UI flow for join-by-invite token input with loading/error handling and auto-open of joined chat.
### Step 22 - Sprint P0 / 5) Realtime stability and reconcile
- Added heartbeat in WebSocket manager (`ping` interval + `pong` timeout detection) with forced reconnect on stale link.
- Improved socket lifecycle hygiene by cancelling heartbeat on close/failure/disconnect paths.
- Added `connect` event mapping and centralized reconcile trigger in realtime handler.
- On realtime reconnect, chat repository now refreshes `all` and `archived` snapshots to reduce stale state after transient disconnects.
### Step 23 - Sprint P0 / 6) Auth hardening foundation
- Extended auth API/repository contracts with sessions management endpoints:
- `GET /api/v1/auth/sessions`
- `DELETE /api/v1/auth/sessions/{jti}`
- `DELETE /api/v1/auth/sessions`
- Added domain model and use-cases for listing/revoking sessions.
- Added unit coverage for session DTO -> domain mapping in `NetworkAuthRepositoryTest`.
### Step 24 - Sprint P0 / 7) Quality pass
- Added realtime parser unit coverage for `connect` event mapping.
- Extended message DAO tests with attachment relation verification.
- Added Android smoke and baseline document (`docs/android-smoke.md`) with test matrix and performance targets.
- Updated Android checklist quality section with initial performance baseline completion.
### Step 25 - UI safe insets fix
- Enabled edge-to-edge mode in `MainActivity` via `enableEdgeToEdge()`.
- Added safe area insets handling (`WindowInsets.safeDrawing`) for login, chat list, session-check and chat screens.
- Added bottom composer protection in chat screen with `navigationBarsPadding()` and `imePadding()`.
- Fixed UI overlap with status bar and navigation bar on modern Android devices.
### Step 26 - Core base / bulk forward foundation
- Added message API/data contracts for bulk forward (`POST /api/v1/messages/{message_id}/forward-bulk`).
- Extended `MessageRepository` with `forwardMessageBulk(...)`.
- Implemented bulk-forward flow in `NetworkMessageRepository` with Room/chat last-message updates.
- Added `ForwardMessageBulkUseCase` for future multi-select message actions.
- Updated message repository unit test fakes to cover new API surface.
### Step 27 - Core base / message action state machine
- Added reusable `MessageActionState` reducer with explicit selection modes (`NONE`, `SINGLE`, `MULTI`).
- Added action-intent contract for message operations (reply/edit/forward/delete/reaction/clear).
- Integrated `ChatViewModel` with reducer-backed selection logic while preserving current UI behavior.
- Added base ViewModel handlers for entering/toggling multi-select mode (`onEnterMultiSelect`, `onToggleMessageMultiSelection`, `onClearSelection`).
- Added unit tests for reducer transitions and available intents (`MessageActionStateTest`).
### Step 28 - Core base / Android multi-forward execution
- Switched chat forward state from single-message payload to `forwardingMessageIds` set.
- Extended `ChatViewModel` forward flow: multi-select now forwards multiple source messages in one action.
- Wired `ForwardMessageBulkUseCase` for multi-message forwarding (sequential safe execution with error short-circuit).
- Updated chat action bar and forward sheet labels for multi-selection count.
### Step 29 - Core base / multi-select delete execution
- Fixed multi-select delete behavior in `ChatViewModel`: `Delete` now applies to all selected messages, not only focused one.
- Added explicit guard for `Delete for all` in multi-select mode (single-message only).
### Step 30 - Core base / reply-forward preview data foundation
- Extended message DTO/Room/domain models with optional preview metadata:
- `replyPreviewText`, `replyPreviewSenderName`
- `forwardedFromDisplayName`
- sender profile fields from API payload (`senderDisplayName`, `senderUsername`, `senderAvatarUrl`)
- Added Room self-relation in `MessageLocalModel` to resolve reply preview fallback from referenced message.
- Updated message mappers and repository/realtime temporary entity creation for new model fields.
- Bumped Room schema version to `7`.
### Step 31 - Chat UI / reply-forward bubble blocks
- Added inline forwarded header rendering in message bubbles with display-name fallback.
- Added inline reply preview block in message bubbles (author + snippet) based on new preview fields/fallbacks.
- Updated Telegram UI batch-2 checklist items for reply-preview and forwarded header.
### Step 32 - Chat UI / pinned message bar
- Added `pinned_message_id` support in chat DTO/local/domain models and DAO selects.
- Extended `ChatViewModel` state with pinned message id + resolved pinned message object.
- Rendered pinned message bar under chat app bar with hide action.
- Updated Telegram UI batch-2 checklist item for pinned message block.
### Step 33 - Chat UI / top app bar restructuring
- Extended chat UI state with resolved chat header fields (`chatTitle`, `chatSubtitle`, `chatAvatarUrl`).
- Updated chat top app bar layout to Telegram-like structure: back, avatar, title, status, call action, menu action.
- Kept load-more behavior accessible via menu placeholder action button.
- Updated Telegram UI batch-2 checklist item for chat top app bar.
### Step 34 - Chat UI / composer restyling
- Reworked chat composer into rounded Telegram-like container with emoji slot, text input, attach button, and send/voice state button.
- Preserved send/upload state guards and existing insets handling (`navigationBarsPadding` + `imePadding`).
- Updated Telegram UI batch-2 checklist composer-related items.
### Step 35 - Chat UI / multi-select bars and overlays
- Split message selection UX into dedicated top selection bar (count/close/delete/edit/reactions) and bottom action bar (reply/forward).
- Enhanced selected bubble visual state with explicit selected marker text.
- Updated Telegram UI batch-2 checklist items for multi-select mode.
### Step 36 - Chat list / advanced states baseline
- Added chat-list local type filters (`All`, `People`, `Groups`, `Channels`) with new `ChatListFilter` UI state.
- Added archive statistics stream in `ChatListViewModel` and special archive top-row entry in `All` tab.
- Extended list preview formatting with media-type markers and retained unread/mention/pinned indicators.
- Updated Telegram UI checklists for chat-list advanced states (batch 2 and batch 3).
### Step 37 - Chat UI / wallpaper-aware readability
- Added gradient wallpaper-like chat background layer in `ChatScreen`.
- Kept pinned/composer/action surfaces on semi-transparent containers to preserve readability over wallpaper.
- Updated Telegram UI checklist items for wallpaper and overlay readability.
### Step 38 - Quality/docs / mapper fallback coverage
- Added `MessageMappersTest` to verify reply preview fallback resolution from Room self-relation (`reply_to_message_id`).
- Updated Android master checklist for completed chat list tabs/filters coverage.
### Step 39 - Android scope / remove calls UI
- Removed chat top-bar `Call` action from Android `ChatScreen`.
- Updated Android UI checklist wording to reflect chat header without calls support.
### Step 40 - Invite deep link flow (app links)
- Added Android App Links intent filter for `https://chat.daemonlord.ru/join...`.
- Added invite token extraction from incoming intents (`query token` and `/join/{token}` path formats).
- Wired deep link token into `MessengerNavHost -> ChatListRoute -> ChatListViewModel` auto-join flow.
- Removed manual `Invite token` input row from chat list screen.
### Step 41 - Chat UI / long-press action menu
- Added long-press message action card in `ChatScreen` with quick reactions.
- Added context actions from long-press: reply, edit, forward, delete, select, close.
- Added placeholder disabled pin action in the menu to keep action set consistent with Telegram-like flow.
- Updated Telegram UI batch-2 checklist items for long-press reactions and context menu.
### Step 42 - Chat list / row and FAB parity pass
- Updated chat list rows with avatar rendering, trailing message time, and richer right-side metadata layout.
- Kept unread/mention/pinned/muted indicators while aligning row structure closer to Telegram list pattern.
- Added floating compose FAB placeholder at bottom-right in chat list screen.
- Updated Telegram UI batch-2 checklist chat-list parity items.
### Step 43 - Chat list / floating bottom navigation shell
- Added floating rounded bottom navigation container on chat list screen.
- Added active tab visual state (Chats selected) with pill styling.
- Updated Telegram UI checklists for bottom-nav shell parity (batch 1 and batch 2).
### Step 44 - Chat UI / bubble density pass
- Updated message bubble shapes for incoming/outgoing messages to denser rounded Telegram-like contours.
- Kept bottom-right time + delivery state rendering in bubble footer after time formatting update.
- Updated Telegram UI batch-2 checklist item for message bubble parity.
### Step 45 - Chat UI / media bubble improvements
- Added richer video attachment card rendering in message bubbles.
- Added file-list style attachment rows (icon + filename + type/size metadata).
- Upgraded non-voice audio attachment player with play/pause, progress bar, and current/total duration labels.
- Updated Telegram UI batch-2 checklist media-bubble items.
### Step 46 - Media viewer / header and gallery navigation
- Upgraded chat image viewer to use global image gallery state (`index / total`) instead of a single URL.
- Added fullscreen viewer header with close, index, share placeholder, and delete placeholder actions.
- Added image navigation controls (`Prev`/`Next`) for gallery traversal.
- Updated Telegram UI batch-2 checklist for fullscreen media header support.
### Step 47 - Notifications foundation (FCM + channels + deep links)
- Added Firebase Messaging dependency and Android manifest wiring for `POST_NOTIFICATIONS`.
- Added notification channels (`messages`, `mentions`, `system`) with startup initialization in `MessengerApplication`.
- Added push service (`MessengerFirebaseMessagingService`) + payload parser + notification dispatcher.
- Added notification tap deep-link handling to open target chat from `MainActivity` via nav host.
- Added runtime notification permission request flow (Android 13+) in `MessengerNavHost`.
- Added parser unit test (`PushPayloadParserTest`).
### Step 48 - Foreground local notifications from realtime
- Added `ActiveChatTracker` to suppress local notifications for currently opened chat.
- Wired realtime receive-message handling to trigger local notification via `NotificationDispatcher` when chat is not active.
- Added chat title lookup helper in `ChatDao` for notification titles.
- Added explicit realtime stop in `ChatViewModel.onCleared()` to avoid stale collectors.
### Step 49 - Mention override for muted chats
- Extended realtime receive-message model/parsing with `isMention` flag support.
- Added muted-chat guard in realtime notification flow: muted chats stay silent unless message is a mention.
- Routed mention notifications to mentions channel/priority via `NotificationDispatcher`.
- Added parser unit test for mention-flag mapping.
### Step 50 - Notification settings storage (DataStore)
- Added domain notification settings models/repository contracts (global + per-chat override).
- Added `DataStoreNotificationSettingsRepository` with persistence for global flags and per-chat override mode.
- Added `ShouldShowMessageNotificationUseCase` and wired realtime notifications through it.
- Added unit tests for DataStore notification settings repository and notification visibility use case.
### Step 51 - Logout with full local cleanup
- Added `LogoutUseCase` with centralized sign-out flow: disconnect realtime, clear active chat, clear auth session, and clear local cached data.
- Added `SessionCleanupRepository` + `DefaultSessionCleanupRepository` to wipe Room tables and clear per-chat notification overrides.
- Added logout action in chat list UI and wired it to `AuthViewModel`, with automatic navigation back to login via auth state.
- Added unit tests for logout use case orchestration and notification override cleanup.
### Step 52 - Settings/Profile shell and logout relocation
- Added dedicated `Settings` and `Profile` routes/screens with mobile-safe insets and placeholder content.
- Removed direct logout action from chat list and moved logout action to `Settings`.
- Wired bottom navigation pills in chats to open `Settings` and `Profile`.
### Step 53 - Secure token storage (Keystore-backed)
- Added `EncryptedPrefsTokenRepository` backed by `EncryptedSharedPreferences` and Android `MasterKey` (Keystore).
- Switched DI token binding from DataStore token repository to encrypted shared preferences repository.
- Kept DataStore for non-token app settings and renamed preferences file to `messenger_preferences.preferences_pb`.
### Step 54 - Message interactions: tap menu vs long-press select
- Updated chat message gesture behavior to match Telegram pattern:
- tap opens contextual message menu with reactions/actions,
- long-press enters multi-select mode directly.
- Hid single-selection action bars while contextual menu is visible to avoid mixed UX states.
- Improved multi-select visual affordance with per-message selection indicator circles.
### Step 55 - Chat multi-select action cleanup
- Removed duplicate forward action in multi-select mode (`Forward selected`), leaving a single clear forward action button.
### Step 56 - Unified API error handling
- Added shared API error mapper (`ApiErrorMapper`) with mode-aware mapping (`DEFAULT`, `LOGIN`).
- Switched auth/chat/message/media repositories to a single `Throwable -> AppError` mapping source.
- Kept login-specific invalid-credentials mapping while standardizing unauthorized/server/network handling for other API calls.
### Step 57 - Offline-first message history reading
- Added paged local history reading path by introducing configurable message observe limit (`observeMessages(chatId, limit)`).
- Updated chat screen loading strategy to expand local Room-backed history first when loading older messages.
- Added network-failure fallback in message sync/load-more: if network is unavailable but local cache exists, chat remains readable without blocking error.
### Step 58 - Keep authenticated session when offline at app start
- Updated auth restore flow in `AuthViewModel`: network errors during session restore no longer force logout when local tokens exist.
- App now opens authenticated flow in offline mode instead of redirecting to login.
### Step 59 - Deferred message action queue (send/edit/delete)
- Added Room-backed pending action queue (`pending_message_actions`) for message operations that fail due to network issues.
- Implemented enqueue + optimistic behavior for `sendText`, `editMessage`, and `deleteMessage` on network failures.
- Added automatic pending-action flush on chat sync/load-more and before new message operations.
- Kept non-network server failures as immediate errors (no queueing), while allowing offline continuation.
### Step 60 - Media cache foundation (Coil + Exo cache)
- Added global Coil image loader cache policy in `MessengerApplication` (memory + disk cache).
- Added Media3 `SimpleCache` singleton module for media stream/file caching foundation.
- Added Media3/Coil core dependencies and configured cache sizes for mobile usage.
### Step 61 - Compose UI tests baseline
- Added instrumented Compose UI tests for login and chat list states.
- Added Android test dependencies for Compose test runner (`ui-test-junit4`) and test infra.
- Covered key visual states: auth error rendering, chat list loading state, and empty state.
### Step 62 - Android CI pipeline
- Added dedicated Android CI workflow for `main` branch and PRs.
- CI now runs Android build, unit tests, lint, and androidTest assemble.
- Added optional detekt execution step (auto-skipped when detekt task is not configured).
### Step 63 - Integration tests for auth/chat/realtime
- Kept repository-level integration coverage for auth/chat data flows (MockWebServer + in-memory storage).
- Added `RealtimePipelineIntegrationTest` to validate realtime event handling pipeline (`receive_message` -> Room state update).
- Consolidated quality checklist integration test coverage for auth/chat/realtime.
### Step 64 - Android release workflow
- Added dedicated release workflow (`.github/workflows/android-release.yml`) for `main` branch pushes.
- Adapted version extraction for Kotlin DSL (`android/app/build.gradle.kts`) and guarded release by existing git tag.
- Wired release build, git tag push, and Gitea release publication with APK artifact upload.
### Step 65 - Account and media parity foundation (checklist 1-15)
- Introduced `:core:common` module and moved base `AppError`/`AppResult` contracts out of `:app`.
- Added structured app logging (`Timber`) and crash reporting baseline (`Firebase Crashlytics`) with app startup wiring.
- Added API version header interceptor + build-time feature flags and DI provider.
- Added account network layer for auth/account management:
- verify email, password reset request/reset,
- sessions list + revoke one/all,
- 2FA setup/enable/disable + recovery status/regenerate,
- profile/privacy update and blocked users management.
- Added deep-link aware auth routes for `/verify-email` and `/reset-password`.
- Reworked Settings/Profile screens from placeholders to editable account management screens.
- Added avatar upload with center square crop (`1:1`) before upload.
- Upgraded message attachment rendering with in-bubble multi-image gallery and unified attachment context actions (open/copy/close).
### Step 66 - Voice recording controls + global audio focus
- Added microphone permission (`RECORD_AUDIO`) and in-chat voice recording flow based on press-and-hold gesture.
- Implemented Telegram-like gesture controls for voice button:
- hold to record,
- slide up to lock recording,
- slide left to cancel recording.
- Added minimum voice length validation (`>= 1s`) before sending.
- Integrated voice message sending via existing media upload path (`audio/mp4` attachment).
- Added process-wide audio focus coordinator to enforce single active audio source:
- attachment player pauses when another source starts,
- recording requests focus and stops competing playback.
### Step 67 - Group/channel management baseline in Chat List
- Extended chat API/repository layer with management operations:
- create group/channel,
- discover + join/leave chats,
- invite link create/regenerate,
- members/bans listing and admin actions (add/remove/ban/unban/promote/demote).
- Added domain models for discover/member/ban items and repository mappings.
- Added in-app management panel in `ChatListScreen` (FAB toggle) for:
- creating group/channel,
- joining discovered chats,
- loading chat members/bans by chat id,
- executing admin/member visibility actions from one place.
### Step 68 - Search, inline jump, theme toggle, accessibility pass
- Added global search baseline in chat list:
- users search (`/users/search`),
- messages search (`/messages/search`),
- chat discovery integration (`/chats/discover`).
- Added inline search in chat screen with jump navigation (prev/next) and automatic scroll to matched message.
- Added highlighted message state for active inline search result.
- Added theme switching controls in settings (Light/Dark/System) via `AppCompatDelegate`.
- Added accessibility refinements for key surfaces and controls:
- explicit content descriptions for avatars and tab-like controls,
- voice record button semantic label for TalkBack.
### Step 69 - Bugfix pass: voice recording, theme apply, profile avatar UX
- Fixed voice recording start on Android by switching `VoiceRecorder` to compatible `MediaRecorder()` initialization.
- Fixed microphone permission flow: record action now triggers runtime permission request reliably and auto-starts recording after grant.
- Fixed theme switching application by introducing app-level `MessengerTheme` and switching app manifest base theme to DayNight.
- Fixed profile screen usability after avatar upload:
- enabled vertical scrolling with safe insets/navigation padding,
- constrained avatar preview to a centered circular area instead of full-screen takeover.
### Step 70 - Chat interaction consistency: gestures + sheets/dialogs
- Reworked single-message actions to open in `ModalBottomSheet` (tap action menu) instead of inline action bars.
- Reworked forward target chooser to `ModalBottomSheet` for consistent overlay behavior across chat actions.
- Added destructive action confirmation via `AlertDialog` before delete actions.
- Reduced gesture conflicts by removing attachment-level long-press handlers that collided with message selection gestures.
- Improved voice hold gesture reliability by handling consumed pointer down events (`requireUnconsumed = false`).
### Step 71 - Voice playback waveform/speed + circle video playback
- Added voice-focused audio playback mode with waveform rendering in message bubbles.
- Added playback speed switch for voice messages (`1.0x -> 1.5x -> 2.0x`).
- Added view-only circle video renderer for `video_note` messages with looped playback.
- Kept regular audio/video attachment rendering for non-voice/non-circle media unchanged.
### Step 72 - Adaptive layout baseline (phone/tablet) + voice release fix
- Added tablet-aware max-width layout constraints across major screens (login, verify/reset auth, chats list, chat, profile, settings).
- Kept phone layout unchanged while centering content and limiting line width on larger displays.
- Fixed voice hold-to-send gesture reliability by removing pointer-input restarts during active recording, so release consistently triggers send path.
### Step 73 - Voice message send/playback bugfixes
- Fixed voice media type mapping in message repository: recorded files with `voice_*.m4a` are now sent as message type `voice` (not generic `audio`).
- Fixed audio replay behavior: when playback reaches the end, next play restarts from `0:00`.
- Improved duration display in audio/voice player by adding metadata fallback when `MediaPlayer` duration is not immediately available.
### Step 74 - UI references consolidation (Batch 4)
- Added full Telegram reference mapping checklist (`docs/android-ui-batch-4-checklist.md`) with screenshot-by-screenshot description.
- Added explicit icon policy: no emoji icons in production UI components, Material Icons/vector icons only.
- Updated UI checklist index with Batch 4 entry.
### Step 75 - Material Icons migration (Batch 1 start)
- Replaced symbol/emoji-based UI controls in chat surfaces with Material Icons:
- chat header/menu/search controls (`more`, `up/down`),
- image viewer actions (`close`, `forward`, `delete`),
- multi-select markers (`radio checked/unchecked`, `selected` check),
- attachment/media markers (`movie`, `attach file`).
- Replaced chat list management FAB glyph toggle (`+`/`×`) with Material `Add`/`Close` icons.
- Added `androidx.compose.material:material-icons-extended` dependency for consistent icon usage.
### Step 76 - Shared main tabs shell with scroll-aware visibility
- Moved `Chats / Contacts / Settings / Profile` bottom panel to a shared navigation shell (`AppNavGraph`) so it behaves as global page navigation.
- Added dedicated `Contacts` page route and wired it into main tabs.
- Removed local duplicated bottom panel from chat list screen.
- Implemented scroll-direction behavior for all 4 main pages:
- hide panel on downward scroll,
- show panel on upward scroll / at top.
### Step 77 - Main tabs bar UX/layout fix
- Replaced custom pill-row main bar with compact `NavigationBar` inside rounded container for stable 4-tab layout on small screens.
- Added bottom content paddings for `Chats/Contacts/Settings/Profile` pages so content is not obscured by the floating main bar.
- Raised chats management FAB offset to avoid overlap with the global bottom bar.
### Step 78 - Telegram-like bottom tabs visual tuning
- Tuned shared main bar visual style to better match Telegram references:
- rounded floating container with subtle elevation,
- unified selected/unselected item colors,
- stable 4-item navigation with icons + labels.
- Kept scroll-hide/show behavior and page-level navigation unchanged.
### Step 79 - Main pages app bars + safe-area pass
- Added top app bars for all 4 main pages (`Chats`, `Contacts`, `Settings`, `Profile`) to make them feel like proper standalone sections.
- Moved chats management toggle action into chats app bar.
- Kept safe-area handling and bottom insets consistent with shared floating tabs bar to avoid overlap.
### Step 80 - Top bar offset consistency fix
- Unified top bar alignment across `Chats`, `Contacts`, `Settings`, and `Profile`:
- removed extra outer paddings that shifted headers down/right on some pages,
- separated content padding from top app bar container.
- Result: consistent title baseline and horizontal alignment between main pages.
### Step 81 - Chats bottom gap fix when tabs bar hidden
- Fixed blank gap at the bottom of chats list when global tabs bar auto-hides on scroll.
- Chats screen bottom padding is now dynamic and applied only while tabs bar is visible.
### Step 82 - Chats list header closer to Telegram reference
- Removed `Archived` top tab from chats list UI.
- Added search action in top app bar and unified single search field with leading search icon.
- Kept archive as dedicated row inside chats list; opening archive now happens from that row and back navigation appears in app bar while archive is active.
### Step 83 - Chats header realtime connection status
- Added realtime connection state stream (`Disconnected/Connecting/Reconnecting/Connected`) to `RealtimeManager`.
- Wired websocket lifecycle into that state in `WsRealtimeManager`.
- Bound chats top bar title to realtime state:
- shows `Connecting...` while reconnect/initial connect is in progress,
- shows regular page title once connected.
### Step 84 - Chats list preview icon policy cleanup
- Updated chat last-message preview text to remove emoji prefixes.
- Switched media-type preview prefixes to plain text labels (`Photo`, `Video`, `Voice`, etc.) to match Material-icons-only UI policy.
### Step 85 - Unread counter fix for active/read chats
- Added `ChatDao.markChatRead(chatId)` to clear `unread_count` and `unread_mentions_count` in Room.
- Applied optimistic local unread reset on `markMessageRead(...)` in message repository.
- Fixed realtime unread logic: incoming messages in currently active chat no longer increment unread badge.
### Step 86 - Chats list visual pass toward Telegram reference
- Updated chats list row density: tighter vertical rhythm, larger avatar, stronger title hierarchy, cleaner secondary text.
- Restyled archive as dedicated list row with leading archive icon avatar, subtitle, and unread badge.
- Kept search in top app bar action and changed search field default to collapsed (opens via search icon).
- Returned message-type emoji markers in chat previews:
- `🖼` photo, `🎤` voice, `🎵` audio, `🎥` video, `⭕` circle video, `🔗` links.
### Step 87 - Chats list micro-typography and time formatting
- Refined chat row typography hierarchy to be closer to Telegram density:
- title/body/presence font scale aligned and single-line ellipsis for long values.
- Tightened unread/mention badge sizing and spacing for compact right-side metadata.
- Updated trailing time formatter:
- today: `HH:mm`,
- this week: localized short weekday,
- older: `dd.MM.yy`.
### Step 88 - Chats list interaction states (menu/select/search)
- Added default overflow menu (`⋮`) state in chats header with Telegram-like quick actions UI.
- Added long-press multi-select mode for chat rows with:
- top selection bar (`count`, action icons),
- dedicated overflow menu for selected chats.
- Added dedicated search-mode state in chats screen:
- search field + section chips (`Chats/Channels/Apps/Posts`),
- horizontal recent avatars strip,
- list filtered by active query.
### Step 89 - Chats actions wiring + duplicate menu fix
- Removed duplicated overflow action in chats top bar (single `⋮` remains in default mode).
- Wired selection actions to behavior:
- delete selected -> leave selected chats,
- archive selected -> switch to archived section,
- non-implemented bulk actions now show explicit user feedback.
- Wired default menu actions:
- create group/channel -> open management panel,
- saved -> open saved chat if present,
- unsupported items show clear feedback instead of silent no-op.
### Step 90 - Fullscreen chats search redesign (Telegram-like)
- Reworked chats search mode into a fullscreen flow:
- top rounded search field with inline clear button,
- horizontal category chips (`Chats`, `Channels`, `Apps`, `Posts`),
- dedicated recent avatars row for the active category.
- Added search-mode content states:
- empty query -> `Recent` list block (history-style chat rows),
- non-empty query -> local matches + `Global search` and `Messages` sections.
- Kept search action in chats top bar; while search mode is active, app bar switches to back-navigation + empty title (content drives the page).
### Step 91 - Search history/recent persistence + clear action
- Added `ChatSearchRepository` abstraction and `DataStoreChatSearchRepository` implementation.
- Persisted chats search metadata in `DataStore`:
- recent opened chats list,
- search history list (bounded).
- Wired chats fullscreen search to persisted data:
- green recent avatars strip now reads saved recent chats,
- red `Recent` list now reads saved history with fallback.
- Connected `Очистить` action to real history cleanup in `DataStore`.
- On opening a chat from search results/messages/history, the chat is now stored in recent/history.
### Step 92 - Search filter leak fix on exit
- Fixed chats search state leak: leaving fullscreen search now resets local/global query.
- Main chats list no longer stays filtered by previous search input after returning from search mode.
### Step 93 - Fullscreen search UX polish
- Added system back-handler for search mode with safe query reset.
- Improved fullscreen search result sections:
- `Показать больше / Свернуть` toggle for global users,
- `Показать больше / Свернуть` toggle for message results.
- Added explicit empty-state text when local/global/message search sections all have no results.
### Step 94 - Pinned-only drag markers in selection mode
- Updated chats multi-select row UI: drag markers are now shown only for pinned chats.
- Non-pinned chats no longer render reorder marker in selection mode.
### Step 95 - Selection badge on avatar (Telegram-like)
- Added explicit selection indicator directly on chat avatars in multi-select mode:
- selected chat -> colored circle with check icon,
- unselected chat -> empty outlined circle.
- This matches the reference behavior and makes selected rows easier to scan.
### Step 96 - Selection menu labels and behavior polish
- Updated multi-select top actions/menu to be closer to Telegram reference in wording.
- Added dynamic `Закрепить/Открепить` label in selection overflow based on selected chats pinned state.
- Kept non-supported actions explicit with user feedback (Toast), avoiding silent no-op behavior.
### Step 97 - Chats popup/select actions wired to backend API
- Extended Android chat data layer with missing parity endpoints:
- `archive/unarchive`
- `pin-chat/unpin-chat`
- `clear`
- `delete (for_all=false)`
- `chat notifications get/update`
- Added repository methods and `ViewModel` actions for those operations.
- Replaced chats multi-select UI stubs with real API calls:
- mute/unmute selected chats,
- archive/unarchive selected chats,
- pin/unpin selected chats,
- clear selected chats,
- delete selected chats for current user.
### Step 98 - Realtime sync fix for pin/archive updates
- Improved `chat_updated` handling in realtime flow:
- now refreshes both active and archived chats lists to sync user-scoped flags (`pinned`, `archived`) immediately.
- Added parser fallback for realtime chat events to support payloads with either `chat_id` or `id`.
### Step 99 - Saved chat API parity
- Added Android support for `GET /api/v1/chats/saved`.
- Wired chats overflow `Saved` action to real backend request (instead of local title heuristic).
- Saved chat is now upserted into local Room cache and opened via normal navigation flow.
### Step 100 - Android image compression before upload
- Added pre-upload image compression in Android media pipeline (`NetworkMediaRepository`).
- For non-GIF images:
- decode + resize with max side `1920`,
- re-encode as `image/jpeg` with quality `82`,
- keep original bytes if compression does not reduce payload size.
- Upload request and attachment metadata now use actual prepared payload (`fileName`, `fileType`, `fileSize`), matching web behavior.
### Step 101 - Chat title/profile API parity
- Added Android API integration for:
- `PATCH /api/v1/chats/{chat_id}/title`
- `PATCH /api/v1/chats/{chat_id}/profile`
- Extended `ChatRepository`/`NetworkChatRepository` with `updateChatTitle(...)` and `updateChatProfile(...)`.
- Wired these actions into the existing Chat Management panel:
- edit selected chat title,
- edit selected chat profile fields (title/description).
### Step 102 - Global search + message thread parity
- Added Android data-layer integration for unified backend global search:
- `GET /api/v1/search`
- new `SearchRepository` + `SearchApiService` returning `users/chats/messages`.
- Switched chats fullscreen search flow to use unified backend search instead of composed per-domain calls.
- Extended message data layer with:
- `GET /api/v1/messages/{message_id}/thread`
- `MessageRepository.getMessageThread(...)` for thread/replies usage in upcoming UI steps.
### Step 103 - Contacts API parity + real Contacts screen
- Added Android integration for contacts endpoints:
- `GET /api/v1/users/contacts`
- `POST /api/v1/users/{user_id}/contacts`
- `POST /api/v1/users/contacts/by-email`
- `DELETE /api/v1/users/{user_id}/contacts`
- Extended `AccountRepository` + `NetworkAccountRepository` with contacts methods.
- Replaced placeholder Contacts screen with real stateful flow (`ContactsViewModel`):
- load contacts from backend,
- user search + add contact,
- add contact by email,
- remove contact,
- loading/refresh/error/info states.
### Step 104 - Push token sync (Android + backend)
- Added backend push token lifecycle API and storage:
- `POST /api/v1/notifications/push-token`
- `DELETE /api/v1/notifications/push-token`
- new table `push_device_tokens` (+ Alembic migration `0027_push_device_tokens`).
- Added Android push token sync manager:
- registers FCM token on app start and after auth refresh/login,
- updates backend token on `FirebaseMessagingService.onNewToken`,
- unregisters token on logout.
- Added backend FCM delivery in Celery notification tasks:
- sends to registered user device tokens,
- auto-removes invalid/unregistered tokens,
- safe fallback logs when Firebase is not configured.
### Step 105 - Web Firebase push registration
- Added web-side Firebase Messaging bootstrap (env-driven, no hardcoded secrets):
- fetch web push token and register in backend via `/notifications/push-token`,
- unregister token on logout,
- handle foreground push payload via existing notification service worker.
- Added required env keys to `web/.env.example` and backend Firebase env keys to root `.env.example`.
### Step 106 - Unread counter stabilization in Chat screen
- Fixed read acknowledgement strategy in `ChatViewModel`:
- read status is now acknowledged by the latest visible message id in chat (not only latest incoming),
- delivery status still uses latest incoming message.
- This removes cases where unread badge reappears after chat list refresh because the previous read ack used an outdated incoming id.
### Step 107 - Read-on-visible + cross-device unread sync
- Implemented read acknowledgement from actual visible messages in `ChatScreen`:
- tracks visible `LazyColumn` rows and sends read up to max visible incoming message id.
- unread now drops as messages appear on screen while scrolling.
- Improved cross-device sync (web <-> android):
- `message_read` realtime event now parses `user_id` and `last_read_message_id`.
- on `message_read`, Android refreshes chat snapshot from backend to keep unread counters aligned across devices.
### Step 108 - Strict read boundary by visible incoming only
- Removed fallback read-pointer advancement in `ChatViewModel.acknowledgeLatestMessages(...)` that previously moved `lastReadMessageId` by latest loaded message id.
- Read pointer is now advanced only via `onVisibleIncomingMessageId(...)` from visible incoming rows in `ChatScreen`.
- This prevents read acknowledgements from overshooting beyond what user actually saw during refresh/recompose scenarios.
### Step 109 - Telegram-like Settings/Profile visual refresh
- Redesigned `SettingsScreen` to Telegram-inspired dark card layout:
- profile header card with avatar/name/email/username,
- grouped settings rows with material icons,
- appearance controls (Light/Dark/System),
- quick security/help sections and preserved logout/back actions.
- Redesigned `ProfileScreen` to Telegram-inspired structure:
- gradient hero header with centered avatar, status, and action buttons,
- primary profile info card,
- tab-like section (`Posts/Archived/Gifts`) with placeholder content,
- inline edit card (name/username/bio/avatar URL) with existing save/upload behavior preserved.
### Step 110 - Multi-account foundation (switch active account)
- Extended `TokenRepository` to support account list and active-account switching:
- observe/list stored accounts,
- get active account id,
- switch/remove account,
- clear all tokens.
- Reworked `EncryptedPrefsTokenRepository` storage model:
- stores tokens per `userId` and account metadata list in encrypted prefs,
- migrates legacy single-account keys on first run,
- preserves active account pointer.
- `NetworkAuthRepository` now upserts account metadata after auth/me calls.
- Added `Settings` UI account section:
- shows saved accounts,
- allows switch/remove,
- triggers auth recheck + chats reload on switch.
### Step 111 - Real Settings + persistent theme + add-account UX
- Implemented persistent app theme storage via DataStore (`ThemeRepository`) and applied theme mode on app start in `MainActivity`.
- Reworked `SettingsScreen` to contain only working settings and actions:
- multi-account list (`Switch`/`Remove`) + `Add account` dialog with email/password sign-in,
- appearance (`Light`/`Dark`/`System`) wired to persisted theme,
- notifications (`global` + `preview`) wired to `NotificationSettingsRepository`,
- privacy update, blocked users management, sessions revoke/revoke-all, 2FA controls.
- Updated `ProfileScreen` to follow current app theme colors instead of forced dark palette.
### Step 112 - Settings cleanup (privacy dropdowns + removed extra blocks)
- Replaced free-text privacy inputs with dropdown selectors (`everyone`, `contacts`, `nobody`) for:
- private messages,
- last seen,
- avatar visibility,
- group invites.
- Removed direct `block by user id` controls from Settings UI as requested.
- Removed extra bottom Settings actions (`Profile` row and `Back to chats` button) and kept categorized section layout.
### Step 113 - Auth flow redesign (email -> password/register -> 2FA) + startup no-flicker
- Added step-based auth domain/use-cases for:
- `GET /api/v1/auth/check-email`
- `POST /api/v1/auth/register`
- login with optional `otp_code` / `recovery_code`.
- Updated Android login UI to multi-step flow:
- step 1: email input,
- step 2: password for existing account or register form (`name`, `username`, `password`) for new account,
- step 3: 2FA OTP/recovery code when backend requires it.
- Improved login error mapping for 2FA-required responses, so app switches to OTP step instead of generic invalid-password message.
- Removed auth screen flash on startup:
- introduced dedicated `startup` route with session-check loader,
- delayed auth/chats navigation until session check is finished.
- Added safe fallback in `MainActivity` theme bootstrap to prevent crash if `ThemeRepository` injection is unexpectedly unavailable during startup.
### Step 114 - Multi-account switch sync fix (chats + realtime)
- Fixed account switch flow to fully rebind app data context:
- restart realtime socket on new active account token,
- force refresh chats for both `archived=false` and `archived=true` right after switch.
- Fixed navigation behavior on account switch to avoid noisy `popBackStack ... not found` and stale restored stack state.
### Step 115 - Settings UI restructured into Telegram-like folders
- Reworked Settings into a menu-first screen with Telegram-style grouped rows.
- Added per-item folder pages (subscreens) for:
- Account
- Chat settings
- Privacy
- Notifications
- Devices
- Data/Chat folders/Power/Language placeholders
- Kept theme logic intact and moved appearance controls into `Chat settings` folder.
### Step 116 - Profile cleanup (remove non-working extras)
- Removed non-functional profile tabs and placeholder blocks:
- `Posts`
- `Archived`
- `Gifts`
- Removed `Settings` hero button from profile header.
- Removed bottom `Back to chats` button from profile screen.
- Simplified profile layout so the editable profile form is the primary secondary section toggled by `Edit`.
- Updated `ProfileRoute` navigation contract to match the simplified screen API.
### Step 117 - Settings folders cleanup (remove back button action)
- Removed `Back to chats` button from all Settings folder pages.
- Simplified Settings navigation contract by removing unused `onBackToChats` parameter from:
- `SettingsRoute`
- `SettingsScreen`
- `SettingsFolderView`
- Updated `AppNavGraph` Settings destination call-site accordingly.
### Step 118 - Android push notifications grouped by chat
- Reworked `NotificationDispatcher` to aggregate incoming messages into one notification per chat:
- stable notification id per `chatId`,
- per-chat unread counter,
- multi-line inbox preview of recent messages.
- Added app-level summary notification that groups all active chat notifications.
- Added deduplication guard for repeated push deliveries of the same `messageId`.
- Added notification cleanup on chat open:
- when push-open intent targets a chat in `MainActivity`,
- when `ChatViewModel` enters a chat directly from app UI.
### Step 119 - Chat screen visual baseline (Telegram-like start)
- Reworked chat top bar:
- icon back button instead of text button,
- cleaner title/subtitle styling,
- dedicated search icon in top bar (inline search is now collapsible).
- Updated pinned message strip:
- cleaner card styling,
- close icon action instead of full text button.
- Updated composer baseline:
- icon-based emoji/attach/send/mic controls,
- cleaner container styling closer to Telegram-like bottom bar.
### Step 120 - Message bubble layout pass (Telegram-like geometry)
- Reworked `MessageBubble` structure and density:
- cleaner outgoing/incoming bubble geometry,
- improved max width and alignment behavior,
- tighter paddings and spacing for mobile density.
- Redesigned forwarded/reply blocks:
- compact forwarded caption styling,
- reply block with accent stripe and nested preview text.
- Improved message meta line:
- cleaner time + status line placement and contrast.
- Refined reactions and attachments rendering inside bubbles:
- chip-like reaction containers,
- rounded image/file/media surfaces closer to Telegram-like visual rhythm.
### Step 121 - Chat selection and message action UX cleanup
- Added Telegram-like multi-select top bar in chat:
- close selection,
- selected counter,
- quick forward/delete actions.
- Simplified tap action menu flow for single message:
- richer reaction row (`❤️ 👍 👎 🔥 🥰 👏 😁`),
- reply/edit/forward/delete actions kept in one sheet.
- Removed duplicate/conflicting selection controls between top and bottom action rows.
### Step 122 - Chat 3-dot menu + chat info media tabs shell
- Added chat header `3-dot` popup menu with Telegram-like actions:
- `Chat info`
- `Search`
- `Notifications`
- `Change wallpaper`
- `Clear history`
- Added `Chat info` bottom sheet with tabbed sections:
- `Media`
- `Files`
- `Links`
- `Voice`
- Implemented local tab content from current loaded chat messages/attachments to provide immediate media/files/links/voice overview.
### Step 123 - Chat info visual pass (Telegram-like density)
- Updated `Chat info` tabs to pill-style horizontal chips with tighter Telegram-like spacing.
- Improved tab content rendering:
- `Media` now uses a 3-column thumbnail grid.
- `Files / Links / Voice` use denser card rows with icon+meta layout.
- `Voice` rows now show a dedicated play affordance.
- Refined menu order in chat `3-dot` popup and kept actions consistent with current no-calls scope.
### Step 124 - Inline search close fix + message menu visual pass
- Fixed inline chat search UX:
- added explicit close button in the search row,
- closing search now also clears active query/filter without re-entering chat.
- Added automatic inline-search collapse when entering multi-select mode.
- Reworked message tap action sheet to Telegram-like list actions with icons and clearer destructive `Delete` row styling.
### Step 125 - Chat header/top strips visual refinement
- Refined chat header density and typography to be closer to Telegram-like proportions.
- Updated pinned strip visual:
- accent vertical marker,
- tighter spacing,
- cleaner title/content hierarchy.
- Added top mini audio strip under pinned area:
- shows latest audio/voice context from loaded chat,
- includes play affordance, speed badge, and dismiss action.
### Step 126 - Message bubble/composer micro-polish
- Updated message bubble sizing and density:
- reduced bubble width for cleaner conversation rhythm,
- tighter vertical spacing,
- text style adjusted for better readability.
- Refined bottom composer visuals:
- switched to Telegram-like rounded input container look,
- emoji/attach/send buttons now use circular tinted surfaces,
- text input moved to filled style with hidden indicator lines.
### Step 127 - Top audio strip behavior fix (playback-driven)
- Reworked top audio strip logic to be playback-driven instead of always-on:
- strip appears only when user starts audio/voice playback,
- strip switches to the currently playing file,
- strip auto-hides when playback stops.
- Added close (`X`) behavior that hides the strip and force-stops the currently playing source.
### Step 128 - Parity docs update: text formatting gap
- Synced Android parity documentation with web-core status:
- added explicit `Text formatting parity` gap to `docs/android-checklist.md`,
- added dedicated Android gap block in `docs/backend-web-android-parity.md` for formatting parity.
- Marked formatting parity as part of highest-priority Android parity block.
### Step 129 - Parity block (1/3/4/5/6): formatting, notifications inbox, resend verification, push sync
- Completed Android text formatting parity in chat:
- composer toolbar actions for `bold/italic/underline/strikethrough`,
- spoiler, inline code, code block, quote, link insertion,
- message bubble rich renderer for web-style markdown tokens and clickable links.
- Added server notifications inbox flow in account/settings:
- API wiring for `GET /api/v1/notifications`,
- domain mapping and recent-notifications UI section.
- Added resend verification support on Android:
- API wiring for `POST /api/v1/auth/resend-verification`,
- Verify Email screen action for resending link by email.
- Hardened push token lifecycle sync:
- token registration dedupe by `(userId, token)`,
- marker cleanup on logout,
- best-effort re-sync after account switch.
- Notification delivery polish (foundation):
- foreground notification body now respects preview setting and falls back to media-type labels when previews are disabled.
- Verified with successful `:app:compileDebugKotlin` and `:app:assembleDebug`.
### Step 130 - Chat UX pack: video viewer, emoji/GIF/sticker picker, day separators
- Added chat timeline day separators with Telegram-like chips:
- `Сегодня`, `Вчера`, or localized date labels.
- Added fullscreen video viewer:
- video attachments now open in a fullscreen overlay with close action.
- Added composer media picker sheet:
- tabs: `Эмодзи`, `GIF`, `Стикеры`,
- emoji insertion at cursor,
- remote GIF/sticker selection with download+send flow.
- Extended media type mapping in message send pipeline:
- GIFs now sent as `gif`,
- sticker-like payloads sent as `sticker` (filename/mime detection).
- Added missing fallback resource theme declarations (`themes.xml`) to stabilize clean debug assembly on local builds.
### Step 131 - Channel chat Telegram-like visual alignment
- Added channel-aware chat rendering path:
- `MessageUiState` now carries `chatType` from `ChatViewModel`,
- channel timeline bubbles are rendered as wider post-like cards (left-aligned feed style).
- Refined channel message status presentation:
- post cards now show cleaner timestamp-only footer instead of direct-message style checks.
- Added dedicated read-only channel bottom bar (for non owner/admin):
- compact Telegram-like controls with search + centered `Включить звук` action + notifications icon.
- Kept existing full composer for roles allowed to post in channels (owner/admin).
### Step 132 - Voice recording composer overlap fix
- Fixed composer overlap during voice recording:
- recording status/hint is now rendered in a dedicated top block inside composer,
- formatting toolbar is hidden while recording is active.
- Prevented controls collision for locked-recording actions:
- `Cancel/Send` now render on a separate row in locked state.
### Step 133 - Video/audio player controls upgrade
- Upgraded fullscreen video viewer controls:
- play/pause button,
- seek slider (scrubbing),
- current time / total duration labels.
- Upgraded attachment audio player behavior (voice + audio):
- added seek slider for manual rewind/fast-forward,
- unified speed toggle for both `voice` and `audio` playback.
### Step 134 - Hilt startup crash fix (`MessengerApplication_GeneratedInjector`)
- Fixed startup crash:
- `NoClassDefFoundError: MessengerApplication_GeneratedInjector`.
- Root cause observed in build pipeline:
- `MessengerApplication_GeneratedInjector.class` existed after `javac`,
- but was missing in `transformDebugClassesWithAsm/dirs` before dexing.
- Added Gradle backfill task for `debug/release` variants:
- copies `*Application_GeneratedInjector.class` from `intermediates/javac/.../classes`
into `intermediates/classes/.../transform...ClassesWithAsm/dirs` if missing,
- wired task as dependency of `dexBuilder<Variant>`.
### Step 135 - AppCompat launch crash fix (theme mismatch)
- Fixed `MainActivity` startup crash:
- `IllegalStateException: You need to use a Theme.AppCompat theme`.
- Root cause:
- `Theme.AppCompat.DayNight.NoActionBar` was accidentally overridden in app resources
with non-AppCompat parent (`Theme.DeviceDefault.NoActionBar`).
- Fix applied:
- introduced dedicated app theme `Theme.Messenger` with parent `Theme.AppCompat.DayNight.NoActionBar`,
- switched `AndroidManifest.xml` application theme to `@style/Theme.Messenger`.