yayan 1 yıl önce
ebeveyn
işleme
99e26c8351

+ 9 - 11
app/src/main/java/io/nexilis/alpha/ui/components/BubleChat.kt

@@ -4,8 +4,8 @@ import android.text.format.DateUtils
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
 import androidx.compose.foundation.combinedClickable
-import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
 import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.Spacer
 import androidx.compose.foundation.layout.padding
@@ -39,12 +39,12 @@ fun RightBubbleChat(
     modifier: Modifier,
     message: Message,
     messageStatusModel: MessageStatusViewModel = hiltViewModel(),
-    content: @Composable () -> Unit
+    content: @Composable ColumnScope.() -> Unit
 ) {
     Column(
         modifier = modifier
     ) {
-        Box(
+        Column(
             modifier = Modifier
                 .align(Alignment.End)
                 .graphicsLayer {
@@ -54,9 +54,8 @@ fun RightBubbleChat(
                 .combinedClickable(onLongClick = {}, onClick = {})
                 .background(color = MaterialTheme.colorScheme.primaryContainer)
                 .padding(8.dp),
-        ) {
-            content()
-        }
+            content = content
+        )
         Row(
             modifier = Modifier
                 .padding(3.dp)
@@ -96,12 +95,12 @@ fun RightBubbleChat(
 fun LeftBubbleChat(
     modifier: Modifier,
     message: Message,
-    content: @Composable () -> Unit
+    content: @Composable ColumnScope.() -> Unit
 ) {
     Column(
         modifier = modifier
     ) {
-        Box(
+        Column(
             modifier = Modifier
                 .align(Alignment.Start)
                 .graphicsLayer {
@@ -111,9 +110,8 @@ fun LeftBubbleChat(
                 .combinedClickable(onLongClick = {}, onClick = {})
                 .background(color = MaterialTheme.colorScheme.surface)
                 .padding(8.dp),
-        ) {
-            content()
-        }
+            content = content
+        )
         Row(
             modifier = Modifier
                 .padding(3.dp)

+ 48 - 0
app/src/main/java/io/nexilis/alpha/ui/components/ContentChat.kt

@@ -0,0 +1,48 @@
+package io.nexilis.alpha.ui.components
+
+import androidx.compose.foundation.Image
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.layout.ContentScale
+import androidx.compose.ui.platform.LocalContext
+import androidx.compose.ui.unit.dp
+import androidx.core.content.FileProvider
+import coil.compose.rememberAsyncImagePainter
+import io.nexilis.alpha.BuildConfig
+import io.nexilis.service.data.entities.Message
+import java.util.Objects
+
+@Composable
+fun ContentChat(message: Message) {
+    val context = LocalContext.current
+    if (message.image_id.isNotEmpty()) {
+        val file = context.getFileStreamPath(message.image_id)
+        val uri = FileProvider.getUriForFile(
+            Objects.requireNonNull(context),
+            BuildConfig.APPLICATION_ID + ".provider", file
+        )
+        Image(
+            painter = rememberAsyncImagePainter(uri),
+            contentDescription = "",
+            modifier = Modifier
+                .padding(8.dp)
+                .size(248.dp),
+            contentScale = ContentScale.Crop
+        )
+        if (message.message_text.isNotEmpty()) {
+            Text(
+                text = message.message_text,
+                style = MaterialTheme.typography.bodyMedium,
+            )
+        }
+    } else {
+        Text(
+            text = message.message_text,
+            style = MaterialTheme.typography.bodyMedium,
+        )
+    }
+}

+ 3 - 8
app/src/main/java/io/nexilis/alpha/ui/main/Chat.kt

@@ -25,6 +25,7 @@ import androidx.compose.ui.text.input.TextFieldValue
 import androidx.compose.ui.unit.dp
 import androidx.hilt.navigation.compose.hiltViewModel
 import androidx.navigation.NavHostController
+import io.nexilis.alpha.ui.components.ContentChat
 import io.nexilis.alpha.ui.components.LeftBubbleChat
 import io.nexilis.alpha.ui.components.RightBubbleChat
 import io.nexilis.service.data.entities.Buddy
@@ -72,20 +73,14 @@ fun Chat(
                                     modifier = Modifier.weight(weight = 0.9f, fill = false),
                                     message = message,
                                 ) {
-                                    Text(
-                                        text = list?.get(it)?.message_text ?: "",
-                                        style = MaterialTheme.typography.bodyMedium,
-                                    )
+                                    ContentChat(message = message)
                                 }
                             } else {
                                 LeftBubbleChat(
                                     modifier = Modifier.weight(weight = 0.9f, fill = false),
                                     message = message
                                 ) {
-                                    Text(
-                                        text = list?.get(it)?.message_text ?: "",
-                                        style = MaterialTheme.typography.bodyMedium,
-                                    )
+                                    ContentChat(message = message)
                                 }
                                 Spacer(modifier = Modifier.weight(0.1f))
                             }

+ 3 - 0
cpaas-lite/build.gradle

@@ -62,6 +62,9 @@ dependencies {
 
     implementation(platform("com.google.firebase:firebase-bom:32.7.2"))
     implementation "com.google.firebase:firebase-messaging-ktx"
+
+    implementation "io.coil-kt:coil:2.5.0"
+
 }
 
 kapt {

+ 19 - 2
cpaas-lite/src/main/java/io/nexilis/service/core/ChatNotification.kt

@@ -5,8 +5,10 @@ import android.app.Notification
 import android.app.NotificationChannel
 import android.app.NotificationManager
 import android.content.Context
+import android.net.Uri
 import android.os.Build
 import androidx.core.app.NotificationCompat
+import androidx.core.app.Person
 import io.nexilis.service.R
 
 class ChatNotification(private val context: Context) {
@@ -25,14 +27,29 @@ class ChatNotification(private val context: Context) {
         }
     }
 
-    fun getNotification(title: String, text: String): Notification {
+    fun getNotification(
+        person: Person,
+        title: String,
+        text: String,
+        time: Long,
+        uri: Uri? = null
+    ): Notification {
         val channelId = context.getString(R.string.notification_chat_channel_id)
         val name = context.getString(R.string.channel_name_chat)
-
+        val style = with(NotificationCompat.MessagingStyle(person)) {
+            uri?.let {
+                addMessage(
+                    NotificationCompat.MessagingStyle.Message("", time, person)
+                        .setData("image/*", it)
+                )
+            }
+            addMessage(NotificationCompat.MessagingStyle.Message(text, time, person))
+        }
         val builder = NotificationCompat.Builder(context, channelId)
             .setContentTitle(title)
             .setContentText(text)
             .setSmallIcon(context.applicationInfo.icon)
+            .setStyle(style)
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             createNotificationChannel(channelId, name).also {
                 builder.setChannelId(it.id)

+ 1 - 1
cpaas-lite/src/main/java/io/nexilis/service/core/Extension.kt

@@ -46,7 +46,7 @@ fun Context.createImageFile(): File {
     return File.createTempFile(
         imageFileName,
         ".webp",
-        externalCacheDir
+        filesDir
     )
 }
 

+ 34 - 6
cpaas-lite/src/main/java/io/nexilis/service/core/Incoming.kt

@@ -3,9 +3,16 @@ package io.nexilis.service.core
 import android.Manifest
 import android.content.Context
 import android.content.pm.PackageManager
+import android.graphics.drawable.BitmapDrawable
+import android.net.Uri
 import android.util.Log
 import androidx.core.app.ActivityCompat
 import androidx.core.app.NotificationManagerCompat
+import androidx.core.app.Person
+import androidx.core.graphics.drawable.IconCompat
+import coil.ImageLoader
+import coil.request.ImageRequest
+import coil.transform.CircleCropTransformation
 import com.google.android.gms.tasks.OnCompleteListener
 import com.google.firebase.messaging.FirebaseMessaging
 import io.nexilis.service.Api
@@ -371,7 +378,7 @@ class Incoming(private val context: Context) {
             val messageId = data.bodies["A18"] ?: ""
             if (messageId.isEmpty()) return
             val me = context.getSharedPreferences().getString("pin", "")
-            ApiRoomDatabase.getDatabase(context).messageDao().get(messageId).value?.let {
+            ApiRoomDatabase.getDatabase(context).messageDao().getSync(messageId)?.let {
                 Service.sendAck(me, data.status)
                 return
             }
@@ -380,6 +387,12 @@ class Incoming(private val context: Context) {
             val opposite = if (me == fPin) lPin else fPin
             val scope = data.bodies["A06"] ?: "3"
             val chatId = data.bodies["BA"] ?: ""
+            val imageId = data.bodies["A57"]
+            var uri: Uri? = null
+            Log.d(tag, "data.media:${data.media.size}")
+            imageId?.let { fileName ->
+                uri = Network().download(context, "https://digixplatform.com/filepalio/image/$fileName")
+            }
             ApiRoomDatabase.getDatabase(context).messageDao().insert(
                 Message(
                     messageId,
@@ -439,7 +452,7 @@ class Incoming(private val context: Context) {
             )
             if (scope == "4") {
                 val id = chatId.ifEmpty { lPin }
-                ApiRoomDatabase.getDatabase(context).groupMemberDao().get(id).value?.let {
+                ApiRoomDatabase.getDatabase(context).groupMemberDao().getSync(id)?.let {
                     it.forEach { member ->
                         ApiRoomDatabase.getDatabase(context).messageStatusDao().insert(
                             MessageStatus(
@@ -478,12 +491,27 @@ class Incoming(private val context: Context) {
                     return@with
                 }
                 val buddy = ApiRoomDatabase.getDatabase(context).buddyDao().getBuddySync(opposite)
+                    ?: return@with
                 Log.d(tag, "getBuddy:${buddy}")
+                val request = ImageRequest.Builder(context)
+                    .addHeader("User-Agent", "Mozilla/5.0")
+                    .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
+                    .data("https://digixplatform.com/filepalio/image/${buddy.image_id}")
+                    .transformations(CircleCropTransformation())
+                    .build()
+                val drawable = ImageLoader(context).execute(request).drawable as BitmapDrawable
+                val user = Person.Builder()
+                    .setIcon(IconCompat.createWithBitmap(drawable.bitmap))
+                    .setName("${buddy.first_name} ${buddy.last_name}".trim())
+                    .build()
                 notify(
                     112346,
                     ChatNotification(context).getNotification(
-                        "${buddy.first_name} ${buddy.last_name}".trim(),
-                        data.bodies["A07"]?.toNormalString() ?: ""
+                        user,
+                        "",
+                        data.bodies["A07"]?.toNormalString() ?: "",
+                        data.bodies["A19"]?.toLong() ?: System.currentTimeMillis(),
+                        uri
                     )
                 )
             }
@@ -496,11 +524,11 @@ class Incoming(private val context: Context) {
         try {
             val messageId = data.bodies["A18"] ?: ""
             if (messageId.isEmpty()) return
-            ApiRoomDatabase.getDatabase(context).messageDao().get(messageId).value?.let {
+            ApiRoomDatabase.getDatabase(context).messageDao().getSync(messageId)?.let {
                 Service.sendAsync(data.responseOk())
                 return
             }
-            Service.sendAsync(data.responseNok())
+            Service.sendAsync(data.responseOk())
         } catch (e: Exception) {
             Log.e(tag, e.message, e)
         }

+ 31 - 0
cpaas-lite/src/main/java/io/nexilis/service/core/Network.kt

@@ -1,9 +1,11 @@
 package io.nexilis.service.core
 
+import android.content.Context
 import android.net.Uri
 import android.os.Build
 import android.util.Log
 import android.webkit.MimeTypeMap
+import androidx.core.content.FileProvider
 import androidx.core.net.toUri
 import io.nexilis.service.tag
 import okhttp3.Call
@@ -16,6 +18,8 @@ import okhttp3.RequestBody
 import okhttp3.RequestBody.Companion.asRequestBody
 import okhttp3.RequestBody.Companion.toRequestBody
 import okhttp3.Response
+import okio.buffer
+import okio.sink
 import java.io.File
 import java.io.IOException
 import java.nio.file.Files
@@ -100,4 +104,31 @@ class Network {
         })
     }
 
+    fun download(context: Context, url: String): Uri? {
+        val client = OkHttpClient()
+        val request: Request = Request.Builder()
+            .url(url)
+            .addHeader("User-Agent", "Mozilla/5.0")
+            .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
+            .get()
+            .build()
+        Log.d(tag, "download:execute:$url")
+        client.newCall(request).execute().use { response ->
+            response.body?.let {
+                val file = File(context.filesDir, url.split("/").last())
+                val sink = file.sink().buffer()
+                sink.writeAll(it.source())
+                sink.close()
+                Log.d(tag, "download:execute:file:${file.name} size:${file.length()} saved")
+                val uri = FileProvider.getUriForFile(
+                    context,
+                    context.applicationContext.packageName + ".provider", file
+                )
+                Log.d(tag, "download:execute:uri:${uri}")
+                return uri
+            }
+        }
+        return null
+    }
+
 }

+ 1 - 1
cpaas-lite/src/main/java/io/nexilis/service/data/daos/BuddyDao.kt

@@ -21,7 +21,7 @@ interface BuddyDao {
     fun getBuddy(pin: String): LiveData<Buddy>
 
     @Query("select * from Buddy where f_pin = :pin")
-    fun getBuddySync(pin: String): Buddy
+    fun getBuddySync(pin: String): Buddy?
 
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insert(entity: Buddy)

+ 1 - 1
cpaas-lite/src/main/java/io/nexilis/service/data/daos/GroupMemberDao.kt

@@ -14,7 +14,7 @@ interface GroupMemberDao {
     fun getAll(): LiveData<List<GroupMember>>
 
     @Query("select * from GroupMember where group_id = :id")
-    fun get(id: String): LiveData<List<GroupMember>>
+    fun getSync(id: String): List<GroupMember>?
 
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     suspend fun insert(entity: GroupMember)

+ 3 - 0
cpaas-lite/src/main/java/io/nexilis/service/data/daos/MessageDao.kt

@@ -16,6 +16,9 @@ abstract class MessageDao {
     @Query("select * from Message where message_id = :id")
     abstract fun get(id: String): LiveData<Message>
 
+    @Query("select * from Message where message_id = :id")
+    abstract fun getSync(id: String): Message?
+
     @Query("select * from Message where opposite_pin = :pin order by server_date desc")
     abstract fun getOpposite(pin: String): LiveData<List<Message>>
 

+ 1 - 1
cpaas-lite/src/main/java/io/nexilis/service/data/repositories/MessageRepository.kt

@@ -53,7 +53,7 @@ class MessageRepository @Inject constructor(
         dao.insert(message)
         if (message.message_scope_id == "4") {
             val id = message.chat_id.ifEmpty { message.l_pin }
-            groupMemberDao.get(id).value?.let {
+            groupMemberDao.getSync(id)?.let {
                 it.forEach { member ->
                     messageStatusDao.insert(
                         MessageStatus(

+ 14 - 2
cpaas-lite/src/main/res/xml/path_provider.xml

@@ -1,6 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
 <paths>
+    <external-path
+        name="external"
+        path="." />
+    <external-files-path
+        name="external_files"
+        path="." />
+    <cache-path
+        name="cache"
+        path="." />
     <external-cache-path
-        name="my_images"
-        path="/" />
+        name="external_cache"
+        path="." />
+    <files-path
+        name="files"
+        path="." />
 </paths>