diff --git a/.gitignore b/.gitignore
index e7b9f8d296dfc60c809a9e32f9f473f1bc9698af..07958fdf4391420420b3b52bc97c0feec66c5adc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,4 +2,4 @@
/.idea
Brain/firebase_cred.json
Brain/logs/*
-
+**/.DS_Store
diff --git a/Android/app/src/main/AndroidManifest.xml b/Android/app/src/main/AndroidManifest.xml
index 51be55a1a2968d64f0b101d360576b37cc77cdbf..390f27ef59f40a12a2fd9677246e4fd7e80405b2 100644
--- a/Android/app/src/main/AndroidManifest.xml
+++ b/Android/app/src/main/AndroidManifest.xml
@@ -39,18 +39,20 @@
android:supportsRtl="true"
android:theme="@style/AppTheme">
-
+ android:name=".ui.splash.SplashActivity"
+ android:exported="true">
+
+
+) {
+ override fun toString(): String {
+ val gson = Gson()
+ return gson.toJson(this)
+ }
+
+ companion object {
+ fun init(string: String): MailsProps {
+ val gson = Gson()
+ return gson.fromJson(string, MailsProps::class.java)
+ }
+ }
+}
\ No newline at end of file
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
index 5e91e71c3058d603a2b93215296285ab5aba6f3e..fc1e1cacef4c221225a63de309e9b8498cb6adcd 100644
--- 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
@@ -9,29 +9,6 @@ data class ScheduleAlarmProps(
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)
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 27b0809674a361711884f29b7c26c759129fdbe8..c7a9ea2da8573c066146df5b8544112313a978fa 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,25 +1,27 @@
package com.matthaigh27.chatgptwrapper.data.remote
import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.API_BASE_URL
-import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.TIME_OUT_CALL
-import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.TIME_OUT_CONNECT
-import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.TIME_OUT_READ
-import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.TIME_OUT_WRITE
import okhttp3.OkHttpClient
-import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
object ApiClient {
- private val client = OkHttpClient.Builder()
+ val TIME_OUT_CALL = 60L
+ val TIME_OUT_CONNECT = 60L
+ val TIME_OUT_READ = 60L
+ val TIME_OUT_WRITE = 60L
+
+ private val client = OkHttpClient
+ .Builder()
.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()
+ private val retrofit = Retrofit
+ .Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiResource.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiResource.kt
index a10d70c74c0540a89045b9e6ca5d14b227a42000..6583064efcde18a0bf5bc11834cffdc6804d302e 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiResource.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiResource.kt
@@ -1,8 +1,7 @@
package com.matthaigh27.chatgptwrapper.data.remote
sealed class ApiResource(
- val data: T? = null,
- val message: String? = null
+ val data: T? = null, val message: String? = null
) {
class Success(data: T) : ApiResource(data)
class Error(message: String, data: T? = null) : ApiResource(data, message)
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 350558e4533aa663e16f26f26514c643076e3ecd..b92e422e874cf1ad5c2b239701383f08bb871e42 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,11 @@
package com.matthaigh27.chatgptwrapper.data.remote
+import com.matthaigh27.chatgptwrapper.data.models.chat.MailModel
import com.matthaigh27.chatgptwrapper.data.remote.requests.BaseApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.ComposeMailApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.ImageRelatednessApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.NotificationApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.ReadMailApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainContactsApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainImageApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.responses.ApiResponse
@@ -16,13 +19,23 @@ import retrofit2.http.POST
interface ApiService {
@POST("commands")
- fun getAllHelpCommands(@Body request: BaseApiRequest) : Call>
+ fun getAllHelpCommands(@Body request: BaseApiRequest): Call>
+
@POST("sendNotification")
- fun sendNotification(@Body request: NotificationApiRequest) : Call>
+ fun sendNotification(@Body request: NotificationApiRequest): Call>
+
@POST("train/contacts")
- fun trainContacts(@Body request: TrainContactsApiRequest) : Call>
+ fun trainContacts(@Body request: TrainContactsApiRequest): Call>
+
@POST("image_relatedness")
- fun getImageRelatedness(@Body request: ImageRelatednessApiRequest) : Call>
+ fun getImageRelatedness(@Body request: ImageRelatednessApiRequest): Call>
+
@POST("uploadImage")
- fun trainImage(@Body request: TrainImageApiRequest) : Call>
+ fun trainImage(@Body request: TrainImageApiRequest): Call>
+
+ @POST("email/read_emails")
+ fun readEmails(@Body request: ReadMailApiRequest): Call>>
+
+ @POST("email/send_email")
+ fun sendEmail(@Body request: ComposeMailApiRequest): Call>
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ComposeMailApiRequest.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ComposeMailApiRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4420fbdc772d2f26b9a0e8de7e7139e81d6b6cf6
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ComposeMailApiRequest.kt
@@ -0,0 +1,19 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests
+
+import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
+
+data class ComposeMailApiRequest(
+ val data: ComposeMailData,
+ val confs: Keys
+)
+
+data class ComposeMailData(
+ private val sender: String,
+ private val pwd: String,
+ private val to: String,
+ private val subject: String,
+ private val body: String,
+ private val to_send: Boolean,
+ private val filename: String,
+ private val file_content: String
+)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ReadMailApiRequest.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ReadMailApiRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..57fc69d137020b91f851ddc09384abe3c5d00aec
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/ReadMailApiRequest.kt
@@ -0,0 +1,14 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests
+
+import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
+
+data class ReadMailApiRequest(
+ val data: ReadMailData,
+ val confs: Keys
+)
+
+data class ReadMailData(
+ val sender: String,
+ val pwd: String,
+ val imap_folder: String,
+)
\ No newline at end of file
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 eea004d6a8e78c4187d1731ddac677639163cf18..ef76ad39d88dfbb97cf01c8c5b884587f9dea5fd 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
@@ -1,6 +1,6 @@
package com.matthaigh27.chatgptwrapper.data.remote.responses
-data class ApiResponse (
+data class ApiResponse(
val status_code: Int,
val message: List,
val result: T
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/CommonResult.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/CommonResult.kt
index 8c0f53d90f43fbd896010bf4ee170d1654ae0a78..16cc8a284ba1e0869736d388338117983df6ab63 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/CommonResult.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/CommonResult.kt
@@ -2,7 +2,7 @@ package com.matthaigh27.chatgptwrapper.data.remote.responses.results
import com.google.gson.JsonElement
-data class CommonResult (
+data class CommonResult(
val program: String,
val content: JsonElement
)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/ImageRelatenessResult.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/ImageRelatenessResult.kt
index d24ea8c7a58ce206077713f329b665d8364cb42c..f8cec8336edfa1bf52fefda5fcba94b41908e3a6 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/ImageRelatenessResult.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/results/ImageRelatenessResult.kt
@@ -5,7 +5,7 @@ data class ImageRelatenessResult(
val content: ImageRelatenessContent
)
-data class ImageRelatenessContent (
+data class ImageRelatenessContent(
val image_name: String,
val image_desc: 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 adbb2166f9d2d809dcc6bc049d28d82ebbe9bc70..4cfb2204a91177f6dc46dcdecf3f47d93cf72652 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,21 +1,15 @@
package com.matthaigh27.chatgptwrapper.data.repository
import com.google.firebase.storage.FirebaseStorage
-import com.google.protobuf.Empty
-import com.matthaigh27.chatgptwrapper.data.models.chat.AutoTaskModel
-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(
- name: String,
- onSuccess: OnSuccess,
- onFailure: OnFailure
+ name: String, onSuccess: OnSuccess, onFailure: OnFailure
) {
val reference = "images/$name"
@@ -29,9 +23,7 @@ object FirebaseRepository {
}
fun uploadImageAsync(
- imageByteArray: ByteArray,
- onSuccess: OnSuccess,
- onFailure: OnFailure
+ imageByteArray: ByteArray, onSuccess: OnSuccess, onFailure: OnFailure
) {
val storageRef = FirebaseStorage.getInstance().reference
val uuid = UUID.randomUUID()
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 4fd15d0c46dcce36333cdd9cf0b67b8efbb9511c..7774ec3896f697345b8d21beda4308d5841e0ee8 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,12 +1,15 @@
package com.matthaigh27.chatgptwrapper.data.repository
import com.matthaigh27.chatgptwrapper.RisingApplication.Companion.appContext
+import com.matthaigh27.chatgptwrapper.data.models.chat.MailModel
import com.matthaigh27.chatgptwrapper.data.models.setting.SettingModel
import com.matthaigh27.chatgptwrapper.data.remote.ApiClient
import com.matthaigh27.chatgptwrapper.data.remote.ApiResource
import com.matthaigh27.chatgptwrapper.data.remote.requests.BaseApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.ComposeMailApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.ImageRelatednessApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.NotificationApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.ReadMailApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainContactsApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.TrainImageApiRequest
import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
@@ -45,7 +48,8 @@ object RemoteRepository {
}
fun getAllHelpCommands(
- onSuccess: OnSuccess>, onFailure: OnFailure
+ onSuccess: OnSuccess>,
+ onFailure: OnFailure
) {
val call = apiService.getAllHelpCommands(BaseApiRequest(getKeys()))
@@ -154,4 +158,52 @@ object RemoteRepository {
}
})
}
+
+ fun readEmails(
+ request: ReadMailApiRequest,
+ onSuccess: OnSuccess>>,
+ onFailure: OnFailure
+ ) {
+ val call = apiService.readEmails(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())
+ }
+ })
+ }
+
+ fun sendEmail(
+ request: ComposeMailApiRequest,
+ onSuccess: OnSuccess>,
+ onFailure: OnFailure
+ ) {
+ val call = apiService.sendEmail(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())
+ }
+ })
+ }
}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/SharedPreferencesRepository.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/SharedPreferencesRepository.kt
index a5084b3903372d3eaef19b5f017a5e7eedec235e..fa725cc3450b7c58f73850ce5587a56f7ed3d4fb 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/SharedPreferencesRepository.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/SharedPreferencesRepository.kt
@@ -1,7 +1,6 @@
package com.matthaigh27.chatgptwrapper.data.repository
import android.content.Context
-import android.content.SharedPreferences
import com.matthaigh27.chatgptwrapper.RisingApplication.Companion.appContext
import com.matthaigh27.chatgptwrapper.data.models.setting.SettingModel
import com.matthaigh27.chatgptwrapper.utils.helpers.chat.SettingHelper.emptySettingModel
@@ -18,7 +17,7 @@ object SharedPreferencesRepository {
fun getConfig(): SettingModel {
val sharedPreferences = appContext.getSharedPreferences("prefs", Context.MODE_PRIVATE)
val jsonString = sharedPreferences.getString("config", "")
- if(jsonString == "" || jsonString == null) {
+ if (jsonString == "" || jsonString == null) {
return emptySettingModel()
} else {
return SettingModel.init(jsonString)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/ChatActivity.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/ChatActivity.kt
index dfb736b69b0dfca23ae0c7af8a4b8f80444161c4..e44895d3582d1b630905222f6d5abef955d1eeae 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/ChatActivity.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/ChatActivity.kt
@@ -1,100 +1,16 @@
package com.matthaigh27.chatgptwrapper.ui.chat.view
-import android.Manifest
-import android.annotation.SuppressLint
-import android.content.pm.PackageManager
-import android.os.Build
import android.os.Bundle
-import androidx.appcompat.app.AppCompatActivity
import com.matthaigh27.chatgptwrapper.R
import com.matthaigh27.chatgptwrapper.ui.base.BaseActivity
-import com.matthaigh27.chatgptwrapper.ui.chat.view.dialogs.ConfirmDialog
import com.matthaigh27.chatgptwrapper.ui.chat.view.fragments.ChatMainFragment
class ChatActivity : BaseActivity() {
-
- private val PERMISSIONS_REQUEST_CODE = 1
- private lateinit var permissions: Array
- private val CONFIRM_MESSAGE =
- "This app requires SMS, Contacts and Phone " +
- "permissions to function properly. " +
- "Please grant the necessary permissions."
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_chat)
-
- requestPermissions()
- }
-
- private fun requestPermissions() {
- /**
- * In mobile phones that use Google API 33 or higher, the permission for reading external storage
- * is disabled because the phones don't support the feature.
- */
- permissions = if(Build.VERSION.SDK_INT > Build.VERSION_CODES.S_V2) {
- arrayOf(
- Manifest.permission.SEND_SMS,
- Manifest.permission.READ_CONTACTS,
- Manifest.permission.CALL_PHONE
- )
- } else {
- arrayOf(
- Manifest.permission.SEND_SMS,
- Manifest.permission.READ_CONTACTS,
- Manifest.permission.CALL_PHONE,
- Manifest.permission.READ_EXTERNAL_STORAGE
- )
- }
- val notGrantedPermissions = permissions.filter {
- checkSelfPermission(it) != PackageManager.PERMISSION_GRANTED
- }
-
- if (notGrantedPermissions.isNotEmpty()) {
- if (shouldShowRequestPermissionRationale(notGrantedPermissions[0])) {
- // show custom permission rationale
- val confirmDialog = ConfirmDialog(this@ChatActivity)
- confirmDialog.setOnClickListener(object :
- ConfirmDialog.OnDialogButtonClickListener {
- override fun onPositiveButtonClick() {
- requestPermissions(
- notGrantedPermissions.toTypedArray(), PERMISSIONS_REQUEST_CODE
- )
- }
-
- override fun onNegativeButtonClick() {
- finish()
- }
- })
-
- confirmDialog.show()
- confirmDialog.setMessage(CONFIRM_MESSAGE)
-
- } else {
- requestPermissions(notGrantedPermissions.toTypedArray(), PERMISSIONS_REQUEST_CODE)
- }
- } else {
- // Permissions already granted, navigate to your desired fragment
- navigateToChatMainFragment()
- }
- }
-
- @SuppressLint("MissingSuperCall")
- override fun onRequestPermissionsResult(
- requestCode: Int, permissions: Array, grantResults: IntArray
- ) {
- when (requestCode) {
- PERMISSIONS_REQUEST_CODE -> {
- if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
- // Permissions granted, navigate to your desired fragment
- navigateToChatMainFragment()
- } else {
- requestPermissions()
- }
- return
- }
- }
+ navigateToChatMainFragment()
}
private fun navigateToChatMainFragment() {
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 e7db4f55a39bf961bb299d0c208e166329a237c4..a91a7d69cf577d01328f236b352c298d2136092d 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
@@ -14,6 +14,7 @@ import androidx.recyclerview.widget.RecyclerView
import com.matthaigh27.chatgptwrapper.R
import com.matthaigh27.chatgptwrapper.data.models.chat.ChatMessageModel
import com.matthaigh27.chatgptwrapper.data.models.chat.HelpPromptModel
+import com.matthaigh27.chatgptwrapper.data.models.chatwidgetprops.MailsProps
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
@@ -21,10 +22,12 @@ import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.SendSmsWid
import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.alarm.ScheduleAlarmWidget
import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.contact.ContactWidget
import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.helpprompt.HelpPromptWidget
+import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.mail.ComposeMailWidget
import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.mail.MailWidget
-import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.mail.compose.ComposeMailWidget
+import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.mail.ReadMailWidget
import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.PROPS_WIDGET_DESC
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_HELP_PROMPT
+import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_MAILS
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_MAIL_READ
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_MAIL_WRITE
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_SCHEDULE_ALARM
@@ -35,19 +38,29 @@ import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ContactHelper.getContac
import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ImageHelper
import org.json.JSONArray
+/**
+ * This adapter class is used to display a list of chat messages on a recycler view.
+ */
class ChatMainAdapter(
context: Context, list: ArrayList, callbacks: ChatMessageInterface
) : RecyclerView.Adapter() {
+ /**
+ * These variables are used to presents the type of messages
+ */
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
private var chatMessageList: ArrayList = ArrayList()
+ /**
+ * This is a callback that retrieves result from chat widgets.
+ */
+ private var callbacks: ChatMessageInterface
+
init {
this.context = context
this.chatMessageList = list
@@ -114,7 +127,13 @@ class ChatMainAdapter(
}
}
+ /**
+ * This function is used to set data for common messages.
+ */
private fun setMessageData(holder: MessageViewHolder, data: ChatMessageModel) {
+ /**
+ * If an image is included into a message, the image is displayed by below code.
+ */
if (data.hasImage) {
data.image?.let { image ->
val originBitmap = BitmapFactory.decodeByteArray(image, 0, image.size)
@@ -140,12 +159,18 @@ class ChatMainAdapter(
}
}
+ /**
+ * This function is used to display chat widgets on a recycler view.
+ */
private fun setMessageData(holder: ChatWidgetViewHolder, data: ChatMessageModel) {
holder.itemLayout.visibility = View.VISIBLE
holder.llHorizontalScroll.removeAllViews()
holder.itemLayout.removeAllViews()
val index = holder.adapterPosition
+ /**
+ * Depending on type of widget, the proper widget is displayed.
+ */
when (data.content) {
TYPE_WIDGET_SMS -> {
val sendSmsWidget = SendSmsWidget(context).apply {
@@ -222,19 +247,46 @@ class ChatMainAdapter(
holder.itemLayout.addView(scheduleAlarmWidget)
}
- TYPE_WIDGET_MAIL_READ -> {
+ TYPE_WIDGET_MAILS -> {
holder.llHorizontalScroll.visibility = View.VISIBLE
+ val props = data.data?.run {
+ val widgetDesc = data.data.asJsonObject[PROPS_WIDGET_DESC].asString
+ MailsProps.init(widgetDesc)
+ }
- for (i in 0 until 10) {
- val mailWidget = MailWidget(context).apply {
+ props?.mails?.forEach { mail ->
+ val mailWidget = MailWidget(context, mail).apply {
this.callback = callbacks
}
holder.llHorizontalScroll.addView(mailWidget)
}
}
+ TYPE_WIDGET_MAIL_READ -> {
+ val readMailWidget = ReadMailWidget(context).apply {
+ this.callback = callbacks
+ this.hideListener = object : OnHideListener {
+ override fun hide() {
+ holder.itemLayout.visibility = View.GONE
+ chatMessageList.removeAt(index)
+ notifyItemRemoved(index)
+ }
+ }
+ }
+ holder.itemLayout.addView(readMailWidget)
+ }
+
TYPE_WIDGET_MAIL_WRITE -> {
- val composeMailWIdget = ComposeMailWidget(context)
+ val composeMailWIdget = ComposeMailWidget(context).apply {
+ this.callback = callbacks
+ this.hideListener = object : OnHideListener {
+ override fun hide() {
+ holder.itemLayout.visibility = View.GONE
+ chatMessageList.removeAt(index)
+ notifyItemRemoved(index)
+ }
+ }
+ }
holder.itemLayout.addView(composeMailWIdget)
}
@@ -244,6 +296,9 @@ class ChatMainAdapter(
}
}
+ /**
+ * ViewHolder for common messages with message and image
+ */
inner class MessageViewHolder internal constructor(itemView: View) :
RecyclerView.ViewHolder(itemView) {
var txtMessage: TextView
@@ -257,6 +312,9 @@ class ChatMainAdapter(
}
}
+ /**
+ * ViewHolder for chat widgets
+ */
inner class ChatWidgetViewHolder internal constructor(itemView: View) :
RecyclerView.ViewHolder(itemView) {
var itemLayout: FrameLayout
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/dialogs/ConfirmDialog.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/dialogs/ConfirmDialog.kt
index 08608e8e12bf8fa267ad2d9b7c7f6f15b8776e47..c69bd29e5d3fdc4b342f903de85ab2939768f12c 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/dialogs/ConfirmDialog.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/dialogs/ConfirmDialog.kt
@@ -12,6 +12,9 @@ import android.widget.Button
import android.widget.TextView
import com.matthaigh27.chatgptwrapper.R
+/**
+ * This dialog is used to show confirm message to users.
+ */
class ConfirmDialog(context: Context) : Dialog(context), View.OnClickListener {
private var txtMessage: TextView? = null
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 68f63eaf018883bbc5dbb27dd26518a1a1c79712..544735e7f0e5e19558f3111ce7fe99b5203822fe 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
@@ -23,6 +23,8 @@ import com.matthaigh27.chatgptwrapper.R
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.chat.MailModel
+import com.matthaigh27.chatgptwrapper.data.models.chatwidgetprops.MailsProps
import com.matthaigh27.chatgptwrapper.data.models.chatwidgetprops.ScheduleAlarmProps
import com.matthaigh27.chatgptwrapper.data.models.common.Time
import com.matthaigh27.chatgptwrapper.data.remote.ApiResource
@@ -33,9 +35,11 @@ import com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces.ChatMessageInterfa
import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.toolbar.ChatToolsWidget
import com.matthaigh27.chatgptwrapper.ui.chat.viewmodel.ChatViewModel
import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.ERROR_MSG_NOEXIST_COMMAND
+import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.ERROR_MSG_UNKNOWN_ERROR
import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.HELP_COMMAND_ALL
import com.matthaigh27.chatgptwrapper.utils.constants.CommonConstants.PROPS_WIDGET_DESC
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_HELP_PROMPT
+import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_MAILS
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_MAIL_READ
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_MAIL_WRITE
import com.matthaigh27.chatgptwrapper.utils.constants.TypeChatWidgetConstants.TYPE_WIDGET_SCHEDULE_ALARM
@@ -50,8 +54,10 @@ import com.matthaigh27.chatgptwrapper.utils.constants.TypeResponseConstants.TYPE
import com.matthaigh27.chatgptwrapper.utils.constants.TypeResponseConstants.TYPE_RESPONSE_MAIL_SEND
import com.matthaigh27.chatgptwrapper.utils.constants.TypeResponseConstants.TYPE_RESPONSE_MAIL_WRITE
import com.matthaigh27.chatgptwrapper.utils.constants.TypeResponseConstants.TYPE_RESPONSE_MESSAGE
+import com.matthaigh27.chatgptwrapper.utils.constants.TypeResponseConstants.TYPE_RESPONSE_SMS
import com.matthaigh27.chatgptwrapper.utils.helpers.Converter
import com.matthaigh27.chatgptwrapper.utils.helpers.Converter.responseToHelpPromptList
+import com.matthaigh27.chatgptwrapper.utils.helpers.OnSuccess
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
@@ -59,8 +65,17 @@ import com.matthaigh27.chatgptwrapper.utils.helpers.chat.CommandHelper.makePromp
import com.matthaigh27.chatgptwrapper.utils.helpers.ui.NoNewLineInputFilter
import org.json.JSONArray
+/**
+ * A ChatMainFragment class is a class for chatting with users and show the result that
+ * our AI plugin - Brain returned.
+ *
+ * In this class, almost important features are implemented.
+ */
class ChatMainFragment : Fragment(), OnClickListener {
+ /**
+ * These variables(TYPE_CHAT_XXX) are variables that present type of widget to display on chatting list.
+ */
private val TYPE_CHAT_SENT = 0
private val TYPE_CHAT_RECEIVE = 1
private val TYPE_CHAT_WIDGET = 2
@@ -69,10 +84,12 @@ class ChatMainFragment : Fragment(), OnClickListener {
private lateinit var rootView: View
lateinit var viewModel: ChatViewModel
- /** View Components */
private var loadingRotate: RotateAnimation? = null
private var edtMessageInput: EditText? = null
+ /**
+ * These variables are for recyclerview that shows chatting list items.
+ */
private var rvChatList: RecyclerView? = null
private var chatMainAdapter: ChatMainAdapter? = null
private var chatMessageList: ArrayList = ArrayList()
@@ -81,9 +98,16 @@ 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
+ /**
+ * These variables are used to identify whether users picked an image to send to Brain.
+ */
+ private var currentSelectedImage: ByteArray? =
+ null // bytearray data of a picked image by camera or gallery
+ private var currentUploadedImageName: String? =
+ null // resource name that is uploaded to firebase storage
+ private var isImagePicked: Boolean =
+ false // boolean variable that presents whether users picked an image
+
private var showLoadingCount = 0
override fun onCreateView(
@@ -95,6 +119,9 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
private fun init() {
+ /**
+ * These are functions to init views
+ */
initViewModel()
initLoadingRotate()
initButtonsClickListener()
@@ -105,11 +132,16 @@ class ChatMainFragment : Fragment(), OnClickListener {
fetchAllCommands()
}
-
+ /**
+ * This function is used to init viewmodel.
+ */
private fun initViewModel() {
viewModel = ViewModelProvider(this)[ChatViewModel::class.java]
}
+ /**
+ * This function is used to init rotate animation for loading spinner.
+ */
private fun initLoadingRotate() {
loadingRotate = RotateAnimation(/* fromDegrees = */ 0f, /* toDegrees = */
720f, /* pivotXType = */
@@ -124,11 +156,17 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
}
+ /**
+ * In this function, click listener is set to buttons on main chat interface.
+ */
private fun initButtonsClickListener() {
rootView.findViewById(R.id.btn_open_chat_tools).setOnClickListener(this)
rootView.findViewById(R.id.btn_audio_recognition).setOnClickListener(this)
}
+ /**
+ * Send text message to Brain when users finish typing text to EditText component.
+ */
private fun initChatInputListener() {
edtMessageInput = rootView.findViewById(R.id.edt_message)
edtMessageInput?.filters = edtMessageInput?.filters?.plus(NoNewLineInputFilter())
@@ -141,7 +179,13 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
}
+ /**
+ * This function is used to init recyclerview that stores chatting messages.
+ */
private fun initChatRecyclerView() {
+ /**
+ * Init callback function that binds the event emitted in all chat widgets
+ */
initChatInterface()
rvChatList = rootView.findViewById(R.id.rv_chat_list)
@@ -153,6 +197,10 @@ class ChatMainFragment : Fragment(), OnClickListener {
rvChatList?.layoutManager = LinearLayoutManager(context)
}
+ /**
+ * This function is used to init chat tool widget that pops up when users click plus button
+ * at the right bottom corner.
+ */
private fun initChatToolsWidget() {
chatToolsWidget = ChatToolsWidget(requireContext(), requireActivity()).apply {
this.callback = chatMessageInterface
@@ -161,6 +209,14 @@ class ChatMainFragment : Fragment(), OnClickListener {
llToolBar.addView(chatToolsWidget)
}
+ /**
+ * This function is used to show loading spinner.
+ *
+ * If isLoading is true, loading spinner is displayed. But loading spinner might not be visible,
+ * even though isLoading is true. Current visible loading spinner count should be 0 to make loading spinner invisible.
+ *
+ * @param isLoading boolean parameter that presents whether loading spinner is visible
+ */
private fun showLoading(isLoading: Boolean) {
val imgLoading = rootView.findViewById(R.id.sp_loading)
@@ -179,6 +235,19 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
}
+ /**
+ * This function is used mostly to add messages to chatting list.
+ *
+ * According to type of message, messages can be common messages or widgets for sending sms, setting an alarm, sending help prompt, etc.
+ * Depending on whether an image is contained into message, different network functions are executed.
+ * If message start with '/', help prompt widget is displayed.
+ *
+ * @param type A variable that present type of chat messages
+ * @param content Contains content of message to present
+ * @param data Contains properties of widget as json string when type is widget.
+ * @param hasImage Presents whether an image is contained into message
+ * @param image If a message has an image, this variable is used to store the bytearray data of the contained image.
+ */
private fun addMessage(
type: Int,
content: String? = null,
@@ -188,11 +257,17 @@ class ChatMainFragment : Fragment(), OnClickListener {
) {
when (type) {
TYPE_CHAT_SENT -> {
+ /**
+ * If message starts with '/', help prompt widget is displayed.
+ */
if (content!!.isNotEmpty() && content.first() == '/') {
openHelpPromptWidget(content)
return
}
if (isImagePicked) {
+ /**
+ * If an image is contained into a message, image relatedness function is executed.
+ */
addChatItemToList(
ChatMessageModel(
type = type,
@@ -205,6 +280,9 @@ class ChatMainFragment : Fragment(), OnClickListener {
fetchImageRelatedness(currentUploadedImageName!!, content)
isImagePicked = false
} else {
+ /**
+ * If not, send notification function is executed.
+ */
addChatItemToList(ChatMessageModel(type, content, data, hasImage, image))
sendNotification(content)
}
@@ -216,6 +294,9 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
}
+ /**
+ * This function is used to display messages to show errors in more detail to users
+ */
private fun addErrorMessage(
message: String
) {
@@ -233,42 +314,49 @@ class ChatMainFragment : Fragment(), OnClickListener {
rvChatList?.scrollToPosition(chatMessageList.size - 1)
}
- private fun trainContacts() {
- viewModel.trainContacts().observe(viewLifecycleOwner) { resource ->
- when (resource) {
- is ApiResource.Loading -> {
- showLoading(true)
- }
-
- is ApiResource.Success -> {
- showLoading(false)
- }
-
- is ApiResource.Error -> {
- showLoading(false)
- }
+ /**
+ * This function is used to process ApiResource data from viewmodel.
+ *
+ * When status is loading or error, default functions are executed. When success, onSuccess
+ * lambda function is executed.
+ *
+ * @param resource A ApiResource that is retrieved from ViewModel
+ * @param onSuccess A lambda function to process the resource data
+ */
+ private fun commonProcessResource(
+ resource: ApiResource,
+ onSuccess: OnSuccess>
+ ) {
+ when (resource) {
+ is ApiResource.Loading -> {
+ showLoading(true)
}
- }
- }
- private fun trainImages() {
- viewModel.trainImages().observe(viewLifecycleOwner) { resource ->
- when (resource) {
- is ApiResource.Loading -> {
- showLoading(true)
- }
+ is ApiResource.Success -> {
+ showLoading(false)
+ onSuccess(resource)
+ }
- is ApiResource.Success -> {
- showLoading(false)
+ is ApiResource.Error -> {
+ showLoading(false)
+ resource.message?.let {
+ addErrorMessage(resource.message)
+ } ?: run {
+ addErrorMessage(ERROR_MSG_UNKNOWN_ERROR)
}
- is ApiResource.Error -> {
- showLoading(false)
- }
}
}
}
+ /**
+ * Open help prompt widgets when message is valid help command.
+ *
+ * @param message A String variable that contains message users sent
+ * If message is /help, all the description of help commands is displayed,
+ * If message is /help prompt name, the description of a given prompt help command is displayed.
+ * If message is /prompt name, A help prompt widget about the given name is displayed.
+ */
private fun openHelpPromptWidget(message: String) {
try {
val command: HelpCommandModel = getHelpCommandFromStr(message)
@@ -318,112 +406,90 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
}
} catch (e: Exception) {
- e.printStackTrace()
addErrorMessage(e.message.toString())
}
}
+ /**
+ * This Network function is used to fetch all help commands
+ */
private fun fetchAllCommands() {
viewModel.getAllHelpCommands().observe(viewLifecycleOwner) { resource ->
- when (resource) {
- is ApiResource.Loading -> {
- showLoading(true)
- }
-
- is ApiResource.Success -> {
- showLoading(false)
- resource.data?.let { data ->
- helpPromptList = responseToHelpPromptList(data.result.content)
- }
- }
-
- is ApiResource.Error -> {
- showLoading(false)
- addErrorMessage(resource.message!!)
+ commonProcessResource(resource) {
+ resource.data?.let { data ->
+ helpPromptList = responseToHelpPromptList(data.result.content)
}
}
}
}
+ /**
+ * This Network function is used to fetch a similar image to image that is stored with imageName parameter
+ * in Firebase storage.
+ *
+ * @param imageName The image name of a image that a user uploaded to the Firebase
+ * @param message The description about the image
+ */
private fun fetchImageRelatedness(imageName: String, message: String) {
viewModel.getImageRelatedness(imageName, message).observe(viewLifecycleOwner) { resource ->
- when (resource) {
- is ApiResource.Loading -> {
- showLoading(true)
- }
-
- is ApiResource.Success -> {
- showLoading(false)
- addMessage(
- type = TYPE_CHAT_RECEIVE,
- content = resource.data?.description,
- data = null,
- hasImage = true,
- image = resource.data?.image
- )
- }
-
- is ApiResource.Error -> {
- showLoading(false)
- addErrorMessage(resource.message!!)
- }
+ commonProcessResource(resource) {
+ addMessage(
+ type = TYPE_CHAT_RECEIVE,
+ content = resource.data?.description,
+ data = null,
+ hasImage = true,
+ image = resource.data?.image
+ )
}
}
}
+ /**
+ * This network function is used to retrieve a command analyzed with user's message by Brain
+ *
+ * @param message A message that users sent
+ */
private fun sendNotification(message: String) {
viewModel.sendNotification(message).observe(viewLifecycleOwner) { resource ->
- when (resource) {
- 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.asString
- )
-
- TYPE_RESPONSE_BROWSER -> fetchResponseBrowser(apiResponse)
- TYPE_RESPONSE_CONTACT -> fetchResponseContact(apiResponse)
- TYPE_RESPONSE_IMAGE -> fetchResponseImage(apiResponse)
- TYPE_RESPONSE_ALARM -> fetchResponseAlarm(apiResponse)
- TYPE_RESPONSE_MAIL_READ -> fetchResponseMail(TYPE_RESPONSE_MAIL_READ)
- TYPE_RESPONSE_MAIL_WRITE -> fetchResponseMail(TYPE_RESPONSE_MAIL_WRITE)
- TYPE_RESPONSE_MAIL_SEND -> fetchResponseMail(TYPE_RESPONSE_MAIL_SEND)
- TYPE_RESPONSE_AUTO_TASK -> fetchResponseAutoTask(apiResponse)
- else -> addMessage(TYPE_CHAT_RECEIVE, apiResponse!!.result.toString())
- }
- }
+ commonProcessResource(resource) {
+ val apiResponse = resource.data
+ when (apiResponse?.result?.program) {
+ TYPE_RESPONSE_MESSAGE -> addMessage(
+ TYPE_CHAT_RECEIVE,
+ apiResponse.result.content.asString
+ )
- is ApiResource.Error -> {
- addErrorMessage(resource.message!!)
- showLoading(false)
+ TYPE_RESPONSE_SMS -> addMessage(TYPE_CHAT_WIDGET, TYPE_WIDGET_SMS)
+ TYPE_RESPONSE_BROWSER -> fetchResponseBrowser(apiResponse)
+ TYPE_RESPONSE_CONTACT -> fetchResponseContact(apiResponse)
+ TYPE_RESPONSE_IMAGE -> fetchResponseImage(apiResponse)
+ TYPE_RESPONSE_ALARM -> fetchResponseAlarm(apiResponse)
+ TYPE_RESPONSE_MAIL_READ -> fetchResponseMail(TYPE_RESPONSE_MAIL_READ)
+ TYPE_RESPONSE_MAIL_WRITE -> fetchResponseMail(TYPE_RESPONSE_MAIL_WRITE)
+ TYPE_RESPONSE_MAIL_SEND -> fetchResponseMail(TYPE_RESPONSE_MAIL_SEND)
+ TYPE_RESPONSE_AUTO_TASK -> fetchResponseAutoTask(apiResponse)
+ else -> addMessage(TYPE_CHAT_RECEIVE, apiResponse!!.result.toString())
}
}
-
}
}
+ /**
+ * This function is used to process data from Brain that is for browser.
+ */
private fun fetchResponseBrowser(apiResponse: ApiResponse) {
addMessage(TYPE_CHAT_RECEIVE, apiResponse.result.content.asString)
}
+ /**
+ * This function is used to process data from Brain that is for image.
+ */
private fun fetchResponseImage(apiResponse: ApiResponse) {
val content = apiResponse.result.content.asJsonObject
- viewModel.downloadImageFromFirebase(
- content["image_name"].asString
- ).observe(viewLifecycleOwner) { resource ->
- when (resource) {
- is ApiResource.Loading -> {
- showLoading(true)
- }
-
- is ApiResource.Success -> {
- showLoading(false)
+ viewModel.downloadImageFromFirebase(content["image_name"].asString)
+ .observe(viewLifecycleOwner) { resource ->
+ commonProcessResource(resource) {
addMessage(
type = TYPE_CHAT_RECEIVE,
content = null,
@@ -432,15 +498,12 @@ class ChatMainFragment : Fragment(), OnClickListener {
image = resource.data
)
}
-
- is ApiResource.Error -> {
- addErrorMessage(resource.message!!)
- showLoading(false)
- }
}
- }
}
+ /**
+ * This function is used to process data from Brain that is for contact.
+ */
private fun fetchResponseContact(apiResponse: ApiResponse) {
val contactIds = JSONArray(apiResponse.result.content.asString.replace("'", "\""))
if (contactIds.length() > 0) {
@@ -457,6 +520,9 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
}
+ /**
+ * This function is used to process data from Brain that is for alarm.
+ */
private fun fetchResponseAlarm(apiResponse: ApiResponse) {
val time: Time =
Converter.stringToTime(apiResponse.result.content.asJsonObject.get("time").asString)
@@ -468,18 +534,13 @@ class ChatMainFragment : Fragment(), OnClickListener {
addMessage(TYPE_CHAT_WIDGET, TYPE_WIDGET_SCHEDULE_ALARM, widgetDesc)
}
+ /**
+ * This function is used to process data from Brain that is for mail.
+ */
private fun fetchResponseMail(type: String) {
when (type) {
- TYPE_RESPONSE_MAIL_READ -> {
- addMessage(TYPE_CHAT_WIDGET, TYPE_WIDGET_MAIL_READ)
- }
-
- TYPE_RESPONSE_MAIL_WRITE -> {
- addMessage(TYPE_CHAT_WIDGET, TYPE_WIDGET_MAIL_WRITE)
- }
-
- TYPE_RESPONSE_MAIL_SEND -> {
- }
+ TYPE_RESPONSE_MAIL_READ -> addMessage(TYPE_CHAT_WIDGET, TYPE_WIDGET_MAIL_READ)
+ TYPE_RESPONSE_MAIL_SEND -> addMessage(TYPE_CHAT_WIDGET, TYPE_WIDGET_MAIL_WRITE)
}
}
@@ -495,35 +556,47 @@ class ChatMainFragment : Fragment(), OnClickListener {
).observe(viewLifecycleOwner) { resource ->
when (resource) {
is ApiResource.Loading -> {
+ showLoading(true)
resource.data?.let { data ->
if (data.result == null) {
data.thoughts?.let { thoughts ->
addMessage(
- type = TYPE_CHAT_RECEIVE,
- content = thoughts.speak
+ type = TYPE_CHAT_RECEIVE, content = thoughts.speak
)
}
} else {
addMessage(
- type = TYPE_CHAT_RECEIVE,
- content = data.result
+ type = TYPE_CHAT_RECEIVE, content = data.result
)
}
}
}
is ApiResource.Success -> {
+ showLoading(false)
addMessage(TYPE_CHAT_RECEIVE, "Task is finished.")
}
is ApiResource.Error -> {
+ showLoading(false)
+ resource.message?.let {
+ addErrorMessage(resource.message)
+ } ?: run {
+ addErrorMessage(ERROR_MSG_UNKNOWN_ERROR)
+ }
}
}
}
}
+ /**
+ * This interface is a callback function that retrieves the results of chat widgets.
+ */
private fun initChatInterface() {
chatMessageInterface = object : ChatMessageInterface {
+ /**
+ * When a user sends sms using SMS Widget, this function is called.
+ */
override fun sentSms(phoneNumber: String, message: String) {
addMessage(
type = TYPE_CHAT_RECEIVE,
@@ -531,6 +604,9 @@ class ChatMainFragment : Fragment(), OnClickListener {
)
}
+ /**
+ * When a user cancels sms using SMS Widget, this function is called.
+ */
override fun canceledSms() {
addMessage(
type = TYPE_CHAT_RECEIVE,
@@ -538,30 +614,46 @@ class ChatMainFragment : Fragment(), OnClickListener {
)
}
+ /**
+ * When a user sends help prompt using help Prompt Widget, this function is called.
+ */
override fun sentHelpPrompt(prompt: String) {
addMessage(
type = TYPE_CHAT_SENT, content = prompt
)
}
+ /**
+ * When a user cancels help prompt using help prompt Widget, this function is called.
+ */
override fun canceledHelpPrompt() {
addMessage(
type = TYPE_CHAT_RECEIVE, content = "You canceled Help prompt."
)
}
+ /**
+ * When a user makes a voice call after searching for contacts, this function is called.
+ */
override fun doVoiceCall(phoneNumber: String) {
addMessage(
type = TYPE_CHAT_RECEIVE, content = "You made a voice call to $phoneNumber"
)
}
+ /**
+ * When a user makes a video call after searching for contacts, this function is called.
+ */
override fun doVideoCall(phoneNumber: String) {
addMessage(
type = TYPE_CHAT_RECEIVE, content = "You made a video call to $phoneNumber"
)
}
+ /**
+ * When a user sends sms with phone number after searching for contacts,
+ * this function is called.
+ */
override fun sendSmsWithPhoneNumber(phoneNumber: String) {
val widgetDesc = JsonObject().apply {
this.addProperty(PROPS_WIDGET_DESC, phoneNumber)
@@ -571,29 +663,25 @@ class ChatMainFragment : Fragment(), OnClickListener {
)
}
+ /**
+ * When a user picks an image to send to Brain to search or compare similarity,
+ * this function is called.
+ */
override fun pickImage(isSuccess: Boolean, data: ByteArray?) {
if (!isSuccess) addErrorMessage("Fail to pick image")
- viewModel.uploadImageToFirebase(data!!).observe(viewLifecycleOwner) { 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)
- }
+ viewModel.uploadImageToFirebase(data!!).observe(viewLifecycleOwner) { resource ->
+ commonProcessResource(resource) {
+ currentSelectedImage = data
+ currentUploadedImageName = resource.data
+ isImagePicked = true
}
}
}
+ /**
+ * When a user sets an alarm by using alarm widget, this function is called.
+ */
override fun setAlarm(hours: Int, minutes: Int, label: String) {
addMessage(
type = TYPE_CHAT_RECEIVE,
@@ -601,11 +689,64 @@ class ChatMainFragment : Fragment(), OnClickListener {
)
}
+ /**
+ * When a user cancels an alarm by using alarm widget, this function is called.
+ */
override fun cancelAlarm() {
addMessage(
type = TYPE_CHAT_RECEIVE, content = "You canceled setting an alarm."
)
}
+
+ /**
+ * When a user reads mail by using read mail widget, this function is called.
+ */
+ override fun readMail(from: String, password: String, imap_folder: String) {
+ viewModel.readMails(from, password, imap_folder)
+ .observe(viewLifecycleOwner) { resource ->
+ commonProcessResource(resource) {
+ val props = MailsProps(resource.data!!)
+ val widgetDesc = JsonObject().apply {
+ this.addProperty(PROPS_WIDGET_DESC, props.toString())
+ }
+ addMessage(
+ type = TYPE_CHAT_WIDGET,
+ content = TYPE_WIDGET_MAILS,
+ data = widgetDesc
+ )
+ }
+ }
+ }
+
+ /**
+ * When a user sends mail by using compose mail widget, this function is called.
+ */
+ override fun sendMail(
+ from: String,
+ password: String,
+ to: String,
+ subject: String,
+ body: String,
+ isInbox: Boolean,
+ filename: String,
+ fileContent: String
+ ) {
+
+ viewModel.sendMail(
+ sender = from,
+ pwd = password,
+ to = to,
+ subject = subject,
+ body = body,
+ to_send = isInbox,
+ filename = filename,
+ file_content = fileContent
+ ).observe(viewLifecycleOwner) { resource -> commonProcessResource(resource) {} }
+ }
+
+ override fun readMailInDetail(mail: MailModel) {
+
+ }
}
}
@@ -616,14 +757,21 @@ class ChatMainFragment : Fragment(), OnClickListener {
}
R.id.btn_audio_recognition -> {
-
+ //Here are some codes.
}
}
}
override fun onResume() {
super.onResume()
- trainImages()
- trainContacts()
+
+ /**
+ * when main fragment resumes, search for changed images and contacts in mobile and send the changed data
+ * to Brain to train.
+ */
+ viewModel.trainContacts()
+ .observe(viewLifecycleOwner) { resource -> commonProcessResource(resource) {} }
+ viewModel.trainImages()
+ .observe(viewLifecycleOwner) { resource -> commonProcessResource(resource) {} }
}
}
\ 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 fe99148c23f44c8d0a4aea8f411c4be3becc8556..89d88bc92af56774a06829615831904d9115a6f4 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
@@ -1,5 +1,10 @@
package com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces
+import com.matthaigh27.chatgptwrapper.data.models.chat.MailModel
+
+/**
+ * This interface is a callback function that retrieves the results of chat widgets.
+ */
interface ChatMessageInterface {
fun sentSms(phoneNumber: String, message: String)
fun canceledSms()
@@ -9,6 +14,19 @@ 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 setAlarm(hours: Int, minutes: Int, label: String)
fun cancelAlarm()
+ fun readMail(from: String, password: String, imap_folder: String)
+ fun sendMail(
+ from: String,
+ password: String,
+ to: String,
+ subject: String,
+ body: String,
+ isInbox: Boolean,
+ filename: String,
+ fileContent: String
+ )
+
+ fun readMailInDetail(mail: MailModel)
}
\ 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
index a1fe0595ccf8714498dc5a868973adf3965972ed..67ec2ec434aab28f3521aabe663b3de39383e7f2 100644
--- 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
@@ -1,5 +1,8 @@
package com.matthaigh27.chatgptwrapper.ui.chat.view.interfaces
+/**
+ * This interface is used to retrieve hide event when a user closes chat widgets.
+ */
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/helpprompt/HelpPromptKeyEditText.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptKeyEditText.kt
deleted file mode 100644
index 8ba3b65e544e42ef91b848a4b9fe8404aea77017..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptKeyEditText.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.helpprompt
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.view.ViewGroup
-import android.widget.EditText
-import android.widget.LinearLayout
-import androidx.annotation.Dimension
-import com.matthaigh27.chatgptwrapper.R
-
-@SuppressLint("AppCompatCustomView")
-class HelpPromptKeyEditText(context: Context) : EditText(context) {
- init {
- val layoutParams: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT
- )
- val marginBottom =
- context.resources.getDimensionPixelSize(R.dimen.spacing_tiny)
- layoutParams.setMargins(0, 0, 0, marginBottom)
- this.layoutParams = layoutParams
-
- minHeight =
- context.resources.getDimensionPixelSize(R.dimen.height_edittext_normal)
-
- val paddingStart =
- context.resources.getDimensionPixelSize(R.dimen.spacing_tiny)
- setPadding(paddingStart, 0, 0, 0)
-
-
- setTextSize(
- Dimension.DP,
- context.resources.getDimensionPixelSize(R.dimen.font_normal)
- .toFloat()
- )
- setTextColor(context.getColor(R.color.color_accent))
- setHintTextColor(context.getColor(R.color.color_primary_dark))
- background = context.getDrawable(R.drawable.bg_edittext_radius_small)
- }
-
- fun initView(keyName: String) {
- hint = keyName
- tag = keyName
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptKeyItem.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptKeyItem.kt
new file mode 100644
index 0000000000000000000000000000000000000000..dc9781c21487e043f158a431439696f5224c09ad
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/widgets/chatwidget/helpprompt/HelpPromptKeyItem.kt
@@ -0,0 +1,30 @@
+package com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.helpprompt
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.view.LayoutInflater
+import android.widget.FrameLayout
+import com.google.android.material.textfield.TextInputLayout
+import com.matthaigh27.chatgptwrapper.R
+
+@SuppressLint("AppCompatCustomView")
+class HelpPromptKeyItem(context: Context) : FrameLayout(context) {
+
+ private val edtKey: TextInputLayout
+
+ init {
+ LayoutInflater.from(context).inflate(R.layout.item_help_prompt_key, this, true)
+
+ edtKey = findViewById(R.id.edt_key)
+ }
+
+ fun initView(keyName: String) {
+ if(keyName.isNotEmpty())
+ edtKey.hint = keyName.subSequence(1, keyName.length)
+ tag = keyName
+ }
+
+ fun getText(): String {
+ return edtKey.editText?.text.toString()
+ }
+}
\ No newline at end of file
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 48c59992c939a5df05b6c95e802d8b81ca09d942..565ae8a373c07d2d25e7317ebee6be6c808f5033 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
@@ -6,6 +6,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
+import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout
@@ -19,7 +20,7 @@ class HelpPromptWidget(context: Context, model: HelpPromptModel) : ConstraintLay
private lateinit var llPromptKeys: LinearLayout
private lateinit var txtKeysTitle: TextView
- private var promptEditTextList: ArrayList? = null
+ private var promptEditTextList: ArrayList? = null
private val promptModel: HelpPromptModel
var callback: ChatMessageInterface? = null
var hideListener: OnHideListener? = null
@@ -41,8 +42,8 @@ class HelpPromptWidget(context: Context, model: HelpPromptModel) : ConstraintLay
txtKeysTitle = findViewById(R.id.txt_keys_title)
txtKeysTitle.text = promptModel.name
- findViewById