This commit refactors the `Reply` composable for better layout consistency and simplifies its implementation.
The `Reply` component no longer uses a fixed height, allowing it to dynamically resize based on its content. The layout has been updated from a `Box` to a `Row` to properly align the side indicator bar with the height of the text content. Padding and corner rounding logic has been simplified and centralized within the `Reply` composable itself, removing redundant parameters from the `MessageBubble`.
Key changes:
- `Reply` composable now uses `Row` for its root layout instead of `Box`.
- Removed the fixed `48.dp` height to allow dynamic content sizing.
- The side indicator bar's height now matches the text content's height.
- Simplified padding and shape logic in `MessageBubble` by removing conditional parameters passed to `Reply`.
- Adjusted padding inside `MessageBubble` to accommodate the new `Reply` layout.
- Add minute/second abbreviations and kotlin.time-based relative time formatter
- Introduce FastPreview and update previews to use AppTheme with dark/dynamic colors
- Refactor attachments preview grid & waveform to use ImmutableList and reduce recompositions
- Tweak message bubble reply styling and swipe-to-reply animation/haptics
- Add Compose Stability Analyzer plugin and enable it in debug builds
- Cache shared images by sha256 and improve share intent/chooser text
- Minor UX polish (e.g., “No views”) and immutability annotations
This commit updates the icons used to indicate a message's status and within the message context menu. The outlined "star" and "edit" icons have been replaced with their filled variants for better visual distinction.
Key changes:
- Replaced `ic_star_round_24` with `ic_star_fill_round_24` for "important" messages in `DateStatus` and the "Mark as Important" action.
- Replaced `ic_edit_round_24` with `ic_edit_fill_round_24` for "edited" messages in `DateStatus`.
- Added the new `ic_edit_fill_round_24` drawable resource.
- In `MessageBubble`, the `derivedStateOf` for `shouldFill` is now wrapped in a `remember` block to prevent unnecessary recompositions.
This commit wraps the reply summary `Text` composable within an `AnimatedVisibility` component. This ensures that the summary animates in and out of view smoothly when its content changes, preventing abrupt layout shifts.
Updates the container colors for incoming and outgoing message bubbles to align with Material 3 design tokens.
- The outgoing message bubble container color is changed from `surfaceColorAtElevation(2.dp)` to `surfaceContainer`.
- The reply container color within an outgoing message is changed from `primaryContainer` to `surfaceContainerHighest`.
Additionally, the `@Preview` for `MessageBubble` is updated to display both an incoming and an outgoing message for better design validation.
This commit refactors the `MessageBubble` composable by extracting the color logic into a private `messageBubbleColors` function. This function returns an immutable `MessageBubbleColors` data class, which holds the container, content, and reply container colors.
This change cleans up the main composable, improves readability, and centralizes color definitions for both incoming and outgoing messages. Additionally, the background color logic for attachments has been simplified to make it transparent for media types like stickers and videos.
This commit resolves an issue where the sender's name in incoming message bubbles would not truncate properly, potentially breaking the layout. The fix ensures the name text correctly adapts to the width of the message bubble.
Additionally, this change introduces `ImmutableList` for message attachments to improve performance and refactors where the conversion to `ImmutableList` happens, moving it into the `MessageMapper`.
Key changes:
- The `MessageBubble` now reports its width, allowing the sender's name `Text` to be constrained correctly.
- Sender's name now uses `labelMedium` typography.
- Enabled showing the sender's name by default in `MessagesHistoryViewModelImpl`.
- Changed `UiItem.Message.attachments` from `List` to `ImmutableList` for better Compose performance.
- Moved the `toImmutableList()` conversion for attachments into the `MessageMapper`.
This commit refactors the UI composition logic by extracting it from `MainActivity` into a new, dedicated `RootScreen` composable. This improves the separation of concerns and simplifies `MainActivity`.
Additionally, a bug has been fixed where a replied-to message would incorrectly display the author of the parent message instead of its own author.
Key changes:
- Moved theme setup, permission handling, Long-Poll/Online service management, and navigation graph hosting into the new `RootScreen.kt`.
- `MainActivity` is now significantly simplified, delegating its UI composition to `RootScreen`.
- Corrected the user and group assignment for `replyMessage` in `MessagesRepositoryImpl` to ensure the correct author is displayed.
- Introduced `OnlineFriendsViewModel` to the `FriendsRoute` to separate the logic for online friends.
- Replaced `List` with a custom `ImmutableList` for `photoViewerInfo` state to improve Compose stability.
This commit introduces the ability to see how many people have read an outgoing message in a group chat. A "views" count is now displayed in the message options dialog for relevant messages.
- **API & Data Layer:**
- Added `getMessageReadPeers` to `MessagesService` and `MessagesRepository` to fetch users who have read a specific message.
- Introduced `MessagesGetReadPeersResponse` to handle the API response.
- A new URL constant `GET_MESSAGE_READ_PEERS` was added.
- **Domain Layer:**
- A new `GetMessageReadPeersUseCase` is created to provide the view count to the ViewModel.
- The use case is registered in the `DomainModule`.
- **ViewModel:**
- `MessagesHistoryViewModel` now includes `loadMessageReadPeers` to asynchronously fetch and return the view count for a message.
- **UI (Compose):**
- The `MessageOptionsDialog` now displays a "views" count for outgoing chat messages.
- It uses a `LaunchedEffect` to call `loadMessageReadPeers` when the dialog is shown.
- The `visibility` icon has been updated and its XML file renamed to `round_visibility_24px.xml` to follow a consistent naming convention.
- **Refactoring & Minor Fixes:**
- Simplified several `derivedStateOf` usages to direct calculations or property delegates in `MessageBubble.kt` and `MessagesList.kt` for minor performance improvements.
- Renamed `IncomingMessageBubble.kt` and `OutgoingMessageBubble.kt` to `MessageBubbleIncoming.kt` and `MessageBubbleOutgoing.kt` respectively for consistency.
- Removed an unnecessary log statement in `MessagesList.kt`.
This commit refactors the swipe-to-dismiss gesture and the image sharing logic in the photo viewer.
The swipe-to-dismiss animation is now smoother and more reliable, using `Animatable` instead of `animateFloatAsState`. The background dimming effect has also been improved to be more responsive to the drag gesture.
Additionally, the responsibility for creating the share `Intent` has been moved from the composable screen into the `PhotoViewViewModel`, improving the separation of concerns.
Key changes:
- Replaced `animateFloatAsState` with `Animatable` for smoother swipe-to-dismiss animations.
- Improved the alpha calculation for the background during the drag gesture.
- Moved the creation of the share `Intent` into the `PhotoViewViewModel`.
- Simplified the drag-handling logic by removing local state management from the composable.
This commit introduces the ability to reply to a message by swiping it to the right. The message input bar and related components have been redesigned and refactored for a cleaner look and better user experience.
Key changes:
- Added a swipe-to-reply gesture on message bubbles.
- Redesigned the message `InputBar` with updated styling, animations, and rounded corners that adapt to the reply state.
- Renamed `MessagesHistoryInputBar` to a more generic `InputBar`.
- Introduced `FastTextField`, a customized `BasicTextField`, for better performance and control.
- Replaced `IconButton` with `FastIconButton` and `RippledClickContainer` in several places for consistent click handling.
- Refactored `PinnedMessageContainer` and `ReplyContainer` with improved UI.
- Updated the Compose BOM to `2025.12.00`.
Moves the `RippledClickContainer` composable from the `messageshistory` feature module to the `core/ui` module to allow for reuse across different features.
Additionally, this change introduces text truncation with an ellipsis for the title and text within the `ReplyContainer` to prevent long content from breaking the layout.
This commit introduces the ability to reply to messages.
- **API & Data Layer:**
- Replaced `replyTo` parameter with `forward` in `sendMessage` calls across the data, domain, and repository layers to support the new reply mechanism.
- **ViewModel:**
- Added logic to handle the reply state, including storing the replied message's ID (`replyToCmId`).
- When a message is sent, it now correctly constructs a `forward` JSON object if it is a reply.
- The UI state (`MessagesHistoryScreenState`) is updated to show and hide the reply preview.
- Added a `onReplyCloseClicked` handler to cancel a reply.
- The ViewModel interface was removed, and the implementation class `MessagesHistoryViewModelImpl` is used directly.
- **UI (Compose):**
- A new `ReplyContainer` is displayed above the message input bar when a reply is active.
- The input bar's corner radius animates to integrate with the reply container.
- Added a `FocusRequester` to automatically focus the input field when the reply action is selected.
- Added spacing in the message list to prevent the reply preview from overlapping messages.
- The message options dialog now passes the `messageId` and `cmId` when an option is picked.
This commit introduces the ability to reply to messages.
- **API & Data Layer:**
- Replaced `replyTo` parameter with `forward` in `sendMessage` calls across the data, domain, and repository layers to support the new reply mechanism.
- **ViewModel:**
- Added logic to handle the reply state, including storing the replied message's ID (`replyToCmId`).
- When a message is sent, it now correctly constructs a `forward` JSON object if it is a reply.
- The UI state (`MessagesHistoryScreenState`) is updated to show and hide the reply preview.
- Added a `onReplyCloseClicked` handler to cancel a reply.
- The ViewModel interface was removed, and the implementation class `MessagesHistoryViewModelImpl` is used directly.
- **UI (Compose):**
- A new `ReplyContainer` is displayed above the message input bar when a reply is active.
- The input bar's corner radius animates to integrate with the reply container.
- Added a `FocusRequester` to automatically focus the input field when the reply action is selected.
- Added spacing in the message list to prevent the reply preview from overlapping messages.
- The message options dialog now passes the `messageId` and `cmId` when an option is picked.
This commit introduces a confirmation dialog before creating a new chat. The dialog displays the final chat title, which is now dynamically generated based on the user's input or the names of the selected participants.
Key changes:
- Added a confirmation dialog that appears when the user clicks the "create chat" button.
- Implemented logic to generate a provisional chat title from participants' names if no title is explicitly set.
- Refactored `CreateChatViewModel` by removing the interface and simplifying the implementation.
- Added new string resources for the confirmation dialog.
This commit refactors the `ActionMode` sealed class into an enum and adds a new `RECORD_VIDEO` state. This allows for distinct actions for recording audio and video messages.
Specifically, the following changes were made:
- Converted `ActionMode` from a sealed class to an enum.
- Added `RECORD_VIDEO` to `ActionMode`.
- Updated `MessagesHistoryInputBar` to:
- Animate the action button icon change between record modes.
- Remove the shake animation from emoji, attachment, and mic buttons.
- Updated `MessagesHistoryViewModel` to toggle between `RECORD_AUDIO` and `RECORD_VIDEO` when the action button is clicked in a record mode.
- Added support for displaying `VIDEO_MESSAGE` attachments in `Attachments.kt`, including an animated circular preview.
- Updated `MessageBubble` to render video messages without a background, similar to stickers.
- Added `image` property to `VkVideoMessageDomain` to hold the URL for the video message preview.
- Added a new drawable `rounded_photo_camera_24` for the video record button.
- Updated `VkVideoMessageData` to parse and provide the square preview image URL to the domain model.
This commit introduces a dismiss functionality to the `FullScreenDialog`.
The `FullScreenDialog` now accepts an `onDismiss` lambda parameter.
This `onDismiss` lambda is invoked when a dismiss request is made for the dialog.
In `PhotoViewScreen`, the `onDismiss` lambda passed to `FullScreenDialog` is now the `onDismiss` lambda received by the `PhotoViewScreen` itself.
This commit refactors the PhotoViewScreen to be displayed as a Dialog instead of a separate navigation destination.
Key changes:
- Introduced `PhotoViewDialog` composable that wraps `PhotoViewRoute` in a `FullScreenDialog`.
- Modified `RootScreen` to use `PhotoViewDialog` for displaying images.
- Updated `PhotoViewViewModelImpl` to handle loading state and display a loader while downloading images.
- Made `Loader` and `ContainedLoader` colors configurable.
- Adjusted `PhotoViewScreen` UI:
- Set background to translucent black.
- Updated TopAppBar background color and icon tints.
- Improved vertical drag gesture for dismissing the viewer.
- Made `VkUserData.LastSeen.platform` nullable.
- Removed unused navigation functions related to the old PhotoViewScreen.
This commit introduces "Share" and "Open in..." actions to the `PhotoViewScreen`, allowing users to share images via other apps or open them in external viewers.
**Key changes:**
- **PhotoViewer:**
- Added "Share" and "Open in..." options to the `PhotoViewScreen` dropdown menu.
- `PhotoViewViewModel`:
- Implemented `onShareClicked()` and `onOpenInClicked()` to handle these new actions.
- Added `shareRequest` StateFlow to manage image sharing intents.
- Introduced `downloadAndStoreImageToCache()` to download and cache images for sharing.
- `onImageShared()` resets `shareRequest` after sharing.
- Updated `TopBar` to include the new menu items.
- Added string resources for "Open in…" and "Share".
- **Reply UI:**
- `Reply.kt`: Title and summary text now use `TextOverflow.Ellipsis` to prevent long text from breaking the layout.
- **API Model:**
- `MessagesResponse.kt`: Added `MessagesMarkAsImportantResponse` data class to handle the response for marking messages as important.
- **Data Layer:**
- `MessagesRepositoryImpl`: Updated `markAsImportant` to correctly map the API response using `MessagesMarkAsImportantResponse`.
- **Minor:**
- `README.md`: Updated feature checklist for external viewer.
- `ApplicationModule.kt`: Added experimental Coil API opt-in.
This commit introduces the ability to display stickers within message bubbles.
Key changes:
- `Attachments.kt`: Added handling for `AttachmentType.STICKER`. If an attachment type is unsupported, a placeholder text is now displayed.
- `Sticker.kt`: New composable created to render `VkStickerDomain` using `AsyncImage`.
- `MessageBubble.kt`:
- Adjusted background alpha for sticker messages to make the bubble transparent.
- Minor refactoring of `minDateContainerWidth` and `dateContainerWidth` initialization.
- `VkStickerDomain.kt`: Added `getUrl()` function to construct sticker image URLs, with options for specifying width and background.
This commit introduces `FullScreenContainedLoader` and replaces usages of `FullScreenLoader` where appropriate.
It also updates several composables to use `rememberUpdatedState` for lambda parameters to ensure the latest versions are used.
Additionally, the following changes are included:
- Add a setting to show/hide the attachment button in the chat input bar.
- Implement navigation to `PhotoViewScreen` when a photo attachment is clicked in a message.
- Add "Copy link" and "Copy image" actions to `PhotoViewScreen`.
- Remove unused settings and their corresponding logic from `SettingsViewModel` and `UserSettings`.
* Bump haze version to 1.6.0.
* Blur now works on android 11 and older
* Add "Sign up" and "Forgot password?" links to the auth screen.
* Add logic to toggle dynamic colors on logo click in the auth screen (Android 12+).