A cheap attempt at a native Bluesky client for Android
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

ProfileView: Replace filter chips with PrimaryTabRow for feed filters

Use M3 PrimaryTabRow with Posts, Replies, Media, Video tabs instead of
FilterChip pills for profile feed filtering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

geesawra 418a882c 53bf81a0

+23 -29
+23 -29
app/src/main/java/industries/geesawra/monarch/ProfileView.kt
··· 47 47 import androidx.compose.material3.DropdownMenu 48 48 import androidx.compose.material3.DropdownMenuItem 49 49 import androidx.compose.material3.ExperimentalMaterial3Api 50 - import androidx.compose.material3.FilterChip 51 50 import androidx.compose.material3.FilledTonalButton 52 51 import androidx.compose.material3.FilledTonalIconButton 53 52 import androidx.compose.material3.Button ··· 87 86 import app.bsky.actor.ProfileViewDetailed 88 87 import app.bsky.actor.VerifiedStatus 89 88 import app.bsky.feed.GetAuthorFeedFilter 89 + import androidx.compose.material3.PrimaryTabRow 90 + import androidx.compose.material3.Tab 90 91 import coil3.compose.AsyncImage 91 92 import coil3.request.ImageRequest 92 93 import coil3.request.crossfade ··· 265 266 ) 266 267 } 267 268 268 - // Feed filter chips 269 - item(key = "filter_chips") { 270 - ProfileFeedFilters(timelineViewModel) 269 + // Feed tabs 270 + item(key = "feed_tabs") { 271 + ProfileFeedTabs(timelineViewModel) 271 272 } 272 273 273 274 // Posts ··· 742 743 } 743 744 } 744 745 746 + private val profileTabs = listOf( 747 + "Posts" to null, 748 + "Replies" to GetAuthorFeedFilter.PostsWithReplies, 749 + "Media" to GetAuthorFeedFilter.PostsWithMedia, 750 + "Video" to GetAuthorFeedFilter.PostsWithVideo, 751 + ) 752 + 753 + @OptIn(ExperimentalMaterial3Api::class) 745 754 @Composable 746 - private fun ProfileFeedFilters(timelineViewModel: TimelineViewModel) { 755 + private fun ProfileFeedTabs(timelineViewModel: TimelineViewModel) { 747 756 val currentFilter = timelineViewModel.uiState.profileFeedFilter 757 + val selectedIndex = profileTabs.indexOfFirst { it.second == currentFilter }.coerceAtLeast(0) 748 758 749 - Row( 750 - horizontalArrangement = Arrangement.spacedBy(8.dp), 751 - modifier = Modifier.padding(vertical = 4.dp), 752 - ) { 753 - FilterChip( 754 - selected = currentFilter == null, 755 - onClick = { timelineViewModel.setProfileFeedFilter(null) }, 756 - label = { Text("Posts") }, 757 - ) 758 - FilterChip( 759 - selected = currentFilter == GetAuthorFeedFilter.PostsWithReplies, 760 - onClick = { timelineViewModel.setProfileFeedFilter(GetAuthorFeedFilter.PostsWithReplies) }, 761 - label = { Text("Replies") }, 762 - ) 763 - FilterChip( 764 - selected = currentFilter == GetAuthorFeedFilter.PostsWithMedia, 765 - onClick = { timelineViewModel.setProfileFeedFilter(GetAuthorFeedFilter.PostsWithMedia) }, 766 - label = { Text("Media") }, 767 - ) 768 - FilterChip( 769 - selected = currentFilter == GetAuthorFeedFilter.PostsWithVideo, 770 - onClick = { timelineViewModel.setProfileFeedFilter(GetAuthorFeedFilter.PostsWithVideo) }, 771 - label = { Text("Video") }, 772 - ) 759 + PrimaryTabRow(selectedTabIndex = selectedIndex) { 760 + profileTabs.forEachIndexed { index, (label, filter) -> 761 + Tab( 762 + selected = selectedIndex == index, 763 + onClick = { timelineViewModel.setProfileFeedFilter(filter) }, 764 + text = { Text(label) }, 765 + ) 766 + } 773 767 } 774 768 }