diff --git a/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectScreenContent.kt b/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectScreenContent.kt index 1b05ffb..9f9d9c7 100644 --- a/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectScreenContent.kt +++ b/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectScreenContent.kt @@ -203,6 +203,7 @@ fun ConnectScreenContent( val username = sharedPreferences.getString(Constants.COMMUNITY_USERNAME, "") ?: "" if (token.isNotEmpty()) { + connectViewModel.initializePinnedFriends(sharedPreferences) connectViewModel.getFriendList(token, username) connectViewModel.getCircleList(token) connectViewModel.getFriendRequest(token) diff --git a/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectViewModel.kt b/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectViewModel.kt index 6d28cdc..935d129 100644 --- a/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectViewModel.kt +++ b/app/src/main/java/com/dscvit/vitty/ui/connect/ConnectViewModel.kt @@ -51,6 +51,7 @@ class ConnectViewModel : ViewModel() { private val _circleActionResponse = MutableLiveData() private val _activeFriends = MutableLiveData??>() private val _ghostModeResponse = MutableLiveData() + private val _pinnedFriends = MutableLiveData>() val ghostModeResponse: MutableLiveData = _ghostModeResponse val friendList: MutableLiveData = _friendList @@ -73,6 +74,7 @@ class ConnectViewModel : ViewModel() { val isCircleRequestsLoading: MutableLiveData = _isCircleRequestsLoading val circleActionResponse: MutableLiveData = _circleActionResponse val activeFriends: MutableLiveData??> = _activeFriends + val pinnedFriends: MutableLiveData> = _pinnedFriends fun getFriendList( token: String, @@ -779,6 +781,95 @@ class ConnectViewModel : ViewModel() { _activeFriends.postValue(data) } + fun pinFriend( + username: String, + prefs: SharedPreferences, + ): Boolean { + val pinnedFriend1 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_1, "") + val pinnedFriend2 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_2, "") + val pinnedFriend3 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_3, "") + + val success = + when { + pinnedFriend1.isNullOrEmpty() -> { + prefs.edit { putString(Constants.COMMUNITY_PINNED_FRIEND_1, username) } + true + } + pinnedFriend2.isNullOrEmpty() -> { + prefs.edit { putString(Constants.COMMUNITY_PINNED_FRIEND_2, username) } + true + } + pinnedFriend3.isNullOrEmpty() -> { + prefs.edit { putString(Constants.COMMUNITY_PINNED_FRIEND_3, username) } + true + } + else -> false + } + + if (success) { + updatePinnedFriendsState(prefs) + } + return success + } + + fun unpinFriend( + username: String, + prefs: SharedPreferences, + ) { + val pinnedFriend1 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_1, "") + val pinnedFriend2 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_2, "") + val pinnedFriend3 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_3, "") + + when (username) { + pinnedFriend1 -> prefs.edit { putString(Constants.COMMUNITY_PINNED_FRIEND_1, "") } + pinnedFriend2 -> prefs.edit { putString(Constants.COMMUNITY_PINNED_FRIEND_2, "") } + pinnedFriend3 -> prefs.edit { putString(Constants.COMMUNITY_PINNED_FRIEND_3, "") } + } + + updatePinnedFriendsState(prefs) + } + + fun isFriendPinned( + username: String, + prefs: SharedPreferences, + ): Boolean { + val pinnedFriend1 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_1, "") + val pinnedFriend2 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_2, "") + val pinnedFriend3 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_3, "") + + return username == pinnedFriend1 || username == pinnedFriend2 || username == pinnedFriend3 + } + + fun getPinnedFriends(prefs: SharedPreferences): List { + val pinnedFriends = mutableListOf() + val pinnedFriend1 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_1, "") + val pinnedFriend2 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_2, "") + val pinnedFriend3 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_3, "") + + if (!pinnedFriend1.isNullOrEmpty()) pinnedFriends.add(pinnedFriend1) + if (!pinnedFriend2.isNullOrEmpty()) pinnedFriends.add(pinnedFriend2) + if (!pinnedFriend3.isNullOrEmpty()) pinnedFriends.add(pinnedFriend3) + + return pinnedFriends + } + + fun initializePinnedFriends(prefs: SharedPreferences) { + updatePinnedFriendsState(prefs) + } + + private fun updatePinnedFriendsState(prefs: SharedPreferences) { + val pinnedFriends = mutableSetOf() + val pinnedFriend1 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_1, "") + val pinnedFriend2 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_2, "") + val pinnedFriend3 = prefs.getString(Constants.COMMUNITY_PINNED_FRIEND_3, "") + + if (!pinnedFriend1.isNullOrEmpty()) pinnedFriends.add(pinnedFriend1) + if (!pinnedFriend2.isNullOrEmpty()) pinnedFriends.add(pinnedFriend2) + if (!pinnedFriend3.isNullOrEmpty()) pinnedFriends.add(pinnedFriend3) + + _pinnedFriends.postValue(pinnedFriends) + } + data class GhostModeResponse( val success: Boolean, ) diff --git a/app/src/main/java/com/dscvit/vitty/ui/connect/components/ConnectScreenComponents.kt b/app/src/main/java/com/dscvit/vitty/ui/connect/components/ConnectScreenComponents.kt index 39ea8de..4b3fb91 100644 --- a/app/src/main/java/com/dscvit/vitty/ui/connect/components/ConnectScreenComponents.kt +++ b/app/src/main/java/com/dscvit/vitty/ui/connect/components/ConnectScreenComponents.kt @@ -1,6 +1,7 @@ package com.dscvit.vitty.ui.connect.components import android.content.Context +import android.widget.Toast import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.animateFloat @@ -48,6 +49,8 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -339,9 +342,41 @@ fun ConnectTabContent( onFriendsRefresh: () -> Unit = {}, onCirclesRefresh: () -> Unit = {}, ) { + val context = LocalContext.current + val sharedPreferences = context.getSharedPreferences(Constants.USER_INFO, Context.MODE_PRIVATE) + val pinnedFriends by viewModel.pinnedFriends.observeAsState() + val allFriends = friendList?.data ?: emptyList() + + val sortedFriends = + allFriends.sortedWith { friend1, friend2 -> + val currentPinnedFriends = pinnedFriends ?: emptySet() + + val getPinPriority = { username: String -> + if (currentPinnedFriends.contains(username)) { + val pinnedFriend1 = sharedPreferences.getString(Constants.COMMUNITY_PINNED_FRIEND_1, "") + val pinnedFriend2 = sharedPreferences.getString(Constants.COMMUNITY_PINNED_FRIEND_2, "") + val pinnedFriend3 = sharedPreferences.getString(Constants.COMMUNITY_PINNED_FRIEND_3, "") + + when (username) { + pinnedFriend1 -> 1 + pinnedFriend2 -> 2 + pinnedFriend3 -> 3 + else -> 4 + } + } else { + Int.MAX_VALUE + } + } + + val priority1 = getPinPriority(friend1.username) + val priority2 = getPinPriority(friend2.username) + + priority1.compareTo(priority2) + } + val displayedFriends = - allFriends.filter { friend -> + sortedFriends.filter { friend -> val matchesSearch = searchQuery.isBlank() || friend.name.contains(searchQuery, ignoreCase = true) || @@ -421,6 +456,22 @@ fun ConnectTabContent( FriendCard( friend = friend, onClick = { onFriendClick(friend) }, + viewModel = viewModel, + onPinToggle = { username, shouldPin -> + if (shouldPin) { + val success = viewModel.pinFriend(username, sharedPreferences) + if (!success) { + Toast + .makeText( + context, + "Maximum 3 friends can be pinned", + android.widget.Toast.LENGTH_SHORT, + ).show() + } + } else { + viewModel.unpinFriend(username, sharedPreferences) + } + }, ) } } @@ -532,7 +583,12 @@ fun EmptyStateContent( fun FriendCard( friend: UserResponse, onClick: () -> Unit = {}, + viewModel: ConnectViewModel? = null, + onPinToggle: ((String, Boolean) -> Unit)? = null, ) { + val pinnedFriends by viewModel?.pinnedFriends?.observeAsState() ?: remember { mutableStateOf(emptySet()) } + val isPinned = pinnedFriends?.contains(friend.username) ?: false + Box( modifier = Modifier @@ -618,6 +674,25 @@ fun FriendCard( ) } } + + if (viewModel != null && onPinToggle != null) { + IconButton( + onClick = { + onPinToggle(friend.username, !isPinned) + }, + modifier = Modifier.size(40.dp), + ) { + Icon( + painter = + painterResource( + id = R.drawable.ic_pin, + ), + contentDescription = if (isPinned) "Unpin friend" else "Pin friend", + tint = if (isPinned) Accent else Accent.copy(alpha = 0.3f), + modifier = Modifier.size(20.dp), + ) + } + } } } } diff --git a/app/src/main/java/com/dscvit/vitty/util/LogoutHelper.kt b/app/src/main/java/com/dscvit/vitty/util/LogoutHelper.kt index 43ecd54..d25b03d 100755 --- a/app/src/main/java/com/dscvit/vitty/util/LogoutHelper.kt +++ b/app/src/main/java/com/dscvit/vitty/util/LogoutHelper.kt @@ -45,7 +45,7 @@ object LogoutHelper { } logout.setOnClickListener { - prefs.edit().apply { + prefs.edit { putInt(Constants.TIMETABLE_AVAILABLE, 0) putInt(Constants.UPDATE, 0) putString(Constants.UID, "") @@ -60,8 +60,9 @@ object LogoutHelper { putString(Constants.CACHE_COMMUNITY_TIMETABLE, null) putBoolean(Constants.ACTIVE_FRIENDS_FETCHED, false) putString(Constants.ACTIVE_FRIENDS_FETCHED, null) - - apply() + putString(Constants.COMMUNITY_PINNED_FRIEND_1, null) + putString(Constants.COMMUNITY_PINNED_FRIEND_2, null) + putString(Constants.COMMUNITY_PINNED_FRIEND_3, null) } prefs.edit { clear() } FirebaseAuth.getInstance().signOut()