Files
Messenger/android/CHANGELOG.md
Codex 158126555c
Some checks failed
Android CI / android (push) Has started running
Android Release / release (push) Has been cancelled
CI / test (push) Has been cancelled
android: remove back-to-chats from settings folders
2026-03-10 00:33:10 +03:00

50 KiB
Raw Blame History

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.
  • 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.
  • 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.
  • 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.