- Redesign feed invalidations to account for changes in the follow list
- Redesign scroll to the top implementation to avoid using arguments in the navigator.
This commit is contained in:
@@ -7,6 +7,10 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
object BookmarkPrivateFeedFilter : FeedFilter<Note>() {
|
object BookmarkPrivateFeedFilter : FeedFilter<Note>() {
|
||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().latestBookmarkList?.id ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val privKey = account.loggedIn.privKey ?: return emptyList()
|
val privKey = account.loggedIn.privKey ?: return emptyList()
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
object BookmarkPublicFeedFilter : FeedFilter<Note>() {
|
object BookmarkPublicFeedFilter : FeedFilter<Note>() {
|
||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return BookmarkPrivateFeedFilter.account.userProfile().latestBookmarkList?.id ?: ""
|
||||||
|
}
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val bookmarks = account.userProfile().latestBookmarkList
|
val bookmarks = account.userProfile().latestBookmarkList
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ import com.vitorpamplona.amethyst.model.Channel
|
|||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
|
||||||
class ChannelFeedFilter(val channel: Channel, val account: Account) : AdditiveFeedFilter<Note>() {
|
class ChannelFeedFilter(val channel: Channel, val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return channel.idHex
|
||||||
|
}
|
||||||
|
|
||||||
// returns the last Note of each user.
|
// returns the last Note of each user.
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
return channel.notes
|
return channel.notes
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ import com.vitorpamplona.amethyst.model.User
|
|||||||
|
|
||||||
class ChatroomFeedFilter(val withUser: User, val account: Account) : AdditiveFeedFilter<Note>() {
|
class ChatroomFeedFilter(val withUser: User, val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
// returns the last Note of each user.
|
// returns the last Note of each user.
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return withUser.pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val messages = account
|
val messages = account
|
||||||
.userProfile()
|
.userProfile()
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ import kotlin.time.measureTimedValue
|
|||||||
|
|
||||||
class ChatroomListKnownFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
class ChatroomListKnownFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
// returns the last Note of each user.
|
// returns the last Note of each user.
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val me = account.userProfile()
|
val me = account.userProfile()
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ import kotlin.time.measureTimedValue
|
|||||||
|
|
||||||
class ChatroomListNewFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
class ChatroomListNewFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
// returns the last Note of each user.
|
// returns the last Note of each user.
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val me = account.userProfile()
|
val me = account.userProfile()
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ abstract class FeedFilter<T> {
|
|||||||
return feed.take(1000)
|
return feed.take(1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string that serves as the key to invalidate the list if it changes.
|
||||||
|
*/
|
||||||
|
abstract fun feedKey(): String
|
||||||
|
|
||||||
abstract fun feed(): List<T>
|
abstract fun feed(): List<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import com.vitorpamplona.amethyst.service.model.*
|
|||||||
|
|
||||||
class GlobalFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
class GlobalFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val notes = innerApplyFilter(LocalCache.notes.values)
|
val notes = innerApplyFilter(LocalCache.notes.values)
|
||||||
val longFormNotes = innerApplyFilter(LocalCache.addressables.values)
|
val longFormNotes = innerApplyFilter(LocalCache.addressables.values)
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ object HashtagFeedFilter : AdditiveFeedFilter<Note>() {
|
|||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
var tag: String? = null
|
var tag: String? = null
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + tag
|
||||||
|
}
|
||||||
|
|
||||||
fun loadHashtag(account: Account, tag: String?) {
|
fun loadHashtag(account: Account, tag: String?) {
|
||||||
this.account = account
|
this.account = account
|
||||||
this.tag = tag
|
this.tag = tag
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import com.vitorpamplona.amethyst.model.LocalCache
|
|||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
|
|
||||||
class HiddenAccountsFeedFilter(val account: Account) : FeedFilter<User>() {
|
class HiddenAccountsFeedFilter(val account: Account) : FeedFilter<User>() {
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + HashtagFeedFilter.tag
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
return (account.hiddenUsers + account.transientHiddenUsers)
|
return (account.hiddenUsers + account.transientHiddenUsers)
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ import com.vitorpamplona.amethyst.service.model.PollNoteEvent
|
|||||||
import com.vitorpamplona.amethyst.service.model.TextNoteEvent
|
import com.vitorpamplona.amethyst.service.model.TextNoteEvent
|
||||||
|
|
||||||
class HomeConversationsFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
class HomeConversationsFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + account.defaultHomeFollowList
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
return sort(innerApplyFilter(LocalCache.notes.values))
|
return sort(innerApplyFilter(LocalCache.notes.values))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ import com.vitorpamplona.amethyst.service.model.RepostEvent
|
|||||||
import com.vitorpamplona.amethyst.service.model.TextNoteEvent
|
import com.vitorpamplona.amethyst.service.model.TextNoteEvent
|
||||||
|
|
||||||
class HomeNewThreadFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
class HomeNewThreadFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + account.defaultHomeFollowList
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val notes = innerApplyFilter(LocalCache.notes.values)
|
val notes = innerApplyFilter(LocalCache.notes.values)
|
||||||
val longFormNotes = innerApplyFilter(LocalCache.addressables.values)
|
val longFormNotes = innerApplyFilter(LocalCache.addressables.values)
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
import com.vitorpamplona.amethyst.service.model.*
|
import com.vitorpamplona.amethyst.service.model.*
|
||||||
|
|
||||||
class NotificationFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
class NotificationFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + account.defaultNotificationFollowList
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
return sort(innerApplyFilter(LocalCache.notes.values))
|
return sort(innerApplyFilter(LocalCache.notes.values))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import com.vitorpamplona.amethyst.service.model.PeopleListEvent
|
|||||||
object PeopleListFeedFilter : FeedFilter<Note>() {
|
object PeopleListFeedFilter : FeedFilter<Note>() {
|
||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val privKey = account.loggedIn.privKey ?: return emptyList()
|
val privKey = account.loggedIn.privKey ?: return emptyList()
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import com.vitorpamplona.amethyst.model.ThreadAssembler
|
|||||||
@Immutable
|
@Immutable
|
||||||
class ThreadFeedFilter(val noteId: String) : FeedFilter<Note>() {
|
class ThreadFeedFilter(val noteId: String) : FeedFilter<Note>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return noteId
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val cachedSignatures: MutableMap<Note, String> = mutableMapOf()
|
val cachedSignatures: MutableMap<Note, String> = mutableMapOf()
|
||||||
val eventsToWatch = ThreadAssembler().findThreadFor(noteId) ?: emptySet()
|
val eventsToWatch = ThreadAssembler().findThreadFor(noteId) ?: emptySet()
|
||||||
|
|||||||
+4
@@ -6,6 +6,10 @@ import com.vitorpamplona.amethyst.model.User
|
|||||||
import com.vitorpamplona.amethyst.service.model.AppRecommendationEvent
|
import com.vitorpamplona.amethyst.service.model.AppRecommendationEvent
|
||||||
|
|
||||||
class UserProfileAppRecommendationsFeedFilter(val user: User) : FeedFilter<Note>() {
|
class UserProfileAppRecommendationsFeedFilter(val user: User) : FeedFilter<Note>() {
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return user.pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val recommendations = LocalCache.addressables.values.filter {
|
val recommendations = LocalCache.addressables.values.filter {
|
||||||
(it.event as? AppRecommendationEvent)?.pubKey == user.pubkeyHex
|
(it.event as? AppRecommendationEvent)?.pubKey == user.pubkeyHex
|
||||||
|
|||||||
@@ -9,6 +9,10 @@ object UserProfileBookmarksFeedFilter : FeedFilter<Note>() {
|
|||||||
lateinit var account: Account
|
lateinit var account: Account
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + user?.pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
this.user = user
|
this.user = user
|
||||||
|
|||||||
+4
@@ -8,6 +8,10 @@ object UserProfileConversationsFeedFilter : FeedFilter<Note>() {
|
|||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account?.userProfile()?.pubkeyHex + "-" + user?.pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User?) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
this.user = user
|
this.user = user
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ import com.vitorpamplona.amethyst.model.User
|
|||||||
|
|
||||||
class UserProfileFollowersFeedFilter(val user: User, val account: Account) : FeedFilter<User>() {
|
class UserProfileFollowersFeedFilter(val user: User, val account: Account) : FeedFilter<User>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + user.pubkeyHex
|
||||||
|
}
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
return LocalCache.users.values.filter { it.isFollowing(user) && !account.isHidden(it) }
|
return LocalCache.users.values.filter { it.isFollowing(user) && !account.isHidden(it) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import com.vitorpamplona.amethyst.service.model.ContactListEvent
|
|||||||
|
|
||||||
class UserProfileFollowsFeedFilter(val user: User, val account: Account) : FeedFilter<User>() {
|
class UserProfileFollowsFeedFilter(val user: User, val account: Account) : FeedFilter<User>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile()?.pubkeyHex + "-" + user.pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
val cache: MutableMap<ContactListEvent, List<User>> = mutableMapOf()
|
val cache: MutableMap<ContactListEvent, List<User>> = mutableMapOf()
|
||||||
|
|
||||||
override fun feed(): List<User> {
|
override fun feed(): List<User> {
|
||||||
|
|||||||
@@ -12,6 +12,10 @@ object UserProfileNewThreadFeedFilter : FeedFilter<Note>() {
|
|||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account?.userProfile()?.pubkeyHex + "-" + user?.pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
fun loadUserProfile(accountLoggedIn: Account, user: User) {
|
fun loadUserProfile(accountLoggedIn: Account, user: User) {
|
||||||
account = accountLoggedIn
|
account = accountLoggedIn
|
||||||
this.user = user
|
this.user = user
|
||||||
|
|||||||
@@ -8,6 +8,10 @@ import com.vitorpamplona.amethyst.service.model.ReportEvent
|
|||||||
object UserProfileReportsFeedFilter : FeedFilter<Note>() {
|
object UserProfileReportsFeedFilter : FeedFilter<Note>() {
|
||||||
var user: User? = null
|
var user: User? = null
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return user?.pubkeyHex ?: ""
|
||||||
|
}
|
||||||
|
|
||||||
fun loadUserProfile(user: User?) {
|
fun loadUserProfile(user: User?) {
|
||||||
this.user = user
|
this.user = user
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ import com.vitorpamplona.amethyst.service.model.zaps.UserZaps
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.ZapReqResponse
|
import com.vitorpamplona.amethyst.ui.screen.ZapReqResponse
|
||||||
|
|
||||||
class UserProfileZapsFeedFilter(val user: User) : FeedFilter<ZapReqResponse>() {
|
class UserProfileZapsFeedFilter(val user: User) : FeedFilter<ZapReqResponse>() {
|
||||||
|
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return user.pubkeyHex
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<ZapReqResponse> {
|
override fun feed(): List<ZapReqResponse> {
|
||||||
return UserZaps.forProfileFeed(user.zaps)
|
return UserZaps.forProfileFeed(user.zaps)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,10 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
import com.vitorpamplona.amethyst.service.model.*
|
import com.vitorpamplona.amethyst.service.model.*
|
||||||
|
|
||||||
class VideoFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
class VideoFeedFilter(val account: Account) : AdditiveFeedFilter<Note>() {
|
||||||
|
override fun feedKey(): String {
|
||||||
|
return account.userProfile().pubkeyHex + "-" + account.defaultStoriesFollowList
|
||||||
|
}
|
||||||
|
|
||||||
override fun feed(): List<Note> {
|
override fun feed(): List<Note> {
|
||||||
val notes = innerApplyFilter(LocalCache.notes.values)
|
val notes = innerApplyFilter(LocalCache.notes.values)
|
||||||
|
|
||||||
|
|||||||
@@ -60,51 +60,10 @@ fun AppNavigation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
NavHost(navController, startDestination = Route.Home.route) {
|
NavHost(navController, startDestination = Route.Home.route) {
|
||||||
Route.Video.let { route ->
|
|
||||||
composable(route.route, route.arguments, content = {
|
|
||||||
val scrollToTop = it.arguments?.getBoolean("scrollToTop") ?: false
|
|
||||||
|
|
||||||
if (scrollToTop) {
|
|
||||||
videoFeedViewModel.sendToTop()
|
|
||||||
it.arguments?.remove("scrollToTop")
|
|
||||||
}
|
|
||||||
|
|
||||||
VideoScreen(
|
|
||||||
videoFeedView = videoFeedViewModel,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Route.Search.let { route ->
|
|
||||||
composable(route.route, route.arguments, content = {
|
|
||||||
val scrollToTop = it.arguments?.getBoolean("scrollToTop") ?: false
|
|
||||||
|
|
||||||
if (scrollToTop) {
|
|
||||||
searchFeedViewModel.sendToTop()
|
|
||||||
it.arguments?.remove("scrollToTop")
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchScreen(
|
|
||||||
searchFeedViewModel = searchFeedViewModel,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Route.Home.let { route ->
|
Route.Home.let { route ->
|
||||||
composable(route.route, route.arguments, content = { it ->
|
composable(route.route, route.arguments, content = { it ->
|
||||||
val scrollToTop = it.arguments?.getBoolean("scrollToTop") ?: false
|
|
||||||
val nip47 = it.arguments?.getString("nip47")
|
val nip47 = it.arguments?.getString("nip47")
|
||||||
|
|
||||||
if (scrollToTop) {
|
|
||||||
homeFeedViewModel.sendToTop()
|
|
||||||
repliesFeedViewModel.sendToTop()
|
|
||||||
it.arguments?.remove("scrollToTop")
|
|
||||||
}
|
|
||||||
|
|
||||||
HomeScreen(
|
HomeScreen(
|
||||||
homeFeedViewModel = homeFeedViewModel,
|
homeFeedViewModel = homeFeedViewModel,
|
||||||
repliesFeedViewModel = repliesFeedViewModel,
|
repliesFeedViewModel = repliesFeedViewModel,
|
||||||
@@ -124,25 +83,6 @@ fun AppNavigation(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
Route.Notification.let { route ->
|
|
||||||
composable(route.route, route.arguments, content = {
|
|
||||||
val scrollToTop = it.arguments?.getBoolean("scrollToTop") ?: false
|
|
||||||
|
|
||||||
if (scrollToTop) {
|
|
||||||
notifFeedViewModel.clear()
|
|
||||||
notifFeedViewModel.invalidateDataAndSendToTop()
|
|
||||||
it.arguments?.remove("scrollToTop")
|
|
||||||
}
|
|
||||||
|
|
||||||
NotificationScreen(
|
|
||||||
notifFeedViewModel = notifFeedViewModel,
|
|
||||||
userReactionsStatsModel = userReactionsStatsModel,
|
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
composable(
|
composable(
|
||||||
Route.Message.route,
|
Route.Message.route,
|
||||||
content = {
|
content = {
|
||||||
@@ -155,6 +95,37 @@ fun AppNavigation(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Route.Video.let { route ->
|
||||||
|
composable(route.route, route.arguments, content = {
|
||||||
|
VideoScreen(
|
||||||
|
videoFeedView = videoFeedViewModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Route.Search.let { route ->
|
||||||
|
composable(route.route, route.arguments, content = {
|
||||||
|
SearchScreen(
|
||||||
|
searchFeedViewModel = searchFeedViewModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Route.Notification.let { route ->
|
||||||
|
composable(route.route, route.arguments, content = {
|
||||||
|
NotificationScreen(
|
||||||
|
notifFeedViewModel = notifFeedViewModel,
|
||||||
|
userReactionsStatsModel = userReactionsStatsModel,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
composable(Route.BlockedUsers.route, content = { HiddenUsersScreen(accountViewModel, nav) })
|
composable(Route.BlockedUsers.route, content = { HiddenUsersScreen(accountViewModel, nav) })
|
||||||
composable(Route.Bookmarks.route, content = { BookmarkListScreen(accountViewModel, nav) })
|
composable(Route.Bookmarks.route, content = { BookmarkListScreen(accountViewModel, nav) })
|
||||||
|
|
||||||
|
|||||||
@@ -33,31 +33,27 @@ sealed class Route(
|
|||||||
get() = route.substringBefore("?")
|
get() = route.substringBefore("?")
|
||||||
|
|
||||||
object Home : Route(
|
object Home : Route(
|
||||||
route = "Home?scrollToTop={scrollToTop}&nip47={nip47}",
|
route = "Home?nip47={nip47}",
|
||||||
icon = R.drawable.ic_home,
|
icon = R.drawable.ic_home,
|
||||||
arguments = listOf(
|
arguments = listOf(
|
||||||
navArgument("scrollToTop") { type = NavType.BoolType; defaultValue = false },
|
|
||||||
navArgument("nip47") { type = NavType.StringType; nullable = true; defaultValue = null }
|
navArgument("nip47") { type = NavType.StringType; nullable = true; defaultValue = null }
|
||||||
).toImmutableList(),
|
).toImmutableList(),
|
||||||
hasNewItems = { accountViewModel, newNotes -> HomeLatestItem.hasNewItems(accountViewModel, newNotes) }
|
hasNewItems = { accountViewModel, newNotes -> HomeLatestItem.hasNewItems(accountViewModel, newNotes) }
|
||||||
)
|
)
|
||||||
|
|
||||||
object Search : Route(
|
object Search : Route(
|
||||||
route = "Search?scrollToTop={scrollToTop}",
|
route = "Search",
|
||||||
icon = R.drawable.ic_globe,
|
icon = R.drawable.ic_globe
|
||||||
arguments = listOf(navArgument("scrollToTop") { type = NavType.BoolType; defaultValue = false }).toImmutableList()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
object Video : Route(
|
object Video : Route(
|
||||||
route = "Video?scrollToTop={scrollToTop}",
|
route = "Video",
|
||||||
icon = R.drawable.ic_video,
|
icon = R.drawable.ic_video
|
||||||
arguments = listOf(navArgument("scrollToTop") { type = NavType.BoolType; defaultValue = false }).toImmutableList()
|
|
||||||
)
|
)
|
||||||
|
|
||||||
object Notification : Route(
|
object Notification : Route(
|
||||||
route = "Notification?scrollToTop={scrollToTop}",
|
route = "Notification",
|
||||||
icon = R.drawable.ic_notifications,
|
icon = R.drawable.ic_notifications,
|
||||||
arguments = listOf(navArgument("scrollToTop") { type = NavType.BoolType; defaultValue = false }).toImmutableList(),
|
|
||||||
hasNewItems = { accountViewModel, newNotes -> NotificationLatestItem.hasNewItems(accountViewModel, newNotes) }
|
hasNewItems = { accountViewModel, newNotes -> NotificationLatestItem.hasNewItems(accountViewModel, newNotes) }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
|||||||
val scrollToTop = _scrollToTop.asStateFlow()
|
val scrollToTop = _scrollToTop.asStateFlow()
|
||||||
var scrolltoTopPending = false
|
var scrolltoTopPending = false
|
||||||
|
|
||||||
|
private var lastFeedKey: String? = null
|
||||||
|
|
||||||
fun sendToTop() {
|
fun sendToTop() {
|
||||||
if (scrolltoTopPending) return
|
if (scrolltoTopPending) return
|
||||||
|
|
||||||
@@ -84,6 +86,7 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
|||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
val notes = localFilter.feed()
|
val notes = localFilter.feed()
|
||||||
|
lastFeedKey = localFilter.feedKey()
|
||||||
|
|
||||||
val thisAccount = (localFilter as? NotificationFeedFilter)?.account
|
val thisAccount = (localFilter as? NotificationFeedFilter)?.account
|
||||||
val lastNotesCopy = if (thisAccount == lastAccount) lastNotes else null
|
val lastNotesCopy = if (thisAccount == lastAccount) lastNotes else null
|
||||||
@@ -233,6 +236,8 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
|||||||
val lastNotesCopy = if (thisAccount == lastAccount) lastNotes else null
|
val lastNotesCopy = if (thisAccount == lastAccount) lastNotes else null
|
||||||
|
|
||||||
if (lastNotesCopy != null && localFilter is AdditiveFeedFilter && oldNotesState is CardFeedState.Loaded) {
|
if (lastNotesCopy != null && localFilter is AdditiveFeedFilter && oldNotesState is CardFeedState.Loaded) {
|
||||||
|
lastFeedKey = localFilter.feedKey()
|
||||||
|
|
||||||
val filteredNewList = localFilter.applyFilter(newItems)
|
val filteredNewList = localFilter.applyFilter(newItems)
|
||||||
|
|
||||||
if (filteredNewList.isEmpty()) return
|
if (filteredNewList.isEmpty()) return
|
||||||
@@ -279,15 +284,18 @@ open class CardFeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalTime::class)
|
@OptIn(ExperimentalTime::class)
|
||||||
fun invalidateDataAndSendToTop(ignoreIfDoing: Boolean = false) {
|
fun checkKeysInvalidateDataAndSendToTop() {
|
||||||
bundler.invalidate(ignoreIfDoing) {
|
if (lastFeedKey != localFilter.feedKey()) {
|
||||||
// adds the time to perform the refresh into this delay
|
clear()
|
||||||
// holding off new updates in case of heavy refresh routines.
|
bundler.invalidate(false) {
|
||||||
val (value, elapsed) = measureTimedValue {
|
// adds the time to perform the refresh into this delay
|
||||||
refreshSuspended()
|
// holding off new updates in case of heavy refresh routines.
|
||||||
sendToTop()
|
val (value, elapsed) = measureTimedValue {
|
||||||
|
refreshSuspended()
|
||||||
|
sendToTop()
|
||||||
|
}
|
||||||
|
Log.d("Time", "${this.javaClass.simpleName} Card update $elapsed")
|
||||||
}
|
}
|
||||||
Log.d("Time", "${this.javaClass.simpleName} Card update $elapsed")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,14 +40,13 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
|||||||
fun RefresheableFeedView(
|
fun RefresheableFeedView(
|
||||||
viewModel: FeedViewModel,
|
viewModel: FeedViewModel,
|
||||||
routeForLastRead: String?,
|
routeForLastRead: String?,
|
||||||
accountViewModel: AccountViewModel,
|
enablePullRefresh: Boolean = true,
|
||||||
nav: (String) -> Unit,
|
|
||||||
|
|
||||||
scrollStateKey: String? = null,
|
scrollStateKey: String? = null,
|
||||||
enablePullRefresh: Boolean = true
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
RefresheableView(viewModel, enablePullRefresh) {
|
RefresheableView(viewModel, enablePullRefresh) {
|
||||||
SaveableFeedState(viewModel, accountViewModel, nav, routeForLastRead, scrollStateKey)
|
SaveableFeedState(viewModel, routeForLastRead, scrollStateKey, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,10 +81,10 @@ fun RefresheableView(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun SaveableFeedState(
|
private fun SaveableFeedState(
|
||||||
viewModel: FeedViewModel,
|
viewModel: FeedViewModel,
|
||||||
accountViewModel: AccountViewModel,
|
|
||||||
nav: (String) -> Unit,
|
|
||||||
routeForLastRead: String?,
|
routeForLastRead: String?,
|
||||||
scrollStateKey: String? = null
|
scrollStateKey: String? = null,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
nav: (String) -> Unit
|
||||||
) {
|
) {
|
||||||
SaveableFeedState(viewModel, scrollStateKey) { listState ->
|
SaveableFeedState(viewModel, scrollStateKey) { listState ->
|
||||||
RenderFeed(viewModel, accountViewModel, listState, nav, routeForLastRead)
|
RenderFeed(viewModel, accountViewModel, listState, nav, routeForLastRead)
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel(), I
|
|||||||
val scrollToTop = _scrollToTop.asStateFlow()
|
val scrollToTop = _scrollToTop.asStateFlow()
|
||||||
var scrolltoTopPending = false
|
var scrolltoTopPending = false
|
||||||
|
|
||||||
|
private var lastFeedKey: String? = null
|
||||||
|
|
||||||
fun sendToTop() {
|
fun sendToTop() {
|
||||||
if (scrolltoTopPending) return
|
if (scrolltoTopPending) return
|
||||||
|
|
||||||
@@ -151,10 +153,6 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel(), I
|
|||||||
scrolltoTopPending = false
|
scrolltoTopPending = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun newListFromDataSource(): ImmutableList<Note> {
|
|
||||||
return localFilter.loadTop().toImmutableList()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun refresh() {
|
private fun refresh() {
|
||||||
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
val scope = CoroutineScope(Job() + Dispatchers.Default)
|
||||||
scope.launch {
|
scope.launch {
|
||||||
@@ -165,7 +163,8 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel(), I
|
|||||||
fun refreshSuspended() {
|
fun refreshSuspended() {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
val notes = newListFromDataSource()
|
val notes = localFilter.loadTop().toImmutableList()
|
||||||
|
lastFeedKey = localFilter.feedKey()
|
||||||
|
|
||||||
val oldNotesState = _feedContent.value
|
val oldNotesState = _feedContent.value
|
||||||
if (oldNotesState is FeedState.Loaded) {
|
if (oldNotesState is FeedState.Loaded) {
|
||||||
@@ -197,11 +196,13 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel(), I
|
|||||||
if (localFilter is AdditiveFeedFilter) {
|
if (localFilter is AdditiveFeedFilter) {
|
||||||
if (oldNotesState is FeedState.Loaded) {
|
if (oldNotesState is FeedState.Loaded) {
|
||||||
val newList = localFilter.updateListWith(oldNotesState.feed.value, newItems.toSet()).toImmutableList()
|
val newList = localFilter.updateListWith(oldNotesState.feed.value, newItems.toSet()).toImmutableList()
|
||||||
|
lastFeedKey = localFilter.feedKey()
|
||||||
if (!equalImmutableLists(newList, oldNotesState.feed.value)) {
|
if (!equalImmutableLists(newList, oldNotesState.feed.value)) {
|
||||||
updateFeed(newList)
|
updateFeed(newList)
|
||||||
}
|
}
|
||||||
} else if (oldNotesState is FeedState.Empty) {
|
} else if (oldNotesState is FeedState.Empty) {
|
||||||
val newList = localFilter.updateListWith(emptyList(), newItems.toSet()).toImmutableList()
|
val newList = localFilter.updateListWith(emptyList(), newItems.toSet()).toImmutableList()
|
||||||
|
lastFeedKey = localFilter.feedKey()
|
||||||
if (newList.isNotEmpty()) {
|
if (newList.isNotEmpty()) {
|
||||||
updateFeed(newList)
|
updateFeed(newList)
|
||||||
}
|
}
|
||||||
@@ -226,12 +227,14 @@ abstract class FeedViewModel(val localFilter: FeedFilter<Note>) : ViewModel(), I
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun invalidateDataAndSendToTop(ignoreIfDoing: Boolean = false) {
|
fun checkKeysInvalidateDataAndSendToTop() {
|
||||||
bundler.invalidate(ignoreIfDoing) {
|
if (lastFeedKey != localFilter.feedKey()) {
|
||||||
// adds the time to perform the refresh into this delay
|
bundler.invalidate(false) {
|
||||||
// holding off new updates in case of heavy refresh routines.
|
// adds the time to perform the refresh into this delay
|
||||||
refreshSuspended()
|
// holding off new updates in case of heavy refresh routines.
|
||||||
sendToTop()
|
refreshSuspended()
|
||||||
|
sendToTop()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+12
-2
@@ -73,8 +73,18 @@ fun BookmarkListScreen(accountViewModel: AccountViewModel, nav: (String) -> Unit
|
|||||||
}
|
}
|
||||||
HorizontalPager(pageCount = 2, state = pagerState) { page ->
|
HorizontalPager(pageCount = 2, state = pagerState) { page ->
|
||||||
when (page) {
|
when (page) {
|
||||||
0 -> RefresheableFeedView(privateFeedViewModel, null, accountViewModel, nav)
|
0 -> RefresheableFeedView(
|
||||||
1 -> RefresheableFeedView(publicFeedViewModel, null, accountViewModel, nav)
|
privateFeedViewModel,
|
||||||
|
null,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
|
1 -> RefresheableFeedView(
|
||||||
|
publicFeedViewModel,
|
||||||
|
null,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,12 @@ fun HashtagScreen(tag: String?, accountViewModel: AccountViewModel, nav: (String
|
|||||||
modifier = Modifier.padding(vertical = 0.dp)
|
modifier = Modifier.padding(vertical = 0.dp)
|
||||||
) {
|
) {
|
||||||
HashtagHeader(tag, accountViewModel)
|
HashtagHeader(tag, accountViewModel)
|
||||||
RefresheableFeedView(feedViewModel, null, accountViewModel, nav)
|
RefresheableFeedView(
|
||||||
|
feedViewModel,
|
||||||
|
null,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,10 +123,10 @@ private fun HomePages(
|
|||||||
HorizontalPager(pageCount = 2, state = pagerState) { page ->
|
HorizontalPager(pageCount = 2, state = pagerState) { page ->
|
||||||
RefresheableFeedView(
|
RefresheableFeedView(
|
||||||
viewModel = tabs[page].viewModel,
|
viewModel = tabs[page].viewModel,
|
||||||
accountViewModel = accountViewModel,
|
|
||||||
nav = nav,
|
|
||||||
routeForLastRead = tabs[page].routeForLastRead,
|
routeForLastRead = tabs[page].routeForLastRead,
|
||||||
scrollStateKey = tabs[page].scrollStateKey
|
scrollStateKey = tabs[page].scrollStateKey,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -143,16 +143,14 @@ fun WatchAccountForHomeScreen(
|
|||||||
LaunchedEffect(accountViewModel, accountState?.account?.defaultHomeFollowList) {
|
LaunchedEffect(accountViewModel, accountState?.account?.defaultHomeFollowList) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
NostrHomeDataSource.invalidateFilters()
|
NostrHomeDataSource.invalidateFilters()
|
||||||
homeFeedViewModel.invalidateDataAndSendToTop(true)
|
homeFeedViewModel.checkKeysInvalidateDataAndSendToTop()
|
||||||
repliesFeedViewModel.invalidateDataAndSendToTop(true)
|
repliesFeedViewModel.checkKeysInvalidateDataAndSendToTop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(followState) {
|
LaunchedEffect(followState) {
|
||||||
launch(Dispatchers.IO) {
|
launch(Dispatchers.IO) {
|
||||||
NostrHomeDataSource.invalidateFilters()
|
NostrHomeDataSource.invalidateFilters()
|
||||||
homeFeedViewModel.invalidateData(true)
|
|
||||||
repliesFeedViewModel.invalidateData(true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,23 +73,6 @@ fun MainScreen(accountViewModel: AccountViewModel, accountStateViewModel: Accoun
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val navBottomRow = remember(navController) {
|
|
||||||
{ route: Route, selected: Boolean ->
|
|
||||||
if (!selected) {
|
|
||||||
navController.navigate(route.base) {
|
|
||||||
popUpTo(Route.Home.route)
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val newRoute = route.route.replace("{scrollToTop}", "true")
|
|
||||||
navController.navigate(newRoute) {
|
|
||||||
popUpTo(Route.Home.route)
|
|
||||||
launchSingleTop = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val followLists: FollowListViewModel = viewModel(
|
val followLists: FollowListViewModel = viewModel(
|
||||||
key = accountViewModel.userProfile().pubkeyHex + "FollowListViewModel",
|
key = accountViewModel.userProfile().pubkeyHex + "FollowListViewModel",
|
||||||
factory = FollowListViewModel.Factory(accountViewModel.account)
|
factory = FollowListViewModel.Factory(accountViewModel.account)
|
||||||
@@ -136,6 +119,41 @@ fun MainScreen(accountViewModel: AccountViewModel, accountStateViewModel: Accoun
|
|||||||
factory = NostrChatroomListNewFeedViewModel.Factory(accountViewModel.account)
|
factory = NostrChatroomListNewFeedViewModel.Factory(accountViewModel.account)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val navBottomRow = remember(navController) {
|
||||||
|
{ route: Route, selected: Boolean ->
|
||||||
|
if (!selected) {
|
||||||
|
navController.navigate(route.base) {
|
||||||
|
popUpTo(Route.Home.route)
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// deals with scroll to top here to avoid passing as parameter
|
||||||
|
// and having to deal with all recompositions with scroll to top true
|
||||||
|
when (route.base) {
|
||||||
|
Route.Home.base -> {
|
||||||
|
homeFeedViewModel.sendToTop()
|
||||||
|
repliesFeedViewModel.sendToTop()
|
||||||
|
}
|
||||||
|
Route.Search.base -> {
|
||||||
|
searchFeedViewModel.sendToTop()
|
||||||
|
}
|
||||||
|
Route.Video.base -> {
|
||||||
|
videoFeedViewModel.sendToTop()
|
||||||
|
}
|
||||||
|
Route.Notification.base -> {
|
||||||
|
notifFeedViewModel.clear()
|
||||||
|
notifFeedViewModel.sendToTop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
navController.navigate(route.route) {
|
||||||
|
popUpTo(route.route)
|
||||||
|
launchSingleTop = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ModalBottomSheetLayout(
|
ModalBottomSheetLayout(
|
||||||
sheetState = sheetState,
|
sheetState = sheetState,
|
||||||
sheetContent = {
|
sheetContent = {
|
||||||
|
|||||||
+2
-9
@@ -102,16 +102,9 @@ fun WatchAccountForNotifications(
|
|||||||
) {
|
) {
|
||||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||||
|
|
||||||
var firstTime by remember(accountViewModel) { mutableStateOf(true) }
|
|
||||||
|
|
||||||
LaunchedEffect(accountViewModel, accountState?.account?.defaultNotificationFollowList) {
|
LaunchedEffect(accountViewModel, accountState?.account?.defaultNotificationFollowList) {
|
||||||
if (firstTime) {
|
NostrAccountDataSource.invalidateFilters()
|
||||||
firstTime = false
|
notifFeedViewModel.checkKeysInvalidateDataAndSendToTop()
|
||||||
} else {
|
|
||||||
NostrAccountDataSource.invalidateFilters()
|
|
||||||
notifFeedViewModel.clear()
|
|
||||||
notifFeedViewModel.invalidateDataAndSendToTop(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1130,7 +1130,13 @@ fun TabNotesNewThreads(accountViewModel: AccountViewModel, nav: (String) -> Unit
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(vertical = 0.dp)
|
modifier = Modifier.padding(vertical = 0.dp)
|
||||||
) {
|
) {
|
||||||
RefresheableFeedView(feedViewModel, null, accountViewModel, nav, enablePullRefresh = false)
|
RefresheableFeedView(
|
||||||
|
feedViewModel,
|
||||||
|
null,
|
||||||
|
enablePullRefresh = false,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1147,7 +1153,13 @@ fun TabNotesConversations(accountViewModel: AccountViewModel, nav: (String) -> U
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(vertical = 0.dp)
|
modifier = Modifier.padding(vertical = 0.dp)
|
||||||
) {
|
) {
|
||||||
RefresheableFeedView(feedViewModel, null, accountViewModel, nav, enablePullRefresh = false)
|
RefresheableFeedView(
|
||||||
|
feedViewModel,
|
||||||
|
null,
|
||||||
|
enablePullRefresh = false,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1164,7 +1176,13 @@ fun TabBookmarks(baseUser: User, accountViewModel: AccountViewModel, nav: (Strin
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(vertical = 0.dp)
|
modifier = Modifier.padding(vertical = 0.dp)
|
||||||
) {
|
) {
|
||||||
RefresheableFeedView(feedViewModel, null, accountViewModel, nav, enablePullRefresh = false)
|
RefresheableFeedView(
|
||||||
|
feedViewModel,
|
||||||
|
null,
|
||||||
|
enablePullRefresh = false,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1246,7 +1264,13 @@ fun TabReports(baseUser: User, accountViewModel: AccountViewModel, nav: (String)
|
|||||||
|
|
||||||
Column(Modifier.fillMaxHeight()) {
|
Column(Modifier.fillMaxHeight()) {
|
||||||
Column() {
|
Column() {
|
||||||
RefresheableFeedView(feedViewModel, null, accountViewModel, nav, enablePullRefresh = false)
|
RefresheableFeedView(
|
||||||
|
feedViewModel,
|
||||||
|
null,
|
||||||
|
enablePullRefresh = false,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -138,7 +138,13 @@ fun SearchScreen(
|
|||||||
modifier = Modifier.padding(vertical = 0.dp)
|
modifier = Modifier.padding(vertical = 0.dp)
|
||||||
) {
|
) {
|
||||||
SearchBar(searchBarViewModel, accountViewModel, nav)
|
SearchBar(searchBarViewModel, accountViewModel, nav)
|
||||||
RefresheableFeedView(searchFeedViewModel, null, accountViewModel, nav, ScrollStateKeys.GLOBAL_SCREEN)
|
RefresheableFeedView(
|
||||||
|
searchFeedViewModel,
|
||||||
|
null,
|
||||||
|
scrollStateKey = ScrollStateKeys.GLOBAL_SCREEN,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,7 +127,12 @@ fun VideoScreen(
|
|||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(vertical = 0.dp)
|
modifier = Modifier.padding(vertical = 0.dp)
|
||||||
) {
|
) {
|
||||||
SaveableFeedState(videoFeedView, accountViewModel, nav, ScrollStateKeys.VIDEO_SCREEN)
|
SaveableFeedState(
|
||||||
|
videoFeedView = videoFeedView,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
nav = nav,
|
||||||
|
scrollStateKey = ScrollStateKeys.VIDEO_SCREEN
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,17 +140,10 @@ fun VideoScreen(
|
|||||||
@Composable
|
@Composable
|
||||||
fun WatchAccountForVideoScreen(videoFeedView: NostrVideoFeedViewModel, accountViewModel: AccountViewModel) {
|
fun WatchAccountForVideoScreen(videoFeedView: NostrVideoFeedViewModel, accountViewModel: AccountViewModel) {
|
||||||
val accountState by accountViewModel.accountLiveData.observeAsState()
|
val accountState by accountViewModel.accountLiveData.observeAsState()
|
||||||
val account = remember(accountState) { accountState?.account } ?: return
|
|
||||||
|
|
||||||
var firstTime by remember(accountViewModel) { mutableStateOf(true) }
|
LaunchedEffect(accountViewModel, accountState?.account?.defaultStoriesFollowList) {
|
||||||
|
NostrVideoDataSource.resetFilters()
|
||||||
LaunchedEffect(accountViewModel, account.defaultStoriesFollowList) {
|
videoFeedView.checkKeysInvalidateDataAndSendToTop()
|
||||||
if (firstTime) {
|
|
||||||
firstTime = false
|
|
||||||
} else {
|
|
||||||
NostrVideoDataSource.resetFilters()
|
|
||||||
videoFeedView.invalidateDataAndSendToTop(true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +153,6 @@ private fun SaveableFeedState(
|
|||||||
videoFeedView: NostrVideoFeedViewModel,
|
videoFeedView: NostrVideoFeedViewModel,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
nav: (String) -> Unit,
|
nav: (String) -> Unit,
|
||||||
routeForLastRead: String?,
|
|
||||||
scrollStateKey: String? = null
|
scrollStateKey: String? = null
|
||||||
) {
|
) {
|
||||||
val pagerState = if (scrollStateKey != null) {
|
val pagerState = if (scrollStateKey != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user