Merge pull request #2460 from vitorpamplona/claude/fix-empty-groups-display-MO6E9
Show placeholder notes for empty Marmot groups in chat list
This commit is contained in:
+15
@@ -56,6 +56,8 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.shorts.dal.ShortsFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.dal.VideoFeedFilter
|
||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.webBookmarks.dal.WebBookmarkFeedFilter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class AccountFeedContentStates(
|
||||
val account: Account,
|
||||
@@ -100,6 +102,19 @@ class AccountFeedContentStates(
|
||||
|
||||
val webBookmarks = FeedContentState(WebBookmarkFeedFilter(account), scope, LocalCache)
|
||||
|
||||
init {
|
||||
// Marmot group list changes (new group, group marked known, group
|
||||
// metadata synced) don't flow through LocalCache.newEventBundles, so
|
||||
// the additive update path can't see them. Force a full feed rebuild
|
||||
// whenever the list changes so empty groups appear and placeholder
|
||||
// rows get replaced by real messages.
|
||||
scope.launch(Dispatchers.IO) {
|
||||
account.marmotGroupList.groupListChanges.collect {
|
||||
dmKnown.invalidateData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun init() {
|
||||
notificationSummary.initializeSuspend()
|
||||
}
|
||||
|
||||
+15
-5
@@ -85,7 +85,11 @@ fun ChatroomHeaderCompose(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
if (baseNote.event != null) {
|
||||
val isEmptyMarmotPlaceholder =
|
||||
baseNote.event == null &&
|
||||
baseNote.inGatherers?.any { it is MarmotGroupChatroom } == true
|
||||
|
||||
if (baseNote.event != null || isEmptyMarmotPlaceholder) {
|
||||
ChatroomComposeChannelOrUser(baseNote, accountViewModel, nav)
|
||||
} else {
|
||||
val hasEvent by observeNoteHasEvent(baseNote, accountViewModel)
|
||||
@@ -248,21 +252,27 @@ private fun MarmotGroupRoomCompose(
|
||||
accountViewModel: AccountViewModel,
|
||||
nav: INav,
|
||||
) {
|
||||
val authorName by observeUserName(lastMessage.author!!, accountViewModel)
|
||||
val displayName by chatroom.displayName.collectAsStateWithLifecycle()
|
||||
val unread by chatroom.unreadCount.collectAsStateWithLifecycle()
|
||||
|
||||
val author = lastMessage.author
|
||||
val noteEvent = lastMessage.event
|
||||
val description = noteEvent?.content?.take(200)
|
||||
|
||||
val groupName = displayName?.takeIf { it.isNotBlank() } ?: "Group ${chatroom.nostrGroupId.take(8)}"
|
||||
|
||||
val lastContent =
|
||||
if (author != null && noteEvent != null) {
|
||||
val authorName by observeUserName(author, accountViewModel)
|
||||
"$authorName: ${noteEvent.content.take(200)}"
|
||||
} else {
|
||||
stringRes(R.string.marmot_group_no_messages_yet)
|
||||
}
|
||||
|
||||
ChannelName(
|
||||
channelIdHex = chatroom.nostrGroupId,
|
||||
channelPicture = null,
|
||||
channelTitle = { modifier -> ChannelTitleWithLabelInfo(groupName, R.string.marmot_group, modifier) },
|
||||
channelLastTime = lastMessage.createdAt(),
|
||||
channelLastContent = "$authorName: $description",
|
||||
channelLastContent = lastContent,
|
||||
hasNewMessages = unread > 0,
|
||||
loadProfilePicture = accountViewModel.settings.showProfilePictures(),
|
||||
loadRobohash = accountViewModel.settings.isNotPerformanceMode(),
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@ class ChatroomListKnownFeedFilter(
|
||||
|
||||
val marmotGroups =
|
||||
account.marmotGroupList.rooms.mapNotNull { _, chatroom ->
|
||||
chatroom.newestMessage
|
||||
chatroom.newestMessage ?: chatroom.placeholderNote()
|
||||
}
|
||||
|
||||
return (privateMessages + publicChannels + ephemeralChats + marmotGroups).sortedWith(DefaultFeedOrder)
|
||||
|
||||
@@ -284,6 +284,7 @@
|
||||
|
||||
<string name="public_chat">Public Chat</string>
|
||||
<string name="marmot_group">MLS Group</string>
|
||||
<string name="marmot_group_no_messages_yet">No messages yet</string>
|
||||
<string name="public_chat_title">Public Chat Metadata</string>
|
||||
<string name="public_chat_explainer">Public chats are visible to everyone on Nostr and anyone
|
||||
can participate on them. They are great for open communities around specific topics.
|
||||
|
||||
+21
@@ -69,6 +69,27 @@ class MarmotGroupChatroom(
|
||||
*/
|
||||
var ownerSentMessage: Boolean = false
|
||||
|
||||
// Synthetic note used by list views to represent the group when no
|
||||
// messages have been received yet. Lazily created and kept stable so
|
||||
// equality-based feed diffing treats it as the same row across refreshes.
|
||||
private var cachedPlaceholder: Note? = null
|
||||
|
||||
@Synchronized
|
||||
fun placeholderNote(): Note {
|
||||
val existing = cachedPlaceholder
|
||||
if (existing != null) return existing
|
||||
val created =
|
||||
Note(placeholderIdHex(nostrGroupId)).apply {
|
||||
addGatherer(this@MarmotGroupChatroom)
|
||||
}
|
||||
cachedPlaceholder = created
|
||||
return created
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun placeholderIdHex(nostrGroupId: HexKey): HexKey = "marmot-empty-$nostrGroupId"
|
||||
}
|
||||
|
||||
private var changesFlow: WeakReference<MutableSharedFlow<ListChange<Note>>> = WeakReference(null)
|
||||
|
||||
fun changesFlow(): MutableSharedFlow<ListChange<Note>> {
|
||||
|
||||
Reference in New Issue
Block a user