diff --git a/app/src/main/java/com/bitchat/android/ui/ChatState.kt b/app/src/main/java/com/bitchat/android/ui/ChatState.kt index 394ffbe8..9dc16cf6 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatState.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatState.kt @@ -78,6 +78,12 @@ class ChatState { private val _commandSuggestions = MutableLiveData>(emptyList()) val commandSuggestions: LiveData> = _commandSuggestions + // Favorites + private val _favoritePeers = MutableLiveData>(emptySet()) + val favoritePeers: LiveData> = _favoritePeers + + val peerIDToPublicKeyFingerprint = mutableMapOf() + // Unread state computed properties val hasUnreadChannels: MediatorLiveData = MediatorLiveData() val hasUnreadPrivateMessages: MediatorLiveData = MediatorLiveData() @@ -110,6 +116,7 @@ class ChatState { fun getShowSidebarValue() = _showSidebar.value ?: false fun getShowCommandSuggestionsValue() = _showCommandSuggestions.value ?: false fun getCommandSuggestionsValue() = _commandSuggestions.value ?: emptyList() + fun getFavoritePeersValue() = _favoritePeers.value ?: emptySet() // Setters for state updates fun setMessages(messages: List) { @@ -179,4 +186,9 @@ class ChatState { fun setCommandSuggestions(suggestions: List) { _commandSuggestions.value = suggestions } + + fun setFavoritePeers(favorites: Set) { + _favoritePeers.value = favorites + } + } diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index 4cfb92c3..90a17ce2 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -33,7 +33,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B private val dataManager = DataManager(context) private val messageManager = MessageManager(state) private val channelManager = ChannelManager(state, messageManager, dataManager, viewModelScope) - private val privateChatManager = PrivateChatManager(state, messageManager, dataManager) + val privateChatManager = PrivateChatManager(state, messageManager, dataManager) private val commandProcessor = CommandProcessor(state, messageManager, channelManager, privateChatManager) // Delegate handler for mesh callbacks @@ -67,6 +67,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B val hasUnreadPrivateMessages = state.hasUnreadPrivateMessages val showCommandSuggestions: LiveData = state.showCommandSuggestions val commandSuggestions: LiveData> = state.commandSuggestions + val favoritePeers: LiveData> = state.favoritePeers init { meshService.delegate = this @@ -94,6 +95,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B // Load other data dataManager.loadFavorites() + state.setFavoritePeers(dataManager.favoritePeers) dataManager.loadBlockedUsers() // Start mesh service diff --git a/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt b/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt index c9341f04..cb94ab4e 100644 --- a/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt +++ b/app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt @@ -104,6 +104,7 @@ class PrivateChatManager( } else { dataManager.addFavorite(fingerprint) } + state.setFavoritePeers(dataManager.favoritePeers) } fun isFavorite(peerID: String): Boolean { diff --git a/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt b/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt index a0575f0a..cdb7adfa 100644 --- a/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt +++ b/app/src/main/java/com/bitchat/android/ui/SidebarComponents.kt @@ -261,12 +261,16 @@ fun PeopleSection( // Get unread private messages and private chat history for sorting val hasUnreadPrivateMessages by viewModel.unreadPrivateMessages.observeAsState(emptySet()) val privateChats by viewModel.privateChats.observeAsState(emptyMap()) - - // Smart sorting: unread DMs first, then by most recent DM, then favorites, then alphabetical + val favoritePeers by viewModel.favoritePeers.observeAsState(emptySet()) + + // Smart sorting: unread DMs first, then by most recent DM, then favorites, then alphabetical val sortedPeers = connectedPeers.sortedWith( compareBy { !hasUnreadPrivateMessages.contains(it) } // Unread DM senders first .thenByDescending { privateChats[it]?.maxByOrNull { msg -> msg.timestamp }?.timestamp?.time ?: 0L } // Most recent DM (convert Date to Long) - .thenBy { !viewModel.isFavorite(it) } // Favorites + .thenBy { + val fingerprint = viewModel.privateChatManager.getPeerFingerprint(it) + fingerprint == null || !favoritePeers.contains(fingerprint) + } // Favorites .thenBy { (if (it == nickname) "You" else (peerNicknames[it] ?: it)).lowercase() } // Alphabetical ) @@ -276,7 +280,7 @@ fun PeopleSection( displayName = if (peerID == nickname) "You" else (peerNicknames[peerID] ?: peerID), signalStrength = peerRSSI[peerID] ?: 0, isSelected = peerID == selectedPrivatePeer, - isFavorite = viewModel.isFavorite(peerID), + isFavorite = favoritePeers.contains(viewModel.privateChatManager.getPeerFingerprint(peerID)), hasUnreadDM = hasUnreadPrivateMessages.contains(peerID), colorScheme = colorScheme, onItemClick = { onPrivateChatStart(peerID) },