Replaces the Live bar in the top of the feed for Notification dots in the LiveStream bottom button.

This commit is contained in:
Vitor Pamplona
2023-07-05 10:28:21 -04:00
parent 18ac527629
commit 2947c2c7d0
10 changed files with 63 additions and 189 deletions

View File

@@ -10,7 +10,7 @@ import okhttp3.Request
data class OnlineCheckResult(val timeInMs: Long, val online: Boolean) data class OnlineCheckResult(val timeInMs: Long, val online: Boolean)
object OnlineChecker { object OnlineChecker {
val checkOnlineCache = LruCache<String, OnlineCheckResult>(10) val checkOnlineCache = LruCache<String, OnlineCheckResult>(100)
val fiveMinutes = 1000 * 60 * 5 val fiveMinutes = 1000 * 60 * 5
fun isOnline(url: String?): Boolean { fun isOnline(url: String?): Boolean {

View File

@@ -9,7 +9,7 @@ import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.ST
import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_LIVE import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_LIVE
import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_PLANNED import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_PLANNED
class DiscoverFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() { open class DiscoverFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
override fun feedKey(): String { override fun feedKey(): String {
return account.userProfile().pubkeyHex + "-" + account.defaultDiscoveryFollowList return account.userProfile().pubkeyHex + "-" + account.defaultDiscoveryFollowList
} }
@@ -27,7 +27,7 @@ class DiscoverFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
return innerApplyFilter(collection) return innerApplyFilter(collection)
} }
private fun innerApplyFilter(collection: Collection<Note>): Set<Note> { protected open fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
val now = System.currentTimeMillis() / 1000 val now = System.currentTimeMillis() / 1000
val isGlobal = account.defaultDiscoveryFollowList == GLOBAL_FOLLOWS val isGlobal = account.defaultDiscoveryFollowList == GLOBAL_FOLLOWS
@@ -37,8 +37,8 @@ class DiscoverFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
val activities = collection val activities = collection
.asSequence() .asSequence()
.filter { it.event is LiveActivitiesEvent } .filter { it.event is LiveActivitiesEvent }
.filter { isGlobal || it.author?.pubkeyHex in followingKeySet } .filter { isGlobal || it.author?.pubkeyHex in followingKeySet || it.event?.isTaggedHashes(followingTagSet) == true }
.filter { account.isAcceptable(it) } .filter { it.author?.let { !account.isHidden(it.pubkeyHex) } ?: true }
.filter { (it.createdAt() ?: 0) <= now } .filter { (it.createdAt() ?: 0) <= now }
.toSet() .toSet()

View File

@@ -0,0 +1,20 @@
package com.vitorpamplona.amethyst.ui.dal
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.OnlineChecker
import com.vitorpamplona.amethyst.service.model.*
import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_LIVE
class DiscoverLiveNowFeedFilter(account: Account) : DiscoverFeedFilter(account) {
override fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
val allItems = super.innerApplyFilter(collection)
val onlineOnly = allItems.filter {
val noteEvent = it.event as? LiveActivitiesEvent
noteEvent?.status() == STATUS_LIVE && OnlineChecker.isOnline(noteEvent.streaming())
}
return onlineOnly.toSet()
}
}

View File

@@ -1,58 +0,0 @@
package com.vitorpamplona.amethyst.ui.dal
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.GLOBAL_FOLLOWS
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.OnlineChecker
import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent
import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent.Companion.STATUS_LIVE
import java.util.Date
class HomeLiveActivitiesFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
override fun feedKey(): String {
val followingKeySet = account.selectedUsersFollowList(account.defaultHomeFollowList)?.size ?: 0
val followingTagSet = account.selectedTagsFollowList(account.defaultHomeFollowList)?.size ?: 0
return account.userProfile().pubkeyHex + "-" + account.defaultHomeFollowList + "-" + followingKeySet + "-" + followingTagSet
}
override fun feed(): List<Note> {
val longFormNotes = innerApplyFilter(LocalCache.addressables.values)
return sort(longFormNotes)
}
override fun applyFilter(collection: Set<Note>): Set<Note> {
return innerApplyFilter(collection)
}
private fun innerApplyFilter(collection: Collection<Note>): Set<Note> {
checkNotInMainThread()
val isGlobal = account.defaultHomeFollowList == GLOBAL_FOLLOWS
val followingKeySet = account.selectedUsersFollowList(account.defaultHomeFollowList) ?: emptySet()
val followingTagSet = account.selectedTagsFollowList(account.defaultHomeFollowList) ?: emptySet()
val twoHrs = (Date().time / 1000) - 60 * 60 * 2 // hrs
return collection
.asSequence()
.filter { it ->
val noteEvent = it.event
(noteEvent is LiveActivitiesEvent && noteEvent.createdAt > twoHrs && noteEvent.status() == STATUS_LIVE && OnlineChecker.isOnline(noteEvent.streaming())) &&
(isGlobal || it.author?.pubkeyHex in followingKeySet || noteEvent.isTaggedHashes(followingTagSet)) &&
// && account.isAcceptable(it) // This filter follows only. No need to check if acceptable
it.author?.let { !account.isHidden(it.pubkeyHex) } ?: true
}
.toSet()
}
override fun limit() = 2
override fun sort(collection: Set<Note>): List<Note> {
return collection.sortedWith(compareBy({ it.createdAt() }, { it.idHex })).reversed()
}
}

View File

@@ -13,7 +13,6 @@ import com.vitorpamplona.amethyst.ui.note.UserReactionsViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListNewFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListNewFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedLiveActivitiesViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel
@@ -40,7 +39,6 @@ import kotlinx.coroutines.launch
fun AppNavigation( fun AppNavigation(
homeFeedViewModel: NostrHomeFeedViewModel, homeFeedViewModel: NostrHomeFeedViewModel,
repliesFeedViewModel: NostrHomeRepliesFeedViewModel, repliesFeedViewModel: NostrHomeRepliesFeedViewModel,
liveActivitiesViewModel: NostrHomeFeedLiveActivitiesViewModel,
knownFeedViewModel: NostrChatroomListKnownFeedViewModel, knownFeedViewModel: NostrChatroomListKnownFeedViewModel,
newFeedViewModel: NostrChatroomListNewFeedViewModel, newFeedViewModel: NostrChatroomListNewFeedViewModel,
videoFeedViewModel: NostrVideoFeedViewModel, videoFeedViewModel: NostrVideoFeedViewModel,
@@ -70,7 +68,6 @@ fun AppNavigation(
HomeScreen( HomeScreen(
homeFeedViewModel = homeFeedViewModel, homeFeedViewModel = homeFeedViewModel,
repliesFeedViewModel = repliesFeedViewModel, repliesFeedViewModel = repliesFeedViewModel,
liveActivitiesViewModel = liveActivitiesViewModel,
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
nav = nav, nav = nav,
nip47 = nip47 nip47 = nip47

View File

@@ -17,6 +17,7 @@ import com.vitorpamplona.amethyst.service.checkNotInMainThread
import com.vitorpamplona.amethyst.service.model.PrivateDmEvent import com.vitorpamplona.amethyst.service.model.PrivateDmEvent
import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter
import com.vitorpamplona.amethyst.ui.dal.ChatroomListKnownFeedFilter import com.vitorpamplona.amethyst.ui.dal.ChatroomListKnownFeedFilter
import com.vitorpamplona.amethyst.ui.dal.DiscoverLiveNowFeedFilter
import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter
import com.vitorpamplona.amethyst.ui.dal.NotificationFeedFilter import com.vitorpamplona.amethyst.ui.dal.NotificationFeedFilter
import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.ImmutableList
@@ -59,7 +60,8 @@ sealed class Route(
object Discover : Route( object Discover : Route(
route = "Discover", route = "Discover",
icon = R.drawable.ic_sensors icon = R.drawable.ic_sensors,
hasNewItems = { accountViewModel, newNotes -> DiscoverLatestItem.hasNewItems(accountViewModel, newNotes) }
) )
object Notification : Route( object Notification : Route(
@@ -186,6 +188,21 @@ object HomeLatestItem : LatestItem() {
} }
} }
object DiscoverLatestItem : LatestItem() {
fun hasNewItems(
account: Account,
newNotes: Set<Note>
): Boolean {
checkNotInMainThread()
val lastTime = account.loadLastRead(Route.Discover.base)
val newestItem = updateNewestItem(newNotes, account, DiscoverLiveNowFeedFilter(account))
return (newestItem?.createdAt() ?: 0) > lastTime
}
}
object NotificationLatestItem : LatestItem() { object NotificationLatestItem : LatestItem() {
fun hasNewItems( fun hasNewItems(
account: Account, account: Account,

View File

@@ -25,7 +25,6 @@ import com.vitorpamplona.amethyst.ui.dal.DiscoverFeedFilter
import com.vitorpamplona.amethyst.ui.dal.FeedFilter import com.vitorpamplona.amethyst.ui.dal.FeedFilter
import com.vitorpamplona.amethyst.ui.dal.HashtagFeedFilter import com.vitorpamplona.amethyst.ui.dal.HashtagFeedFilter
import com.vitorpamplona.amethyst.ui.dal.HomeConversationsFeedFilter import com.vitorpamplona.amethyst.ui.dal.HomeConversationsFeedFilter
import com.vitorpamplona.amethyst.ui.dal.HomeLiveActivitiesFeedFilter
import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter
import com.vitorpamplona.amethyst.ui.dal.ThreadFeedFilter import com.vitorpamplona.amethyst.ui.dal.ThreadFeedFilter
import com.vitorpamplona.amethyst.ui.dal.UserProfileAppRecommendationsFeedFilter import com.vitorpamplona.amethyst.ui.dal.UserProfileAppRecommendationsFeedFilter
@@ -130,15 +129,6 @@ class NostrChatroomListNewFeedViewModel(val account: Account) : FeedViewModel(Ch
} }
} }
@Stable
class NostrHomeFeedLiveActivitiesViewModel(val account: Account) : FeedViewModel(HomeLiveActivitiesFeedFilter(account)) {
class Factory(val account: Account) : ViewModelProvider.Factory {
override fun <NostrHomeFeedLiveActivitiesViewModel : ViewModel> create(modelClass: Class<NostrHomeFeedLiveActivitiesViewModel>): NostrHomeFeedLiveActivitiesViewModel {
return NostrHomeFeedLiveActivitiesViewModel(account) as NostrHomeFeedLiveActivitiesViewModel
}
}
}
@Stable @Stable
class NostrHomeFeedViewModel(val account: Account) : FeedViewModel(HomeNewThreadFeedFilter(account)) { class NostrHomeFeedViewModel(val account: Account) : FeedViewModel(HomeNewThreadFeedFilter(account)) {
class Factory(val account: Account) : ViewModelProvider.Factory { class Factory(val account: Account) : ViewModelProvider.Factory {

View File

@@ -25,6 +25,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.amethyst.service.NostrDiscoveryDataSource import com.vitorpamplona.amethyst.service.NostrDiscoveryDataSource
import com.vitorpamplona.amethyst.ui.navigation.Route
import com.vitorpamplona.amethyst.ui.note.ChannelCardCompose import com.vitorpamplona.amethyst.ui.note.ChannelCardCompose
import com.vitorpamplona.amethyst.ui.screen.FeedEmpty import com.vitorpamplona.amethyst.ui.screen.FeedEmpty
import com.vitorpamplona.amethyst.ui.screen.FeedError import com.vitorpamplona.amethyst.ui.screen.FeedError
@@ -70,7 +71,7 @@ fun DiscoverScreen(
) { ) {
RefresheableView(discoveryFeedViewModel, true) { RefresheableView(discoveryFeedViewModel, true) {
SaveableFeedState(discoveryFeedViewModel, scrollStateKey = ScrollStateKeys.DISCOVER_SCREEN) { listState -> SaveableFeedState(discoveryFeedViewModel, scrollStateKey = ScrollStateKeys.DISCOVER_SCREEN) { listState ->
RenderDiscoverFeed(discoveryFeedViewModel, accountViewModel, listState, nav) RenderDiscoverFeed(discoveryFeedViewModel, Route.Discover.base, accountViewModel, listState, nav)
} }
} }
} }
@@ -80,6 +81,7 @@ fun DiscoverScreen(
@Composable @Composable
private fun RenderDiscoverFeed( private fun RenderDiscoverFeed(
viewModel: FeedViewModel, viewModel: FeedViewModel,
routeForLastRead: String?,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
listState: LazyListState, listState: LazyListState,
nav: (String) -> Unit nav: (String) -> Unit
@@ -106,6 +108,7 @@ private fun RenderDiscoverFeed(
is FeedState.Loaded -> { is FeedState.Loaded -> {
DiscoverFeedLoaded( DiscoverFeedLoaded(
state, state,
routeForLastRead,
listState, listState,
accountViewModel, accountViewModel,
nav nav
@@ -133,6 +136,7 @@ fun WatchAccountForDiscoveryScreen(discoveryViewModel: NostrDiscoverFeedViewMode
@Composable @Composable
private fun DiscoverFeedLoaded( private fun DiscoverFeedLoaded(
state: FeedState.Loaded, state: FeedState.Loaded,
routeForLastRead: String?,
listState: LazyListState, listState: LazyListState,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: (String) -> Unit nav: (String) -> Unit
@@ -150,7 +154,8 @@ private fun DiscoverFeedLoaded(
} }
ChannelCardCompose( ChannelCardCompose(
item, baseNote = item,
routeForLastRead = routeForLastRead,
modifier = defaultModifier, modifier = defaultModifier,
accountViewModel = accountViewModel, accountViewModel = accountViewModel,
nav = nav nav = nav

View File

@@ -1,15 +1,10 @@
package com.vitorpamplona.amethyst.ui.screen.loggedIn package com.vitorpamplona.amethyst.ui.screen.loggedIn
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.core.tween
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.PagerState
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
@@ -20,7 +15,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -33,17 +27,12 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.map
import com.vitorpamplona.amethyst.R import com.vitorpamplona.amethyst.R
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.service.NostrHomeDataSource import com.vitorpamplona.amethyst.service.NostrHomeDataSource
import com.vitorpamplona.amethyst.service.OnlineChecker import com.vitorpamplona.amethyst.service.OnlineChecker
import com.vitorpamplona.amethyst.service.model.LiveActivitiesEvent
import com.vitorpamplona.amethyst.ui.navigation.Route import com.vitorpamplona.amethyst.ui.navigation.Route
import com.vitorpamplona.amethyst.ui.note.UpdateZapAmountDialog import com.vitorpamplona.amethyst.ui.note.UpdateZapAmountDialog
import com.vitorpamplona.amethyst.ui.screen.FeedState
import com.vitorpamplona.amethyst.ui.screen.FeedViewModel import com.vitorpamplona.amethyst.ui.screen.FeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedLiveActivitiesViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.PagerStateKeys import com.vitorpamplona.amethyst.ui.screen.PagerStateKeys
@@ -60,7 +49,6 @@ import kotlinx.coroutines.launch
fun HomeScreen( fun HomeScreen(
homeFeedViewModel: NostrHomeFeedViewModel, homeFeedViewModel: NostrHomeFeedViewModel,
repliesFeedViewModel: NostrHomeRepliesFeedViewModel, repliesFeedViewModel: NostrHomeRepliesFeedViewModel,
liveActivitiesViewModel: NostrHomeFeedLiveActivitiesViewModel,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: (String) -> Unit, nav: (String) -> Unit,
nip47: String? = null nip47: String? = null
@@ -69,7 +57,7 @@ fun HomeScreen(
val pagerState = rememberForeverPagerState(key = PagerStateKeys.HOME_SCREEN) val pagerState = rememberForeverPagerState(key = PagerStateKeys.HOME_SCREEN)
WatchAccountForHomeScreen(homeFeedViewModel, repliesFeedViewModel, liveActivitiesViewModel, accountViewModel) WatchAccountForHomeScreen(homeFeedViewModel, repliesFeedViewModel, accountViewModel)
if (wantsToAddNip47 != null) { if (wantsToAddNip47 != null) {
UpdateZapAmountDialog({ wantsToAddNip47 = null }, wantsToAddNip47, accountViewModel) UpdateZapAmountDialog({ wantsToAddNip47 = null }, wantsToAddNip47, accountViewModel)
@@ -77,8 +65,6 @@ fun HomeScreen(
val lifeCycleOwner = LocalLifecycleOwner.current val lifeCycleOwner = LocalLifecycleOwner.current
DisposableEffect(accountViewModel) { DisposableEffect(accountViewModel) {
liveActivitiesViewModel.invalidateData(true)
val observer = LifecycleEventObserver { _, event -> val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_RESUME) { if (event == Lifecycle.Event.ON_RESUME) {
NostrHomeDataSource.invalidateFilters() NostrHomeDataSource.invalidateFilters()
@@ -104,7 +90,7 @@ fun HomeScreen(
Column( Column(
modifier = Modifier.padding(vertical = 0.dp) modifier = Modifier.padding(vertical = 0.dp)
) { ) {
HomePages(pagerState, tabs, liveActivitiesViewModel, accountViewModel, nav) HomePages(pagerState, tabs, accountViewModel, nav)
} }
} }
} }
@@ -114,7 +100,6 @@ fun HomeScreen(
private fun HomePages( private fun HomePages(
pagerState: PagerState, pagerState: PagerState,
tabs: ImmutableList<TabItem>, tabs: ImmutableList<TabItem>,
liveActivitiesViewModel: NostrHomeFeedLiveActivitiesViewModel,
accountViewModel: AccountViewModel, accountViewModel: AccountViewModel,
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
@@ -137,12 +122,6 @@ private fun HomePages(
} }
} }
LiveActivities(
liveActivitiesViewModel = liveActivitiesViewModel,
accountViewModel = accountViewModel,
nav = nav
)
HorizontalPager(pageCount = 2, state = pagerState) { page -> HorizontalPager(pageCount = 2, state = pagerState) { page ->
RefresheableFeedView( RefresheableFeedView(
viewModel = tabs[page].viewModel, viewModel = tabs[page].viewModel,
@@ -154,73 +133,6 @@ private fun HomePages(
} }
} }
@Composable
fun LiveActivities(
liveActivitiesViewModel: NostrHomeFeedLiveActivitiesViewModel,
accountViewModel: AccountViewModel,
nav: (String) -> Unit
) {
val feedState by liveActivitiesViewModel.feedContent.collectAsState()
Crossfade(
targetState = feedState,
animationSpec = tween(durationMillis = 100)
) { state ->
when (state) {
is FeedState.Loaded -> {
FeedLoaded(
state,
accountViewModel,
nav
)
}
else -> {
}
}
}
}
@Composable
private fun FeedLoaded(
state: FeedState.Loaded,
accountViewModel: AccountViewModel,
nav: (String) -> Unit
) {
val listState = rememberLazyListState()
LazyColumn(
contentPadding = PaddingValues(),
state = listState
) {
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
CheckIfLiveActivityIsOnline(item) {
ChannelHeader(
channelHex = remember { item.idHex },
showVideo = false,
showBottomDiviser = true,
modifier = remember {
Modifier.padding(start = 10.dp, end = 10.dp, top = 5.dp, bottom = 5.dp)
},
accountViewModel = accountViewModel,
nav = nav
)
}
}
}
}
@Composable
fun CheckIfLiveActivityIsOnline(note: Note, whenOnline: @Composable () -> Unit) {
val url by note.live().metadata.map {
(note.event as? LiveActivitiesEvent)?.streaming()
}.observeAsState()
url?.let {
CheckIfUrlIsOnline(it, whenOnline)
}
}
@Composable @Composable
fun CheckIfUrlIsOnline(url: String, whenOnline: @Composable () -> Unit) { fun CheckIfUrlIsOnline(url: String, whenOnline: @Composable () -> Unit) {
var online by remember { mutableStateOf(false) } var online by remember { mutableStateOf(false) }
@@ -242,7 +154,6 @@ fun CheckIfUrlIsOnline(url: String, whenOnline: @Composable () -> Unit) {
fun WatchAccountForHomeScreen( fun WatchAccountForHomeScreen(
homeFeedViewModel: NostrHomeFeedViewModel, homeFeedViewModel: NostrHomeFeedViewModel,
repliesFeedViewModel: NostrHomeRepliesFeedViewModel, repliesFeedViewModel: NostrHomeRepliesFeedViewModel,
liveActivitiesViewModel: NostrHomeFeedLiveActivitiesViewModel,
accountViewModel: AccountViewModel accountViewModel: AccountViewModel
) { ) {
val accountState by accountViewModel.accountLiveData.observeAsState() val accountState by accountViewModel.accountLiveData.observeAsState()
@@ -253,7 +164,6 @@ fun WatchAccountForHomeScreen(
NostrHomeDataSource.invalidateFilters() NostrHomeDataSource.invalidateFilters()
homeFeedViewModel.checkKeysInvalidateDataAndSendToTop() homeFeedViewModel.checkKeysInvalidateDataAndSendToTop()
repliesFeedViewModel.checkKeysInvalidateDataAndSendToTop() repliesFeedViewModel.checkKeysInvalidateDataAndSendToTop()
liveActivitiesViewModel.checkKeysInvalidateDataAndSendToTop()
} }
} }
} }

View File

@@ -44,7 +44,6 @@ import com.vitorpamplona.amethyst.ui.screen.AccountStateViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListNewFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListNewFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedLiveActivitiesViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel
import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel
@@ -89,11 +88,6 @@ fun MainScreen(accountViewModel: AccountViewModel, accountStateViewModel: Accoun
factory = NostrHomeRepliesFeedViewModel.Factory(accountViewModel.account) factory = NostrHomeRepliesFeedViewModel.Factory(accountViewModel.account)
) )
val liveActivitiesViewModel: NostrHomeFeedLiveActivitiesViewModel = viewModel(
key = accountViewModel.userProfile().pubkeyHex + "NostrHomeLiveActivitiesFeedViewModel",
factory = NostrHomeFeedLiveActivitiesViewModel.Factory(accountViewModel.account)
)
val videoFeedViewModel: NostrVideoFeedViewModel = viewModel( val videoFeedViewModel: NostrVideoFeedViewModel = viewModel(
key = accountViewModel.userProfile().pubkeyHex + "NostrVideoFeedViewModel", key = accountViewModel.userProfile().pubkeyHex + "NostrVideoFeedViewModel",
factory = NostrVideoFeedViewModel.Factory(accountViewModel.account) factory = NostrVideoFeedViewModel.Factory(accountViewModel.account)
@@ -187,18 +181,17 @@ fun MainScreen(accountViewModel: AccountViewModel, accountStateViewModel: Accoun
) { ) {
Column(modifier = Modifier.padding(bottom = it.calculateBottomPadding())) { Column(modifier = Modifier.padding(bottom = it.calculateBottomPadding())) {
AppNavigation( AppNavigation(
homeFeedViewModel, homeFeedViewModel = homeFeedViewModel,
repliesFeedViewModel, repliesFeedViewModel = repliesFeedViewModel,
liveActivitiesViewModel, knownFeedViewModel = knownFeedViewModel,
knownFeedViewModel, newFeedViewModel = newFeedViewModel,
newFeedViewModel, videoFeedViewModel = videoFeedViewModel,
videoFeedViewModel, discoveryFeedViewModel = discoveryFeedViewModel,
discoveryFeedViewModel, notifFeedViewModel = notifFeedViewModel,
notifFeedViewModel, userReactionsStatsModel = userReactionsStatsModel,
userReactionsStatsModel, navController = navController,
navController, accountViewModel = accountViewModel,
accountViewModel, nextPage = startingPage
startingPage
) )
} }
} }