add delta sync for dm-v11
This commit is contained in:
parent
afff839122
commit
ce9c146576
3 changed files with 43 additions and 12 deletions
|
|
@ -135,35 +135,52 @@ data class Message(
|
|||
// --- 🚀 新增:全域媒體屬性,讓 UI 秒讀不塞車 ---
|
||||
|
||||
val isImage: Boolean get() = type == "image" || attachment?.mimeType?.startsWith("image/") == true ||
|
||||
content.lowercase().let { it.endsWith(".jpg") || it.endsWith(".jpeg") || it.endsWith(".png") || it.endsWith(".webp") || it.endsWith(".heic") || it.endsWith(".heif") || it.endsWith(".gif") }
|
||||
content.substringBefore("?").lowercase().let { it.endsWith(".jpg") || it.endsWith(".jpeg") || it.endsWith(".png") || it.endsWith(".webp") || it.endsWith(".heic") || it.endsWith(".heif") || it.endsWith(".gif") }
|
||||
|
||||
val isGif: Boolean get() = attachment?.mimeType == "image/gif" || content.lowercase().endsWith(".gif")
|
||||
val isGif: Boolean get() = attachment?.mimeType == "image/gif" || content.substringBefore("?").lowercase().endsWith(".gif")
|
||||
|
||||
val isVideo: Boolean get() = type == "video" || attachment?.mimeType?.startsWith("video/") == true ||
|
||||
content.lowercase().let { it.endsWith(".mp4") || it.endsWith(".mov") || it.endsWith(".mkv") || it.endsWith(".avi") || it.endsWith(".3gp") || it.endsWith(".webm") }
|
||||
content.substringBefore("?").lowercase().let { it.endsWith(".mp4") || it.endsWith(".mov") || it.endsWith(".mkv") || it.endsWith(".avi") || it.endsWith(".3gp") || it.endsWith(".webm") }
|
||||
|
||||
val isAudio: Boolean get() = type == "audio" || attachment?.mimeType?.startsWith("audio/") == true ||
|
||||
content.lowercase().let { it.endsWith(".mp3") || it.endsWith(".wav") || it.endsWith(".m4a") || it.endsWith(".aac") || it.endsWith(".ogg") || it.endsWith(".opus") || it.endsWith(".amr") }
|
||||
content.substringBefore("?").lowercase().let { it.endsWith(".mp3") || it.endsWith(".wav") || it.endsWith(".m4a") || it.endsWith(".aac") || it.endsWith(".ogg") || it.endsWith(".opus") || it.endsWith(".amr") }
|
||||
|
||||
val isFile: Boolean get() = attachment?.mimeType?.startsWith("application/") == true || attachment?.mimeType == "text/plain" ||
|
||||
content.lowercase().let { it.endsWith(".zip") || it.endsWith(".rar") || it.endsWith(".7z") || it.endsWith(".pdf") || it.endsWith(".doc") || it.endsWith(".docx") || it.endsWith(".xls") || it.endsWith(".xlsx") || it.endsWith(".ppt") || it.endsWith(".pptx") || it.endsWith(".txt") }
|
||||
content.substringBefore("?").lowercase().let { it.endsWith(".zip") || it.endsWith(".rar") || it.endsWith(".7z") || it.endsWith(".pdf") || it.endsWith(".doc") || it.endsWith(".docx") || it.endsWith(".xls") || it.endsWith(".xlsx") || it.endsWith(".ppt") || it.endsWith(".pptx") || it.endsWith(".txt") }
|
||||
|
||||
val mediaUrl: String get() {
|
||||
val rawPath = attachment?.filename ?: content
|
||||
// 🎯 核心修正:媒體檔案必須優先使用 content,因為 content 包含正確的 Hash 路徑與專屬簽名
|
||||
// attachment.filename 通常只是顯示用的原始檔名 (例如 IMG_123.jpg)
|
||||
val rawPath = if (isImage || isVideo || isAudio) content else (attachment?.filename ?: content)
|
||||
val baseUrl = "https://tg.technologia-tw.com"
|
||||
return when {
|
||||
|
||||
// 🎯 Step 1: 基礎 URL 處理
|
||||
var finalUrl = when {
|
||||
rawPath.isBlank() -> ""
|
||||
rawPath.startsWith("http") -> rawPath
|
||||
rawPath.startsWith("/uploads/") -> "$baseUrl$rawPath"
|
||||
rawPath.startsWith("uploads/") -> "$baseUrl/$rawPath"
|
||||
else -> {
|
||||
val cleanPath = rawPath.removePrefix("/").removePrefix("uploads/")
|
||||
if (cleanPath.startsWith("attachment/")) {
|
||||
"$baseUrl/uploads/$cleanPath"
|
||||
} else {
|
||||
"$baseUrl/uploads/attachment/$cleanPath"
|
||||
if (cleanPath.contains("/")) "$baseUrl/uploads/$cleanPath"
|
||||
else "$baseUrl/uploads/attachment/$cleanPath"
|
||||
}
|
||||
}
|
||||
|
||||
// 🎯 Step 2: 簽名繼承 (如果 content 本身沒簽名,才去借縮圖的)
|
||||
if (!finalUrl.contains("?")) {
|
||||
attachment?.thumbnailUrl?.let { thumb ->
|
||||
if (thumb.contains("?")) {
|
||||
val signature = thumb.substringAfter("?", "")
|
||||
if (signature.isNotEmpty()) {
|
||||
finalUrl += "?$signature"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return finalUrl
|
||||
}
|
||||
}
|
||||
|
||||
@JsonClass(generateAdapter = true)
|
||||
|
|
|
|||
|
|
@ -64,11 +64,16 @@ fun ImageLightbox(
|
|||
.clickable(enabled = scale == 1f) { onDismiss() },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
// 1. 底層:大圖檢視元件(保持不變)
|
||||
AsyncImage(
|
||||
model = imageUrl,
|
||||
contentDescription = "放大檢視圖片",
|
||||
contentScale = ContentScale.Fit,
|
||||
onLoading = { android.util.Log.d("LightboxDebug", "Loading original image: $imageUrl") },
|
||||
onSuccess = { android.util.Log.d("LightboxDebug", "Successfully loaded original image") },
|
||||
onError = { error ->
|
||||
android.util.Log.e("LightboxDebug", "Failed to load original image: ${error.result.throwable.message}")
|
||||
error.result.throwable.printStackTrace()
|
||||
},
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.fillMaxHeight(0.85f)
|
||||
|
|
|
|||
|
|
@ -535,6 +535,15 @@ fun MessageMessaging(
|
|||
|
||||
val onRowClickStable = remember(viewModel) {
|
||||
{ message: MessageUiModel ->
|
||||
// Debug Logs
|
||||
Log.d("ChatDebug", "--- Clicked Message Content ---")
|
||||
Log.d("ChatDebug", "Message ID: ${message.id}")
|
||||
Log.d("ChatDebug", "Type: ${message.type}")
|
||||
Log.d("ChatDebug", "Raw Content: ${message.content}")
|
||||
Log.d("ChatDebug", "Attachment Filename: ${message.attachment?.filename}")
|
||||
Log.d("ChatDebug", "Thumbnail URL: ${message.thumbnailUrl}")
|
||||
Log.d("ChatDebug", "Final Media URL (OG): ${message.mediaUrl}")
|
||||
|
||||
//is image
|
||||
val isImage = message.isImage
|
||||
//is video
|
||||
|
|
|
|||
Loading…
Reference in a new issue