auth to server-V81
This commit is contained in:
parent
2ec5028b3e
commit
cbe0bc58ce
1 changed files with 94 additions and 5 deletions
|
|
@ -18,9 +18,13 @@ import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
import androidx.compose.material.icons.filled.Close
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material.icons.filled.PersonAdd
|
||||||
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
|
|
@ -60,10 +64,13 @@ import coil.request.ImageRequest
|
||||||
import com.example.login_v3.R
|
import com.example.login_v3.R
|
||||||
import com.example.login_v3.data.api.api_class.Friend
|
import com.example.login_v3.data.api.api_class.Friend
|
||||||
import com.example.login_v3.data.api.api_class.PendingFriendApiModel
|
import com.example.login_v3.data.api.api_class.PendingFriendApiModel
|
||||||
|
import com.example.login_v3.data.api.api_class.UserDetail
|
||||||
import com.example.login_v3.data.api.api_class.fullFriendsAvatarUrl
|
import com.example.login_v3.data.api.api_class.fullFriendsAvatarUrl
|
||||||
import com.example.login_v3.data.api.api_class.fullPendingAvatarUrl
|
import com.example.login_v3.data.api.api_class.fullPendingAvatarUrl
|
||||||
import com.example.login_v3.home.Message.ViewModel.Detail.ContactListViewModel
|
import com.example.login_v3.home.Message.ViewModel.Detail.ContactListViewModel
|
||||||
import com.example.login_v3.navigation.BottomBarViewModel
|
import com.example.login_v3.navigation.BottomBarViewModel
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun Message_contact_list(
|
fun Message_contact_list(
|
||||||
|
|
@ -74,7 +81,6 @@ fun Message_contact_list(
|
||||||
// 統一觀察 uiState 即可,避免觀察多個 Flow 導致狀態不同步
|
// 統一觀察 uiState 即可,避免觀察多個 Flow 導致狀態不同步
|
||||||
val uiState by contactListViewModel.uiState.collectAsStateWithLifecycle()
|
val uiState by contactListViewModel.uiState.collectAsStateWithLifecycle()
|
||||||
// 判斷目前是否處於「搜尋模式」
|
// 判斷目前是否處於「搜尋模式」
|
||||||
val isSearching = uiState.searchQuery.isNotBlank()
|
|
||||||
val friends = uiState.friends // 直接從 uiState 裡面取
|
val friends = uiState.friends // 直接從 uiState 裡面取
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
|
|
@ -89,17 +95,40 @@ fun Message_contact_list(
|
||||||
.padding(horizontal = 6.dp),
|
.padding(horizontal = 6.dp),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// 頂部間距
|
// 頂部間距
|
||||||
item { Spacer(modifier = Modifier.height(60.dp)) }
|
item { Spacer(modifier = Modifier.height(60.dp)) }
|
||||||
|
|
||||||
//add friends
|
// --- 搜尋框 ---
|
||||||
item {
|
item {
|
||||||
AddUserBar(
|
UserSearchBar(
|
||||||
isLoading = uiState.isLoading,
|
query = uiState.searchQuery,
|
||||||
onSendRequest = { id -> contactListViewModel.sendFriendRequest(id) }
|
onQueryChange = { contactListViewModel.onSearchQueryChanged(it) },
|
||||||
|
onSearch = { contactListViewModel.performSearch() },
|
||||||
|
isLoading = uiState.isLoading
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --- 搜尋結果區塊 (僅在有結果時顯示) ---
|
||||||
|
if (uiState.searchResults.isNotEmpty()) {
|
||||||
|
item {
|
||||||
|
Text(
|
||||||
|
"搜尋結果",
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(8.dp),
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
items(uiState.searchResults) { user ->
|
||||||
|
// 這裡你可以自定義搜尋結果的 Row
|
||||||
|
SearchResultRow(
|
||||||
|
user = user,
|
||||||
|
onAddFriend = { contactListViewModel.sendFriendRequest(user.id) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
item { HorizontalDivider(modifier = Modifier.padding(vertical = 12.dp)) }
|
||||||
|
}
|
||||||
|
|
||||||
// --- 區塊一:待處理好友 (只有在有資料時才顯示) ---
|
// --- 區塊一:待處理好友 (只有在有資料時才顯示) ---
|
||||||
if (uiState.pendingRequests.isNotEmpty()) {
|
if (uiState.pendingRequests.isNotEmpty()) {
|
||||||
item {
|
item {
|
||||||
|
|
@ -347,4 +376,64 @@ fun PendingFriendRow(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//search user
|
||||||
|
@Composable
|
||||||
|
fun UserSearchBar(
|
||||||
|
query: String,
|
||||||
|
onQueryChange: (String) -> Unit,
|
||||||
|
onSearch: () -> Unit,
|
||||||
|
isLoading: Boolean
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
value = query,
|
||||||
|
onValueChange = onQueryChange,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(8.dp),
|
||||||
|
placeholder = { Text("搜尋使用者 ID 或名稱...") },
|
||||||
|
leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
|
||||||
|
trailingIcon = {
|
||||||
|
if (isLoading) {
|
||||||
|
CircularProgressIndicator(modifier = Modifier.size(24.dp), strokeWidth = 2.dp)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
|
||||||
|
keyboardActions = KeyboardActions(onSearch = { onSearch() }),
|
||||||
|
shape = RoundedCornerShape(12.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@Composable
|
||||||
|
fun SearchResultRow(
|
||||||
|
user: UserDetail,
|
||||||
|
onAddFriend: () -> Unit
|
||||||
|
) {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.surfaceVariant)
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.padding(12.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
// 這裡放頭像
|
||||||
|
AsyncImage(
|
||||||
|
model = user.avatarUrl,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.size(40.dp).clip(CircleShape)
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(modifier = Modifier.weight(1f).padding(horizontal = 12.dp)) {
|
||||||
|
Text(user.displayName, style = MaterialTheme.typography.bodyLarge)
|
||||||
|
Text("@${user.username}", style = MaterialTheme.typography.bodySmall)
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(onClick = onAddFriend) {
|
||||||
|
Icon(Icons.Default.PersonAdd, contentDescription = "加好友")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue