Merge pull request #2080 from vitorpamplona/claude/preload-bookmark-events-hq9nL

Preload bookmark events to improve scrolling performance
This commit is contained in:
Vitor Pamplona
2026-04-02 15:42:56 -04:00
committed by GitHub
2 changed files with 61 additions and 0 deletions
@@ -31,8 +31,10 @@ import androidx.compose.material3.SecondaryScrollableTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -40,6 +42,7 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.EventFinderQueryState
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
@@ -90,6 +93,9 @@ fun BookmarkListScreen(
pinnedNotesFeedViewModel.invalidateData()
}
// Preload all bookmarked and pinned events so they don't load one-by-one when scrolling
PreloadBookmarkEvents(bookmarkState, pinState, accountViewModel)
RenderBookmarkScreen(publicFeedViewModel, privateFeedViewModel, pinnedNotesFeedViewModel, accountViewModel, nav)
}
@@ -171,3 +177,28 @@ private fun RenderBookmarkScreen(
}
}
}
@Composable
private fun PreloadBookmarkEvents(
bookmarkState: com.vitorpamplona.amethyst.commons.model.nip51Lists.BookmarkListState.BookmarkList?,
pinState: List<com.vitorpamplona.amethyst.model.Note>?,
accountViewModel: AccountViewModel,
) {
val eventFinder = accountViewModel.dataSources().eventFinder
val account = accountViewModel.account
val queries =
remember(bookmarkState, pinState) {
val allNotes = (bookmarkState?.public.orEmpty() + bookmarkState?.private.orEmpty() + pinState.orEmpty())
allNotes
.filter { it.event == null }
.map { EventFinderQueryState(it, account) }
}
DisposableEffect(queries) {
eventFinder.subscribe(queries)
onDispose {
eventFinder.unsubscribe(queries)
}
}
}
@@ -36,8 +36,10 @@ import androidx.compose.material3.SecondaryTabRow
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@@ -45,6 +47,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.EventFinderQueryState
import com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton
@@ -81,6 +84,9 @@ fun OldBookmarkListScreen(
privateFeedViewModel.invalidateData()
}
// Preload all bookmarked events so they don't load one-by-one when scrolling
PreloadOldBookmarkEvents(bookmarkState, accountViewModel)
RenderOldBookmarkScreen(publicFeedViewModel, privateFeedViewModel, accountViewModel, nav)
}
@@ -172,3 +178,27 @@ private fun RenderOldBookmarkScreen(
}
}
}
@Composable
private fun PreloadOldBookmarkEvents(
bookmarkState: com.vitorpamplona.amethyst.commons.model.nip51Lists.OldBookmarkListState.BookmarkList?,
accountViewModel: AccountViewModel,
) {
val eventFinder = accountViewModel.dataSources().eventFinder
val account = accountViewModel.account
val queries =
remember(bookmarkState) {
val allNotes = bookmarkState?.public.orEmpty() + bookmarkState?.private.orEmpty()
allNotes
.filter { it.event == null }
.map { EventFinderQueryState(it, account) }
}
DisposableEffect(queries) {
eventFinder.subscribe(queries)
onDispose {
eventFinder.unsubscribe(queries)
}
}
}