From d6ec4581173ef0345d076eacc70736c4e8d73fe0 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 23:55:35 +0000 Subject: [PATCH] fix(git): close Issues/PR feed top gap; add "Mine" repo feed filter The status feed drew its filter-chip header at the top of the content area (under the disappearing top bar) while the feed's LazyColumn separately re-applied the full bar-height inset as content padding, leaving an empty band above the first item. The header now consumes the scaffold top inset itself and the inner feed renders with the top inset zeroed, matching the Code tab's padding pattern. Also adds a "Mine" option to the git repositories top-nav filter so the feed can show only the logged-in user's own repositories. The feed side already resolves TopFilter.Mine generically; this just exposes it via a dedicated gitRepositoryRoutes catalog (kind3 + Around Me + Global + Mine). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01DpNmN8CvP6HnEsdTGAjVUr --- .../amethyst/ui/screen/TopNavFilterState.kt | 23 ++++++++++ .../loggedIn/gitRepo/GitRepositoryScreen.kt | 43 ++++++++++++++----- .../gitRepositories/GitRepositoriesTopBar.kt | 2 +- 3 files changed, 57 insertions(+), 11 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt index b8a78cd5fb..9e05c1d6a9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt @@ -310,6 +310,24 @@ class TopNavFilterState( ) } + private val _gitRepositoryRoutes = + combineTransform( + livePeopleListsFlow, + liveInterestFlows, + ) { peopleLists, interests -> + checkNotInMainThread() + emit( + listOf( + // Git repository announcements can be narrowed by author, hashtag and geohash, + // so this mirrors the kind3 catalog plus "Mine" — the user's own repositories. + listOf(allFollows, userFollows, kind3Follows, aroundMe, globalFollow, mineFollow), + peopleLists, + interests, + listOf(muteListFollow), + ).flatten().toImmutableList(), + ) + } + private val _kind3GlobalPeople = livePeopleListsFlow.transform { peopleLists -> checkNotInMainThread() @@ -385,6 +403,11 @@ class TopNavFilterState( .flowOn(Dispatchers.IO) .stateIn(scope, SharingStarted.Eagerly, persistentListOf(allFollows, userFollows, kind3Follows, aroundMe, globalFollow, mineFollow, muteListFollow)) + val gitRepositoryRoutes = + _gitRepositoryRoutes + .flowOn(Dispatchers.IO) + .stateIn(scope, SharingStarted.Eagerly, persistentListOf(allFollows, userFollows, kind3Follows, aroundMe, globalFollow, mineFollow, muteListFollow)) + fun destroy() { Log.d("Init") { "OnCleared: ${this.javaClass.simpleName}" } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepo/GitRepositoryScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepo/GitRepositoryScreen.kt index d2b10d5910..546f90b584 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepo/GitRepositoryScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepo/GitRepositoryScreen.kt @@ -28,6 +28,8 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.calculateEndPadding +import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -43,6 +45,7 @@ import androidx.compose.material3.SecondaryTabRow import androidx.compose.material3.Tab import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -52,6 +55,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp @@ -62,6 +66,7 @@ import com.vitorpamplona.amethyst.commons.icons.symbols.Icon import com.vitorpamplona.amethyst.commons.icons.symbols.MaterialSymbols import com.vitorpamplona.amethyst.commons.nip34Git.GitRepositoryBrowserViewModel import com.vitorpamplona.amethyst.commons.ui.feeds.FeedState +import com.vitorpamplona.amethyst.commons.ui.layouts.LocalDisappearingScaffoldPadding import com.vitorpamplona.amethyst.model.AddressableNote import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteEvent @@ -394,7 +399,23 @@ private fun StatusSplitFeed( if (selectedLabel != null && selectedLabel !in labels) selectedLabel = null } - Column(Modifier.fillMaxSize()) { + // The filter header is drawn statically below the disappearing top bar, so it must + // consume the scaffold's top inset itself. The inner feed then renders with the top + // inset zeroed — otherwise its LazyColumn re-applies the full bar height as content + // padding on top of the header, leaving the empty band reported above the items. + val scaffoldPadding = LocalDisappearingScaffoldPadding.current + val layoutDirection = LocalLayoutDirection.current + val feedPadding = + remember(scaffoldPadding, layoutDirection) { + PaddingValues( + start = scaffoldPadding.calculateStartPadding(layoutDirection), + top = 0.dp, + end = scaffoldPadding.calculateEndPadding(layoutDirection), + bottom = scaffoldPadding.calculateBottomPadding(), + ) + } + + Column(Modifier.fillMaxSize().padding(top = scaffoldPadding.calculateTopPadding())) { Row( modifier = Modifier @@ -456,15 +477,17 @@ private fun StatusSplitFeed( } } - RefresheableFeedView( - viewModel = if (showClosed) closedViewModel else openViewModel, - routeForLastRead = null, - accountViewModel = accountViewModel, - nav = nav, - onLoaded = { loaded, listState -> - GitItemFeedLoaded(loaded, listState, accountViewModel, nav, labelFilter = selectedLabel) - }, - ) + CompositionLocalProvider(LocalDisappearingScaffoldPadding provides feedPadding) { + RefresheableFeedView( + viewModel = if (showClosed) closedViewModel else openViewModel, + routeForLastRead = null, + accountViewModel = accountViewModel, + nav = nav, + onLoaded = { loaded, listState -> + GitItemFeedLoaded(loaded, listState, accountViewModel, nav, labelFilter = selectedLabel) + }, + ) + } } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/GitRepositoriesTopBar.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/GitRepositoriesTopBar.kt index d28ff11f96..4c30842a95 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/GitRepositoriesTopBar.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/GitRepositoriesTopBar.kt @@ -58,7 +58,7 @@ private fun GitRepositoriesTopNavFilterBar( accountViewModel: AccountViewModel, onChange: (FeedDefinition) -> Unit, ) { - val allLists by followListsModel.kind3GlobalPeopleRoutes.collectAsStateWithLifecycle() + val allLists by followListsModel.gitRepositoryRoutes.collectAsStateWithLifecycle() FeedFilterSpinner( placeholderCode = listName,