Browse Source

friend profile update

master
osman160128 2 weeks ago
parent
commit
fbd1f81c9a
  1. 119
      app/src/main/java/com/example/dattingapp/FriendProfile.kt
  2. 29
      app/src/main/java/com/example/dattingapp/LikeANdMatchActivity.kt
  3. 5
      app/src/main/java/com/example/dattingapp/Login/LoginActivity.kt
  4. 59
      app/src/main/java/com/example/dattingapp/ShowPostingActivity.kt
  5. 4
      app/src/main/java/com/example/dattingapp/dataclass/DataClass.kt
  6. 3
      app/src/main/java/com/example/dattingapp/homes/ExploreScreen.kt
  7. 18
      app/src/main/java/com/example/dattingapp/homes/MeetScreen.kt
  8. 28
      app/src/main/java/com/example/dattingapp/homes/MyProfile.kt
  9. 11
      app/src/main/java/com/example/dattingapp/homes/networkandapi/HomeApiService.kt
  10. 48
      app/src/main/java/com/example/dattingapp/homes/networkandapi/HomeViewModelClass.kt
  11. 4
      app/src/main/java/com/example/dattingapp/homes/networkandapi/TokenManager.kt
  12. 4
      app/src/main/java/com/example/dattingapp/registration/RegisterRequest.kt
  13. 2
      app/src/main/java/com/example/dattingapp/ui/theme/Color.kt

119
app/src/main/java/com/example/dattingapp/FriendProfile.kt

@ -51,6 +51,7 @@ import com.example.dattingapp.homes.profile.FrienPostMedia
import com.example.dattingapp.homes.profile.FriendAuthor
import com.example.dattingapp.homes.profile.FriendPost
import com.example.dattingapp.homes.profile.FriendProfileResponse
import com.example.dattingapp.homes.profile.LikedUserResponse
import com.example.dattingapp.ui.theme.*
import java.time.LocalDate
import java.time.Period
@ -82,6 +83,9 @@ class FriendProfile : ComponentActivity() {
}
}
when (val state = profileUiState) {
is FriendProfileUiState.Loading -> {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
@ -120,6 +124,36 @@ fun FriendProfileScreen(
onStarClick: () -> Unit = {},
onCancelClick: () -> Unit = {}
) {
val likedViewModel: LikedViewModel = viewModel()
// ✅ collect each state separately
val likesState by likedViewModel.likesUiState.collectAsState() // who liked me
val likedState by likedViewModel.likedUiState.collectAsState() // I liked
val matchesState by likedViewModel.matchesUiState.collectAsState() // matches
// ✅ load all three lists once
LaunchedEffect(Unit) {
likedViewModel.likedResponse(context, "Likes")
likedViewModel.likedResponse(context, "Liked")
likedViewModel.likedResponse(context, "Matches")
}
// ✅ turn each into a set of ids
val likedMeIds = (likesState as? LikedUiState.Success)
?.LikeData?.map { it.id }?.toSet() ?: emptySet()
val iLikedIds = (likedState as? LikedUiState.Success)
?.LikeData?.map { it.id }?.toSet() ?: emptySet()
val matchIds = (matchesState as? LikedUiState.Success)
?.LikeData?.map { it.id }?.toSet() ?: emptySet()
// ✅ the three booleans for the button row
val isMatch = friendProfileData.id in matchIds
val heLikedMe = friendProfileData.id in likedMeIds
val iLikedHim = friendProfileData.id in iLikedIds
val age = remember(friendProfileData.birth_date) {
calculateAge(friendProfileData.birth_date)
}
@ -269,6 +303,7 @@ fun FriendProfileScreen(
)
}
// Action Buttons Row
Row(
modifier = Modifier
@ -277,85 +312,109 @@ fun FriendProfileScreen(
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
Button(
// Message — inside a card
if (isMatch) {
Card(
onClick = onMessageClick,
modifier = Modifier
.weight(1f)
.height(48.dp)
.background(
brush = gradientBrush,
shape = RoundedCornerShape(10.dp)
),
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
contentColor = Color.White
),
shape = RoundedCornerShape(10.dp)
.height(48.dp),
shape = RoundedCornerShape(10.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Row(
modifier = Modifier.fillMaxSize(),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically
) {
Icon(
imageVector = Icons.Default.ChatBubble,
contentDescription = "Message",
tint = textDark,
modifier = Modifier.size(18.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "Message",
fontSize = 16.sp,
fontWeight = FontWeight.Bold
fontWeight = FontWeight.Bold,
color = textDark
)
}
}
}
IconButton(
// ❤️ Like — red ICON when the user liked ME, hidden when matched
if (!isMatch) {
Card(
onClick = {
onLikeClick()
handleLikeAndDislikeAction(context, "right", friendProfileData, swipeViewModel)
},
modifier = Modifier
.size(48.dp)
.background(color = purpleButtonColor, shape = RoundedCornerShape(10.dp))
modifier = Modifier.size(48.dp),
shape = RoundedCornerShape(10.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Icon(
imageVector = Icons.Default.Favorite,
contentDescription = "Like",
tint = Color(0xFFE2C4FF),
modifier = Modifier.size(20.dp)
tint = when {
heLikedMe -> Color(0xFFE53935) // 🔴 user liked me
iLikedHim -> Color(0xFF1E88E5) // 🔵 I liked the user
else -> textDark // ⚫ no relation yet
},
modifier = Modifier.size(22.dp)
)
}
}
IconButton(
// Super Like — inside a card
Card(
onClick = {
onStarClick()
handleLikeAndDislikeAction(context, "right", friendProfileData, swipeViewModel)
},
modifier = Modifier
.size(48.dp)
.background(color = purpleButtonColor, shape = RoundedCornerShape(10.dp))
modifier = Modifier.size(48.dp),
shape = RoundedCornerShape(10.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Icon(
imageVector = Icons.Default.Star,
contentDescription = "Favorite",
tint = Color(0xFFE2C4FF),
modifier = Modifier.size(20.dp)
tint = textDark,
modifier = Modifier.size(22.dp)
)
}
}
}
IconButton(
// Cancel — inside a card, always visible
Card(
onClick = {
onCancelClick()
handleLikeAndDislikeAction(context, "left", friendProfileData, swipeViewModel)
},
modifier = Modifier
.size(48.dp)
.background(color = purpleButtonColor, shape = RoundedCornerShape(10.dp))
modifier = Modifier.size(48.dp),
shape = RoundedCornerShape(10.dp),
colors = CardDefaults.cardColors(containerColor = Color.White),
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Dislike",
tint = Color(0xFFE2C4FF),
modifier = Modifier.size(20.dp)
tint = textDark,
modifier = Modifier.size(22.dp)
)
}
}
}
Spacer(modifier = Modifier.height(16.dp))

29
app/src/main/java/com/example/dattingapp/LikeANdMatchActivity.kt

@ -54,13 +54,14 @@ class LikeANdMatchActivity : ComponentActivity() {
DattingAPPTheme {
val likedViewModel: LikedViewModel = viewModel()
val context = LocalContext.current
val type = intent.getStringExtra("TYPE") ?: "liked"
// Collect state from ViewModel
val uiState by likedViewModel.likeUiState.collectAsState()
val uiState by likedViewModel.likesUiState.collectAsState()
// Trigger network call once when screen loads
LaunchedEffect(Unit) {
likedViewModel.likedResponse(context)
likedViewModel.likedResponse(context,type)
}
Scaffold(
@ -95,7 +96,7 @@ class LikeANdMatchActivity : ComponentActivity() {
color = MaterialTheme.colorScheme.error,
fontWeight = FontWeight.Medium
)
Button(onClick = { likedViewModel.likedResponse(context) }) {
Button(onClick = { likedViewModel.likedResponse(context,"like") }) {
Text("Retry")
}
}
@ -120,7 +121,6 @@ fun ProfileCard(context: Context, likedProfile: LikedUserResponse, modifier: Mod
modifier = modifier.fillMaxWidth()
) {
Column(
modifier = Modifier.padding(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Box(
@ -128,6 +128,14 @@ fun ProfileCard(context: Context, likedProfile: LikedUserResponse, modifier: Mod
.fillMaxWidth()
.height(180.dp)
.clip(RoundedCornerShape(12.dp))
.clickable {
// Create an intent to launch your target activity (e.g., FriendProfileActivity)
val intent = Intent(context, FriendProfile::class.java).apply {
putExtra("USER_ID", likedProfile.id) // Pass the user ID here
}
context.startActivity(intent)
onNameClick() }
) {
// Use profile_image_url or fallback to the first media item
AsyncImage(
@ -182,17 +190,10 @@ fun ProfileCard(context: Context, likedProfile: LikedUserResponse, modifier: Mod
Column(
modifier = Modifier
.align(Alignment.BottomStart)
.clickable {
// Create an intent to launch your target activity (e.g., FriendProfileActivity)
val intent = Intent(context, FriendProfile::class.java).apply {
putExtra("USER_ID", likedProfile.id) // Pass the user ID here
}
context.startActivity(intent)
onNameClick() } // Makes just this text section clickable
// Makes just this text section clickable
.padding(8.dp)
){
val displayName = likedProfile.full_name.ifBlank { "User" }
val displayName = likedProfile.full_name?.ifBlank { "User" }
val age = remember(likedProfile.birth_date) {
calculateAge(likedProfile.birth_date)
}
@ -201,7 +202,7 @@ fun ProfileCard(context: Context, likedProfile: LikedUserResponse, modifier: Mod
Log.d("user","$likedProfile.id")
Text(
text = nameAndAge,
text = nameAndAge?:"",
color = Color.White,
fontWeight = FontWeight.Bold,
fontSize = 14.sp

5
app/src/main/java/com/example/dattingapp/Login/LoginActivity.kt

@ -270,13 +270,14 @@ fun LoginScreenContent(
// Save retrieved tokens via TokenManager
val tokenManager = TokenManager.getInstance(context)
val id=loginData.user?.profile?.full_name
val id=loginData.user?.id
Log.d("useridlogin","$id")
tokenManager.saveTokens(
accessToken = loginData.accessToken ?: "",
refreshToken = loginData.refreshToken ?: "",
userId = loginData.user?.id ?: -1,
currenUserName = loginData.user?.profile?.full_name
currenUserName = loginData.user?.profile?.full_name,
profile_image_url=loginData.user?.profile?.profile_image_url
)
Toast.makeText(context, "Login successful!", Toast.LENGTH_SHORT).show()

59
app/src/main/java/com/example/dattingapp/ShowPostingActivity.kt

@ -1,4 +1,5 @@
package com.example.dattingapp
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
@ -44,6 +45,7 @@ import com.example.dattingapp.homes.networkandapi.ShowPostUiState
import com.example.dattingapp.homes.networkandapi.ShowPostViewModel
import androidx.compose.material.icons.filled.Send
import androidx.compose.material3.CardDefaults
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
@ -135,38 +137,52 @@ fun PostCard(
.padding(horizontal = 12.dp, vertical = 8.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
AsyncImage(
model = post.author?.profile_image_url,
contentDescription = "Post author image",
placeholder = painterResource(id = R.drawable.locationpermissionbg), // your existing placeholder
error = painterResource(id = R.drawable.locationpermissionbg),
modifier = Modifier
.size(40.dp)
.clip(CircleShape)
.background(Color.LightGray),
contentAlignment = Alignment.Center
) {
Text(text = post.author?.full_name?.take(1) ?: "U")
}
.clip(CircleShape),
contentScale = ContentScale.Crop
)
Spacer(modifier = Modifier.width(8.dp))
Column {
Row(verticalAlignment = Alignment.CenterVertically) {
val authorName = post.author?.full_name ?: "Anonymous"
val feelingText = post.feeling ?: ""
val context = LocalContext.current
// ✅ Clickable author name
Text(
text = buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append("$authorName ")
text = authorName,
fontSize = 16.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.clickable {
val intent = Intent(context, FriendProfile::class.java).apply {
putExtra("USER_ID", post.author?.id) // ← send the user id
}
context.startActivity(intent)
}
)
// Rest of the line, unchanged
if (feelingText.isNotEmpty()) {
Text(
text = buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Normal)) {
append(" — feeling ")
}
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append(feelingText)
}
}
},
fontSize = 16.sp
)
}
}
if (!post.location?.name.isNullOrEmpty()) {
Text(
@ -295,6 +311,7 @@ fun CommentSection(
val tokenManager = remember { TokenManager.getInstance(context) }
val currentUserName = remember { tokenManager.currentUserName() }
val currentProfileImage = remember { tokenManager.currentProfileImage() }
// ✅ get the logged-in user's id once
val currentUserId = remember { tokenManager.getUserId() }
@ -383,19 +400,16 @@ fun CommentSection(
.padding(vertical = 6.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
AsyncImage(
model = currentProfileImage,
contentDescription = "Post author image",
placeholder = painterResource(id = R.drawable.locationpermissionbg), // your existing placeholder
error = painterResource(id = R.drawable.locationpermissionbg),
modifier = Modifier
.size(32.dp)
.clip(CircleShape)
.background(Color.LightGray),
contentAlignment = Alignment.Center
) {
Text(
text = comment.author?.full_name?.take(1) ?: "U",
style = MaterialTheme.typography.bodySmall,
fontWeight = FontWeight.Bold
.clip(CircleShape),
contentScale = ContentScale.Crop
)
}
Spacer(modifier = Modifier.width(8.dp))
@ -513,6 +527,7 @@ fun ShowPostScreenPreview() {
full_name = "Alex Rivera",
city = "Shanghai",
country = "China",
profile_image_url=null,
compatibilityPercentage = 95
),
like_count = 12,
@ -542,6 +557,7 @@ fun ShowPostScreenPreview() {
full_name = "Sarah",
city = "Shanghai",
country = "China",
profile_image_url=null,
compatibilityPercentage = 100
),
createdAt = "2026-10-13T07:45:15"
@ -555,6 +571,7 @@ fun ShowPostScreenPreview() {
full_name = "David",
city = "Beijing",
country = "China",
profile_image_url=null,
compatibilityPercentage = 90
),
createdAt = "2026-10-13T08:04:48"

4
app/src/main/java/com/example/dattingapp/dataclass/DataClass.kt

@ -32,6 +32,10 @@ data class Author(
val full_name: String?,
val city: String?,
val country: String?,
@SerialName("profile_image_url")
val profile_image_url:String?,
@SerialName("compatibility_percentage") val compatibilityPercentage: Int? = 0
)

3
app/src/main/java/com/example/dattingapp/homes/ExploreScreen.kt

@ -54,6 +54,7 @@ import com.example.dattingapp.ui.theme.OverlayShadow
import com.example.dattingapp.ui.theme.TextPostTextColor
import com.example.dattingapp.ui.theme.lightChipBg
import com.example.dattingapp.ui.theme.primaryColor
import kotlinx.serialization.SerialName
// Data Models
@ -628,6 +629,7 @@ private val mockFeed = listOf(
full_name = "Alex Rivera",
city = "Shanghai",
country = "China",
profile_image_url = null,
compatibilityPercentage = 95
),
like_count = 12,
@ -657,6 +659,7 @@ private val mockFeed = listOf(
full_name = "Sarah",
city = "Beijing",
country = "China",
profile_image_url = null,
compatibilityPercentage = 88
),
like_count = 0,

18
app/src/main/java/com/example/dattingapp/homes/MeetScreen.kt

@ -4,6 +4,7 @@ import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
@ -205,12 +206,15 @@ private fun ProfileCardItem(
}
val defaultPainter = rememberVectorPainter(Icons.Default.Person)
if (!photoUrl.isNullOrBlank()) {
AsyncImage(
model = ImageRequest.Builder(context)
.data(photoUrl.takeIf { !it.isNullOrBlank() })
.data(photoUrl) // ← guaranteed non-null here
.apply {
if (!token.isNullOrBlank()) {
val authHeader = if (token.startsWith("Bearer ", ignoreCase = true)) token else "Bearer $token"
val authHeader =
if (token.startsWith("Bearer ", ignoreCase = true)) token
else "Bearer $token"
addHeader("Authorization", authHeader)
}
}
@ -218,7 +222,6 @@ private fun ProfileCardItem(
.build(),
placeholder = defaultPainter,
error = defaultPainter,
fallback = defaultPainter, // Shows Icons.Default.Person immediately when photoUrl is null/blank
contentDescription = "Profile Image",
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop,
@ -226,6 +229,15 @@ private fun ProfileCardItem(
Log.e("CoilStatus", "Failed to load image", errorState.result.throwable)
}
)
} else {
// No URL at all → show the default directly, Coil never runs
Image(
painter = defaultPainter,
contentDescription = "Profile Image",
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Crop
)
}
// DARK GRADIENT OVERLAY
Box(

28
app/src/main/java/com/example/dattingapp/homes/MyProfile.kt

@ -45,6 +45,7 @@ import androidx.core.content.ContextCompat.startActivity
// MY PROFILE SCREEN
// ============================================================
@Composable
fun MyProfileScreen(
profileResponse : UserResponse?, // Change from MyProfileData? to MyProfileResponse?
@ -305,7 +306,10 @@ fun MyProfileScreen(
label = "Likes",
modifier = Modifier.weight(1f),
onClick = {
val intent = Intent(context, LikeANdMatchActivity::class.java)
val intent = Intent(context, LikeANdMatchActivity::class.java).apply {
putExtra("TYPE", "Likes") // ← e.g. "like", "liked", or "matches"
// putExtra("USER_ID", userId.toString()) // ← if you also need a user id
}
context.startActivity(intent)
onLikesClick()
}
@ -316,7 +320,14 @@ fun MyProfileScreen(
number = profileResponse?.liked_by_users_count?.toString() ?: "0",
label = "Liked",
modifier = Modifier.weight(1f),
onClick = { /* Optional: Handle Matches click */ }
onClick = {
val intent = Intent(context, LikeANdMatchActivity::class.java).apply {
putExtra("TYPE", "Liked") // ← e.g. "like", "liked", or "matches"
// putExtra("USER_ID", userId.toString()) // ← if you also need a user id
}
context.startActivity(intent)
onLikesClick()
}
)
@ -330,7 +341,14 @@ fun MyProfileScreen(
number = profileResponse?.matches_count?.toString() ?: "0",
label = "Matches",
modifier = Modifier.weight(1f),
onClick = { /* Optional: Handle Matches click */ }
onClick = {
val intent = Intent(context, LikeANdMatchActivity::class.java).apply {
putExtra("TYPE", "Matches") // ← e.g. "like", "liked", or "matches"
// putExtra("USER_ID", userId.toString()) // ← if you also need a user id
}
context.startActivity(intent)
onLikesClick()
}
)
}
Spacer(
@ -346,6 +364,8 @@ fun MyProfileScreen(
}
// ============================================================
// PROFILE MEDIA GRID
// ============================================================
@ -414,7 +434,7 @@ private fun StatCard(
) {
Column(
modifier = Modifier.fillMaxWidth().padding(vertical = 12.dp),
modifier = Modifier.fillMaxWidth().padding(vertical = 5.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(

11
app/src/main/java/com/example/dattingapp/homes/networkandapi/HomeApiService.kt

@ -69,9 +69,20 @@ interface HomeApiService {
): Response<UserResponse>
@GET("api/v1/users/me/liked")
suspend fun getLikeUsers(
): Response<List<LikedUserResponse>>
@GET("/api/v1/users/me/likes")
suspend fun getLikedUsers(
): Response<List<LikedUserResponse>>
@GET("/api/v1/matches")
suspend fun getMatches(
@Query("limit") limit: Int = 20,
@Query("offset") offset: Int = 0
): Response<List<LikedUserResponse>>
@GET("api/v1/explore/posts/{post_id}")
suspend fun getPostById(
@Path("post_id") postId: Int

48
app/src/main/java/com/example/dattingapp/homes/networkandapi/HomeViewModelClass.kt

@ -534,49 +534,62 @@ sealed interface LikedUiState {
class LikedViewModel : ViewModel() {
private val _likeUiState = MutableStateFlow<LikedUiState>(LikedUiState.Idle)
val likeUiState: StateFlow<LikedUiState> = _likeUiState.asStateFlow()
// ✅ three separate states, one per list type
private val _likesUiState = MutableStateFlow<LikedUiState>(LikedUiState.Idle) // users who liked ME
val likesUiState: StateFlow<LikedUiState> = _likesUiState.asStateFlow()
fun likedResponse(context: Context) {
if (_likeUiState.value is LikedUiState.Loading) return
private val _likedUiState = MutableStateFlow<LikedUiState>(LikedUiState.Idle) // users I liked
val likedUiState: StateFlow<LikedUiState> = _likedUiState.asStateFlow()
private val _matchesUiState = MutableStateFlow<LikedUiState>(LikedUiState.Idle) // matches
val matchesUiState: StateFlow<LikedUiState> = _matchesUiState.asStateFlow()
fun likedResponse(context: Context, type: String) {
val appContext = context.applicationContext
// ✅ pick which state this call writes to
val targetFlow = when (type) {
"Likes" -> _likesUiState
"Liked" -> _likedUiState
else -> _matchesUiState
}
if (targetFlow.value is LikedUiState.Loading) return
viewModelScope.launch {
_likeUiState.value = LikedUiState.Loading
targetFlow.value = LikedUiState.Loading
if (TokenManager.getInstance(appContext).getAccessToken().isNullOrBlank()) {
Log.e("MeetApi", "No access token in user_tokens preferences")
_likeUiState.value = LikedUiState.Error("No access token found. Please log in again.")
targetFlow.value = LikedUiState.Error("No access token found. Please log in again.")
return@launch
}
try {
// Returns CreatePostResponse directly
val createdPost = HomeNetworkModule
.getApiService(appContext)
.getLikedUsers()
val createdPost = when (type) {
"Likes" -> HomeNetworkModule.getApiService(appContext).getLikeUsers()
"Liked" -> HomeNetworkModule.getApiService(appContext).getLikedUsers()
else -> HomeNetworkModule.getApiService(appContext).getMatches(20, 10)
}
Log.d("CreatePostDebug", "Response Code: ${createdPost.code()}")
Log.d("CreatePostDebug", "$type Response Code: ${createdPost.code()}")
if (createdPost.isSuccessful && createdPost.body() != null) {
_likeUiState.value = LikedUiState.Success(createdPost.body()!!) // Use .body() here!
targetFlow.value = LikedUiState.Success(createdPost.body()!!)
} else {
_likeUiState.value = LikedUiState.Error("No post data received from the server.")
targetFlow.value = LikedUiState.Error("No data received from the server.")
}
} catch (e: HttpException) {
// Handle HTTP errors via HttpException automatically thrown by Retrofit
val message = when (e.code()) {
401 -> "Authentication failed. Please log in again."
403 -> "The server refused access to this profile."
404 -> "User profile was not found."
else -> "Request failed: HTTP ${e.code()}."
}
_likeUiState.value = LikedUiState.Error(message)
targetFlow.value = LikedUiState.Error(message)
} catch (e: Exception) {
Log.e("MeetApi", "Unexpected request failure", e)
_likeUiState.value = LikedUiState.Error("Request failed: ${e.javaClass.simpleName}")
targetFlow.value = LikedUiState.Error("Request failed: ${e.javaClass.simpleName}")
}
}
}
@ -653,6 +666,7 @@ class ShowPostViewModel : ViewModel() {
full_name = currentUserName ?: "You",
city = null,
country = null,
profile_image_url = null,
compatibilityPercentage = null
),
createdAt = "Just now"

4
app/src/main/java/com/example/dattingapp/homes/networkandapi/TokenManager.kt

@ -11,7 +11,7 @@ class TokenManager private constructor(context: Context) {
Context.MODE_PRIVATE
)
fun saveTokens(accessToken: String, refreshToken: String?,userId: Int,currenUserName:String?) {
fun saveTokens(accessToken: String, refreshToken: String?,userId: Int,currenUserName:String?,profile_image_url:String?) {
val cleanToken = accessToken.trim()
.replace(
Regex("^Bearer\\s+", RegexOption.IGNORE_CASE),
@ -24,6 +24,7 @@ class TokenManager private constructor(context: Context) {
.putString(KEY_REFRESH_TOKEN, refreshToken)
.putInt("user_id", userId)
.putString("currenUserName", currenUserName)
.putString("profile_image_url", profile_image_url)
.commit()
// Do not log the token itself.
@ -37,6 +38,7 @@ class TokenManager private constructor(context: Context) {
}
fun currentUserName(): String? = preferences.getString("full_name", null)
fun currentProfileImage(): String? = preferences.getString("profile_image_url", null)
fun getAccessToken(): String? {
return preferences.getString(KEY_ACCESS_TOKEN, null)

4
app/src/main/java/com/example/dattingapp/registration/RegisterRequest.kt

@ -74,5 +74,7 @@ data class LoginUser(
data class LoginProfile(
@SerializedName("full_name")
val full_name: String? = null
val full_name: String? = null,
@SerializedName("profile_image_url")
val profile_image_url: String? = null
)

2
app/src/main/java/com/example/dattingapp/ui/theme/Color.kt

@ -113,7 +113,7 @@ colors = listOf(
Color(0xFF6B00B0) // Deep Purple
)
)
val purpleButtonColor = Color(0xFF6B00F5)
val purpleButtonColor = Color(0x236B00F5)
// Same post id always gives the same color
val OverlayShadow = Shadow(

Loading…
Cancel
Save