dm-padding message-9
This commit is contained in:
parent
4d5d5ca916
commit
47fb10d4e4
7 changed files with 70 additions and 8 deletions
26
.idea/appInsightsSettings.xml
Normal file
26
.idea/appInsightsSettings.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="AppInsightsSettings">
|
||||||
|
<option name="tabSettings">
|
||||||
|
<map>
|
||||||
|
<entry key="Firebase Crashlytics">
|
||||||
|
<value>
|
||||||
|
<InsightsFilterSettings>
|
||||||
|
<option name="connection">
|
||||||
|
<ConnectionSetting>
|
||||||
|
<option name="appId" value="PLACEHOLDER" />
|
||||||
|
<option name="mobileSdkAppId" value="" />
|
||||||
|
<option name="projectId" value="" />
|
||||||
|
<option name="projectNumber" value="" />
|
||||||
|
</ConnectionSetting>
|
||||||
|
</option>
|
||||||
|
<option name="signal" value="SIGNAL_UNSPECIFIED" />
|
||||||
|
<option name="timeIntervalDays" value="THIRTY_DAYS" />
|
||||||
|
<option name="visibilityType" value="ALL" />
|
||||||
|
</InsightsFilterSettings>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/studiobot.xml
Normal file
6
.idea/studiobot.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="StudioBotProjectSettings">
|
||||||
|
<option name="shareContext" value="OptedIn" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
|
|
@ -108,8 +108,8 @@ interface TecnologiaApi {
|
||||||
@GET("api/dm/{room_id}/messages")
|
@GET("api/dm/{room_id}/messages")
|
||||||
suspend fun getChatMessages(
|
suspend fun getChatMessages(
|
||||||
@Path("room_id") roomId: String,
|
@Path("room_id") roomId: String,
|
||||||
@Query("cursor") cursor: String? = null, // 🎯 新增這個:載入歷史紀錄時帶入上一次的 nextCursor
|
@Query("before_id") cursor: String? = null, // 🎯 修正為與後端文件一致的 before_id
|
||||||
@Query("limit") limit: Int? = null // 💡 選填:如果後端有支援控制數量的話可以加上
|
@Query("limit") limit: Int? = null
|
||||||
): Response<MessageResponse>
|
): Response<MessageResponse>
|
||||||
|
|
||||||
// 標記聊天室已讀
|
// 標記聊天室已讀
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,18 @@ object NetworkModule {
|
||||||
tokenInterceptor: Interceptor,
|
tokenInterceptor: Interceptor,
|
||||||
tokenAuthenticator: TokenAuthenticator // 👈 注入前面實作好的 Authenticator
|
tokenAuthenticator: TokenAuthenticator // 👈 注入前面實作好的 Authenticator
|
||||||
): OkHttpClient {
|
): OkHttpClient {
|
||||||
|
val loggingInterceptor = Interceptor { chain ->
|
||||||
|
val request = chain.request()
|
||||||
|
android.util.Log.d("ChatDebug", "🚀 [Network] Request: ${request.method} ${request.url}")
|
||||||
|
val response = chain.proceed(request)
|
||||||
|
android.util.Log.d("ChatDebug", "📦 [Network] Response: ${response.code} for ${request.url}")
|
||||||
|
response
|
||||||
|
}
|
||||||
|
|
||||||
return OkHttpClient.Builder()
|
return OkHttpClient.Builder()
|
||||||
.connectTimeout(15, TimeUnit.SECONDS)
|
.connectTimeout(15, TimeUnit.SECONDS)
|
||||||
.readTimeout(15, TimeUnit.SECONDS)
|
.readTimeout(15, TimeUnit.SECONDS)
|
||||||
|
.addInterceptor(loggingInterceptor) // 負責 Log 網路請求
|
||||||
.addInterceptor(tokenInterceptor) // 負責幫一般請求加上 Token
|
.addInterceptor(tokenInterceptor) // 負責幫一般請求加上 Token
|
||||||
.authenticator(tokenAuthenticator) // 負責在 401 時自動刷新 Token
|
.authenticator(tokenAuthenticator) // 負責在 401 時自動刷新 Token
|
||||||
.build()
|
.build()
|
||||||
|
|
|
||||||
|
|
@ -180,13 +180,17 @@ class ChatRoomsRepository @Inject constructor(
|
||||||
cursor: String? = null,
|
cursor: String? = null,
|
||||||
limit: Int? = null
|
limit: Int? = null
|
||||||
): Result<MessageResponse> {
|
): Result<MessageResponse> {
|
||||||
|
Log.d("ChatDebug", "📡 [Repository] refreshChatMessages 觸發 | roomId: $roomId | cursor: $cursor | limit: $limit")
|
||||||
return try {
|
return try {
|
||||||
// 1. 把 cursor 傳給 API
|
// 1. 把 cursor 與 limit 傳給 API
|
||||||
val response = api.getChatMessages(roomId, cursor = cursor)
|
val response = api.getChatMessages(roomId, cursor = cursor, limit = limit)
|
||||||
|
|
||||||
if (response.isSuccessful) {
|
if (response.isSuccessful) {
|
||||||
val body = response.body()
|
val body = response.body()
|
||||||
if (body != null) {
|
if (body != null) {
|
||||||
|
val firstId = body.messages.firstOrNull()?.id
|
||||||
|
val lastId = body.messages.lastOrNull()?.id
|
||||||
|
Log.d("ChatDebug", "✅ [Repository] API 成功 | 收到 ${body.messages.size} 條訊息 | 首條ID: $firstId | 末條ID: $lastId | nextCursor: ${body.nextCursor}")
|
||||||
|
|
||||||
// 2. 轉換成 Entity 列表
|
// 2. 轉換成 Entity 列表
|
||||||
val entities = body.messages.map { networkMessage ->
|
val entities = body.messages.map { networkMessage ->
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,12 @@ fun MessageMessaging(
|
||||||
) { uri: Uri? ->
|
) { uri: Uri? ->
|
||||||
uri?.let { viewModel.uploadAttachment(roomId, it) }
|
uri?.let { viewModel.uploadAttachment(roomId, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//進入時重整
|
||||||
|
LaunchedEffect(roomId) {
|
||||||
|
viewModel.loadMessages(roomId)
|
||||||
|
}
|
||||||
|
|
||||||
//bottom bar on and off
|
//bottom bar on and off
|
||||||
DisposableEffect(Unit) {
|
DisposableEffect(Unit) {
|
||||||
bottomBarViewModel.setVisible(false)
|
bottomBarViewModel.setVisible(false)
|
||||||
|
|
|
||||||
|
|
@ -190,10 +190,21 @@ class ChatViewModel @Inject constructor(
|
||||||
// 💡 核心新增:往上滑載入更多老訊息 (補上 limit)
|
// 💡 核心新增:往上滑載入更多老訊息 (補上 limit)
|
||||||
// =====================================================================
|
// =====================================================================
|
||||||
fun loadMoreMessages(roomId: String) {
|
fun loadMoreMessages(roomId: String) {
|
||||||
if (isLoadingMore || !hasMore || nextCursor.isNullOrBlank()) return
|
if (isLoadingMore) {
|
||||||
|
Log.d("ChatDebug", "⚠️ [ViewModel] loadMoreMessages 略過: 正在加載中...")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!hasMore) {
|
||||||
|
Log.d("ChatDebug", "⚠️ [ViewModel] loadMoreMessages 略過: 沒有更多訊息了 (hasMore=false)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (nextCursor.isNullOrBlank()) {
|
||||||
|
Log.d("ChatDebug", "⚠️ [ViewModel] loadMoreMessages 略過: nextCursor 為空")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
isLoadingMore = true
|
isLoadingMore = true
|
||||||
Log.d("ChatViewModel", "觸發載入更多,當前 cursor: $nextCursor")
|
Log.d("ChatDebug", "🚀 [ViewModel] 開始載入更多 | 當前 cursor: $nextCursor | roomId: $roomId")
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
// 🎯 補上 limit = 20 傳遞給 Repository 與 API
|
// 🎯 補上 limit = 20 傳遞給 Repository 與 API
|
||||||
|
|
@ -201,10 +212,10 @@ class ChatViewModel @Inject constructor(
|
||||||
.onSuccess { response ->
|
.onSuccess { response ->
|
||||||
this@ChatViewModel.nextCursor = response.nextCursor
|
this@ChatViewModel.nextCursor = response.nextCursor
|
||||||
this@ChatViewModel.hasMore = response.hasMore
|
this@ChatViewModel.hasMore = response.hasMore
|
||||||
Log.d("ChatViewModel", "載入更多成功,新 cursor: $nextCursor, hasMore: $hasMore")
|
Log.d("ChatDebug", "✅ [ViewModel] 載入更多成功 | 新 cursor: $nextCursor | hasMore: $hasMore")
|
||||||
}
|
}
|
||||||
.onFailure { error ->
|
.onFailure { error ->
|
||||||
Log.e("ChatViewModel", "載入更多老訊息失敗", error)
|
Log.e("ChatDebug", "❌ [ViewModel] 載入更多失敗", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoadingMore = false
|
isLoadingMore = false
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue