auth to server-V69

This commit is contained in:
Eric85710 2026-05-08 15:49:02 +08:00
parent a9a17915c5
commit 041fa0bd9c
3 changed files with 31 additions and 45 deletions

View file

@ -6,7 +6,8 @@ import com.squareup.moshi.JsonClass
@JsonClass(generateAdapter = true)
data class FriendListResponse(
val friends: List<Friend>
// 這樣寫最安全:即便 JSON 裡少了這個欄位,也會變成 emptyList
val friends: List<Friend> = emptyList()
)
@JsonClass(generateAdapter = true)
data class Friend(
@ -15,10 +16,10 @@ data class Friend(
val username: String?, // 建議 username 也改可空
@field:Json(name = "display_name")
@Json(name = "display_name") // 移除 field: 試試看
val displayName: String?,
@field:Json(name = "avatar_url")
@Json(name = "avatar_url")
val avatarUrl: String?,
val status: String?,
@ -27,12 +28,13 @@ data class Friend(
val acceptedAt: String?
)
val Friend.fullFriendsAvatarUrl: Any
get() = if (avatarUrl.isNullOrBlank()) {
R.drawable.avatar_v1
} else if (avatarUrl.startsWith("http")) {
avatarUrl
} else {
"http://192.168.0.217$avatarUrl"
get() {
val url = avatarUrl ?: ""
return when {
url.isBlank() -> R.drawable.avatar_v1
url.startsWith("http") -> url
else -> "http://192.168.0.217$url"
}
}

View file

@ -12,10 +12,11 @@ class FriendsRepository @Inject constructor(
suspend fun getFriendList(): Result<List<Friend>> {
return try {
val response = apiService.getFriends()
// 回傳成功,並直接提取裡面的 List<Friend>
Result.success(response.friends)
// 如果 apiService 直接回傳 FriendListResponse (非 Response 封裝)
// 則直接取用,並處理 null
Result.success(response.friends ?: emptyList())
} catch (e: Exception) {
// 處理連線超時、404、500 等各種錯誤
// 這裡可以根據 e 的型別做額外處理,例如 HttpException 或 IOException
Result.failure(e)
}
}
@ -23,8 +24,8 @@ class FriendsRepository @Inject constructor(
suspend fun getPendingRequests(): Result<List<PendingFriendApiModel>> {
return try {
val response = apiService.getFriendsPending()
// 這裡回傳 API Model,轉換邏輯可以放在 ViewModel
Result.success(response.pendingRequests)
// 這裡同樣建議處理可能為 null 的情況
Result.success(response.pendingRequests ?: emptyList())
} catch (e: Exception) {
Result.failure(e)
}

View file

@ -29,44 +29,27 @@ class ContactListViewModel @Inject constructor(
private val _uiState = MutableStateFlow(ContactUiState())
val uiState: StateFlow<ContactUiState> = _uiState.asStateFlow()
// 🚩 建議刪除獨立的 _friends,全部統一使用 _uiState
init {
refreshAll()
}
fun refreshAll() {
fetchFriends()
fetchPendingRequests()
}
fun fetchFriends() {
viewModelScope.launch {
_uiState.update { it.copy(isLoading = true) }
// 1. 開始 Loading 並清除舊錯誤
_uiState.update { it.copy(isLoading = true, error = null) }
val result = repository.getFriendList()
// 2. 使用 zip 或單獨 fetch,這裡示範簡單的循序或並行處理
val friendsResult = repository.getFriendList()
val pendingResult = repository.getPendingRequests()
result.onSuccess { list ->
Log.d("DEBUG_API", "好友列表抓取成功,數量: ${list.size}")
_uiState.update { it.copy(isLoading = false, friends = list) }
}.onFailure { error ->
Log.e("DEBUG_API", "好友列表抓取失敗: ${error.message}")
_uiState.update { it.copy(isLoading = false, error = error.message) }
}
}
}
fun fetchPendingRequests() {
viewModelScope.launch {
val result = repository.getPendingRequests()
result.onSuccess { requests ->
Log.d("DEBUG_API", "待處理請求抓取成功,數量: ${requests.size}")
_uiState.update { it.copy(pendingRequests = requests) }
}.onFailure { error ->
// 🚩 這裡一定要加 Log,否則 API 壞了你不知道
Log.e("DEBUG_API", "待處理請求抓取失敗: ${error.message}")
_uiState.update { it.copy(error = error.message) }
// 3. 統一處理結果
_uiState.update { state ->
state.copy(
isLoading = false,
friends = friendsResult.getOrDefault(state.friends),
pendingRequests = pendingResult.getOrDefault(state.pendingRequests),
error = (friendsResult.exceptionOrNull() ?: pendingResult.exceptionOrNull())?.message
)
}
}
}