diff --git a/Android/app/src/main/AndroidManifest.xml b/Android/app/src/main/AndroidManifest.xml
index ba0f495f6065fcca8608f5ce7ff5d4a94241389a..51be55a1a2968d64f0b101d360576b37cc77cdbf 100644
--- a/Android/app/src/main/AndroidManifest.xml
+++ b/Android/app/src/main/AndroidManifest.xml
@@ -9,6 +9,9 @@
+
+
+
@@ -48,6 +51,11 @@
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/RisingApplication.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/RisingApplication.kt
index b5910f63aa2d54c3141a59bb90f9626ed8c3d5d0..3eb5b16292de4c68326ed2028816bfe4063de946 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/RisingApplication.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/RisingApplication.kt
@@ -3,6 +3,7 @@ package com.matthaigh27.chatgptwrapper
import android.annotation.SuppressLint
import android.app.Application
import android.provider.Settings
+import android.util.Log
import com.google.android.gms.tasks.OnCompleteListener
import com.google.firebase.messaging.FirebaseMessaging
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ContactDao.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ContactDao.kt
index 9eb2010056fe52c67f60cb174ea3f2431a0d26a6..ecb1de64c94b6c0e6cca209dcc15649a30b42563 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ContactDao.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ContactDao.kt
@@ -7,14 +7,14 @@ import com.matthaigh27.chatgptwrapper.data.local.entity.ContactEntity
@Dao
interface ContactDao {
@Insert
- fun insert(contact: ContactEntity)
+ suspend fun insert(contact: ContactEntity)
@Update
- fun update(contact: ContactEntity)
+ suspend fun update(contact: ContactEntity)
@Delete
- fun delete(contact: ContactEntity)
+ suspend fun delete(contact: ContactEntity)
@Query("SELECT * FROM contacts")
- fun getAllData(): List
+ suspend fun getAllData(): List
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ImageDao.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ImageDao.kt
index a68090332134d04543ac8dcbd3e8eae5481c3264..83d6a562ab88f20110e4ecba8d692bc241b34770 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ImageDao.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ImageDao.kt
@@ -7,14 +7,14 @@ import com.matthaigh27.chatgptwrapper.data.local.entity.ImageEntity
@Dao
interface ImageDao {
@Insert
- fun insert(image: ImageEntity)
+ suspend fun insert(image: ImageEntity)
@Update
- fun update(image: ImageEntity)
+ suspend fun update(image: ImageEntity)
@Delete
- fun delete(image: ImageEntity)
+ suspend fun delete(image: ImageEntity)
@Query("SELECT * FROM images")
- fun getAllData(): List
+ suspend fun getAllData(): List
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ContactModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ContactModel.kt
deleted file mode 100644
index 37acc802af87eec9934b70770c16e8a8da2fff27..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ContactModel.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.matthaigh27.chatgptwrapper.data.models
-
-data class ContactModel(
- var id: String = "",
- var name: String = "",
- var phoneList: ArrayList = ArrayList(),
- var status: String = ""
-)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpPromptModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpPromptModel.kt
deleted file mode 100644
index dfbf1fefd0526d3bda705a37e36fda5ab3b0dfa6..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpPromptModel.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.matthaigh27.chatgptwrapper.data.models
-
-data class HelpPromptModel(
- var name: String = "",
- var description: String = "",
- var prompt: String = "",
- var tags: ArrayList = ArrayList()
-)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/AlarmModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/AlarmModel.kt
similarity index 62%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/AlarmModel.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/AlarmModel.kt
index 8ffd6e9b0d9492f5431e0df363e42e550dfe8833..af305e5e5f883cf3262ff5d8552cf25b014e2ba1 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/AlarmModel.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/AlarmModel.kt
@@ -1,3 +1,3 @@
-package com.matthaigh27.chatgptwrapper.data.models
+package com.matthaigh27.chatgptwrapper.data.models.chat
data class AlarmModel(val id: Int, val time: Long, val enabled: Boolean, val label: String)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ChatMessageModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ChatMessageModel.kt
similarity index 94%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ChatMessageModel.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ChatMessageModel.kt
index ce6fb97eb53df247050cf85163eddd3211b95e94..3894530a75ff62e21fb1cb95e017b0fc7c495c09 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ChatMessageModel.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ChatMessageModel.kt
@@ -1,4 +1,4 @@
-package com.matthaigh27.chatgptwrapper.data.models
+package com.matthaigh27.chatgptwrapper.data.models.chat
import com.google.gson.JsonElement
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ContactModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ContactModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5e359ab9080991ad26b7df267a663e13f6383c7f
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ContactModel.kt
@@ -0,0 +1,8 @@
+package com.matthaigh27.chatgptwrapper.data.models.chat
+
+data class ContactModel(
+ var contactId: String = String(),
+ var displayName: String = String(),
+ var phoneNumbers: ArrayList = ArrayList(),
+ var status: String = String()
+)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpCommandModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/HelpCommandModel.kt
similarity index 62%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpCommandModel.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/HelpCommandModel.kt
index b6bd5d3dd5be36cd7044c7c65ba08dafe6a8be74..0ac371761b96706e50e96f1fd2a9c0c44bc512f5 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpCommandModel.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/HelpCommandModel.kt
@@ -1,4 +1,4 @@
-package com.matthaigh27.chatgptwrapper.data.models
+package com.matthaigh27.chatgptwrapper.data.models.chat
data class HelpCommandModel (
var main: String? = null,
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/HelpPromptModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/HelpPromptModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..635a80e1f19a636ac71280c96059b7430ab571fb
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/HelpPromptModel.kt
@@ -0,0 +1,22 @@
+package com.matthaigh27.chatgptwrapper.data.models.chat
+
+import com.google.gson.Gson
+
+data class HelpPromptModel(
+ var name: String = "",
+ var description: String = "",
+ var prompt: String = "",
+ var tags: ArrayList = ArrayList()
+) {
+ override fun toString(): String {
+ val gson = Gson()
+ return gson.toJson(this)
+ }
+
+ companion object {
+ fun init(string: String): HelpPromptModel {
+ val gson = Gson()
+ return gson.fromJson(string, HelpPromptModel::class.java)
+ }
+ }
+}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ImageModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ImageModel.kt
similarity index 62%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ImageModel.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ImageModel.kt
index c346042454201baea4d740ef0e6d638c743b724f..b3fbd5d53b469deb26853c73770e6749aba68697 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ImageModel.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chat/ImageModel.kt
@@ -1,4 +1,4 @@
-package com.matthaigh27.chatgptwrapper.data.models
+package com.matthaigh27.chatgptwrapper.data.models.chat
import android.net.Uri
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chatwidgetprops/ScheduleAlarmProps.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chatwidgetprops/ScheduleAlarmProps.kt
new file mode 100644
index 0000000000000000000000000000000000000000..5e91e71c3058d603a2b93215296285ab5aba6f3e
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/chatwidgetprops/ScheduleAlarmProps.kt
@@ -0,0 +1,46 @@
+package com.matthaigh27.chatgptwrapper.data.models.chatwidgetprops
+
+import com.google.gson.Gson
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpPromptModel
+import com.matthaigh27.chatgptwrapper.data.models.common.Time
+
+data class ScheduleAlarmProps(
+ val time: Time? = null,
+ val label: String? = null,
+ val repeat: BooleanArray? = null
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as ScheduleAlarmProps
+
+ if (time != other.time) return false
+ if (repeat != null) {
+ if (other.repeat == null) return false
+ if (!repeat.contentEquals(other.repeat)) return false
+ } else if (other.repeat != null) return false
+ if (label != other.label) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = time?.hashCode() ?: 0
+ result = 31 * result + (repeat?.contentHashCode() ?: 0)
+ result = 31 * result + (label?.hashCode() ?: 0)
+ return result
+ }
+
+ override fun toString(): String {
+ val gson = Gson()
+ return gson.toJson(this)
+ }
+
+ companion object {
+ fun init(string: String): ScheduleAlarmProps {
+ val gson = Gson()
+ return gson.fromJson(string, ScheduleAlarmProps::class.java)
+ }
+ }
+}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/common/Time.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/common/Time.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6ce132adcbbeec0efc541855789d3bba3a111bc9
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/common/Time.kt
@@ -0,0 +1,7 @@
+package com.matthaigh27.chatgptwrapper.data.models.common
+
+data class Time (
+ val hour:Int,
+ val minute:Int,
+ val second:Int,
+)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiClient.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiClient.kt
index f996199814238b7209885d74fde7021d9798ce4c..3923677834f7a909e11cafcff5fa1f379f301b1b 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiClient.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiClient.kt
@@ -1,6 +1,10 @@
package com.matthaigh27.chatgptwrapper.data.remote
import com.matthaigh27.chatgptwrapper.utils.Constants.API_BASE_URL
+import com.matthaigh27.chatgptwrapper.utils.Constants.TIME_OUT_CALL
+import com.matthaigh27.chatgptwrapper.utils.Constants.TIME_OUT_CONNECT
+import com.matthaigh27.chatgptwrapper.utils.Constants.TIME_OUT_READ
+import com.matthaigh27.chatgptwrapper.utils.Constants.TIME_OUT_WRITE
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
@@ -9,10 +13,10 @@ import java.util.concurrent.TimeUnit
object ApiClient {
private val client = OkHttpClient.Builder()
- .callTimeout(240, TimeUnit.SECONDS)
- .connectTimeout(240, TimeUnit.SECONDS)
- .readTimeout(240, TimeUnit.SECONDS)
- .writeTimeout(240, TimeUnit.SECONDS)
+ .callTimeout(TIME_OUT_CALL, TimeUnit.SECONDS)
+ .connectTimeout(TIME_OUT_CONNECT, TimeUnit.SECONDS)
+ .readTimeout(TIME_OUT_READ, TimeUnit.SECONDS)
+ .writeTimeout(TIME_OUT_WRITE, TimeUnit.SECONDS)
.build()
private val retrofit = Retrofit.Builder()
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiService.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiService.kt
index aba49215779f85e86c0614ae017d70fd11952e12..dec32d613a41fc5634e9b5864fd97bf2e3e5b47e 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiService.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiService.kt
@@ -1,8 +1,13 @@
package com.matthaigh27.chatgptwrapper.data.remote
import com.matthaigh27.chatgptwrapper.data.remote.requests.BaseApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.ImageRelatednessApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.NotificationApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainContactsApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainImageApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.responses.ApiResponse
+import com.matthaigh27.chatgptwrapper.data.remote.responses.EmptyResultApiResponse
+import com.matthaigh27.chatgptwrapper.data.remote.responses.TrainImageApiResponse
import retrofit2.Call
import retrofit2.http.Body
import retrofit2.http.POST
@@ -12,4 +17,10 @@ interface ApiService {
fun getAllHelpCommands(@Body request: BaseApiRequest) : Call
@POST("sendNotification")
fun sendNotification(@Body request: NotificationApiRequest) : Call
+ @POST("train/contacts")
+ fun trainContacts(@Body request: TrainContactsApiRequest) : Call
+ @POST("image_relatedness")
+ fun getImageRelatedness(@Body request: ImageRelatednessApiRequest) : Call
+ @POST("uploadImage")
+ fun trainImage(@Body request: TrainImageApiRequest) : Call
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ImageRelatednessApiRequest.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ImageRelatednessApiRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c637c99e45072f96160c912da0927914b558cd82
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ImageRelatednessApiRequest.kt
@@ -0,0 +1,9 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests
+
+import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
+
+data class ImageRelatednessApiRequest(
+ val image_name: String,
+ val message: String,
+ val confs: Keys
+)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/TrainContactsApiRequest.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/TrainContactsApiRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6aaf90aaa18b92ac0a269782962f87705bb828df
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/TrainContactsApiRequest.kt
@@ -0,0 +1,9 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests
+
+import com.matthaigh27.chatgptwrapper.data.models.chat.ContactModel
+import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
+
+data class TrainContactsApiRequest(
+ val contacts: ArrayList,
+ val confs: Keys
+)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/TrainImageApiRequest.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/TrainImageApiRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..781b17c1c3170d1ccfaa66fbc9491cc0d6bfd2f9
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/TrainImageApiRequest.kt
@@ -0,0 +1,9 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests
+
+import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
+
+data class TrainImageApiRequest(
+ val image_name: String,
+ val status: String,
+ val confs: Keys
+)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/ApiResponse.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/ApiResponse.kt
index 035c9a2a8bffde48d83ab4c67e39b4b5ab315df5..502ebe4e3ac935df2ecd2c7ceb264067e4f2e4b1 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/ApiResponse.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/ApiResponse.kt
@@ -8,8 +8,3 @@ data class ApiResponse (
val result: Result
)
-data class Result (
- val program: String,
- val content: JsonElement,
- val url: String
-)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/EmptyResultApiResponse.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/EmptyResultApiResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..250961cab023963f7dea7691f500ad7708cdd650
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/EmptyResultApiResponse.kt
@@ -0,0 +1,7 @@
+package com.matthaigh27.chatgptwrapper.data.remote.responses
+
+data class EmptyResultApiResponse(
+ val status_code: Int,
+ val message: List,
+ val result: String
+)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/Result.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/Result.kt
new file mode 100644
index 0000000000000000000000000000000000000000..652d70188920db95f4d29acc4a93425e30664e2d
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/Result.kt
@@ -0,0 +1,9 @@
+package com.matthaigh27.chatgptwrapper.data.remote.responses
+
+import com.google.gson.JsonElement
+
+data class Result (
+ val program: String,
+ val content: JsonElement,
+ val url: String
+)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/TrainImageApiResponse.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/TrainImageApiResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..336ba4c3db289d3b3af515f345bfe5622aed3a90
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/TrainImageApiResponse.kt
@@ -0,0 +1,12 @@
+package com.matthaigh27.chatgptwrapper.data.remote.responses
+
+data class TrainImageApiResponse(
+ val status_code: Int,
+ val message: List,
+ val result: ImageInfo
+)
+
+data class ImageInfo(
+ val image_name: String,
+ val image_text: String
+)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/FirebaseRepository.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/FirebaseRepository.kt
index 2b74b7ce97a00d32146d9a716e7b3f959df55a1d..dfa3d6c7f754a856ded7bba6367b2e414e41f3bd 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/FirebaseRepository.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/FirebaseRepository.kt
@@ -1,8 +1,14 @@
package com.matthaigh27.chatgptwrapper.data.repository
import com.google.firebase.storage.FirebaseStorage
-import com.matthaigh27.chatgptwrapper.utils.helpers.network.OnFailure
-import com.matthaigh27.chatgptwrapper.utils.helpers.network.OnSuccess
+import com.google.protobuf.Empty
+import com.matthaigh27.chatgptwrapper.data.remote.ApiResource
+import com.matthaigh27.chatgptwrapper.utils.helpers.OnFailure
+import com.matthaigh27.chatgptwrapper.utils.helpers.OnSuccess
+import kotlinx.coroutines.suspendCancellableCoroutine
+import java.util.UUID
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
object FirebaseRepository {
fun downloadImageWithName(
@@ -20,4 +26,37 @@ object FirebaseRepository {
}
return
}
+
+ fun uploadImageAsync(
+ imageByteArray: ByteArray,
+ onSuccess: OnSuccess,
+ onFailure: OnFailure
+ ) {
+ val storageRef = FirebaseStorage.getInstance().reference
+ val uuid = UUID.randomUUID()
+ val imageName = "images/${uuid}"
+ val imageRef = storageRef.child(imageName)
+
+ val uploadTask = imageRef.putBytes(imageByteArray)
+ uploadTask.addOnFailureListener {
+ onFailure("Fail to upload image to firebase.")
+ }.addOnSuccessListener {
+ onSuccess("$uuid")
+ }
+ }
+
+ suspend fun uploadImage(imageByteArray: ByteArray): String = suspendCoroutine { continuation ->
+ val storageRef = FirebaseStorage.getInstance().reference
+ val uuid = UUID.randomUUID()
+ val imageName = "images/${uuid}"
+ val imageRef = storageRef.child(imageName)
+
+ val uploadTask = imageRef.putBytes(imageByteArray)
+
+ uploadTask.addOnFailureListener {
+ continuation.resume("Error")
+ }.addOnSuccessListener {
+ continuation.resume("$uuid")
+ }
+ }
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RemoteRepository.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RemoteRepository.kt
index 7797ca5f08088eeb2d63b29d5853cf36b57cc1c9..cd6b8a7054a17baf3f95314a16b48c32447a952f 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RemoteRepository.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RemoteRepository.kt
@@ -1,30 +1,37 @@
package com.matthaigh27.chatgptwrapper.data.repository
import com.matthaigh27.chatgptwrapper.data.remote.ApiClient
+import com.matthaigh27.chatgptwrapper.data.remote.ApiResource
+import com.matthaigh27.chatgptwrapper.data.remote.requests.ImageRelatednessApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.NotificationApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainContactsApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainImageApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.responses.ApiResponse
-import com.matthaigh27.chatgptwrapper.utils.helpers.network.OnFailure
-import com.matthaigh27.chatgptwrapper.utils.helpers.network.OnSuccess
+import com.matthaigh27.chatgptwrapper.data.remote.responses.EmptyResultApiResponse
+import com.matthaigh27.chatgptwrapper.data.remote.responses.TrainImageApiResponse
+import com.matthaigh27.chatgptwrapper.utils.helpers.OnFailure
+import com.matthaigh27.chatgptwrapper.utils.helpers.OnSuccess
import com.matthaigh27.chatgptwrapper.utils.helpers.network.RequestFactory.buildBaseApiRequest
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
+import kotlin.coroutines.resume
+import kotlin.coroutines.suspendCoroutine
object RemoteRepository {
private val apiService = ApiClient.apiService
fun getAllHelpCommands(
- onSuccess: OnSuccess,
- onFailure: OnFailure
+ onSuccess: OnSuccess, onFailure: OnFailure
) {
val call = apiService.getAllHelpCommands(buildBaseApiRequest())
call.enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
- response.body()?.let {
- onSuccess(ApiResponse(it.status_code, it.message, it.result))
- }?: run {
+ response.body()?.let { data ->
+ onSuccess(data)
+ } ?: run {
onFailure(response.message())
}
}
@@ -45,8 +52,77 @@ object RemoteRepository {
call.enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
response.body()?.let { data ->
- onSuccess(ApiResponse(data.status_code, data.message, data.result))
- }?: run {
+ onSuccess(data)
+ } ?: run {
+ onFailure(response.message())
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ onFailure(t.message.toString())
+ }
+ })
+ }
+
+ fun trainContacts(
+ request: TrainContactsApiRequest,
+ onSuccess: OnSuccess,
+ onFailure: OnFailure
+ ) {
+ val call = apiService.trainContacts(request)
+
+ call.enqueue(object : Callback {
+ override fun onResponse(
+ call: Call, response: Response
+ ) {
+ response.body()?.let { data ->
+ onSuccess(data)
+ } ?: run {
+ onFailure(response.message())
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ onFailure(t.message.toString())
+ }
+ })
+ }
+
+ suspend fun trainImage(request: TrainImageApiRequest) : ApiResource = suspendCoroutine { continuation ->
+
+ val call = apiService.trainImage(request)
+
+ call.enqueue(object : Callback {
+ override fun onResponse(
+ call: Call, response: Response
+ ) {
+ response.body()?.let { data ->
+ continuation.resume(ApiResource.Success(data))
+ } ?: run {
+ continuation.resume(ApiResource.Error("Error"))
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ continuation.resume(ApiResource.Error(t.message.toString()))
+ }
+ })
+ }
+
+ fun getImageRelatedness(
+ request: ImageRelatednessApiRequest,
+ onSuccess: OnSuccess,
+ onFailure: OnFailure
+ ) {
+ val call = apiService.getImageRelatedness(request)
+
+ call.enqueue(object : Callback {
+ override fun onResponse(
+ call: Call, response: Response
+ ) {
+ response.body()?.let { data ->
+ onSuccess(data)
+ } ?: run {
onFailure(response.message())
}
}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RoomRepository.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RoomRepository.kt
index 81cb0a36f9e86df7b8176fa3c5e4dc7fd6e6df01..86d825f20f6bb16b79dd947b4abb6eb3dff1edbc 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RoomRepository.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RoomRepository.kt
@@ -13,35 +13,35 @@ object RoomRepository {
private var imageDao = databaseHandler.imageDao()
private var contactDao = databaseHandler.contactDao()
- fun getAllImages(): MutableLiveData> {
+ suspend fun getAllImages(): MutableLiveData> {
return MutableLiveData(imageDao.getAllData())
}
- fun insertImage(entity: ImageEntity) {
+ suspend fun insertImage(entity: ImageEntity) {
imageDao.insert(entity)
}
- fun updateImage(entity: ImageEntity) {
+ suspend fun updateImage(entity: ImageEntity) {
imageDao.update(entity)
}
- fun deleteImage(entity: ImageEntity) {
+ suspend fun deleteImage(entity: ImageEntity) {
imageDao.delete(entity)
}
- fun getAllContacts(): MutableLiveData> {
+ suspend fun getAllContacts(): MutableLiveData> {
return MutableLiveData(contactDao.getAllData())
}
- fun insertImage(entity: ContactEntity) {
+ suspend fun insertContact(entity: ContactEntity) {
contactDao.insert(entity)
}
- fun updateImage(entity: ContactEntity) {
+ suspend fun updateContact(entity: ContactEntity) {
contactDao.update(entity)
}
- fun deleteImage(entity: ContactEntity) {
+ suspend fun deleteContact(entity: ContactEntity) {
contactDao.delete(entity)
}
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/adapters/ChatMainAdapter.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/adapters/ChatMainAdapter.kt
index 03deb5e800281637c07a1a8641ca31bb176f3f03..604c689af46a7199eb695e1adaa028563254b812 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/adapters/ChatMainAdapter.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/adapters/ChatMainAdapter.kt
@@ -7,16 +7,29 @@ import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ImageView
+import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.recyclerview.widget.RecyclerView
import com.matthaigh27.chatgptwrapper.R
-import com.matthaigh27.chatgptwrapper.data.models.ChatMessageModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.ChatMessageModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpPromptModel
+import com.matthaigh27.chatgptwrapper.data.models.chatwidgetprops.ScheduleAlarmProps
import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.ChatMessageInterface
+import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.OnHideListener
import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.SendSmsWidget
+import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.alarm.ScheduleAlarmWidget
+import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.contact.SearchContactWidget
import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.helpprompt.HelpPromptWidget
-import com.matthaigh27.chatgptwrapper.utils.Constants
+import com.matthaigh27.chatgptwrapper.utils.Constants.PROPS_WIDGET_DESC
+import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_HELP_PROMPT
+import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_SCHEDULE_ALARM
+import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_SEARCH_CONTACT
+import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_SMS
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ContactHelper.getContactModelById
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ContactHelper.getContacts
import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ImageHelper
+import org.json.JSONArray
class ChatMainAdapter(
context: Context, list: ArrayList, callbacks: ChatMessageInterface
@@ -25,6 +38,7 @@ class ChatMainAdapter(
private val VIEW_TYPE_MSG_SENT = 0
private val VIEW_TYPE_MSG_RECEIVED = 1
private val VIEW_TYPE_CHAT_WIDGET = 2
+ private val VIEW_TYPE_CHAT_ERROR = 3
private var context: Context
private var callbacks: ChatMessageInterface
@@ -41,7 +55,7 @@ class ChatMainAdapter(
return when (viewType) {
VIEW_TYPE_MSG_SENT -> {
- SentMessageViewHolder(
+ MessageViewHolder(
inflater.inflate(
R.layout.item_container_sent_message, parent, false
)
@@ -49,13 +63,21 @@ class ChatMainAdapter(
}
VIEW_TYPE_MSG_RECEIVED -> {
- ReceivedMessageViewHolder(
+ MessageViewHolder(
inflater.inflate(
R.layout.item_container_received_message, parent, false
)
)
}
+ VIEW_TYPE_CHAT_ERROR -> {
+ MessageViewHolder(
+ inflater.inflate(
+ R.layout.item_container_error_message, parent, false
+ )
+ )
+ }
+
else -> {
ChatWidgetViewHolder(
inflater.inflate(
@@ -78,25 +100,17 @@ class ChatMainAdapter(
val index = holder.adapterPosition
val chatMessageModel: ChatMessageModel = chatMessageList[index]
when (chatMessageModel.type) {
- VIEW_TYPE_MSG_SENT -> {
- setMessageData(holder as SentMessageViewHolder, chatMessageModel)
- }
-
- VIEW_TYPE_MSG_RECEIVED -> {
- setMessageData(holder as ReceivedMessageViewHolder, chatMessageModel)
+ VIEW_TYPE_CHAT_WIDGET -> {
+ setMessageData(holder as ChatWidgetViewHolder, chatMessageModel)
}
else -> {
- setMessageData(holder as ChatWidgetViewHolder, chatMessageModel)
+ setMessageData(holder as MessageViewHolder, chatMessageModel)
}
}
}
- private fun setMessageData(holder: SentMessageViewHolder, data: ChatMessageModel) {
- holder.txtMessage.text = data.content
- }
-
- private fun setMessageData(holder: ReceivedMessageViewHolder, data: ChatMessageModel) {
+ private fun setMessageData(holder: MessageViewHolder, data: ChatMessageModel) {
if (data.hasImage) {
data.image?.let { image ->
val originBitmap = BitmapFactory.decodeByteArray(image, 0, image.size)
@@ -114,48 +128,101 @@ class ChatMainAdapter(
} else {
holder.txtMessage.text = data.content
holder.imgMessage.visibility = View.GONE
- holder.txtMessage.visibility = View.VISIBLE
+ data.content?.let {
+ holder.txtMessage.visibility = View.VISIBLE
+ } ?: run {
+ holder.txtMessage.visibility = View.GONE
+ }
}
}
private fun setMessageData(holder: ChatWidgetViewHolder, data: ChatMessageModel) {
+ holder.itemLayout.visibility = View.VISIBLE
+ val index = holder.adapterPosition
+
when (data.content) {
- Constants.TYPE_WIDGET_SMS -> {
+ TYPE_WIDGET_SMS -> {
val sendSmsWidget = SendSmsWidget(context).apply {
this.callback = callbacks
+ this.hideListener = object : OnHideListener {
+ override fun hide() {
+ holder.itemLayout.visibility = View.GONE
+ chatMessageList.removeAt(index)
+ notifyItemRemoved(index)
+ }
+ }
+ }
+
+ if (data.data != null) {
+ val widgetDesc = data.data.asJsonObject[PROPS_WIDGET_DESC].asString
+ if (widgetDesc.isNotEmpty()) {
+ sendSmsWidget.setPhoneNumber(widgetDesc)
+ }
}
+
holder.itemLayout.addView(sendSmsWidget)
- holder.itemLayout.visibility = View.VISIBLE
}
- Constants.TYPE_WIDGET_HELP_PROMPT -> {
-// val helpPromptWidget = HelpPromptWidget(context)
+ TYPE_WIDGET_HELP_PROMPT -> {
+ val widgetDesc = data.data!!.asJsonObject[PROPS_WIDGET_DESC].asString
+ val helpPromptWidget =
+ HelpPromptWidget(context, HelpPromptModel.init(widgetDesc)).apply {
+ this.callback = callbacks
+ this.hideListener = object : OnHideListener {
+ override fun hide() {
+ holder.itemLayout.visibility = View.GONE
+ chatMessageList.removeAt(index)
+ notifyItemRemoved(index)
+ }
+ }
+ }
+ holder.itemLayout.addView(helpPromptWidget)
}
- Constants.TYPE_WIDGET_SEARCH_CONTACT -> {
+ TYPE_WIDGET_SEARCH_CONTACT -> {
+ holder.llSearchContact.visibility = View.VISIBLE
- }
+ val contacts = getContacts(context)
- Constants.TYPE_WIDGET_FEEDBACK -> {
+ val contactIds = JSONArray(data.data!!.asString.replace("'", "\""))
+ for (i in 0 until contactIds.length()) {
+ val contactId = contactIds[i].toString()
+ val contact = getContactModelById(contactId, contacts)
+ val searchContactWidget = SearchContactWidget(context, contact).apply {
+ this.callback = callbacks
+ }
+ holder.llSearchContact.addView(searchContactWidget)
+ }
}
- }
- }
- inner class ReceivedMessageViewHolder internal constructor(itemView: View) :
- RecyclerView.ViewHolder(itemView) {
- var txtMessage: TextView
- var imgMessage: ImageView
- var itemLayout: ConstraintLayout
+ TYPE_WIDGET_SCHEDULE_ALARM -> {
+ var props = ScheduleAlarmProps()
+ data.data?.run {
+ val widgetDesc = data.data.asJsonObject[PROPS_WIDGET_DESC].asString
+ props = ScheduleAlarmProps.init(widgetDesc)
+ }
+ val scheduleAlarmWidget =
+ ScheduleAlarmWidget(context, props.time, props.label, props.repeat).apply {
+ this.callback = callbacks
+ this.hideListener = object : OnHideListener {
+ override fun hide() {
+ holder.itemLayout.visibility = View.GONE
+ chatMessageList.removeAt(index)
+ notifyItemRemoved(index)
+ }
+ }
+ }
+ holder.itemLayout.addView(scheduleAlarmWidget)
+ }
- init {
- txtMessage = itemView.findViewById(R.id.txt_message) as TextView
- imgMessage = itemView.findViewById(R.id.img_message) as ImageView
- itemLayout = itemView.findViewById(R.id.cl_received_message) as ConstraintLayout
+ else -> {
+ holder.itemLayout.visibility = View.GONE
+ }
}
}
- inner class SentMessageViewHolder internal constructor(itemView: View) :
+ inner class MessageViewHolder internal constructor(itemView: View) :
RecyclerView.ViewHolder(itemView) {
var txtMessage: TextView
var imgMessage: ImageView
@@ -164,16 +231,18 @@ class ChatMainAdapter(
init {
txtMessage = itemView.findViewById(R.id.txt_message) as TextView
imgMessage = itemView.findViewById(R.id.img_message) as ImageView
- itemLayout = itemView.findViewById(R.id.cl_sent_message) as ConstraintLayout
+ itemLayout = itemView.findViewById(R.id.cl_message) as ConstraintLayout
}
}
inner class ChatWidgetViewHolder internal constructor(itemView: View) :
RecyclerView.ViewHolder(itemView) {
var itemLayout: FrameLayout
+ var llSearchContact: LinearLayout
init {
itemLayout = itemView.findViewById(R.id.fl_widget_message) as FrameLayout
+ llSearchContact = itemView.findViewById(R.id.ll_contacts_widget) as LinearLayout
}
}
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/fragments/ChatMainFragment.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/fragments/ChatMainFragment.kt
index b24d07cea244ac302757188e6789318f2f8feb56..2367d21fc82ff7e3ec7f250b7624167f6d317330 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/fragments/ChatMainFragment.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/fragments/ChatMainFragment.kt
@@ -13,17 +13,19 @@ import android.view.animation.RotateAnimation
import android.widget.EditText
import android.widget.ImageView
import android.widget.LinearLayout
-import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.gson.JsonElement
+import com.google.gson.JsonObject
import com.matthaigh27.chatgptwrapper.R
-import com.matthaigh27.chatgptwrapper.data.models.ChatMessageModel
-import com.matthaigh27.chatgptwrapper.data.models.HelpCommandModel
-import com.matthaigh27.chatgptwrapper.data.models.HelpPromptModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.ChatMessageModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpCommandModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpPromptModel
+import com.matthaigh27.chatgptwrapper.data.models.chatwidgetprops.ScheduleAlarmProps
+import com.matthaigh27.chatgptwrapper.data.models.common.Time
import com.matthaigh27.chatgptwrapper.data.remote.ApiResource
import com.matthaigh27.chatgptwrapper.data.remote.responses.ApiResponse
import com.matthaigh27.chatgptwrapper.ui.chat.view.adapters.ChatMainAdapter
@@ -32,26 +34,33 @@ import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.toolbar.ChatToolsWidg
import com.matthaigh27.chatgptwrapper.ui.chat.viewmodel.ChatViewModel
import com.matthaigh27.chatgptwrapper.utils.Constants.ERROR_MSG_NOEXIST_COMMAND
import com.matthaigh27.chatgptwrapper.utils.Constants.HELP_COMMAND_ALL
+import com.matthaigh27.chatgptwrapper.utils.Constants.PROPS_WIDGET_DESC
+import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_RESPONSE_ALARM
import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_RESPONSE_ALERT
import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_RESPONSE_BROWSER
import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_RESPONSE_CONTACT
import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_RESPONSE_IMAGE
import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_RESPONSE_MESSAGE
-import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_RESPONSE_SMS
import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_HELP_PROMPT
+import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_SCHEDULE_ALARM
+import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_SEARCH_CONTACT
import com.matthaigh27.chatgptwrapper.utils.Constants.TYPE_WIDGET_SMS
+import com.matthaigh27.chatgptwrapper.utils.helpers.Converter
import com.matthaigh27.chatgptwrapper.utils.helpers.Converter.stringToHelpPromptList
import com.matthaigh27.chatgptwrapper.utils.helpers.chat.CommandHelper.getHelpCommandFromStr
import com.matthaigh27.chatgptwrapper.utils.helpers.chat.CommandHelper.isMainHelpCommand
import com.matthaigh27.chatgptwrapper.utils.helpers.chat.CommandHelper.makePromptItemUsage
import com.matthaigh27.chatgptwrapper.utils.helpers.chat.CommandHelper.makePromptUsage
import com.matthaigh27.chatgptwrapper.utils.helpers.ui.NoNewLineInputFilter
+import org.json.JSONArray
+import java.util.Calendar
class ChatMainFragment : Fragment(), OnClickListener {
private val TYPE_CHAT_SENT = 0
private val TYPE_CHAT_RECEIVE = 1
private val TYPE_CHAT_WIDGET = 2
+ private val TYPE_CHAT_ERROR = 3
private lateinit var rootView: View
lateinit var viewModel: ChatViewModel
@@ -68,6 +77,11 @@ class ChatMainFragment : Fragment(), OnClickListener {
private var chatToolsWidget: ChatToolsWidget? = null
private var helpPromptList: ArrayList? = null
+ private var currentSelectedImage: ByteArray? = null
+ private var currentUploadedImageName: String? = null
+ private var isImagePicked: Boolean = false
+ private var showloadingCount = 0
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
@@ -87,13 +101,15 @@ class ChatMainFragment : Fragment(), OnClickListener {
fetchAllCommands()
}
+
+
private fun initViewModel() {
viewModel = ViewModelProvider(this)[ChatViewModel::class.java]
}
private fun initLoadingRotate() {
loadingRotate = RotateAnimation(/* fromDegrees = */ 0f, /* toDegrees = */
- 360f, /* pivotXType = */
+ 720f, /* pivotXType = */
Animation.RELATIVE_TO_SELF, /* pivotXValue = */
0.5f, /* pivotYType = */
Animation.RELATIVE_TO_SELF, /* pivotYValue = */
@@ -135,24 +151,28 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
private fun initChatToolsWidget() {
- chatToolsWidget = ChatToolsWidget(requireContext(), requireActivity())
+ chatToolsWidget = ChatToolsWidget(requireContext(), requireActivity()).apply {
+ this.callback = chatMessageInterface
+ }
val llToolBar = rootView.findViewById(R.id.ll_toolbar)
llToolBar.addView(chatToolsWidget)
}
- private fun showToast(message: String) {
- Toast.makeText(requireContext(), message, Toast.LENGTH_LONG).show()
- }
-
private fun showLoading(isLoading: Boolean) {
val imgLoading = rootView.findViewById(R.id.sp_loading)
if (isLoading) {
imgLoading.startAnimation(loadingRotate)
imgLoading.visibility = View.VISIBLE
+ edtMessageInput?.isEnabled = false
+ showloadingCount++
} else {
- imgLoading.clearAnimation()
- imgLoading.visibility = View.GONE
+ showloadingCount--
+ if(showloadingCount == 0) {
+ imgLoading.clearAnimation()
+ imgLoading.visibility = View.GONE
+ edtMessageInput?.isEnabled = true
+ }
}
}
@@ -163,18 +183,44 @@ class ChatMainFragment : Fragment(), OnClickListener {
hasImage: Boolean = false,
image: ByteArray? = null
) {
- addChatItemToList(ChatMessageModel(type, content, data, hasImage, image))
when (type) {
TYPE_CHAT_SENT -> {
if (content!!.isNotEmpty() && content.first() == '/') {
openHelpPromptWidget(content)
return
}
- sendNotification(content)
+ if (isImagePicked) {
+ addChatItemToList(
+ ChatMessageModel(
+ type = type,
+ content = content,
+ data = data,
+ hasImage = true,
+ image = currentSelectedImage
+ )
+ )
+ isImagePicked = false
+ } else {
+ addChatItemToList(ChatMessageModel(type, content, data, hasImage, image))
+ sendNotification(content)
+ }
+ }
+
+ else -> {
+ addChatItemToList(ChatMessageModel(type, content, data, hasImage, image))
}
}
}
+ private fun addErrorMessage(
+ message: String
+ ) {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = message
+ )
+ }
+
@SuppressLint("NotifyDataSetChanged")
private fun addChatItemToList(chatModel: ChatMessageModel) {
edtMessageInput?.setText("")
@@ -184,6 +230,18 @@ class ChatMainFragment : Fragment(), OnClickListener {
rvChatList?.scrollToPosition(chatMessageList.size - 1)
}
+ private fun trainContacts() {
+ viewModel.trainContacts().observe(viewLifecycleOwner, Observer { state ->
+ showLoading(state)
+ })
+ }
+
+ private fun trainImages() {
+ viewModel.trainImages().observe(viewLifecycleOwner, Observer { state ->
+ showLoading(state)
+ })
+ }
+
private fun openHelpPromptWidget(message: String) {
try {
val command: HelpCommandModel = getHelpCommandFromStr(message)
@@ -201,17 +259,22 @@ class ChatMainFragment : Fragment(), OnClickListener {
model.name == command.main
}
- if(data.isEmpty()) {
+ if (data.isEmpty()) {
addMessage(
type = TYPE_CHAT_RECEIVE, content = ERROR_MSG_NOEXIST_COMMAND
)
} else {
+ val widgetDesc = JsonObject().apply {
+ this.addProperty(PROPS_WIDGET_DESC, data[0].toString())
+ }
addMessage(
type = TYPE_CHAT_WIDGET,
content = TYPE_WIDGET_HELP_PROMPT,
- data = data[0].toString() as JsonElement
+ data = widgetDesc
)
}
+ } ?: run {
+ addErrorMessage("Help commands don't exist.")
}
}
}
@@ -229,7 +292,7 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
} catch (e: Exception) {
e.printStackTrace()
- showToast(e.message.toString())
+ addErrorMessage(e.message.toString())
}
}
@@ -251,7 +314,7 @@ class ChatMainFragment : Fragment(), OnClickListener {
is ApiResource.Error -> {
showLoading(false)
- showToast(resource.message!!)
+ addErrorMessage(resource.message!!)
}
}
})
@@ -263,35 +326,22 @@ class ChatMainFragment : Fragment(), OnClickListener {
is ApiResource.Loading -> {
showLoading(true)
}
+
is ApiResource.Success -> {
showLoading(false)
val apiResponse = resource.data
when (apiResponse?.result?.program) {
- TYPE_RESPONSE_MESSAGE -> {
- addMessage(TYPE_CHAT_RECEIVE, apiResponse.result.content.toString())
- }
- TYPE_RESPONSE_BROWSER -> {
- fetchResponseBrowser(apiResponse)
- }
- TYPE_RESPONSE_ALERT -> {
-
- }
- TYPE_RESPONSE_CONTACT -> {
-
- }
- TYPE_RESPONSE_IMAGE -> {
- fetchResponseImage(apiResponse)
- }
- TYPE_RESPONSE_SMS -> {
-
- }
- else -> {
-
- }
+ TYPE_RESPONSE_MESSAGE -> addMessage(TYPE_CHAT_RECEIVE, apiResponse.result.content.toString())
+ TYPE_RESPONSE_BROWSER -> fetchResponseBrowser(apiResponse)
+ TYPE_RESPONSE_CONTACT -> fetchResponseContact(apiResponse)
+ TYPE_RESPONSE_IMAGE -> fetchResponseImage(apiResponse)
+ TYPE_RESPONSE_ALARM -> fetchResponseAlarm(apiResponse)
+ else -> addMessage(TYPE_CHAT_RECEIVE, apiResponse!!.result.toString())
}
}
+
is ApiResource.Error -> {
- showToast(resource.message!!)
+ addErrorMessage(resource.message!!)
showLoading(false)
}
}
@@ -325,13 +375,38 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
is ApiResource.Error -> {
- showToast(resource.message!!)
+ addErrorMessage(resource.message!!)
showLoading(false)
}
}
})
}
+ private fun fetchResponseContact(apiResponse: ApiResponse) {
+ val contactIds = JSONArray(apiResponse.result.content.asString.replace("'", "\""))
+ if (contactIds.length() > 0) {
+ addMessage(
+ type = TYPE_CHAT_WIDGET,
+ content = TYPE_WIDGET_SEARCH_CONTACT,
+ data = apiResponse.result.content
+ )
+ } else {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = "Contacts that you are looking for don't exist.",
+ )
+ }
+ }
+
+ private fun fetchResponseAlarm(apiResponse: ApiResponse) {
+ val time: Time = Converter.stringToTime(apiResponse.result.content.asJsonObject.get("time").asString)
+ val label = apiResponse.result.content.asJsonObject.get("label").asString
+ val props = ScheduleAlarmProps(time, label)
+ val widgetDesc = JsonObject().apply {
+ this.addProperty(PROPS_WIDGET_DESC, props.toString())
+ }
+ addMessage(TYPE_CHAT_WIDGET, TYPE_WIDGET_SCHEDULE_ALARM, widgetDesc)
+ }
private fun initChatInterface() {
chatMessageInterface = object : ChatMessageInterface {
@@ -350,21 +425,81 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
override fun sentHelpPrompt(prompt: String) {
+ addMessage(
+ type = TYPE_CHAT_SENT,
+ content = prompt
+ )
}
override fun canceledHelpPrompt() {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = "You canceled Help prompt."
+ )
}
override fun doVoiceCall(phoneNumber: String) {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = "You made a voice call to $phoneNumber"
+ )
}
override fun doVideoCall(phoneNumber: String) {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = "You made a video call to $phoneNumber"
+ )
}
override fun sendSmsWithPhoneNumber(phoneNumber: String) {
+ val widgetDesc = JsonObject().apply {
+ this.addProperty(PROPS_WIDGET_DESC, phoneNumber)
+ }
+ addMessage(
+ type = TYPE_CHAT_WIDGET,
+ content = TYPE_WIDGET_SMS,
+ data = widgetDesc
+ )
}
override fun pickImage(isSuccess: Boolean, data: ByteArray?) {
+ if (!isSuccess)
+ addErrorMessage("Fail to pick image")
+ viewModel.uploadImageToFirebase(data!!)
+ .observe(viewLifecycleOwner, Observer { resource ->
+ when (resource) {
+ is ApiResource.Loading -> {
+ showLoading(true)
+ }
+
+ is ApiResource.Success -> {
+ showLoading(false)
+ currentSelectedImage = data
+ currentUploadedImageName = resource.data
+ isImagePicked = true
+ }
+
+ is ApiResource.Error -> {
+ addErrorMessage(resource.message!!)
+ showLoading(false)
+ }
+ }
+ })
+ }
+
+ override fun setAlarm(hours: Int, minutes: Int, label: String) {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = "You set an alarm for $hours:$minutes with the label($label)"
+ )
+ }
+
+ override fun cancelAlarm() {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = "You canceled setting an alarm."
+ )
}
}
}
@@ -380,4 +515,10 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
}
}
+
+ override fun onResume() {
+ super.onResume()
+ trainImages()
+ trainContacts()
+ }
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/interfaces/ChatMessageInterface.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/interfaces/ChatMessageInterface.kt
index db3e2b98cd001eaae36d00fe65ad5a815e14ed6f..fe99148c23f44c8d0a4aea8f411c4be3becc8556 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/interfaces/ChatMessageInterface.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/interfaces/ChatMessageInterface.kt
@@ -9,4 +9,6 @@ interface ChatMessageInterface {
fun doVideoCall(phoneNumber: String)
fun sendSmsWithPhoneNumber(phoneNumber: String)
fun pickImage(isSuccess: Boolean, data: ByteArray? = null)
+ fun setAlarm(hours: Int, minutes:Int, label: String)
+ fun cancelAlarm()
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/interfaces/OnHideListener.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/interfaces/OnHideListener.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a1fe0595ccf8714498dc5a868973adf3965972ed
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/interfaces/OnHideListener.kt
@@ -0,0 +1,5 @@
+package com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces
+
+interface OnHideListener {
+ fun hide()
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/SendSmsWidget.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/SendSmsWidget.kt
index bbcbe8ca9a427c1497f4438a9e3a35aa1a9db986..4e522a29d1186d0bd8de895e953759c977aa136d 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/SendSmsWidget.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/SendSmsWidget.kt
@@ -10,6 +10,7 @@ import android.widget.Toast
import androidx.constraintlayout.widget.ConstraintLayout
import com.matthaigh27.chatgptwrapper.R
import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.ChatMessageInterface
+import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.OnHideListener
class SendSmsWidget(
context: Context, attrs: AttributeSet? = null
@@ -24,6 +25,7 @@ class SendSmsWidget(
private val btnCancel: Button
var callback: ChatMessageInterface? = null
+ var hideListener: OnHideListener? = null
init {
inflate(context, R.layout.widget_send_sms, this)
@@ -47,12 +49,12 @@ class SendSmsWidget(
).show()
return@setOnClickListener
}
- hide()
+ hideListener?.hide()
callback?.sentSms(edtPhoneNumber.text.toString(), edtMessage.text.toString())
}
btnCancel.setOnClickListener {
- hide()
+ hideListener?.hide()
callback?.canceledSms()
}
}
@@ -60,10 +62,4 @@ class SendSmsWidget(
fun setPhoneNumber(phonenumber: String) {
edtPhoneNumber.setText(phonenumber)
}
-
- fun hide() {
- this.visibility = View.GONE
- edtMessage.setText("")
- edtPhoneNumber.setText("")
- }
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/alarm/DayOfWeekItem.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/alarm/DayOfWeekItem.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fe13fdab012abd43d306fa994a1563b3f6e6821a
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/alarm/DayOfWeekItem.kt
@@ -0,0 +1,54 @@
+package com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.alarm
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.core.view.setPadding
+import com.matthaigh27.chatgptwrapper.R
+
+class DayOfWeekItem(
+ context: Context, day: String, attrs: AttributeSet? = null
+) : LinearLayout(context, attrs), View.OnClickListener {
+
+ private val context: Context
+ private var txtDay: TextView
+ var isChecked = false
+
+ init {
+ inflate(context, R.layout.item_day_of_week, this)
+ this.context = context
+
+ layoutParams = LayoutParams(
+ 0,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ 1f
+ )
+
+ val padding = context.resources.getDimensionPixelSize(R.dimen.spacing_tiny)
+
+ txtDay = findViewById(R.id.txt_day)
+ txtDay.text = day
+
+ txtDay.setOnClickListener(this)
+ }
+
+ override fun onClick(view: View?) {
+ when (view?.id) {
+ R.id.txt_day -> {
+ isChecked = !isChecked
+ updateBackground()
+ }
+ }
+ }
+
+ fun updateBackground() {
+ if (isChecked) {
+ txtDay.background = resources.getDrawable(R.drawable.bg_circle_button_schedule_alarm_day_selected)
+ } else {
+ txtDay.background = resources.getDrawable(R.drawable.bg_circle_button_schedule_alarm_day)
+ }
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/alarm/ScheduleAlarmWidget.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/alarm/ScheduleAlarmWidget.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8b644ab2fca5f828a8dc5b50ab51f6f794a7a5c2
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/alarm/ScheduleAlarmWidget.kt
@@ -0,0 +1,110 @@
+package com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.alarm
+
+import android.content.Context
+import android.util.AttributeSet
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TimePicker
+import androidx.constraintlayout.widget.ConstraintLayout
+import com.google.android.material.textfield.TextInputLayout
+import com.matthaigh27.chatgptwrapper.R
+import com.matthaigh27.chatgptwrapper.data.models.common.Time
+import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.ChatMessageInterface
+import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.OnHideListener
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.AlarmHelper
+
+class ScheduleAlarmWidget(
+ context: Context,
+ time: Time? = null,
+ label: String? = null,
+ repeat: BooleanArray? = null,
+ attrs: AttributeSet? = null
+) : ConstraintLayout(context, attrs), View.OnClickListener {
+
+ private val WEEK_DAY_COUNT = 7
+ private val dayOfWeek = arrayOf(
+ "S", "M", "T", "W", "T", "F", "S"
+ )
+ private val selectedDayList: BooleanArray = BooleanArray(WEEK_DAY_COUNT) { false }
+ private val dayItemList: ArrayList = ArrayList()
+
+ private val context: Context
+ private var repeat: BooleanArray? = null
+ private var llRpeat: LinearLayout
+ private var txtLabel: TextInputLayout
+ private var timePicker: TimePicker
+
+ var callback: ChatMessageInterface? = null
+ var hideListener: OnHideListener? = null
+
+ init {
+ inflate(context, R.layout.widget_schedule_alarm, this)
+ this.context = context
+ this.repeat = repeat
+
+ layoutParams = LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
+ )
+
+ findViewById(R.id.btn_ok).setOnClickListener(this)
+ findViewById(R.id.btn_cancel).setOnClickListener(this)
+
+ llRpeat = findViewById(R.id.ll_repeat)
+ txtLabel = findViewById(R.id.txt_label)
+ if (label != null) {
+ txtLabel.editText!!.setText(label)
+ }
+ timePicker = findViewById(R.id.time_picker)
+ if (time != null) {
+ timePicker.hour = time.hour
+ timePicker.minute = time.minute
+ }
+
+ initRepeatSetting()
+ }
+
+ private fun initRepeatSetting() {
+ dayOfWeek.forEachIndexed { index, day ->
+ val item = DayOfWeekItem(context, day)
+ item.setOnClickListener {
+ selectedDayList[index] = !selectedDayList[index]
+ }
+ dayItemList.add(item)
+ llRpeat.addView(item)
+ }
+ if (repeat != null) {
+ setSelectedDay(repeat!!)
+ }
+ }
+
+ private fun setSelectedDay(list: BooleanArray) {
+ list.forEachIndexed { index, status ->
+ dayItemList[index].isChecked = status
+ dayItemList[index].updateBackground()
+ }
+ }
+
+ override fun onClick(view: View?) {
+ when (view?.id) {
+ R.id.btn_ok -> {
+ AlarmHelper.createAlarm(
+ context,
+ timePicker.hour,
+ timePicker.minute,
+ txtLabel.editText?.text.toString()
+ )
+ callback?.setAlarm(
+ timePicker.hour,
+ timePicker.minute,
+ txtLabel.editText?.text.toString()
+ )
+ }
+
+ R.id.btn_cancel -> {
+ callback?.cancelAlarm()
+ }
+ }
+ hideListener?.hide()
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/ContactDetailWidget.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/ContactDetailWidget.kt
index d984993ecf1a97d05cae146e0d94ac86585c2133..56f4f98a1400af2b1339e85df813e684a7838f8d 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/ContactDetailWidget.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/ContactDetailWidget.kt
@@ -11,7 +11,7 @@ import android.widget.TextView
import com.bumptech.glide.Glide
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.matthaigh27.chatgptwrapper.R
-import com.matthaigh27.chatgptwrapper.data.models.ContactModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.ContactModel
import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.ChatMessageInterface
class ContactDetailWidget(
@@ -39,22 +39,24 @@ class ContactDetailWidget(
llPhones = findViewById(R.id.ll_contacts)
llPhones?.removeAllViews()
- txtDisplayName?.text = contactModel.name
- contactModel.phoneList.forEach { phoneNumber ->
- val contactDetailItem = ContactDetailItem(context)
- contactDetailItem.setContactDetailItemInfo(phoneNumber, contactModel.name)
- contactDetailItem.setVisibilityListener(object :
- ContactDetailItem.OnContactDetailVisibilityListener {
- override fun invisible() {
- this@ContactDetailWidget.dismiss()
- }
- })
+ txtDisplayName?.text = contactModel.displayName
+ contactModel.phoneNumbers.forEach { phoneNumber ->
+ val contactDetailItem = ContactDetailItem(context).apply {
+ this.callback = callback
+ this.setContactDetailItemInfo(phoneNumber, contactModel.displayName)
+ this.setVisibilityListener(object :
+ ContactDetailItem.OnContactDetailVisibilityListener {
+ override fun invisible() {
+ this@ContactDetailWidget.dismiss()
+ }
+ })
+ }
llPhones?.addView(contactDetailItem)
}
btnEditContact?.setOnClickListener(this)
imgAvatar = findViewById(R.id.img_avatar)
- imgAvatar?.setContactAvatar(contactModel.id.toLong())
+ imgAvatar?.setContactAvatar(contactModel.contactId.toLong())
}
private fun ImageView.setContactAvatar(contactId: Long) {
@@ -73,7 +75,7 @@ class ContactDetailWidget(
override fun onClick(view: View?) {
when (view!!.id) {
R.id.btn_edit_contact -> {
- goToContactEditor(contactModel.id)
+ goToContactEditor(contactModel.contactId)
}
R.id.btn_send_message -> {
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/SearchContactWidget.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/SearchContactWidget.kt
index 5dbedba37044b9e0f4b7099dc94782587e692763..10579fb5f2531ba7102e847ceeb0e4834fc7419d 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/SearchContactWidget.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/contact/SearchContactWidget.kt
@@ -10,12 +10,12 @@ import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.bumptech.glide.Glide
import com.matthaigh27.chatgptwrapper.R
-import com.matthaigh27.chatgptwrapper.data.models.ContactModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.ContactModel
import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.ChatMessageInterface
import de.hdodenhof.circleimageview.CircleImageView
class SearchContactWidget(
- context: Context, cotactModel: ContactModel, attrs: AttributeSet?
+ context: Context, cotactModel: ContactModel, attrs: AttributeSet? = null
) : ConstraintLayout(context, attrs), View.OnClickListener {
private var context: Context
@@ -38,8 +38,8 @@ class SearchContactWidget(
civInfoAvatar = findViewById(R.id.civ_avatar)
txtInfoName = findViewById(R.id.txt_info_name)
- txtInfoName.text = contactModel.name
- civInfoAvatar.setContactAvatar(context, contactModel.id.toLong())
+ txtInfoName.text = contactModel.displayName
+ civInfoAvatar.setContactAvatar(context, contactModel.contactId.toLong())
this.setOnClickListener(this)
}
@@ -59,7 +59,9 @@ class SearchContactWidget(
private fun showContactDetailView() {
- val bottomSheetDialog = ContactDetailWidget(context, contactModel)
+ val bottomSheetDialog = ContactDetailWidget(context, contactModel).apply {
+ this.callback = callback
+ }
bottomSheetDialog.show()
}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptWidget.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptWidget.kt
index a6f8d750351d1a0370ff72a46f0e508edad08308..48c59992c939a5df05b6c95e802d8b81ca09d942 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptWidget.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptWidget.kt
@@ -10,8 +10,9 @@ import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
import com.matthaigh27.chatgptwrapper.R
-import com.matthaigh27.chatgptwrapper.data.models.HelpPromptModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpPromptModel
import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.ChatMessageInterface
+import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.OnHideListener
class HelpPromptWidget(context: Context, model: HelpPromptModel) : ConstraintLayout(context),
View.OnClickListener {
@@ -21,7 +22,7 @@ class HelpPromptWidget(context: Context, model: HelpPromptModel) : ConstraintLay
private var promptEditTextList: ArrayList? = null
private val promptModel: HelpPromptModel
var callback: ChatMessageInterface? = null
-
+ var hideListener: OnHideListener? = null
init {
promptModel = model
@@ -70,6 +71,7 @@ class HelpPromptWidget(context: Context, model: HelpPromptModel) : ConstraintLay
callback?.canceledHelpPrompt()
}
}
+ hideListener?.hide()
}
private fun outputCompletePrompt() {
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/toolbar/ChatToolsWidget.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/toolbar/ChatToolsWidget.kt
index e5c775a29860cea6ed30df80b1ea2ed1b12fa6f7..7e5affc8c80af6a6c0e03fdc87fb0df697c3c53f 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/toolbar/ChatToolsWidget.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/toolbar/ChatToolsWidget.kt
@@ -95,7 +95,7 @@ class ChatToolsWidget(context: Context, parentActivity: Activity, attrs: Attribu
}
override fun onFailed(exception: Exception) {
-
+ callback?.pickImage(false)
}
})
}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/viewmodel/ChatViewModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/viewmodel/ChatViewModel.kt
index fb6cc737b7999297b746b32b2e68b073d6c4a939..fd109a389bd693a884ed906795ae3abc49589202 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/viewmodel/ChatViewModel.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/viewmodel/ChatViewModel.kt
@@ -1,15 +1,34 @@
package com.matthaigh27.chatgptwrapper.ui.chat.viewmodel
+import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
-import com.matthaigh27.chatgptwrapper.RisingApplication
+import com.matthaigh27.chatgptwrapper.RisingApplication.Companion.appContext
+import com.matthaigh27.chatgptwrapper.data.local.entity.ImageEntity
import com.matthaigh27.chatgptwrapper.data.remote.ApiResource
+import com.matthaigh27.chatgptwrapper.data.remote.requests.ImageRelatednessApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.NotificationApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainContactsApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainImageApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.responses.ApiResponse
+import com.matthaigh27.chatgptwrapper.data.remote.responses.EmptyResultApiResponse
import com.matthaigh27.chatgptwrapper.data.repository.FirebaseRepository
import com.matthaigh27.chatgptwrapper.data.repository.RemoteRepository
-import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ImageHelper
+import com.matthaigh27.chatgptwrapper.data.repository.RoomRepository
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ContactHelper.getChangedContacts
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ContactHelper.getContacts
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ImageHelper.getBytesFromPath
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ImageHelper.getImagesFromExternalStorage
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ImageHelper.getLocalPathFromUri
import com.matthaigh27.chatgptwrapper.utils.helpers.network.RequestFactory
+import com.matthaigh27.chatgptwrapper.utils.helpers.network.RequestFactory.buildApiKeys
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
class ChatViewModel : ViewModel() {
@@ -28,22 +47,17 @@ class ChatViewModel : ViewModel() {
fun sendNotification(message: String): MutableLiveData> {
val request = NotificationApiRequest(
- message = message,
- confs = RequestFactory.buildApiKeys()
+ message = message, confs = RequestFactory.buildApiKeys()
)
val resource: MutableLiveData> = MutableLiveData()
resource.value = ApiResource.Loading()
- RemoteRepository.sendNotification(
- request,
- onSuccess = { apiResponse ->
- resource.value = ApiResource.Success(apiResponse)
- },
- onFailure = { throwable ->
- resource.value = ApiResource.Error(throwable)
- }
- )
+ RemoteRepository.sendNotification(request, onSuccess = { apiResponse ->
+ resource.value = ApiResource.Success(apiResponse)
+ }, onFailure = { throwable ->
+ resource.value = ApiResource.Error(throwable)
+ })
return resource
}
@@ -52,25 +66,158 @@ class ChatViewModel : ViewModel() {
val resource: MutableLiveData> = MutableLiveData()
resource.value = ApiResource.Loading()
- FirebaseRepository.downloadImageWithName(
- name,
- onSuccess = { apiResponse ->
- resource.value = ApiResource.Success(apiResponse)
- },
- onFailure = { throwable ->
- resource.value = ApiResource.Error(throwable)
- }
- )
+ FirebaseRepository.downloadImageWithName(name, onSuccess = { apiResponse ->
+ resource.value = ApiResource.Success(apiResponse)
+ }, onFailure = { throwable ->
+ resource.value = ApiResource.Error(throwable)
+ })
return resource
}
- fun trainImages() {
- val originalLocalImages =
- ImageHelper.getImagesFromExternalStorage(RisingApplication.appContext.contentResolver)
+ fun uploadImageToFirebase(imageByteArray: ByteArray): MutableLiveData> {
+ val resource: MutableLiveData> = MutableLiveData()
+ resource.value = ApiResource.Loading()
+
+ FirebaseRepository.uploadImageAsync(imageByteArray, onSuccess = { apiResponse ->
+ resource.value = ApiResource.Success(apiResponse)
+ }, onFailure = { throwable ->
+ resource.value = ApiResource.Error(throwable)
+ })
+
+ return resource
}
- fun trainContacts() {
+ fun trainImages(): MutableLiveData {
+ val state: MutableLiveData = MutableLiveData()
+ state.value = true
+ CoroutineScope(Dispatchers.IO).launch {
+ val images = getImagesFromExternalStorage(appContext.contentResolver)
+ val originalImages = RoomRepository.getAllImages().value
+ val existImageStatus = BooleanArray(originalImages!!.size) { false }
+ val tasks = mutableListOf>()
+
+ Log.d("Brain", "Start")
+ images.forEach { image ->
+ var isExist = false
+ val path = getLocalPathFromUri(appContext, image.uri)
+ for (i in originalImages.indices) {
+ val entity: ImageEntity = originalImages[i]
+ if (entity.path == path) {
+ if (entity.dataModified != image.modifiedDate) {
+ val byteArray = getBytesFromPath(path)
+ val task = async {
+ val uuid = FirebaseRepository.uploadImage(byteArray)
+ if (uuid != "Error") {
+ RoomRepository.updateImage(
+ ImageEntity(
+ id = 0,
+ path = path,
+ name = uuid,
+ dataModified = image.modifiedDate
+ )
+ )
+ RemoteRepository.trainImage(
+ TrainImageApiRequest(
+ uuid, "updated", buildApiKeys()
+ )
+ )
+ }
+ }
+ tasks.add(task)
+ }
+ isExist = true
+ existImageStatus[i] = true
+ break
+ }
+ }
+ if (!isExist) {
+ path?.let {
+ val byteArray = getBytesFromPath(it)
+ val task = async {
+ val uuid = FirebaseRepository.uploadImage(byteArray)
+ if (uuid != "Error") {
+ RoomRepository.insertImage(
+ ImageEntity(
+ id = 0,
+ path = path,
+ name = uuid,
+ dataModified = image.modifiedDate
+ )
+ )
+ RemoteRepository.trainImage(
+ TrainImageApiRequest(
+ uuid, "created", buildApiKeys()
+ )
+ )
+ }
+ }
+ tasks.add(task)
+ }
+ }
+ }
+
+ for (i in existImageStatus.indices) {
+ if (!existImageStatus[i]) {
+ val task = async {
+ RoomRepository.deleteImage(
+ ImageEntity(
+ originalImages[i].id, "", "", 0L
+ )
+ )
+ val result = RemoteRepository.trainImage(
+ TrainImageApiRequest(
+ originalImages[i].name, "deleted", buildApiKeys()
+ )
+ )
+ }
+ tasks.add(task)
+ }
+ }
+
+ tasks.awaitAll()
+ Log.d("Brain", "Finish")
+ withContext(Dispatchers.Main) {
+ state.value = false
+ }
+ }
+ return state
+ }
+
+ fun trainContacts(): MutableLiveData {
+ val state: MutableLiveData = MutableLiveData()
+ state.value = true
+ val contacts = getContacts(appContext)
+ CoroutineScope(Dispatchers.Main).launch {
+ val resource: MutableLiveData> = MutableLiveData()
+ val changedContacts = getChangedContacts(contacts)
+ val request = TrainContactsApiRequest(changedContacts, RequestFactory.buildApiKeys())
+ RemoteRepository.trainContacts(request, onSuccess = { apiResponse ->
+ resource.value = ApiResource.Success(apiResponse)
+ }, onFailure = { throwable ->
+ resource.value = ApiResource.Error(throwable)
+ })
+ withContext(Dispatchers.Main) {
+ state.value = false
+ }
+ }
+ return state
+ }
+
+ fun getImageRelatedness(imageName: String, message: String): MutableLiveData> {
+ val resource: MutableLiveData> = MutableLiveData()
+ val request = ImageRelatednessApiRequest(
+ image_name = imageName, message = message, confs = buildApiKeys()
+ )
+ resource.value = ApiResource.Loading()
+
+ RemoteRepository.getImageRelatedness(request, onSuccess = { apiResponse ->
+ resource.value = ApiResource.Success(apiResponse)
+ }, onFailure = { throwable ->
+ resource.value = ApiResource.Error(throwable)
+ })
+
+ return resource
}
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/Constants.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/Constants.kt
index a62c2fdc2a57041ed6f61b7357957cd58fe45e6d..b8efcc7cd14dd4a23b68c58678d2efcc1aa77e21 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/Constants.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/Constants.kt
@@ -1,7 +1,9 @@
package com.matthaigh27.chatgptwrapper.utils
+import com.matthaigh27.chatgptwrapper.BuildConfig
+
object Constants {
- val API_BASE_URL = "https://ttt246-brain.hf.space/"
+ val API_BASE_URL = BuildConfig.BASE_URL
val TYPE_RESPONSE_MESSAGE = "message"
val TYPE_RESPONSE_BROWSER = "browser"
@@ -10,12 +12,14 @@ object Constants {
val TYPE_RESPONSE_IMAGE = "image"
val TYPE_RESPONSE_HELP_COMMAND = "help_command"
val TYPE_RESPONSE_SMS = "sms"
+ val TYPE_RESPONSE_ALARM = "alarm"
val TYPE_RESPONSE_CONTACT = "contact"
val TYPE_WIDGET_SMS = "sms"
val TYPE_WIDGET_HELP_PROMPT = "help_prompt"
val TYPE_WIDGET_FEEDBACK = "feedback"
val TYPE_WIDGET_SEARCH_CONTACT = "search_contact"
+ val TYPE_WIDGET_SCHEDULE_ALARM = "schedule_alarm"
val HELP_COMMAND_ERROR_NO_MAIN = "no main command"
val HELP_COMMAND_ERROR_NO_INVALID_FORMAT = "Invalid Command Format"
@@ -31,4 +35,11 @@ object Constants {
val FIELD_HELP_PROMPT_PROMPT = "prompt"
val FIELD_HELP_PROMPT_DESCRIPTION = "description"
val FIELD_HELP_PROMPT_TAGS = "tags"
+
+ val PROPS_WIDGET_DESC = "widget description"
+
+ val TIME_OUT_CALL = 60L
+ val TIME_OUT_CONNECT = 60L
+ val TIME_OUT_READ = 60L
+ val TIME_OUT_WRITE = 60L
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/CallbackTypes.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/CallbackTypes.kt
new file mode 100644
index 0000000000000000000000000000000000000000..53d68b28a3ce4d629e440f29e80e94d5f67d8754
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/CallbackTypes.kt
@@ -0,0 +1,6 @@
+package com.matthaigh27.chatgptwrapper.utils.helpers
+
+typealias OnSuccess = (T) -> Unit
+typealias OnFailure = (T) -> Unit
+
+typealias OnHide = () -> Unit
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/Converter.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/Converter.kt
index bbd2334f35f6ea02cb024cd8b181f6b1ae74b7a5..2fa733490f4424fcb93b2bb0a3476ce0b38cc43e 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/Converter.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/Converter.kt
@@ -1,8 +1,9 @@
package com.matthaigh27.chatgptwrapper.utils.helpers
-import com.matthaigh27.chatgptwrapper.data.models.HelpPromptModel
+import com.google.gson.Gson
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpPromptModel
+import com.matthaigh27.chatgptwrapper.data.models.common.Time
import com.matthaigh27.chatgptwrapper.utils.Constants
-import com.matthaigh27.chatgptwrapper.utils.helpers.chat.CommandHelper
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
@@ -18,7 +19,8 @@ object Converter {
val helpPromptModel = HelpPromptModel()
helpPromptModel.name = helpCommand.getString(Constants.FIELD_HELP_PROMPT_NAME)
- helpPromptModel.description = helpCommand.getString(Constants.FIELD_HELP_PROMPT_DESCRIPTION)
+ helpPromptModel.description =
+ helpCommand.getString(Constants.FIELD_HELP_PROMPT_DESCRIPTION)
helpPromptModel.prompt = helpCommand.getString(Constants.FIELD_HELP_PROMPT_PROMPT)
helpPromptModel.tags = ArrayList()
@@ -34,4 +36,12 @@ object Converter {
}
return promptList
}
+
+ fun stringToTime(strTime: String): Time {
+ val list = strTime.split(':')
+ val hour = list[0].toInt()
+ val minute = list[1].toInt()
+ val time = Time(hour, minute, 0)
+ return time
+ }
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/AlarmHelper.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/AlarmHelper.kt
index ba8b4382c0869e8f7044eb5a17d67571e9415a24..b8624729487f9d05a799d2f3c19793c4c42ea452 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/AlarmHelper.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/AlarmHelper.kt
@@ -1,34 +1,74 @@
package com.matthaigh27.chatgptwrapper.utils.helpers.chat
+import android.app.AlarmManager
+import android.app.PendingIntent
import android.content.Context
-import android.database.Cursor
-import android.net.Uri
-import com.matthaigh27.chatgptwrapper.data.models.AlarmModel
+import android.content.Context.ALARM_SERVICE
+import android.content.Intent
+import android.provider.AlarmClock
+import android.util.Log
+import java.util.Calendar
+
object AlarmHelper {
- fun getAlarmList(context: Context): List {
- val alarmsList = mutableListOf()
- val contentUri: Uri = Uri.parse("content://com.android.alarmclock/alarm")
- val cursor: Cursor? = context.contentResolver.query(contentUri, null, null, null, null)
-
- cursor?.let {
- val idIndex = it.getColumnIndex("_id")
- val timeIndex = it.getColumnIndex("alarmtime")
- val enabledIndex = it.getColumnIndex("enabled")
- val labelIndex = it.getColumnIndex("message")
-
- while (it.moveToNext()) {
- val id = it.getInt(idIndex)
- val time = it.getLong(timeIndex)
- val enabled = it.getInt(enabledIndex) == 1
- val label = it.getString(labelIndex)
-
- val alarm = AlarmModel(id, time, enabled, label)
- alarmsList.add(alarm)
+ fun createAlarm(context: Context, hour: Int, minute: Int, label: String) {
+ val calendar = Calendar.getInstance()
+
+ calendar.set(Calendar.HOUR_OF_DAY, hour)
+ calendar.set(Calendar.MINUTE, minute)
+ calendar.set(Calendar.SECOND, 0)
+
+
+ val intent = Intent("android.intent.action.SET_ALARM")
+ intent.putExtra("android.intent.extra.alarm.HOUR", hour)
+ intent.putExtra("android.intent.extra.alarm.MINUTES", minute)
+ intent.putExtra("android.intent.extra.alarm.SKIP_UI", true)
+ intent.putExtra("android.intent.extra.alarm.MESSAGE", label)
+
+ context.startActivity(intent)
+ }
+
+ fun scheduleRepeatingAlarm(context: Context, selectedDays: ArrayList, hour: Int, minute: Int) {
+ val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+
+ val alarmIntent = Intent(context, AlarmReceiver::class.java)
+ alarmIntent.action = "com.matthaigh27.chatgptwrapper"
+
+ val pendingIntent = PendingIntent.getBroadcast(
+ context,
+ 0,
+ alarmIntent,
+ PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
+ )
+
+ // Calculate the time difference between the next alarm time and now.
+ val calendar = Calendar.getInstance()
+ val timeNow = calendar.timeInMillis
+ var minTimeDiff = Long.MAX_VALUE
+
+ for (dayOfWeek in selectedDays) {
+ calendar.set(Calendar.HOUR_OF_DAY, hour)
+ calendar.set(Calendar.MINUTE, minute)
+ calendar.set(Calendar.SECOND, 0)
+ calendar.set(Calendar.MILLISECOND, 0)
+ calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek)
+
+ var alarmTime = calendar.timeInMillis
+ if (alarmTime < timeNow) { // If the alarm time is in the past, set it for the next week.
+ alarmTime += AlarmManager.INTERVAL_DAY * 7
+ }
+
+ val timeDiff = alarmTime - timeNow
+ if (timeDiff < minTimeDiff) {
+ minTimeDiff = timeDiff
}
}
- cursor?.close()
- return alarmsList
+ alarmManager.setInexactRepeating(
+ AlarmManager.RTC_WAKEUP,
+ timeNow + minTimeDiff,
+ AlarmManager.INTERVAL_DAY * 7, // Set to repeat every week.
+ pendingIntent
+ )
}
-}
\ No newline at end of file
+}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/AlarmReceiver.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/AlarmReceiver.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2d1336cf9e3abcec6df2efaa244d40882329a719
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/AlarmReceiver.kt
@@ -0,0 +1,13 @@
+package com.matthaigh27.chatgptwrapper.utils.helpers.chat
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+
+class AlarmReceiver : BroadcastReceiver() {
+ override fun onReceive(context: Context, intent: Intent) {
+ val label = intent.getStringExtra("label")
+ Log.d("AlarmReceiver", "Alarm triggered. Label: $label")
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/CommandHelper.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/CommandHelper.kt
index e67d2c5822e2549a9f1a9664f14f985c299844f9..4de05e0b86b88f37b6d060ddbdcc85be228e7901 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/CommandHelper.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/CommandHelper.kt
@@ -1,15 +1,11 @@
package com.matthaigh27.chatgptwrapper.utils.helpers.chat
-import com.matthaigh27.chatgptwrapper.data.models.HelpCommandModel
-import com.matthaigh27.chatgptwrapper.data.models.HelpPromptModel
-import com.matthaigh27.chatgptwrapper.utils.Constants.ERROR_MSG_JSON
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpCommandModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.HelpPromptModel
import com.matthaigh27.chatgptwrapper.utils.Constants.HELP_COMMAND
import com.matthaigh27.chatgptwrapper.utils.Constants.HELP_COMMAND_ALL
import com.matthaigh27.chatgptwrapper.utils.Constants.HELP_COMMAND_ERROR_NO_INVALID_FORMAT
import com.matthaigh27.chatgptwrapper.utils.Constants.HELP_COMMAND_ERROR_NO_MAIN
-import org.json.JSONArray
-import org.json.JSONException
-import org.json.JSONObject
object CommandHelper {
fun isMainHelpCommand(model: HelpCommandModel): Boolean {
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ContactHelper.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ContactHelper.kt
index a87e3f6a1b1708a84295289bc6a30ca259fe2739..5e468f3bb3a05e8167c85d0713500dbba0f69f1e 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ContactHelper.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ContactHelper.kt
@@ -4,7 +4,12 @@ import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.Context
import android.provider.ContactsContract
-import com.matthaigh27.chatgptwrapper.data.models.ContactModel
+import com.matthaigh27.chatgptwrapper.data.local.entity.ContactEntity
+import com.matthaigh27.chatgptwrapper.data.models.chat.ContactModel
+import com.matthaigh27.chatgptwrapper.data.repository.RoomRepository
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
object ContactHelper {
@SuppressLint("Range")
@@ -26,8 +31,8 @@ object ContactHelper {
)).toInt()
val contact = ContactModel()
- contact.id = id
- contact.name = name
+ contact.contactId = id
+ contact.displayName = name
if (phoneNumber > 0) {
val cursorPhone = context.contentResolver.query(
@@ -43,7 +48,7 @@ object ContactHelper {
val phoneNumValue = cursorPhone.getString(
cursorPhone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)
)
- contact.phoneList.add(phoneNumValue)
+ contact.phoneNumbers.add(phoneNumValue)
}
}
cursorPhone.close()
@@ -55,4 +60,87 @@ object ContactHelper {
cursor.close()
return contacts
}
+
+ suspend fun getChangedContacts(
+ contacts: ArrayList
+ ): ArrayList {
+ return CoroutineScope(Dispatchers.IO).async {
+ val originalContacts = RoomRepository.getAllContacts().value
+ val changedContactList = ArrayList()
+ for (i in originalContacts!!.indices) {
+ var isExist = false
+ contacts.forEach { contact ->
+ if (originalContacts[i].id == contact.contactId) {
+ if (originalContacts[i].name != contact.displayName || originalContacts[i].phoneNumber != contact.phoneNumbers.toString()) {
+ contact.status = "updated"
+ changedContactList.add(contact)
+
+ try {
+ RoomRepository.updateContact(
+ ContactEntity(
+ contact.contactId,
+ contact.displayName,
+ contact.phoneNumbers.toString()
+ )
+ )
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ } else {
+ contact.status = "nothing"
+ }
+ isExist = true
+ return@forEach
+ }
+ }
+ if (!isExist) {
+ val deletedContacts = ContactModel()
+ deletedContacts.contactId = originalContacts[i].id
+ deletedContacts.status = "deleted"
+ changedContactList.add(deletedContacts)
+
+ try {
+ RoomRepository.deleteContact(
+ ContactEntity(
+ deletedContacts.contactId,
+ deletedContacts.displayName,
+ deletedContacts.phoneNumbers.toString()
+ )
+ )
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ }
+ contacts.forEach { contact ->
+ if (contact.status.isEmpty()) {
+ contact.status = "created"
+ changedContactList.add(contact)
+ try {
+ RoomRepository.insertContact(
+ ContactEntity(
+ contact.contactId,
+ contact.displayName,
+ contact.phoneNumbers.toString()
+ )
+ )
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ }
+ }
+ changedContactList
+ }.await()
+ }
+
+ fun getContactModelById(contactId: String, contacts: ArrayList): ContactModel {
+ var contactModel = ContactModel()
+ val searchResults = contacts.filter { contact ->
+ contactId == contact.contactId
+ }
+ if (searchResults.isNotEmpty()) {
+ contactModel = searchResults[0]
+ }
+ return contactModel
+ }
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ImageHelper.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ImageHelper.kt
index cee191888d8be71dbcfa5adee4a718dc82036b5c..9e94e95628d8a75e958dcf11f6a1bd699e3cc907 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ImageHelper.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/utils/helpers/chat/ImageHelper.kt
@@ -1,6 +1,8 @@
package com.matthaigh27.chatgptwrapper.utils.helpers.chat
import android.content.ContentResolver
+import android.content.Context
+import android.database.Cursor
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
@@ -13,7 +15,7 @@ import android.net.Uri
import android.os.Environment
import android.provider.MediaStore
import com.matthaigh27.chatgptwrapper.RisingApplication
-import com.matthaigh27.chatgptwrapper.data.models.ImageModel
+import com.matthaigh27.chatgptwrapper.data.models.chat.ImageModel
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileInputStream
@@ -110,5 +112,16 @@ object ImageHelper {
return listOfImages
}
-
+ fun getLocalPathFromUri(context: Context, contentUri: Uri?): String? {
+ var cursor: Cursor? = null
+ return try {
+ val proj = arrayOf(MediaStore.Images.Media.DATA)
+ cursor = context.contentResolver.query(contentUri!!, proj, null, null, null)
+ val column_index: Int = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
+ cursor.moveToFirst()
+ cursor.getString(column_index)
+ } finally {
+ cursor?.close()
+ }
+ }
}
\ No newline at end of file
diff --git a/Android/app/src/main/res/drawable/bg_circle_button_schedule_alarm_day.xml b/Android/app/src/main/res/drawable/bg_circle_button_schedule_alarm_day.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e721748920f4a117cdcadd4cf0b943b53e575dd5
--- /dev/null
+++ b/Android/app/src/main/res/drawable/bg_circle_button_schedule_alarm_day.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/res/drawable/bg_circle_button_schedule_alarm_day_selected.xml b/Android/app/src/main/res/drawable/bg_circle_button_schedule_alarm_day_selected.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3c43a978c1791f6c6f9b4081d768afff6d603eab
--- /dev/null
+++ b/Android/app/src/main/res/drawable/bg_circle_button_schedule_alarm_day_selected.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/res/drawable/bg_item_error_message.xml b/Android/app/src/main/res/drawable/bg_item_error_message.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0a10e84a8d5f2b33ab773b41fb8c1a3ddb7ea1e2
--- /dev/null
+++ b/Android/app/src/main/res/drawable/bg_item_error_message.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/res/layout/item_container_chat_widget.xml b/Android/app/src/main/res/layout/item_container_chat_widget.xml
index 134bcfde83d12401c0125f98ae9b698644b67a3d..adea31a10545db076eb93b52f8dc7f069fc133f3 100644
--- a/Android/app/src/main/res/layout/item_container_chat_widget.xml
+++ b/Android/app/src/main/res/layout/item_container_chat_widget.xml
@@ -7,4 +7,16 @@
android:layout_marginTop="@dimen/spacing_tiny"
android:padding="@dimen/spacing_tiny">
+
+
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/res/layout/item_container_error_message.xml b/Android/app/src/main/res/layout/item_container_error_message.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4d3de7dd2ea259ba950f537cde57efe360395751
--- /dev/null
+++ b/Android/app/src/main/res/layout/item_container_error_message.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/res/layout/item_container_received_message.xml b/Android/app/src/main/res/layout/item_container_received_message.xml
index 9401f96f2e46380f5ef62dcb857dcbe40256d744..f418e6f7bdb4bb2d56365ebbd840e8fc206c6506 100644
--- a/Android/app/src/main/res/layout/item_container_received_message.xml
+++ b/Android/app/src/main/res/layout/item_container_received_message.xml
@@ -1,7 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/res/layout/widget_help_prompt.xml b/Android/app/src/main/res/layout/widget_help_prompt.xml
index 090589af91a5784a0a7fb5ee605e8107350c94da..bc309f898fb76400e2e901ca5437a8c686e256af 100644
--- a/Android/app/src/main/res/layout/widget_help_prompt.xml
+++ b/Android/app/src/main/res/layout/widget_help_prompt.xml
@@ -52,12 +52,12 @@
app:layout_constraintTop_toBottomOf="@+id/ll_prompt_keys">
diff --git a/Android/app/src/main/res/layout/widget_schedule_alarm.xml b/Android/app/src/main/res/layout/widget_schedule_alarm.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e68fdf5105c86c97d6f9e499170526c9f28cde64
--- /dev/null
+++ b/Android/app/src/main/res/layout/widget_schedule_alarm.xml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Android/app/src/main/res/layout/widget_search_contact.xml b/Android/app/src/main/res/layout/widget_search_contact.xml
index c6a8f252f41dbc0e4010c1c0229dc2fa065227c5..fe4d77c6d980351565a19d12bde6f607e722679b 100644
--- a/Android/app/src/main/res/layout/widget_search_contact.xml
+++ b/Android/app/src/main/res/layout/widget_search_contact.xml
@@ -39,11 +39,14 @@
diff --git a/Android/app/src/main/res/values/colors.xml b/Android/app/src/main/res/values/colors.xml
index cfc65c844892f785820132f9131ce9b18f29c333..0b7592649def4e02a1f5dcd2e49feb4848ce3db4 100644
--- a/Android/app/src/main/res/values/colors.xml
+++ b/Android/app/src/main/res/values/colors.xml
@@ -9,7 +9,8 @@
#222222
#99DBA7
- #FFC1FF
+ #FF4545
+ #ffffff
#d0d0d0