commits
Refactoring to facet support reverted that change. Bring it back, with pain.
Replace `CircularProgressIndicator` with the new `CircularWavyProgressIndicator` from Material 3 Expressive when a post is being uploaded.
This change provides a more modern-looking progress indicator. The `@OptIn` for `ExperimentalMaterial3ExpressiveApi` has been added to support this.
Simplify the logic for filtering replies in a thread. The new implementation makes it easier to follow the conditions under which a reply is shown.
- If a user follows the parent and the root of a three-post thread, the reply is shown.
- For threads with four or more posts, the reply is shown if the user follows the parent, root, and grandparent.
- Add `parentsParentRef()` and `grandparentAuthor()` helper functions to traverse the reply chain.
Add "Replied to you" and "Mentioned you" labels to the corresponding notification types. This is achieved by passing new boolean flags, `renderingReplyNotif` and `renderingMention`, from the `NotificationsView` to the `SkeetView`.
Delete unused commented-out code and a redundant variable assignment related to embedded media.
Remove the redundant conditional check within the post button's `onClick` lambda. The button's `enabled` state already handles the validation for post text length and content, making the inner `if` statement unnecessary.
Enable the Gradle configuration cache to improve build performance by caching the result of the configuration phase and reusing it for subsequent builds.
Force image compression to use the JPEG format, regardless of the original image's mime type (e.g., PNG, WebP). This allows the compression loop to reduce file size more effectively by adjusting the quality, which was previously skipped for PNGs.
Need to fix quotes with media
Change the keyboard type from `Email` to `Text` and remove the explicit `autoCorrectEnabled` setting for the compose input field.
- Reverse the order of avatars in the like/repost notification row so they stack correctly, with the front-most avatar on the right.
- Move the "liked/reposted this" text to be below the avatar stack, so that it gets hidden when the avatar stack is shown
Replace the `ModalNavigationDrawer` with the new `ModalWideNavigationRail` from Material 3 to display the list of user feeds.
This change updates the slide-out feeds drawer to a side rail, which is more suitable for larger screens. The `FeedsDrawer` composable has been updated to use `WideNavigationRailItem` instead of `NavigationDrawerItem`.
Use the new `PullToRefreshBox` from Material 3 Expressive, which provides a more modern pull-to-refresh indicator.
This also includes updating various androidx and other third-party dependencies.
Renders URLs, @-mentions and hashtags, sends URLs and hashtags facets.
Still need a way to add embeds on-demand for urls, but that's kind of done already IMO.
@-mentions are harder because I need to add on-the-fly search with a dropdown menu.
Highlight URLs, hashtags, and mentions in the compose text field with the primary theme color.
This changes the `OutlinedTextField` from using `TextFieldState` to a `MutableState<TextFieldValue>` in order to support `AnnotatedString` for styling.
Previously, tapping on a quoted skeet within another skeet would navigate to the thread of the top-level skeet. This change correctly passes the `onShowThread` handler down through nested and embedded skeets.
Now, tapping on a quoted skeet will navigate to the thread for that specific skeet, as intended. This also fixes an issue where tapping a "see more" link on a quoted skeet would incorrectly show the parent's thread.
Set the keyboard to capitalize sentences, enable auto-correct, and use the email keyboard type when composing a skeet. This provides a better typing experience for users.
Instead of fetching timeline data when the `TimelineViewModel` is initialized, fetch it when `MainView` is first composed.
This ensures that the data is only loaded when the UI is actually ready to be displayed.
Add a dropdown menu to the login screen, allowing users to select an Appview proxy (e.g., Bluesky, Blacksky). This proxy setting is now required for login and is saved to preferences alongside the session data.
The selected proxy is passed to the Bluesky API client via the `atproto-proxy` header on all authenticated requests. The login, session storage, and client creation logic in the `Bluesky` data layer have been updated to handle this new `AppViewProxy` parameter.
Add a `HorizontalDivider` below skeets in a thread view that are direct replies to the root post.
Set a 1:1 aspect ratio for group of images in the `PostImageGallery`.
Enable the `onShowThread` callback in `SkeetView`. This allows tapping a skeet to view its full thread. The `LazyColumn` was also switched from `items` to `itemsIndexed` to accommodate this.
Use the foreground layer of the launcher icon for the splash screen animation. This ensures only the Monarch logo is animated, without the background circle.
When pulling to refresh, both the timeline and notifications feeds are now fetched at the same time. After the refresh completes, the view scrolls to the top of both lists.
This also changes the top app bar's scroll behavior to `exitUntilCollapsed`.
Adds the logged-in user's avatar to the right side of the top app bar on the timeline view. This required adding a `fetchSelf` method to the Bluesky data layer and the `TimelineViewModel` to retrieve the current user's profile details.
The feed avatar's shadow has also been removed.
Add a back button to the `ThreadView` to allow users to navigate back.
The `MainView` was also updated to use `LargeTopAppBar` instead of `TopAppBar` for a more modern look.
When displaying a single image, respect its original aspect ratio instead of forcing it to be square.
This also updates the gallery viewer to use the full-size image URL when zoomed in.
Pass the aspect ratio (width and height) from the skeet's image data to the `Image` model. This will allow the `ImageGallery` to properly size images.
Change the color of links, mentions, and tags in rich text from `onSurfaceVariant` to the theme's `primary` color to make them more prominent.
Change the color of tags in skeet text from `onSurface` to `onSurfaceVariant` for better visual distinction.
Color the like and repost icons in the notification row to match their standard colors elsewhere in the app.
- Likes are now colored with `MaterialTheme.colorScheme.error` (typically red).
- Reposts are now colored with `MaterialTheme.colorScheme.inverseSurface` (typically green).
Removes the `CircularProgressIndicator` that was previously shown at the bottom of the timeline and notifications lists while fetching more items.
When the compose bottom sheet expands, automatically focus the text field and show the software keyboard. This is achieved by observing `bottomSheetState.targetValue` instead of `currentValue`.
Removes unnecessary logic for fetching the embedded record in a repost notification. The reposted post (`rpp`) is already available and can be used directly.
Instead of fetching the subject of each "like" or "repost" notification individually, fetch all of them in a single bulk request. This reduces network IO and improves performance when loading notifications.
The `isRefreshing` state in `MainView` is now derived directly from the `TimelineViewModel`'s `isFetchingMoreTimeline` and `isFetchingMoreNotifications` properties. This removes the local `mutableStateOf` and simplifies state management.
Additionally, timeline and notification data is now fetched on ViewModel initialization instead of via a `LaunchedEffect` in the view.
When the user navigates to the notifications tab, the badge count is cleared.
Also, a small visual tweak adds spacing between the like/repost buttons in the `LikeRepostRowView`.
Add a badge to the "Notifications" icon in the bottom navigation bar to display the number of unread notifications.
This involved:
* Updating the `TimelineViewModel` to count unread notifications and expose it in the `UiState`.
* Using `BadgedBox` in `MainView` to display the count on the navigation item.
* Adding accessibility content descriptions for the notification badge (e.g., "1 new notification").
needs more work, committing and pushing since i might've solved some performance issues w/lists
the second case is essentially a threaded view of someone that replied to someone we follow
Don't show the "replying to" header on a skeet when it's being displayed as a reply in a thread. This avoids redundant information since the parent skeet is already visible directly above it.
Visually indent replies in a thread to show their nesting level. This change restructures how threads are processed and displayed, showing the full conversation hierarchy instead of just a flat list of replies.
- Add a `nestingLevel` property to `SkeetData` to control indentation.
- Update `TimelineViewModel` to recursively process the entire thread structure.
- Modify `ThreadView` to render each branch of the conversation.
Add a new rule to the Gemini guidelines to never compile with Gradle after making a change.
When rendering annotated text, the portion of the text that came after the final annotation was being dropped.
This is fixed by adding a check to see if the current facet is the last one in the list. If it is, the remaining text from the end of the facet to the end of the content is appended.
When pulling to refresh the notifications timeline, scroll to the top of the list.
The width and height of a compressed image were being taken from the original, uncompressed bitmap. This resulted in incorrect dimensions being stored.
The fix is to decode the compressed `outputBytes` into a new `Bitmap` and read the dimensions from that instead.
Allow tapping the row of avatars to expand into a full list showing each user's avatar and name. Tapping again collapses the list back to the stacked avatar view. This only applies if there is more than one user who has liked or reposted.
Use the `onSurface` color from the `MaterialTheme` for links and mentions in skeet content. This ensures the link color adapts to the current theme (e.g., light or dark mode) instead of being a hardcoded blue.
The `annotatedContent()` function is now a `@Composable` to access the theme's color scheme.
Replace the thumbs-up icon with a heart icon for liking posts. This provides a more conventional and universally understood symbol for likes.
The new filled and outlined heart vector icons have been added and centralized in `VectorImages.kt` for reuse.
Group repost notifications by post, similar to how likes are handled. This combines multiple reposts of the same skeet into a single notification entry.
This change also introduces the following improvements to the notifications view:
* Renamed `LikeRowView` to the more generic `LikeRepostRowView` to accommodate both likes and reposts.
* Increased the spacing between notification items for better readability.
* Removed the card elevation around individual notifications for a flatter design.
Include the aspect ratio when uploading images and videos. This helps clients display the media correctly before it has fully loaded.
The `Compressor` was updated to return a `CompressedImage` data class containing the width and height, in addition to the byte array.
For videos, `MediaMetadataRetriever` is now used to extract the width, height, and rotation to correctly determine the video's dimensions.
Parse and display rich text (links, mentions, tags) within a skeet's content. This is done by processing the `facets` data associated with a post.
The `SkeetData` model now includes `facets` and a new `annotatedContent()` method to build an `AnnotatedString` for rendering. The `SkeetView` uses this new method to display the formatted text.
Simplify the logic for filtering replies in a thread. The new implementation makes it easier to follow the conditions under which a reply is shown.
- If a user follows the parent and the root of a three-post thread, the reply is shown.
- For threads with four or more posts, the reply is shown if the user follows the parent, root, and grandparent.
- Add `parentsParentRef()` and `grandparentAuthor()` helper functions to traverse the reply chain.
Replace the `ModalNavigationDrawer` with the new `ModalWideNavigationRail` from Material 3 to display the list of user feeds.
This change updates the slide-out feeds drawer to a side rail, which is more suitable for larger screens. The `FeedsDrawer` composable has been updated to use `WideNavigationRailItem` instead of `NavigationDrawerItem`.
Previously, tapping on a quoted skeet within another skeet would navigate to the thread of the top-level skeet. This change correctly passes the `onShowThread` handler down through nested and embedded skeets.
Now, tapping on a quoted skeet will navigate to the thread for that specific skeet, as intended. This also fixes an issue where tapping a "see more" link on a quoted skeet would incorrectly show the parent's thread.
Add a dropdown menu to the login screen, allowing users to select an Appview proxy (e.g., Bluesky, Blacksky). This proxy setting is now required for login and is saved to preferences alongside the session data.
The selected proxy is passed to the Bluesky API client via the `atproto-proxy` header on all authenticated requests. The login, session storage, and client creation logic in the `Bluesky` data layer have been updated to handle this new `AppViewProxy` parameter.
The `isRefreshing` state in `MainView` is now derived directly from the `TimelineViewModel`'s `isFetchingMoreTimeline` and `isFetchingMoreNotifications` properties. This removes the local `mutableStateOf` and simplifies state management.
Additionally, timeline and notification data is now fetched on ViewModel initialization instead of via a `LaunchedEffect` in the view.
Add a badge to the "Notifications" icon in the bottom navigation bar to display the number of unread notifications.
This involved:
* Updating the `TimelineViewModel` to count unread notifications and expose it in the `UiState`.
* Using `BadgedBox` in `MainView` to display the count on the navigation item.
* Adding accessibility content descriptions for the notification badge (e.g., "1 new notification").
Visually indent replies in a thread to show their nesting level. This change restructures how threads are processed and displayed, showing the full conversation hierarchy instead of just a flat list of replies.
- Add a `nestingLevel` property to `SkeetData` to control indentation.
- Update `TimelineViewModel` to recursively process the entire thread structure.
- Modify `ThreadView` to render each branch of the conversation.
Use the `onSurface` color from the `MaterialTheme` for links and mentions in skeet content. This ensures the link color adapts to the current theme (e.g., light or dark mode) instead of being a hardcoded blue.
The `annotatedContent()` function is now a `@Composable` to access the theme's color scheme.
Group repost notifications by post, similar to how likes are handled. This combines multiple reposts of the same skeet into a single notification entry.
This change also introduces the following improvements to the notifications view:
* Renamed `LikeRowView` to the more generic `LikeRepostRowView` to accommodate both likes and reposts.
* Increased the spacing between notification items for better readability.
* Removed the card elevation around individual notifications for a flatter design.
Include the aspect ratio when uploading images and videos. This helps clients display the media correctly before it has fully loaded.
The `Compressor` was updated to return a `CompressedImage` data class containing the width and height, in addition to the byte array.
For videos, `MediaMetadataRetriever` is now used to extract the width, height, and rotation to correctly determine the video's dimensions.
Parse and display rich text (links, mentions, tags) within a skeet's content. This is done by processing the `facets` data associated with a post.
The `SkeetData` model now includes `facets` and a new `annotatedContent()` method to build an `AnnotatedString` for rendering. The `SkeetView` uses this new method to display the formatted text.