diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 0000000..8c7d915
--- /dev/null
+++ b/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/chatgptlite/wanted/constants/Constants.kt b/app/src/main/java/com/chatgptlite/wanted/constants/Constants.kt
index 3372de9..a4c0e9f 100644
--- a/app/src/main/java/com/chatgptlite/wanted/constants/Constants.kt
+++ b/app/src/main/java/com/chatgptlite/wanted/constants/Constants.kt
@@ -8,4 +8,4 @@ const val urlToAvatarGPT = "https://gptapk.com/wp-content/uploads/2023/02/chatgp
const val urlToGithub = "https://github.com/lambiengcode"
const val matchResultString = "\"text\":"
-const val matchResultTurboString = "\"content\":"
\ No newline at end of file
+const val matchResultTurboString = "\"content\":"
diff --git a/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepository.kt b/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepository.kt
index 771af81..20f49e3 100644
--- a/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepository.kt
+++ b/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepository.kt
@@ -5,5 +5,5 @@ import com.chatgptlite.wanted.models.ConversationModel
interface ConversationRepository {
suspend fun fetchConversations() : MutableList
fun newConversation(conversation: ConversationModel) : ConversationModel
- fun deleteConversation()
+ suspend fun deleteConversation(conversationId: String)
}
\ No newline at end of file
diff --git a/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepositoryImpl.kt b/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepositoryImpl.kt
index 0ccd169..1c017c3 100644
--- a/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepositoryImpl.kt
+++ b/app/src/main/java/com/chatgptlite/wanted/data/remote/ConversationRepositoryImpl.kt
@@ -1,7 +1,11 @@
package com.chatgptlite.wanted.data.remote
+import android.content.ContentValues
+import android.util.Log
import com.chatgptlite.wanted.constants.conversationCollection
+import com.chatgptlite.wanted.helpers.DataHolder
import com.chatgptlite.wanted.models.ConversationModel
+import com.google.firebase.firestore.FieldValue
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.QuerySnapshot
@@ -11,12 +15,11 @@ import javax.inject.Inject
class ConversationRepositoryImpl @Inject constructor(
private val fsInstance: FirebaseFirestore,
) : ConversationRepository {
+
override suspend fun fetchConversations(): MutableList {
- val result: QuerySnapshot = fsInstance.collection(conversationCollection)
- .orderBy("createdAt", Query.Direction.DESCENDING).get().await()
- if (result.documents.isNotEmpty()) {
- val documents = result.documents
+ if (getFireBaseSnapShot().documents.isNotEmpty()) {
+ val documents = getFireBaseSnapShot().documents
return documents.map {
it.toObject(ConversationModel::class.java)
@@ -31,8 +34,45 @@ class ConversationRepositoryImpl @Inject constructor(
return conversation
}
- override fun deleteConversation() {
- TODO("Not yet implemented")
+ override suspend fun deleteConversation(conversationId: String) {
+ var desiredKey: String? = null
+
+ getFireBaseSnapShot().documents.map { documentSnapshot ->
+ val id = documentSnapshot.getString("id")
+ if (id == conversationId) {
+ desiredKey = documentSnapshot.id
+ } else {
+ null
+ }
+ }
+ DataHolder.docPath = desiredKey.toString()
+
+ val docRef = fsInstance
+ .collection("conversations")
+ .document(DataHolder.docPath)
+
+ // Remove the 'capital' field from the document
+ val updates = hashMapOf(
+ "id" to FieldValue.delete(),
+ "title" to FieldValue.delete(),
+ "createdAt" to FieldValue.delete()
+ )
+ docRef.update(updates)
+ .addOnSuccessListener {
+ Log.d(
+ ContentValues.TAG,
+ "DocumentSnapshot successfully deleted from message!"
+ )
+ }
+ .addOnFailureListener { e ->
+ Log.w(
+ ContentValues.TAG,
+ "Error deleting document", e
+ )
+ }
}
+ private suspend fun getFireBaseSnapShot() =
+ fsInstance.collection(conversationCollection)
+ .orderBy("createdAt", Query.Direction.DESCENDING).get().await()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepository.kt b/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepository.kt
index 6c8d508..28437ca 100644
--- a/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepository.kt
+++ b/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepository.kt
@@ -6,5 +6,5 @@ import kotlinx.coroutines.flow.Flow
interface MessageRepository {
fun fetchMessages(conversationId: String): Flow>
fun createMessage(message: MessageModel): MessageModel
- fun deleteMessage(message: MessageModel)
+ fun deleteMessage()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepositoryImpl.kt b/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepositoryImpl.kt
index 64b9a9d..74dfcc2 100644
--- a/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepositoryImpl.kt
+++ b/app/src/main/java/com/chatgptlite/wanted/data/remote/MessageRepositoryImpl.kt
@@ -1,7 +1,11 @@
package com.chatgptlite.wanted.data.remote
+import android.content.ContentValues
+import android.util.Log
import com.chatgptlite.wanted.constants.messageCollection
+import com.chatgptlite.wanted.helpers.DataHolder
import com.chatgptlite.wanted.models.MessageModel
+import com.google.firebase.firestore.FieldValue
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import com.google.firebase.firestore.QuerySnapshot
@@ -14,9 +18,13 @@ import javax.inject.Inject
class MessageRepositoryImpl @Inject constructor(
private val fsInstance: FirebaseFirestore,
) : MessageRepository {
- override fun fetchMessages(conversationId: String): Flow> = callbackFlow {
- val result: QuerySnapshot =
- fsInstance.collection(messageCollection).whereEqualTo("conversationId", conversationId)
+ private lateinit var result: QuerySnapshot
+ override fun fetchMessages(conversationId: String): Flow> =
+ callbackFlow {
+ result =
+ fsInstance
+ .collection(messageCollection)
+ .whereEqualTo("conversationId", conversationId)
.orderBy("createdAt", Query.Direction.DESCENDING).get().await()
if (result.documents.isNotEmpty()) {
@@ -44,7 +52,32 @@ class MessageRepositoryImpl @Inject constructor(
return message
}
- override fun deleteMessage(message: MessageModel) {
- TODO("Not yet implemented")
+ override fun deleteMessage() {
+ val docRef = fsInstance
+ .collection("messages")
+ .document(DataHolder.docPath)
+
+ // Remove the fields from the document
+ val updates = hashMapOf(
+ "answer" to FieldValue.delete(),
+ "conversationId" to FieldValue.delete(),
+ "createdAt" to FieldValue.delete(),
+ "id" to FieldValue.delete(),
+ "question" to FieldValue.delete()
+ )
+ docRef.update(updates)
+ .addOnSuccessListener {
+ Log.d(
+ ContentValues.TAG,
+ "DocumentSnapshot successfully deleted from message!"
+ )
+ }
+ .addOnFailureListener { e ->
+ Log.w(
+ ContentValues.TAG,
+ "Error deleting document", e
+ )
+ }
+
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/chatgptlite/wanted/helpers/DataHolder.kt b/app/src/main/java/com/chatgptlite/wanted/helpers/DataHolder.kt
new file mode 100644
index 0000000..8dd4955
--- /dev/null
+++ b/app/src/main/java/com/chatgptlite/wanted/helpers/DataHolder.kt
@@ -0,0 +1,5 @@
+package com.chatgptlite.wanted.helpers
+
+object DataHolder {
+ var docPath: String = ""
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/chatgptlite/wanted/ui/common/AppDrawer.kt b/app/src/main/java/com/chatgptlite/wanted/ui/common/AppDrawer.kt
index a7b1d5c..3908a80 100644
--- a/app/src/main/java/com/chatgptlite/wanted/ui/common/AppDrawer.kt
+++ b/app/src/main/java/com/chatgptlite/wanted/ui/common/AppDrawer.kt
@@ -22,10 +22,7 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Edit
-import androidx.compose.material.icons.filled.Message
-import androidx.compose.material.icons.filled.Settings
-import androidx.compose.material.icons.filled.WbSunny
+import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.AddComment
import androidx.compose.material3.Divider
import androidx.compose.material3.Icon
@@ -159,7 +156,7 @@ private fun ColumnScope.HistoryConversations(
.weight(1f, false),
) {
items(conversations.size) { index ->
- ChatItem(
+ RecycleChatItem(
text = conversations[index].title,
Icons.Filled.Message,
selected = conversations[index].id == conversationId,
@@ -170,6 +167,12 @@ private fun ColumnScope.HistoryConversations(
conversationViewModel.onConversation(conversations[index])
}
},
+ onDeleteClicked = {
+ scope.launch {
+ conversationViewModel.deleteConversation(conversations[index].id)
+ conversationViewModel.deleteMessages(conversations[index].id)
+ }
+ }
)
}
}
@@ -240,6 +243,67 @@ private fun ChatItem(
)
}
}
+@Composable
+private fun RecycleChatItem(
+ text: String,
+ icon: ImageVector = Icons.Filled.Edit,
+ selected: Boolean,
+ onChatClicked: () -> Unit,
+ onDeleteClicked: () -> Unit
+) {
+ val background = if (selected) {
+ Modifier.background(MaterialTheme.colorScheme.primaryContainer)
+ } else {
+ Modifier
+ }
+ Row(
+ modifier = Modifier
+ .height(56.dp)
+ .fillMaxWidth()
+ .padding(horizontal = 34.dp)
+ .clip(CircleShape)
+ .then(background)
+ .clickable(onClick = onChatClicked),
+ verticalAlignment = CenterVertically
+ ) {
+ val iconTint = if (selected) {
+ MaterialTheme.colorScheme.primary
+ } else {
+ MaterialTheme.colorScheme.onSurfaceVariant
+ }
+ Icon(
+ icon,
+ tint = iconTint,
+ modifier = Modifier
+ .padding(start = 16.dp, top = 16.dp, bottom = 16.dp)
+ .size(25.dp),
+ contentDescription = null,
+ )
+ Text(
+ text,
+ style = MaterialTheme.typography.bodyMedium,
+ color = if (selected) {
+ MaterialTheme.colorScheme.primary
+ } else {
+ MaterialTheme.colorScheme.onSurface
+ },
+ modifier = Modifier.padding(start = 12.dp).fillMaxWidth(0.85f),
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
+ )
+ Spacer(Modifier.weight(0.9f, true))
+ Icon(
+ imageVector = Icons.Filled.Delete,
+ contentDescription = "Delete",
+ tint = if (selected) {
+ MaterialTheme.colorScheme.primary
+ } else {
+ MaterialTheme.colorScheme.onSurface
+ },
+ modifier = Modifier.clickable { onDeleteClicked() }
+ )
+ }
+}
@Composable
private fun ProfileItem(text: String, urlToImage: String?, onProfileClicked: () -> Unit) {
diff --git a/app/src/main/java/com/chatgptlite/wanted/ui/conversations/ConversationViewModel.kt b/app/src/main/java/com/chatgptlite/wanted/ui/conversations/ConversationViewModel.kt
index 7fbd6a2..8430a14 100644
--- a/app/src/main/java/com/chatgptlite/wanted/ui/conversations/ConversationViewModel.kt
+++ b/app/src/main/java/com/chatgptlite/wanted/ui/conversations/ConversationViewModel.kt
@@ -134,9 +134,11 @@ class ConversationViewModel @Inject constructor(
var response: String = ""
for (message in messagesMap[conversationId]!!.reversed()) {
- response += """
-Human:${message.question.trim()}
-Bot:${if (message.answer == "Let me thinking...") "" else message.answer.trim()}"""
+ response += """Human:${message.question.trim()}
+ |Bot:${
+ if (message.answer == "Let me thinking...") ""
+ else message.answer.trim()
+ }""".trimMargin()
}
return response
@@ -150,8 +152,7 @@ Bot:${if (message.answer == "Let me thinking...") "" else message.answer.trim()}
val response: MutableList = mutableListOf(
MessageTurbo(
- role = TurboRole.system,
- content = "Markdown style if exists code"
+ role = TurboRole.system, content = "Markdown style if exists code"
)
)
@@ -166,8 +167,24 @@ Bot:${if (message.answer == "Let me thinking...") "" else message.answer.trim()}
return response.toList()
}
+ fun deleteMessages(conversationId: String) {
+
+ val conversations: MutableList = _conversations.value.toMutableList()
+ val conversationToRemove = conversations.find { it.id == conversationId }
+
+ if (conversationToRemove != null) {
+ conversations.remove(conversationToRemove)
+ _conversations.value = conversations
+ }
+ messageRepo.deleteMessage()
+ }
+
+ suspend fun deleteConversation(conversationId: String) =
+ conversationRepo.deleteConversation(conversationId)
+
private suspend fun fetchMessages() {
- if (_currentConversation.value.isEmpty() || _messages.value[_currentConversation.value] != null) return
+ if (_currentConversation.value.isEmpty() ||
+ _messages.value[_currentConversation.value] != null) return
val flow: Flow> = messageRepo.fetchMessages(_currentConversation.value)