diff --git a/Android/app/build.gradle b/Android/app/build.gradle
index 77fcacdddaadf0ca4ece00a89c72a15c6de6cf7a..579d8d3e2ed8fa142da303a8a2a3c117a67ba669 100644
--- a/Android/app/build.gradle
+++ b/Android/app/build.gradle
@@ -1,8 +1,8 @@
plugins {
id 'com.android.application'
- id 'kotlin-android'
id 'com.google.gms.google-services'
id 'kotlin-kapt'
+ id 'kotlin-android'
}
android {
@@ -13,19 +13,18 @@ android {
applicationId "com.matthaigh27.chatgptwrapper"
minSdk 28
targetSdk 33
- versionCode 7
- versionName "1.5"
+ versionCode 1
+ versionName "1.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
debug {
- buildConfigField "String", "BASE_URL", "\"https://smartphone.herokuapp.com/\""
+ buildConfigField "String", "BASE_URL", "\"https://ttt246-brain.hf.space/\""
}
release {
- // Use your desired server address for the release version
- buildConfigField "String", "BASE_URL", "\"https://chatgptphone.herokuapp.com/\""
+ buildConfigField "String", "BASE_URL", "\"https://ttt246-brain.hf.space/\""
minifyEnabled true
shrinkResources true
@@ -41,6 +40,7 @@ android {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
+
kotlinOptions {
jvmTarget = JavaVersion.VERSION_11
}
@@ -51,63 +51,73 @@ android {
}
dependencies {
- // App dependencies
+ //Core
implementation 'androidx.core:core-ktx:1.9.0'
+ implementation 'com.google.code.gson:gson:2.8.5'
+
+ //UI & UX
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
-
- implementation platform('com.google.firebase:firebase-bom:31.4.0')
- implementation 'com.google.android.gms:play-services-gcm:17.0.0'
-
- implementation 'com.google.firebase:firebase-messaging'
- implementation 'com.google.firebase:firebase-analytics'
- implementation 'com.google.firebase:firebase-firestore-ktx:24.4.5'
- implementation 'com.google.firebase:firebase-firestore:15.0.0'
-
- implementation 'com.google.firebase:firebase-messaging-ktx'
- implementation 'com.google.firebase:firebase-analytics-ktx'
- implementation 'com.firebaseui:firebase-ui-storage:7.2.0'
-
- implementation 'com.squareup.okhttp3:okhttp:3.0.1'
+ implementation 'de.hdodenhof:circleimageview:3.1.0'
implementation 'com.github.soulqw:CoCo:1.1.2'
implementation 'com.github.dhaval2404:imagepicker:2.1'
- implementation 'com.google.firebase:firebase-storage-ktx:20.1.0'
+ implementation 'com.github.bumptech.glide:glide:4.12.0'
+ annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
+
testImplementation 'org.testng:testng:6.9.6'
// Testing-only dependencies
- androidTestImplementation 'androidx.test:core:' + rootProject.coreVersion;
- androidTestImplementation 'androidx.test.ext:junit:' + rootProject.extJUnitVersion;
- androidTestImplementation 'androidx.test:runner:' + rootProject.runnerVersion;
+ androidTestImplementation "androidx.test:core:$rootProject.coreVersion"
+ androidTestImplementation "androidx.test.ext:junit:$rootProject.extJUnitVersion"
+ androidTestImplementation "androidx.test:runner:$rootProject.runnerVersion"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
// UiAutomator Testing
- androidTestImplementation 'androidx.test.uiautomator:uiautomator:' + rootProject.uiAutomatorVersion;
+ androidTestImplementation "androidx.test.uiautomator:uiautomator:$rootProject.uiAutomatorVersion"
androidTestImplementation 'org.hamcrest:hamcrest-integration:1.3'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-alpha05"
- implementation 'com.github.bumptech.glide:glide:4.12.0'
- annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
+ //Firebase
+ implementation platform('com.google.firebase:firebase-bom:31.4.0')
+ implementation 'com.google.android.gms:play-services-gcm:17.0.0'
- implementation 'com.google.code.gson:gson:2.8.5'
+ implementation 'com.google.firebase:firebase-messaging'
+ implementation 'com.google.firebase:firebase-analytics'
+ implementation 'com.google.firebase:firebase-firestore-ktx:24.4.5'
+ implementation 'com.google.firebase:firebase-firestore:15.0.0'
+ implementation 'com.google.firebase:firebase-storage-ktx:20.1.0'
+ implementation 'com.google.firebase:firebase-messaging-ktx'
+ implementation 'com.google.firebase:firebase-analytics-ktx'
+ implementation 'com.firebaseui:firebase-ui-storage:7.2.0'
- implementation "androidx.room:room-runtime:$room_version"
- annotationProcessor "androidx.room:room-compiler:$room_version"
+ implementation "androidx.room:room-runtime:$rootProject.roomVersion"
+ annotationProcessor "androidx.room:room-compiler:$rootProject.roomVersion"
// To use room database
- implementation "androidx.room:room-ktx:$room_version"
- kapt "androidx.room:room-compiler:$room_version"
- implementation "androidx.room:room-rxjava2:$room_version"
- implementation "androidx.room:room-rxjava3:$room_version"
- implementation "androidx.room:room-guava:$room_version"
- testImplementation "androidx.room:room-testing:$room_version"
- implementation "androidx.room:room-paging:$room_version"
+ implementation "androidx.room:room-ktx:$rootProject.roomVersion"
+ kapt "androidx.room:room-compiler:$rootProject.roomVersion"
+ implementation "androidx.room:room-rxjava2:$rootProject.roomVersion"
+ implementation "androidx.room:room-rxjava3:$rootProject.roomVersion"
+ implementation "androidx.room:room-guava:$rootProject.roomVersion"
+ testImplementation "androidx.room:room-testing:$rootProject.roomVersion"
+ implementation "androidx.room:room-paging:$rootProject.roomVersion"
- implementation 'de.hdodenhof:circleimageview:3.1.0'
+ //To use Retrofit
+
+ implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$rootProject.lifecycleVersion"
+ implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.lifecycleVersion"
+
+ implementation "com.squareup.retrofit2:retrofit:$rootProject.retrofitVersion"
+ implementation "com.squareup.retrofit2:converter-gson:$rootProject.retrofitVersion"
+
+ implementation "com.squareup.okhttp3:okhttp:$rootProject.okHttpVersion"
+ implementation "com.squareup.okhttp3:logging-interceptor:$rootProject.okHttpVersion"
+ implementation "com.squareup.okhttp3:okhttp-urlconnection:$rootProject.okHttpVersion"
}
diff --git a/Android/app/src/main/AndroidManifest.xml b/Android/app/src/main/AndroidManifest.xml
index 1084fe2e7f87fcb9dbb470065ec30cc2f390558b..ba0f495f6065fcca8608f5ce7ff5d4a94241389a 100644
--- a/Android/app/src/main/AndroidManifest.xml
+++ b/Android/app/src/main/AndroidManifest.xml
@@ -9,40 +9,45 @@
-
-
+
+
-
-
+
+
+
+ android:theme="@style/AppTheme">
+ android:name=".ui.setting.view.SettingActivity"
+ android:exported="false" />
+
+
-
-
-
-
-
+
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/MyApplication.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/MyApplication.kt
deleted file mode 100644
index f34f8430b9e8ffb9d4eeb875d75191e08826d65f..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/MyApplication.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.matthaigh27.chatgptwrapper
-
-import android.Manifest
-import android.annotation.SuppressLint
-import android.app.Application
-import android.app.NotificationChannel
-import android.app.NotificationManager
-import android.content.pm.PackageManager
-import android.util.Log
-import com.google.android.gms.tasks.OnCompleteListener
-import com.google.firebase.messaging.FirebaseMessaging
-import com.matthaigh27.chatgptwrapper.utils.Constants
-import android.provider.Settings
-import androidx.core.app.ActivityCompat
-import androidx.core.app.NotificationCompat
-import androidx.core.app.NotificationManagerCompat
-import java.util.Random
-
-class MyApplication : Application() {
-
- private var mFCMToken: String = String()
- private var mUUID: String = String()
- @SuppressLint("HardwareIds")
- override fun onCreate() {
- super.onCreate()
-
- initToken()
- // on below line we are getting device id.
- mUUID = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
- appContext = applicationContext as MyApplication
-
- Log.v("risingandroid mUUID: ", mUUID)
- Log.v("risingandroid FCMToken: ", mFCMToken)
- }
-
- private fun initToken() {
- FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
- if (!task.isSuccessful) {
- Log.w(Constants.TAG, "Fetching FCM registration token failed", task.exception)
- return@OnCompleteListener
- }
-
- /**
- * Get new FCM registration token
- */
-
- /**
- * Get new FCM registration token
- */
- mFCMToken = task.result
- Log.d(Constants.TAG, mFCMToken)
- })
- }
-
- fun getFCMToken(): String {
- return this.mFCMToken
- }
-
- fun getUUID(): String {
- return this.mUUID
- }
-
- /**
- * this shows system notification with message
- * @param message to be shown with system notification
- */
- fun showNotification(message: String) {
- val notificationId: Int = Random().nextInt()
- val channelId = "chat_message"
-
- val builder = NotificationCompat.Builder(this, channelId)
- builder.setSmallIcon(R.drawable.ic_notification)
- builder.setContentTitle(Constants.TAG)
- builder.setContentText(message)
- builder.setStyle(
- NotificationCompat.BigTextStyle().bigText(
- message
- )
- )
- builder.priority = NotificationCompat.PRIORITY_DEFAULT
- builder.setAutoCancel(true)
-
- val channelName: CharSequence = "Chat Message"
- val channelDescription = "This notification channel is used for chat message notifications"
- val importance = NotificationManager.IMPORTANCE_DEFAULT
- val channel = NotificationChannel(channelId, channelName, importance)
- channel.description = channelDescription
- val notificationManager = getSystemService(
- NotificationManager::class.java
- )
- notificationManager.createNotificationChannel(channel)
- val notificationManagerCompat = NotificationManagerCompat.from(this)
- if (ActivityCompat.checkSelfPermission(
- this, Manifest.permission.POST_NOTIFICATIONS
- ) != PackageManager.PERMISSION_GRANTED
- ) {
- return
- }
- notificationManagerCompat.notify(notificationId, builder.build())
- }
-
- companion object {
- lateinit var appContext: MyApplication
- }
-}
\ 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
new file mode 100644
index 0000000000000000000000000000000000000000..b5910f63aa2d54c3141a59bb90f9626ed8c3d5d0
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/RisingApplication.kt
@@ -0,0 +1,45 @@
+package com.matthaigh27.chatgptwrapper
+
+import android.annotation.SuppressLint
+import android.app.Application
+import android.provider.Settings
+import com.google.android.gms.tasks.OnCompleteListener
+import com.google.firebase.messaging.FirebaseMessaging
+
+class RisingApplication : Application() {
+
+ private var fcmToken: String = String()
+ private var uuid: String = String()
+
+ @SuppressLint("HardwareIds")
+ override fun onCreate() {
+ super.onCreate()
+
+ initToken()
+ // on below line we are getting device id.
+ uuid = Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
+ appContext = applicationContext as RisingApplication
+ }
+
+ private fun initToken() {
+ FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
+ if (!task.isSuccessful) {
+ return@OnCompleteListener
+ }
+
+ fcmToken = task.result
+ })
+ }
+
+ fun getFCMToken(): String {
+ return this.fcmToken
+ }
+
+ fun getUUID(): String {
+ return this.uuid
+ }
+
+ companion object {
+ lateinit var appContext: RisingApplication
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/adapters/ChatAdapter.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/adapters/ChatAdapter.kt
deleted file mode 100644
index ee08db3bda773aa3f1b540ea6ff27b177df8c522..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/adapters/ChatAdapter.kt
+++ /dev/null
@@ -1,337 +0,0 @@
-package com.matthaigh27.chatgptwrapper.adapters
-
-import android.annotation.SuppressLint
-import android.app.Dialog
-import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.view.LayoutInflater
-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.models.common.ContactModel
-import com.matthaigh27.chatgptwrapper.models.common.HelpPromptModel
-import com.matthaigh27.chatgptwrapper.models.viewmodels.ChatMessageModel
-import com.matthaigh27.chatgptwrapper.utils.Constants.MSG_WIDGET_TYPE_HELP_PRMOPT
-import com.matthaigh27.chatgptwrapper.utils.Constants.MSG_WIDGET_TYPE_SEARCH_CONTACT
-import com.matthaigh27.chatgptwrapper.utils.Constants.MSG_WIDGET_TYPE_SMS
-import com.matthaigh27.chatgptwrapper.utils.ImageHelper
-import com.matthaigh27.chatgptwrapper.utils.Utils
-import com.matthaigh27.chatgptwrapper.widgets.ContactDetailItem
-import com.matthaigh27.chatgptwrapper.widgets.ContactDetailWidget
-import com.matthaigh27.chatgptwrapper.widgets.HelpPromptWidget
-import com.matthaigh27.chatgptwrapper.widgets.SearchContactWidget
-import com.matthaigh27.chatgptwrapper.widgets.SmsEditorWidget
-import org.json.JSONArray
-
-class ChatAdapter(list: ArrayList, context: Context) :
- RecyclerView.Adapter() {
-
- private var mChatModelList: ArrayList = ArrayList()
- private var mContext: Context
-
- private var mListener: MessageWidgetListener? = null
- var mOnSMSClickListener: ContactDetailItem.OnSMSClickListener? = null
-
- private val feedbackData = arrayOf(
- arrayOf(R.drawable.ic_thumb_up_disable, R.drawable.ic_thumb_down),
- arrayOf(R.drawable.ic_thumb_up_disable, R.drawable.ic_thumb_down_disable),
- arrayOf(R.drawable.ic_thumb_up, R.drawable.ic_thumb_down_disable),
- )
-
- init {
- mChatModelList = list
- mContext = context
- }
-
- override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
- val context = parent.context
- val inflater = LayoutInflater.from(context)
-
- /**
- * Inflate the custom layout and Return a new holder instance
- */
- return if (viewType == 0) {
- SendMessageViewHolder(
- inflater.inflate(
- R.layout.item_container_sent_message, parent, false
- )
- )
- } else {
- ReceiveMessageViewHolder(
- inflater.inflate(
- R.layout.item_container_received_message, parent, false
- )
- )
- }
- }
-
- /**
- * Involves populating data into the item through holder
- */
- override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
- /**
- * Get the data model based on position
- */
- val index = holder.adapterPosition
- val messageModel: ChatMessageModel = mChatModelList[index]
- if (messageModel.isMe) {
- setSentMessageData(holder as SendMessageViewHolder, messageModel)
- } else {
- setReceiveMessageData(holder as ReceiveMessageViewHolder, messageModel)
- }
- }
-
- private fun setSentMessageData(holder: SendMessageViewHolder, messageModel: ChatMessageModel) {
- /**
- * Set item views based on your views and data model
- */
- if (messageModel.message.isEmpty()) {
- holder.textMessage.visibility = View.GONE
- } else {
- holder.textMessage.text = messageModel.message
- holder.textMessage.visibility = View.VISIBLE
- }
-
-
- if (messageModel.image != null) {
- val radius = mContext.resources.getDimensionPixelSize(R.dimen.chat_message_item_radius)
-
- val originBmp = BitmapFactory.decodeByteArray(messageModel.image, 0, messageModel.image!!.size)
- val bmp = ImageHelper.getRoundedCornerBitmap(originBmp, radius)
- holder.imgMessage.visibility = View.VISIBLE
- holder.imgMessage.setImageBitmap(bmp)
- holder.imgMessage.setOnClickListener {
- onImageClick(originBmp)
- }
- } else {
- holder.imgMessage.visibility = View.GONE
- }
-
- if (messageModel.isWidget) {
- when (messageModel.widgetType) {
- MSG_WIDGET_TYPE_HELP_PRMOPT -> {
- val model: HelpPromptModel =
- HelpPromptModel.initModelWithString(messageModel.widgetDescription)
- val helpPromptWidget = HelpPromptWidget(mContext, model)
- val helpPromptListener = object : HelpPromptWidget.OnHelpPromptListener {
- override fun onSuccess(prompt: String) {
- mChatModelList[holder.adapterPosition].isWidget = false
- holder.llMessageWidget.visibility = View.GONE
- holder.llMessageWidget.removeAllViews()
- mListener!!.sentHelpPrompt(prompt)
- }
-
- override fun onCancel() {
- mChatModelList[holder.adapterPosition].isWidget = false
- holder.llMessageWidget.visibility = View.GONE
- holder.llMessageWidget.removeAllViews()
- mListener!!.canceledHelpPrompt()
- }
- }
- helpPromptWidget.setOnClickListener(helpPromptListener)
- holder.llMessageWidget.addView(helpPromptWidget)
- holder.llMessageWidget.visibility = View.VISIBLE
- }
- }
- } else {
- holder.llMessageWidget.visibility = View.GONE
- }
- }
-
- @SuppressLint("UseCompatLoadingForDrawables")
- fun setReceiveMessageData(holder: ReceiveMessageViewHolder, messageModel: ChatMessageModel) {
- /**
- * Set item views based on your views and data model
- */
- if (messageModel.message.isEmpty()) {
- holder.textMessage.visibility = View.GONE
- } else {
- holder.textMessage.text = messageModel.message
- holder.textMessage.visibility = View.VISIBLE
- }
-
-
- if (messageModel.image != null) {
- val radius = mContext.resources.getDimensionPixelSize(R.dimen.chat_message_item_radius)
-
- val originBmp = BitmapFactory.decodeByteArray(messageModel.image, 0, messageModel.image!!.size)
- val bmp = ImageHelper.getRoundedCornerBitmap(originBmp, radius)
- holder.imgMessage.visibility = View.VISIBLE
- holder.imgMessage.setImageBitmap(bmp)
- holder.imgMessage.setOnClickListener {
- onImageClick(originBmp)
- }
- } else {
- holder.imgMessage.visibility = View.GONE
- }
-
- holder.llFeedback.visibility = if (messageModel.visibleFeedback) {
- View.VISIBLE
- } else {
- View.GONE
- }
-
- setThumb(holder)
-
- holder.itemLayout.setOnLongClickListener {
- if (holder.llFeedback.visibility == View.VISIBLE) {
- holder.llFeedback.visibility = View.GONE
- mChatModelList[holder.adapterPosition].visibleFeedback = false
- } else {
- holder.llFeedback.visibility = View.VISIBLE
- mChatModelList[holder.adapterPosition].visibleFeedback = true
- }
- return@setOnLongClickListener true
- }
-
- holder.btnThumbUp.setOnClickListener {
- mChatModelList[holder.adapterPosition].feedback = 1
- setThumb(holder)
-
- }
-
- holder.btnThumbDown.setOnClickListener {
- mChatModelList[holder.adapterPosition].feedback = -1
- setThumb(holder)
- }
-
- if (messageModel.isWidget) {
- holder.llContactWidget.removeAllViews()
- when (messageModel.widgetType) {
- MSG_WIDGET_TYPE_SMS -> {
- val smsWidget = SmsEditorWidget(mContext, null)
- if(messageModel.widgetDescription.isNotEmpty()) {
- smsWidget.setToUserName(messageModel.widgetDescription)
- }
- holder.llMessageWidget.addView(smsWidget)
- holder.llMessageWidget.visibility = View.VISIBLE
-
- val smsListener = object : SmsEditorWidget.OnClickListener {
- override fun confirmSMS(phonenumber: String, message: String) {
- mChatModelList[holder.adapterPosition].isWidget = false
- holder.llMessageWidget.visibility = View.GONE
- holder.llMessageWidget.removeAllViews()
- mListener!!.sentSMS(phonenumber, message)
- }
-
- override fun cancelSMS() {
- mChatModelList[holder.adapterPosition].isWidget = false
- holder.llMessageWidget.visibility = View.GONE
- holder.llMessageWidget.removeAllViews()
- mListener!!.canceledSMS()
- }
- }
-
- smsWidget.setOnClickListener(smsListener)
- }
-
- MSG_WIDGET_TYPE_SEARCH_CONTACT -> {
- val contacts = Utils.instance.getContacts(mContext)
-
- val contactIds = JSONArray(messageModel.widgetDescription)
- for (i in 0 until contactIds.length()) {
- val contactId = contactIds[i].toString()
- val contact = Utils.instance.getContactModelById(contactId, contacts)
-
- val searchContactWidget = SearchContactWidget(mContext, contact, null)
- searchContactWidget.mSMSOnClickListener = mOnSMSClickListener
- holder.llContactWidget.addView(searchContactWidget)
- }
- holder.llContactWidget.visibility = View.VISIBLE
- }
- }
- } else {
- holder.llMessageWidget.visibility = View.GONE
- holder.llContactWidget.visibility = View.GONE
- }
- }
-
- @SuppressLint("UseCompatLoadingForDrawables")
- fun setThumb(holder: ReceiveMessageViewHolder) {
- holder.btnThumbUp.setImageDrawable(
- mContext.getDrawable(
- feedbackData[mChatModelList[holder.adapterPosition].feedback + 1][0]
- )
- )
- holder.btnThumbDown.setImageDrawable(
- mContext.getDrawable(
- feedbackData[mChatModelList[holder.adapterPosition].feedback + 1][1]
- )
- )
- }
-
- /**
- * Returns the total count of items in the list
- */
- override fun getItemCount(): Int {
- return mChatModelList.size
- }
-
- override fun getItemViewType(position: Int): Int {
- return if (mChatModelList[position].isMe) 0 else 1
- }
-
- private fun onImageClick(bitmap: Bitmap) {
- val dialog = Dialog(mContext)
- dialog.setContentView(R.layout.view_full_image)
- val fullImage = dialog.findViewById(R.id.fullImage) as ImageView
- fullImage.setImageBitmap(bitmap)
- dialog.show()
- }
-
- inner class ReceiveMessageViewHolder internal constructor(itemView: View) :
- RecyclerView.ViewHolder(itemView) {
- var textMessage: TextView
- var imgMessage: ImageView
- var llFeedback: LinearLayout
- var btnThumbUp: ImageView
- var btnThumbDown: ImageView
- var itemLayout: ConstraintLayout
- var llMessageWidget: LinearLayout
- var llContactWidget: LinearLayout
-
- init {
- textMessage = itemView.findViewById(R.id.textMessage) as TextView
- imgMessage = itemView.findViewById(R.id.imgMessage) as ImageView
- btnThumbUp = itemView.findViewById(R.id.btn_thumb_up) as ImageView
- btnThumbDown = itemView.findViewById(R.id.btn_thumb_down) as ImageView
- llFeedback = itemView.findViewById(R.id.ll_feedback) as LinearLayout
- itemLayout = itemView.findViewById(R.id.cl_receive_message) as ConstraintLayout
- llMessageWidget = itemView.findViewById(R.id.ll_message_widget) as LinearLayout
- llContactWidget = itemView.findViewById(R.id.ll_contacts_widget) as LinearLayout
- }
- }
-
- inner class SendMessageViewHolder internal constructor(itemView: View) :
- RecyclerView.ViewHolder(itemView) {
- var textMessage: TextView
- var imgMessage: ImageView
- var itemLayout: ConstraintLayout
- var llMessageWidget: LinearLayout
-
- init {
- textMessage = itemView.findViewById(R.id.textMessage) as TextView
- imgMessage = itemView.findViewById(R.id.imgMessage) as ImageView
- itemLayout = itemView.findViewById(R.id.cl_sent_message) as ConstraintLayout
- llMessageWidget = itemView.findViewById(R.id.ll_message_widget) as LinearLayout
- }
- }
-
- interface MessageWidgetListener {
- fun sentSMS(phonenumber: String, message: String)
- fun canceledSMS()
- fun sentHelpPrompt(prompt: String)
- fun canceledHelpPrompt()
- }
-
- fun setMessageWidgetListener(listener: MessageWidgetListener) {
- mListener = listener
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/MyDatabase.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/AppDatabase.kt
similarity index 50%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/MyDatabase.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/AppDatabase.kt
index 24767388367000054442350471abf4c4cfb497e1..4375a5fcfc2f857e295c21443947be3b0b5dc309 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/MyDatabase.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/AppDatabase.kt
@@ -1,34 +1,36 @@
-package com.matthaigh27.chatgptwrapper.database
+package com.matthaigh27.chatgptwrapper.data.local
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
-import com.matthaigh27.chatgptwrapper.database.dao.ContactDao
-import com.matthaigh27.chatgptwrapper.database.dao.ImageDao
-import com.matthaigh27.chatgptwrapper.database.entity.ContactEntity
-import com.matthaigh27.chatgptwrapper.database.entity.ImageEntity
+import com.matthaigh27.chatgptwrapper.data.local.dao.ContactDao
+import com.matthaigh27.chatgptwrapper.data.local.dao.ImageDao
+import com.matthaigh27.chatgptwrapper.data.local.entity.ContactEntity
+import com.matthaigh27.chatgptwrapper.data.local.entity.ImageEntity
@Database(entities = [ImageEntity::class, ContactEntity::class], version = 1, exportSchema = false)
-abstract class MyDatabase : RoomDatabase() {
+abstract class AppDatabase : RoomDatabase() {
abstract fun imageDao(): ImageDao
abstract fun contactDao(): ContactDao
companion object {
+ private val DATABASE_NAME = "RisingPhone"
+
@Volatile
- private var INSTANCE: MyDatabase? = null
+ private var INSTANCE: AppDatabase? = null
- fun getDatabase(context: Context): MyDatabase {
+ fun getDatabase(context: Context): AppDatabase {
val tempInstance = INSTANCE
if (tempInstance != null) {
return tempInstance
}
synchronized(this) {
val instance = Room.databaseBuilder(
- context.applicationContext,
- MyDatabase::class.java,
- "risingphone_database"
+ context = context.applicationContext,
+ klass = AppDatabase::class.java,
+ name = DATABASE_NAME
).build()
INSTANCE = instance
return instance
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
new file mode 100644
index 0000000000000000000000000000000000000000..9eb2010056fe52c67f60cb174ea3f2431a0d26a6
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ContactDao.kt
@@ -0,0 +1,20 @@
+package com.matthaigh27.chatgptwrapper.data.local.dao
+
+import androidx.lifecycle.MutableLiveData
+import androidx.room.*
+import com.matthaigh27.chatgptwrapper.data.local.entity.ContactEntity
+
+@Dao
+interface ContactDao {
+ @Insert
+ fun insert(contact: ContactEntity)
+
+ @Update
+ fun update(contact: ContactEntity)
+
+ @Delete
+ fun delete(contact: ContactEntity)
+
+ @Query("SELECT * FROM contacts")
+ 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
new file mode 100644
index 0000000000000000000000000000000000000000..a68090332134d04543ac8dcbd3e8eae5481c3264
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/dao/ImageDao.kt
@@ -0,0 +1,20 @@
+package com.matthaigh27.chatgptwrapper.data.local.dao
+
+import androidx.lifecycle.MutableLiveData
+import androidx.room.*
+import com.matthaigh27.chatgptwrapper.data.local.entity.ImageEntity
+
+@Dao
+interface ImageDao {
+ @Insert
+ fun insert(image: ImageEntity)
+
+ @Update
+ fun update(image: ImageEntity)
+
+ @Delete
+ fun delete(image: ImageEntity)
+
+ @Query("SELECT * FROM images")
+ fun getAllData(): List
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/entity/ContactEntity.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/entity/ContactEntity.kt
similarity index 79%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/entity/ContactEntity.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/entity/ContactEntity.kt
index be6009712233de4e7746f62d19a3ae5c0ed20a98..481659826963d0ea9f95bb0c3b1d80c4c145e264 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/entity/ContactEntity.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/entity/ContactEntity.kt
@@ -1,4 +1,4 @@
-package com.matthaigh27.chatgptwrapper.database.entity
+package com.matthaigh27.chatgptwrapper.data.local.entity
import androidx.room.Entity
import androidx.room.PrimaryKey
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/entity/ImageEntity.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/entity/ImageEntity.kt
similarity index 71%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/entity/ImageEntity.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/entity/ImageEntity.kt
index 8734569a0faf073e90669393fb2cd5c83a6c0026..337599d26b55b2d6de8d338a75a570f8a5a0d3c0 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/entity/ImageEntity.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/local/entity/ImageEntity.kt
@@ -1,4 +1,4 @@
-package com.matthaigh27.chatgptwrapper.database.entity
+package com.matthaigh27.chatgptwrapper.data.local.entity
import androidx.room.Entity
import androidx.room.PrimaryKey
@@ -8,4 +8,5 @@ data class ImageEntity (
@PrimaryKey(autoGenerate = true) val id: Int,
val path: String,
val name: String,
+ val dataModified: Long
)
\ No newline at end of file
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/AlarmModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8ffd6e9b0d9492f5431e0df363e42e550dfe8833
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/AlarmModel.kt
@@ -0,0 +1,3 @@
+package com.matthaigh27.chatgptwrapper.data.models
+
+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/ChatMessageModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ce6fb97eb53df247050cf85163eddd3211b95e94
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ChatMessageModel.kt
@@ -0,0 +1,36 @@
+package com.matthaigh27.chatgptwrapper.data.models
+
+import com.google.gson.JsonElement
+
+data class ChatMessageModel(
+ val type: Int,
+ val content: String? = null,
+ val data: JsonElement? = null,
+ val hasImage: Boolean = false,
+ val image: ByteArray? = null,
+) {
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as ChatMessageModel
+
+ if (type != other.type) return false
+ if (content != other.content) return false
+ if (data != other.data) return false
+ if (image != null) {
+ if (other.image == null) return false
+ if (!image.contentEquals(other.image)) return false
+ } else if (other.image != null) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = type
+ result = 31 * result + content.hashCode()
+ result = 31 * result + (data?.hashCode() ?: 0)
+ result = 31 * result + (image?.contentHashCode() ?: 0)
+ return result
+ }
+}
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
new file mode 100644
index 0000000000000000000000000000000000000000..37acc802af87eec9934b70770c16e8a8da2fff27
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ContactModel.kt
@@ -0,0 +1,8 @@
+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/HelpCommandModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpCommandModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b6bd5d3dd5be36cd7044c7c65ba08dafe6a8be74
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpCommandModel.kt
@@ -0,0 +1,6 @@
+package com.matthaigh27.chatgptwrapper.data.models
+
+data class HelpCommandModel (
+ var main: String? = null,
+ var assist: String? = null
+)
\ No newline at end of file
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
new file mode 100644
index 0000000000000000000000000000000000000000..dfbf1fefd0526d3bda705a37e36fda5ab3b0dfa6
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/HelpPromptModel.kt
@@ -0,0 +1,8 @@
+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/ImageModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ImageModel.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c346042454201baea4d740ef0e6d638c743b724f
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/models/ImageModel.kt
@@ -0,0 +1,8 @@
+package com.matthaigh27.chatgptwrapper.data.models
+
+import android.net.Uri
+
+data class ImageModel(
+ val uri: Uri,
+ val modifiedDate: Long
+)
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
new file mode 100644
index 0000000000000000000000000000000000000000..f996199814238b7209885d74fde7021d9798ce4c
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiClient.kt
@@ -0,0 +1,25 @@
+package com.matthaigh27.chatgptwrapper.data.remote
+
+import com.matthaigh27.chatgptwrapper.utils.Constants.API_BASE_URL
+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()
+ .callTimeout(240, TimeUnit.SECONDS)
+ .connectTimeout(240, TimeUnit.SECONDS)
+ .readTimeout(240, TimeUnit.SECONDS)
+ .writeTimeout(240, TimeUnit.SECONDS)
+ .build()
+
+ private val retrofit = Retrofit.Builder()
+ .baseUrl(API_BASE_URL)
+ .addConverterFactory(GsonConverterFactory.create())
+ .client(client)
+ .build()
+
+ val apiService: ApiService = retrofit.create(ApiService::class.java)
+}
\ No newline at end of file
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
new file mode 100644
index 0000000000000000000000000000000000000000..5d4f3da16ab283d00c2fc533d30ae8514647a83b
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiResource.kt
@@ -0,0 +1,10 @@
+package com.matthaigh27.chatgptwrapper.data.remote
+
+sealed class ApiResource(
+ val data: T? = null,
+ val message: String? = null
+) {
+ class Success(data: T) : ApiResource(data)
+ class Error(message: String, data: T? = null) : ApiResource(data, message)
+ class Loading : ApiResource()
+}
\ No newline at end of file
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
new file mode 100644
index 0000000000000000000000000000000000000000..aba49215779f85e86c0614ae017d70fd11952e12
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/ApiService.kt
@@ -0,0 +1,15 @@
+package com.matthaigh27.chatgptwrapper.data.remote
+
+import com.matthaigh27.chatgptwrapper.data.remote.requests.BaseApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.requests.NotificationApiRequest
+import com.matthaigh27.chatgptwrapper.data.remote.responses.ApiResponse
+import retrofit2.Call
+import retrofit2.http.Body
+import retrofit2.http.POST
+
+interface ApiService {
+ @POST("commands")
+ fun getAllHelpCommands(@Body request: BaseApiRequest) : Call
+ @POST("sendNotification")
+ fun sendNotification(@Body request: NotificationApiRequest) : Call
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/BaseApiRequest.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/BaseApiRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0142b3f2c11f4acee1bed1fe54ed463af168bad9
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/BaseApiRequest.kt
@@ -0,0 +1,8 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests
+
+import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
+
+data class BaseApiRequest(
+ val confs: Keys
+)
+
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/NotificationApiRequest.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/NotificationApiRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..97817707951a860307654edd2042a4614cb237e8
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/NotificationApiRequest.kt
@@ -0,0 +1,8 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests
+
+import com.matthaigh27.chatgptwrapper.data.remote.requests.common.Keys
+
+data class NotificationApiRequest(
+ val message: String,
+ val confs: Keys
+)
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/common/Keys.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/common/Keys.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c5c48cf1f49c80637bb2feb5a75b4457babd5aec
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/common/Keys.kt
@@ -0,0 +1,11 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests.common
+
+data class Keys(
+ val uuid: String,
+ val token: String,
+ val openai_key: String,
+ val pinecone_key: String,
+ val pinecone_env: String,
+ val firebase_key: String,
+ val settings: Settings,
+)
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/common/Settings.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/common/Settings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..dca4c5634940e61bc1fd4201c4609f6ecc6c3c58
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/requests/common/Settings.kt
@@ -0,0 +1,5 @@
+package com.matthaigh27.chatgptwrapper.data.remote.requests.common
+
+data class Settings(
+ val temperature: Float
+)
\ 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
new file mode 100644
index 0000000000000000000000000000000000000000..035c9a2a8bffde48d83ab4c67e39b4b5ab315df5
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/remote/responses/ApiResponse.kt
@@ -0,0 +1,15 @@
+package com.matthaigh27.chatgptwrapper.data.remote.responses
+
+import com.google.gson.JsonElement
+
+data class ApiResponse (
+ val status_code: Int,
+ val message: List,
+ 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/repository/FirebaseRepository.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/FirebaseRepository.kt
new file mode 100644
index 0000000000000000000000000000000000000000..2b74b7ce97a00d32146d9a716e7b3f959df55a1d
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/FirebaseRepository.kt
@@ -0,0 +1,23 @@
+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
+
+object FirebaseRepository {
+ fun downloadImageWithName(
+ name: String,
+ onSuccess: OnSuccess,
+ onFailure: OnFailure
+ ) {
+ val reference = "images/$name"
+
+ val storageReference = FirebaseStorage.getInstance().getReference(reference)
+ storageReference.getBytes(Long.MAX_VALUE).addOnSuccessListener { bytes ->
+ onSuccess(bytes)
+ }.addOnFailureListener { e ->
+ onFailure(e.toString())
+ }
+ return
+ }
+}
\ 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
new file mode 100644
index 0000000000000000000000000000000000000000..7797ca5f08088eeb2d63b29d5853cf36b57cc1c9
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RemoteRepository.kt
@@ -0,0 +1,59 @@
+package com.matthaigh27.chatgptwrapper.data.repository
+
+import com.matthaigh27.chatgptwrapper.data.remote.ApiClient
+import com.matthaigh27.chatgptwrapper.data.remote.requests.NotificationApiRequest
+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.utils.helpers.network.RequestFactory.buildBaseApiRequest
+import retrofit2.Call
+import retrofit2.Callback
+import retrofit2.Response
+
+
+object RemoteRepository {
+ private val apiService = ApiClient.apiService
+
+ fun getAllHelpCommands(
+ 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 {
+ onFailure(response.message())
+ }
+ }
+
+ override fun onFailure(call: Call, t: Throwable) {
+ onFailure(t.message.toString())
+ }
+ })
+ }
+
+ fun sendNotification(
+ request: NotificationApiRequest,
+ onSuccess: OnSuccess,
+ onFailure: OnFailure
+ ) {
+ val call = apiService.sendNotification(request)
+
+ 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 {
+ 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/RoomRepository.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RoomRepository.kt
new file mode 100644
index 0000000000000000000000000000000000000000..81cb0a36f9e86df7b8176fa3c5e4dc7fd6e6df01
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/data/repository/RoomRepository.kt
@@ -0,0 +1,47 @@
+package com.matthaigh27.chatgptwrapper.data.repository
+
+import androidx.lifecycle.MutableLiveData
+import com.matthaigh27.chatgptwrapper.RisingApplication
+import com.matthaigh27.chatgptwrapper.data.local.AppDatabase
+import com.matthaigh27.chatgptwrapper.data.local.entity.ContactEntity
+import com.matthaigh27.chatgptwrapper.data.local.entity.ImageEntity
+
+
+object RoomRepository {
+ private var databaseHandler: AppDatabase = AppDatabase.getDatabase(RisingApplication.appContext)
+
+ private var imageDao = databaseHandler.imageDao()
+ private var contactDao = databaseHandler.contactDao()
+
+ fun getAllImages(): MutableLiveData> {
+ return MutableLiveData(imageDao.getAllData())
+ }
+
+ fun insertImage(entity: ImageEntity) {
+ imageDao.insert(entity)
+ }
+
+ fun updateImage(entity: ImageEntity) {
+ imageDao.update(entity)
+ }
+
+ fun deleteImage(entity: ImageEntity) {
+ imageDao.delete(entity)
+ }
+
+ fun getAllContacts(): MutableLiveData> {
+ return MutableLiveData(contactDao.getAllData())
+ }
+
+ fun insertImage(entity: ContactEntity) {
+ contactDao.insert(entity)
+ }
+
+ fun updateImage(entity: ContactEntity) {
+ contactDao.update(entity)
+ }
+
+ fun deleteImage(entity: ContactEntity) {
+ contactDao.delete(entity)
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/dao/ContactDao.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/dao/ContactDao.kt
deleted file mode 100644
index 53d3f5ab8edaf727e24dfff3e382753e152b62d1..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/dao/ContactDao.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.matthaigh27.chatgptwrapper.database.dao
-
-import androidx.lifecycle.LiveData
-import androidx.room.*
-import com.matthaigh27.chatgptwrapper.database.entity.ContactEntity
-
-@Dao
-interface ContactDao {
- @Insert
- suspend fun insertContact(contact: ContactEntity)
-
- @Update
- suspend fun updateContact(contact: ContactEntity)
-
- @Delete
- suspend fun deleteContact(contact: ContactEntity)
-
- @Query("SELECT * FROM contacts")
- fun getAllContacts(): List
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/dao/ImageDao.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/dao/ImageDao.kt
deleted file mode 100644
index eb20e1682256bf245ba19178ae4090d554ccb7b5..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/database/dao/ImageDao.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.matthaigh27.chatgptwrapper.database.dao
-
-import androidx.lifecycle.LiveData
-import androidx.room.*
-import com.matthaigh27.chatgptwrapper.database.entity.ImageEntity
-
-@Dao
-interface ImageDao {
- @Insert
- suspend fun insertImage(image: ImageEntity)
-
- @Update
- suspend fun updateImage(image: ImageEntity)
-
- @Delete
- suspend fun deleteImage(image: ImageEntity)
-
- @Query("SELECT * FROM images")
- fun getAllImages(): List
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/fragments/ChatFragment.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/fragments/ChatFragment.kt
deleted file mode 100644
index 783270d0decee30a6a8ba0b1a863492dcea5393e..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/fragments/ChatFragment.kt
+++ /dev/null
@@ -1,888 +0,0 @@
-package com.matthaigh27.chatgptwrapper.fragments
-
-import android.os.Bundle
-import androidx.fragment.app.Fragment
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.annotation.SuppressLint
-import android.app.ActionBar.LayoutParams
-import android.content.*
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.net.Uri
-import android.os.Build
-import android.os.StrictMode
-import android.os.StrictMode.ThreadPolicy
-import android.provider.MediaStore
-import android.telephony.SmsManager
-import android.util.Log
-import android.view.KeyEvent
-import android.view.View.OnClickListener
-import android.view.animation.AccelerateDecelerateInterpolator
-import android.view.animation.AlphaAnimation
-import android.view.animation.Animation
-import android.view.animation.LinearInterpolator
-import android.view.animation.RotateAnimation
-import android.view.animation.TranslateAnimation
-import android.widget.*
-import androidx.annotation.RequiresApi
-import androidx.recyclerview.widget.LinearLayoutManager
-import androidx.recyclerview.widget.RecyclerView
-import com.google.firebase.storage.FirebaseStorage
-import com.matthaigh27.chatgptwrapper.MyApplication
-import com.matthaigh27.chatgptwrapper.R
-import com.matthaigh27.chatgptwrapper.adapters.ChatAdapter
-import com.matthaigh27.chatgptwrapper.database.MyDatabase
-import com.matthaigh27.chatgptwrapper.database.entity.ImageEntity
-import com.matthaigh27.chatgptwrapper.widgets.ImagePickerWidget
-import com.matthaigh27.chatgptwrapper.widgets.ImagePickerWidget.OnPositiveButtonClickListener
-import com.matthaigh27.chatgptwrapper.models.*
-import com.matthaigh27.chatgptwrapper.models.common.HelpCommandModel
-import com.matthaigh27.chatgptwrapper.models.common.HelpPromptModel
-import com.matthaigh27.chatgptwrapper.models.viewmodels.ChatMessageModel
-import com.matthaigh27.chatgptwrapper.services.api.HttpClient
-import com.matthaigh27.chatgptwrapper.services.api.HttpRisingInterface
-import com.matthaigh27.chatgptwrapper.utils.Constants.*
-import com.matthaigh27.chatgptwrapper.utils.Utils
-import com.matthaigh27.chatgptwrapper.widgets.ContactDetailItem
-import com.qw.photo.CoCo
-import com.qw.photo.callback.CoCoAdapter
-import com.qw.photo.callback.CoCoCallBack
-import com.qw.photo.constant.Range
-import com.qw.photo.pojo.PickResult
-import com.qw.photo.pojo.TakeResult
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import okhttp3.*
-import org.json.JSONException
-import org.json.JSONObject
-import java.io.*
-import java.util.*
-import kotlin.collections.ArrayList
-
-class ChatFragment : Fragment(), OnClickListener, HttpRisingInterface {
- private lateinit var rootView: View
- private var mContext: Context? = null
-
- /** ui components for chatlist recyclerview */
- private lateinit var mRvChatList: RecyclerView
- private lateinit var mEtMessage: EditText
-
- /** ui components for loading spinner */
- private lateinit var mSpLoading: ImageView
- private lateinit var mTvLoading: TextView
- private lateinit var mLlLoading: LinearLayout
-
- /** ui components for loading photo */
- private lateinit var mLlLoadPhoto: LinearLayout
- private lateinit var mIvLoadedPhoto: ImageView
- private lateinit var mBtnCancelLoadPhoto: TextView
-
- /** adapter for chat recyclerview and arraylist for store chatting history */
- private var mMessageList: ArrayList = ArrayList()
- private lateinit var mAdapter: ChatAdapter
-
- /** when a user selects image by camera or gallery,
- * these two variables are used to save image source and name */
- private var mSelectedImage: ByteArray? = null
- private var mSelectedImageName: String = ""
-
- /**
- * mImagePickerType is
- * 'image_uplaod' when user is going to upload image
- * 'image_picker' when user is going to pick image for prompting
- */
- private lateinit var mImagePickerWidget: ImagePickerWidget
- private var mImagePickerType: String = ""
-
- /** HttpClient for restful apis */
- private lateinit var httpClient: HttpClient
-
- /** list of help prompt commands */
- private var mHelpPromptList: ArrayList? = null
-
- /** animation variable for loading spinner */
- private val rotate = RotateAnimation(
- 0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f
- )
-
- /** room database handler for local database */
- private lateinit var mRoomDataHandler: MyDatabase
-
- /** status variable that checks if widget in chatting interface does exist */
- private var mIsExistWidget: Boolean = false
-
- /**
- * this is invoked when users click the message icon to send sms on contact detail dialog
- * that is shown when a user search contacts
- */
- private var mSMSOnClickListener: ContactDetailItem.OnSMSClickListener? = null
-
- override fun onCreateView(
- inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
- ): View {
- rootView = inflater.inflate(R.layout.fragment_chat, container, false)
- init()
- return rootView
- }
-
- private fun init() {
- initEnvironment()
- initValues()
- initView()
- initDatabase()
-
- trainImages()
- getAllPromptCommands()
- }
-
-
- private fun getAllPromptCommands() {
- showLoading(true, "Loading Help Prompt Data")
- httpClient.getALlHelpPromptCommands()
- }
-
-
- private fun initEnvironment() {
- val policy = ThreadPolicy.Builder().permitAll().build()
- StrictMode.setThreadPolicy(policy)
- }
-
- private fun initValues() {
- mContext = context
-
- httpClient = HttpClient(this)
-
- rotate.duration = 3000
- rotate.repeatCount = Animation.INFINITE
- rotate.interpolator = LinearInterpolator()
-
- initSMSOnClickListener()
- }
-
- private fun initView() {
- this.mAdapter = ChatAdapter(mMessageList, mContext!!)
- this.mAdapter.mOnSMSClickListener = mSMSOnClickListener
- mRvChatList = rootView.findViewById(R.id.chatRecycleView) as RecyclerView
- mRvChatList.adapter = mAdapter
-
- val sendSMSListener = object : ChatAdapter.MessageWidgetListener {
- override fun sentSMS(phonenumber: String, message: String) {
- mIsExistWidget = false
- sendSms(phonenumber, message)
- addMessage(
- "You sent SMS with belowing content.\n\n " + "To: $phonenumber\n " + "Message: $message",
- false
- )
- }
-
- override fun canceledSMS() {
- mIsExistWidget = false
- addMessage("You canceled SMS.", false)
- }
-
- override fun sentHelpPrompt(prompt: String) {
- mIsExistWidget = false
- addMessage(prompt, true)
- }
-
- override fun canceledHelpPrompt() {
- mIsExistWidget = false
- addMessage("You canceled help command.", false)
- }
- }
-
- mAdapter.setMessageWidgetListener(sendSMSListener)
-
- val linearLayoutManager = LinearLayoutManager(mContext)
- mRvChatList.layoutManager = linearLayoutManager
-
- this.mEtMessage = rootView.findViewById(R.id.et_message)
- mEtMessage.setOnKeyListener { _, keyCode, keyEvent ->
- if (keyEvent.action == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER) {
- addMessage(mEtMessage.text.toString(), true)
- }
- return@setOnKeyListener false
- }
-
- rootView.findViewById(R.id.btn_send_message).setOnClickListener(this)
- rootView.findViewById(R.id.btn_image_upload).setOnClickListener(this)
- rootView.findViewById(R.id.btn_image_picker).setOnClickListener(this)
-
- mSpLoading = rootView.findViewById(R.id.sp_loading)
- mTvLoading = rootView.findViewById(R.id.tv_loading)
- mLlLoading = rootView.findViewById(R.id.ll_loading)
-
- mLlLoadPhoto = rootView.findViewById(R.id.ll_load_photo)
- mIvLoadedPhoto = rootView.findViewById(R.id.iv_load_photo)
- mBtnCancelLoadPhoto = rootView.findViewById(R.id.btn_cancel_load_photo)
- mBtnCancelLoadPhoto.setOnClickListener(this)
-
- initImagePickerWidget()
- }
-
- private fun initDatabase() {
- mRoomDataHandler = MyDatabase.getDatabase(mContext!!)
- }
-
- private fun initSMSOnClickListener() {
- mSMSOnClickListener = object : ContactDetailItem.OnSMSClickListener {
- override fun onSMSClickListener(phoneNumber: String) {
- addMessage(
- "SMS",
- isMe = false,
- isSend = false,
- isWidget = true,
- widgetType = MSG_WIDGET_TYPE_SMS,
- widgetDescription = phoneNumber
- )
- }
-
- override fun onVoiceCallListener(phoneNumber: String, toName: String) {
- addMessage(
- message = "You made a voice call to $toName($phoneNumber)",
- isMe = false,
- isSend = false
- )
- }
- }
- }
-
- /**
- * set loading spinner visible
- */
- private fun setDisableActivity(enable: Boolean) {
- runOnUIThread {
- mEtMessage.isEnabled = enable
- rootView.findViewById(R.id.btn_send_message).isEnabled = enable
- rootView.findViewById(R.id.btn_image_upload).isEnabled = enable
- rootView.findViewById(R.id.btn_image_picker).isEnabled = enable
- }
- }
-
- /**
- * set loading spinner visible
- */
- private fun showLoading(visible: Boolean, text: String = "") {
- runOnUIThread {
- setDisableActivity(!visible)
-
- if (visible) {
- mSpLoading.startAnimation(rotate)
- mLlLoading.visibility = View.VISIBLE
- mTvLoading.text = text
- } else {
- mSpLoading.clearAnimation()
- mLlLoading.visibility = View.GONE
- }
- }
- }
-
- /**
- * show overlay when you picked image and users can cancel to load photo if users want
- */
- private fun showLoadPhotoOverlay(imageByteArray: ByteArray) {
- mLlLoadPhoto.visibility = View.VISIBLE
-
- mIvLoadedPhoto.setImageBitmap(
- BitmapFactory.decodeByteArray(
- /* data = */ imageByteArray, /* offset = */ 0, /* length = */ imageByteArray.size
- )
- )
- }
-
- /**
- * Bind broadcast sent by MessageService
- */
- private val receiver = object : BroadcastReceiver() {
- @RequiresApi(Build.VERSION_CODES.TIRAMISU)
- override fun onReceive(context: Context, intent: Intent) {
- Log.d(TAG, "Receive")
- }
- }
-
-
- /**
- * get download url from firebase imagename in response and generate download url from the imagename
- * With getBitmapFromURL method, get bitmap of the image and set it to mSelectedImage to display it to chatlist
- * Finally, run addmessage and insert it to chat recyclerview
- *
- * @param imageName the firebase store imagename
- */
- private fun getImageResponse(imageName: String, imageDesc: String) {
- if (imageName.isEmpty() && imageDesc.isNotEmpty()) {
- addMessage(message = imageDesc, isMe = false)
- return
- }
-
- showLoading(visible = true, text = LOADING_DOWNLOADING_IMAGE)
-
- val imageNameToUpload = "images/$imageName"
-
- val storageReference = FirebaseStorage.getInstance().getReference(imageNameToUpload)
- storageReference.downloadUrl.addOnSuccessListener { uri ->
- try {
- val image = Utils.instance.getBitmapFromURL(uri.toString())
- if (image == null) showToast("can not get bitmap from url")
- val byteArrayOutputStream = ByteArrayOutputStream()
-
- val isSuccess =
- image!!.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream)
- if (!isSuccess) {
- showToast("Fail to compress image")
- }
- mSelectedImage = byteArrayOutputStream.toByteArray()
- } catch (e: Exception) {
- showToast("cannot get download url from firebase store")
- e.printStackTrace()
- }
-
- addMessage(message = imageDesc, isMe = false)
- showLoading(visible = false)
- }
- return
- }
-
- override fun onResume() {
- super.onResume()
- updateChangedUserData()
- }
-
- private fun updateChangedUserData() {
- trainContacts()
- }
-
- /**
- * Open Help Command Widget with analysing string command
- */
- private fun openHelpCommandWidget(strCommand: String) {
- try {
- val command: HelpCommandModel = Utils.instance.getHelpCommandFromStr(strCommand)
- if (command.isMainCommand()) {
- when (command.mainCommandName) {
- "sms" -> {
- addMessage(
- message = "SMS",
- isMe = false,
- isSend = false,
- isWidget = true,
- widgetType = MSG_WIDGET_TYPE_SMS
- )
- }
-
- else -> {
- mHelpPromptList!!.forEach { model ->
- if (model.name == command.mainCommandName) {
- addMessage(
- "Help Prompt Command",
- isMe = true,
- isSend = false,
- isWidget = true,
- widgetType = MSG_WIDGET_TYPE_HELP_PRMOPT,
- widgetDescription = model.toString()
- )
- return
- }
- }
- addMessage(
- message = "No such command name exists.", isMe = false, isSend = false
- )
- }
- }
- } else {
- if (command.assistCommandName == "all") {
- val usage =
- "usage:\n" + "- help command: /help [command name]\n" + "- prompt command: /\n\n"
- var strHelpList = "help prompt commands:"
- mHelpPromptList!!.forEach { model ->
- strHelpList += "\n- " + model.name
- }
-
- addMessage(message = usage + strHelpList, isMe = false, isSend = false)
- } else {
- var strHelpDesc = ""
- mHelpPromptList!!.forEach { model ->
- if (model.name == command.assistCommandName) {
- var strTags = ""
- model.tags!!.forEach { tag ->
- strTags += " $tag"
- }
- strHelpDesc = "description: " + model.description + "\ntags:" + strTags
- }
- }
- if (strHelpDesc.isEmpty()) addMessage(
- message = "No such command name exists.", isMe = false, isSend = false
- )
- else addMessage(message = strHelpDesc, isMe = false, isSend = false)
- }
- }
- } catch (e: Exception) {
- e.printStackTrace()
- showToast(e.message.toString())
- }
- }
-
- /**
- * add message to chat list
- * if users picked image from camera or gallery, send post request to `sendNotification` to ask generally
- * else do 'imageRelateness' to search image
- *
- * @param message message content for chat list
- * @param isMe this identify if this is sent by langchain server or users send message to server
- * @param isSend is boolean that checks if you send request to server
- * @param isWidget is boolean that checks if message item has widget
- * @param widgetType is type of Widget ex: SMS, HELP_COMMAND, etc
- * @param widgetDescription is string that saves information for widget
- */
- @SuppressLint("NotifyDataSetChanged")
- private fun addMessage(
- message: String,
- isMe: Boolean,
- isSend: Boolean = true,
- isWidget: Boolean = false,
- widgetType: String = "",
- widgetDescription: String = ""
- ) {
- if ((message.isEmpty() && mSelectedImage == null) || mIsExistWidget) return
- if (isWidget) {
- if (widgetType != MSG_WIDGET_TYPE_SEARCH_CONTACT) {
- mIsExistWidget = true
- }
- }
-
- val msg = ChatMessageModel()
- msg.message = message
- msg.isMe = isMe
- msg.isWidget = isWidget
- msg.widgetType = widgetType
- msg.widgetDescription = widgetDescription
-
- /**
- * if users picked some image from camera or gallery, add the image to chatting message
- */
- if (mSelectedImage != null) {
- msg.image = mSelectedImage
- mSelectedImage = null
- }
-
- /**
- * if users picked some image from camera or gallery, the image upload to firebase store
- * mSelectedImageName is uuid created uploading to firebase store
- */
- if (mSelectedImageName.isNotEmpty()) {
- msg.imageName = mSelectedImageName
- mSelectedImageName = ""
- }
-
- runOnUIThread {
- mLlLoadPhoto.visibility = View.GONE
-
- mMessageList.add(msg)
- mAdapter.notifyDataSetChanged()
- mEtMessage.setText("")
- mRvChatList.scrollTo(/* x = */ 1000, /* y = */ -1000)
- mRvChatList.scrollToPosition(mMessageList.size - 1)
- }
-
- if ((message.isNotEmpty() && message.first() == '/') && isMe) {
- openHelpCommandWidget(message)
- return
- }
-
- if (isMe) {
- if (!isSend) {
- return
- }
-
- showLoading(visible = true, text = LOADING_ASKING_TO_GPT)
- if (msg.image != null) {
- httpClient.callImageRelatedness(msg.imageName)
- } else {
- httpClient.callSendNotification(message)
- }
- }
- }
-
- override fun onClick(view: View) {
- when (view.id) {
- R.id.btn_send_message -> {
- addMessage(mEtMessage.text.toString(), true)
- }
-
- R.id.btn_image_upload -> {
- mImagePickerType = PICKERTYPE_IMAGE_UPLOAD
- if(rootView.findViewById(R.id.ll_toolbar).visibility == View.VISIBLE)
- hideSlidingWidget()
- else
- showSlidingWidget()
- }
-
- R.id.btn_image_picker -> {
- mImagePickerType = PICKERTYPE_IMAGE_PICK
- if(rootView.findViewById(R.id.ll_toolbar).visibility == View.VISIBLE)
- hideSlidingWidget()
- else
- showSlidingWidget()
- }
-
- R.id.btn_cancel_load_photo -> {
- mLlLoadPhoto.visibility = View.GONE
- mSelectedImageName = ""
- mSelectedImage = null
- }
- }
- }
-
- /**
- * open browser with url
- * @param url to open with browser
- */
- private fun openBrowser(url: String) {
- val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
- startActivity(Intent.createChooser(intent, "Browse with"))
- }
-
- /**
- * calls when finish picking image
- *
- * @param imageByteData is bytearray of picked image
- * @param type if users are going to upload image or pick image for query
- */
- private fun pickedImage(imageByteData: ByteArray, type: String) {
- if (type == "image_upload") {
- uploadImageToFirebaseStorage(imageByteData)
- } else {
- uploadSearchImage(imageByteData)
- }
- }
-
- /**
- * toast message is invoked when error happens
- */
- private fun showToast(message: String) {
- runOnUIThread {
- Toast.makeText(
- mContext, message, Toast.LENGTH_SHORT
- ).show()
- }
- }
-
-
- /**
- * this can show dialog with camera and gallery icon.
- * when you click camera icon, camera application runs and users can get an image by capturing using camera.
- * when you click gallery icon, users can select image in your storage.
- * A picked image converts into bytearray data and upload to firebase storage.
- */
- private fun initImagePickerWidget() {
- mImagePickerWidget = ImagePickerWidget(mContext!!)
-
- val myImplementation = object : OnPositiveButtonClickListener {
- override fun onPositiveBtnClick(isCamera: Boolean?) {
- if (isCamera == true) {
- CoCo.with(activity!!).take(Utils.instance.createSDCardFile())
- .start(object : CoCoAdapter() {
- override fun onSuccess(data: TakeResult) {
- val byteArray: ByteArray =
- Utils.instance.getBytesFromPath(data.savedFile!!.absolutePath)
- pickedImage(
- byteArray, mImagePickerType
- )
- }
-
- override fun onFailed(exception: Exception) {
- super.onFailed(exception)
- showToast("Fail to pick image. Please try again.")
- }
- })
- } else {
- CoCo.with(activity!!).pick().range(Range.PICK_CONTENT)
- .start(object : CoCoCallBack {
-
- override fun onSuccess(data: PickResult) {
- val byteArray: ByteArray? =
- Utils.instance.convertImageToByte(data.originUri)
- if (byteArray == null) showToast("can not find such a file")
- pickedImage(byteArray!!, mImagePickerType)
- }
-
- override fun onFailed(exception: Exception) {
- showToast("Fail to pick image. Please try again.")
- }
- })
- }
- }
- }
-
- mImagePickerWidget.setOnClickListener(myImplementation)
-
- val slidingWidget = rootView.findViewById(R.id.ll_toolbar)
- slidingWidget.addView(mImagePickerWidget)
- }
-
- private fun uploadSearchImage(imageByteArray: ByteArray) {
- showLoading(true, LOADING_ANALYZING_IMAGE)
- 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 {
- showLoading(false)
- }.addOnSuccessListener {
- Log.d(TAG, "Success upload to firebase storage")
- showLoading(false)
-
- mSelectedImageName = "$uuid"
- mSelectedImage = imageByteArray
-
- showLoadPhotoOverlay(imageByteArray)
- }
- }
-
- /**
- * @param imageByteArray ByteArray data for image to upload to firebase storage
- */
- private fun uploadImageToFirebaseStorage(imageByteArray: ByteArray) {
- showLoading(true, LOADING_UPLOADING_IAMGE)
- 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 {
- showLoading(false)
- }.addOnSuccessListener {
- Log.d(TAG, "Success upload to firebase storage")
-
- showLoading(false)
- httpClient.callImageUpload("$uuid")
- }
- }
-
- override fun onSuccessResult(msg: String) {
- showLoading(false)
- try {
- val json = JSONObject(msg)
- if (json.has(RESPONSE_TYPE_PROGRAM)) {
- when (json.getString(RESPONSE_TYPE_PROGRAM)) {
- RESPONSE_TYPE_BROWSER -> {
- addMessage(json.getString(RESPONSE_TYPE_URL), false)
- openBrowser(json.getString(RESPONSE_TYPE_URL))
- return
- }
-
- RESPONSE_TYPE_ALERT -> {
- MyApplication.appContext.showNotification(
- json.getString(
- RESPONSE_TYPE_CONTENT
- )
- )
- return
- }
-
- RESPONSE_TYPE_MESSAGE -> {
- addMessage(json.getString(RESPONSE_TYPE_CONTENT), false)
- return
- }
-
- RESPONSE_TYPE_IMAGE -> {
- try {
- val imageRes = JSONObject(json.getString(RESPONSE_TYPE_CONTENT))
-
- val imageName = if (imageRes.has("image_name")) {
- imageRes["image_name"] as String
- } else {
- ""
- }
-
- val imageDesc = if (imageRes.has("image_desc")) {
- imageRes["image_desc"] as String
- } else {
- ""
- }
-
- getImageResponse(imageName, imageDesc)
- } catch (e: Exception) {
- e.printStackTrace()
- }
- return
- }
-
- RESPONSE_TYPE_SMS -> {
- addMessage(
- json.getString(RESPONSE_TYPE_CONTENT),
- false,
- isSend = false,
- isWidget = true,
- widgetType = MSG_WIDGET_TYPE_SMS
- )
- }
-
- RESPONSE_TYPE_HELP_COMMAND -> {
- try {
- mHelpPromptList = Utils.instance.getHelpCommandListFromJsonString(
- json.getString(RESPONSE_TYPE_CONTENT)
- )
- } catch (e: java.lang.Exception) {
- e.printStackTrace()
- showToast("JSON Error occured")
- }
- }
-
- RESPONSE_TYPE_CONTACT -> {
- try {
- addMessage(
- message = "Contacts that you are looking for.",
- isMe = false,
- isSend = false,
- isWidget = true,
- widgetType = MSG_WIDGET_TYPE_SEARCH_CONTACT,
- widgetDescription = json.getString(RESPONSE_TYPE_CONTENT)
- )
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- }
- }
- } catch (e: JSONException) {
- e.printStackTrace()
- addMessage(msg, false)
- }
- }
-
- override fun onFailureResult(msg: String) {
- showLoading(false)
-
- showToast(msg)
- }
-
- private fun queryImagesFromExternalStorage(contentResolver: ContentResolver): ArrayList {
- val listOfImageUris = ArrayList()
-
- val projection = arrayOf(MediaStore.Images.Media._ID)
-
- val sortOrder = "${MediaStore.Images.Media.DATE_TAKEN} DESC"
-
- contentResolver.query(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, null, null, sortOrder
- )?.use { cursor ->
- val idColumn = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
- while (cursor.moveToNext()) {
- val id = cursor.getLong(idColumn)
- val contentUri = Uri.withAppendedPath(
- MediaStore.Images.Media.EXTERNAL_CONTENT_URI, id.toString()
- )
- listOfImageUris.add(contentUri)
- }
- }
- return listOfImageUris
- }
-
- private fun trainImages() {
- CoroutineScope(Dispatchers.IO).launch {
- val images = queryImagesFromExternalStorage(requireContext().contentResolver)
- val originalImages = mRoomDataHandler.imageDao().getAllImages()
-
- images.forEach { uri ->
- var isExist = false
- val path = Utils.instance.getRealPathFromUri(requireContext(), uri)
- for (i in originalImages.indices) {
- val entity: ImageEntity = originalImages[i]
- if (entity.path == path) {
- isExist = true
- break
- }
- }
- if (!isExist) {
- val byteArray = Utils.instance.getBytesFromPath(path)
- val uuid = uploadImageToFirebaseStorage(byteArray)
-
- if (path != null)
- mRoomDataHandler.imageDao().insertImage(ImageEntity(0, path, "$uuid"))
- }
- }
- }
- }
-
- private fun trainContacts() {
- showLoading(true, "Train Contacts")
- val contacts = Utils.instance.getContacts(mContext!!)
- CoroutineScope(Dispatchers.Main).launch {
- val changedContacts = Utils.instance.getChangedContacts(contacts, mRoomDataHandler)
- httpClient.trainContacts(changedContacts)
- }
- }
-
- fun sendSms(phoneNumber: String, message: String) {
- try {
- val smsManager = SmsManager.getDefault()
- val parts = smsManager.divideMessage(message)
- smsManager.sendMultipartTextMessage(/* destinationAddress = */ phoneNumber, /* scAddress = */
- null, /* parts = */
- parts, /* sentIntents = */
- null, /* deliveryIntents = */
- null)
- } catch (e: SecurityException) {
- e.printStackTrace()
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
-
- @SuppressLint("UseRequireInsteadOfGet")
- fun runOnUIThread(action: () -> Unit) {
- requireActivity().runOnUiThread {
- action()
- }
- }
-
- private fun showSlidingWidget() {
- val slidingWidget = rootView.findViewById(R.id.ll_toolbar)
-
- val dy = slidingWidget.measuredHeight.toFloat()
- slidingWidget.visibility = View.VISIBLE
-
- val anim = TranslateAnimation(0f, 0f, dy, 0f).apply {
- duration = 150 // Set the animation duration, e.g., 300ms
- interpolator = AccelerateDecelerateInterpolator()
- setAnimationListener(object : Animation.AnimationListener {
- override fun onAnimationStart(animation: Animation?) {
- slidingWidget.visibility = View.VISIBLE
- }
-
- override fun onAnimationEnd(animation: Animation?) {}
-
- override fun onAnimationRepeat(animation: Animation?) {}
- })
- }
-
- slidingWidget.startAnimation(anim)
- }
-
- private fun hideSlidingWidget() {
- val slidingWidget = rootView.findViewById(R.id.ll_toolbar)
-
- val anim = AlphaAnimation(1f, 0f).apply {
- duration = 100 // Set the animation duration, e.g., 300ms
- interpolator = AccelerateDecelerateInterpolator()
- setAnimationListener(object : Animation.AnimationListener {
- override fun onAnimationStart(animation: Animation?) {}
-
- override fun onAnimationEnd(animation: Animation?) {
- slidingWidget.visibility = View.GONE
- }
-
- override fun onAnimationRepeat(animation: Animation?) {}
- })
- }
-
- slidingWidget.startAnimation(anim)
- }
-}
-
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/ContactModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/ContactModel.kt
deleted file mode 100644
index 25153bde8bd1003bcf2f327b76f0a0b876e8b34a..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/ContactModel.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.matthaigh27.chatgptwrapper.models.common
-
-class ContactModel {
- var id: String = ""
- var name: String = ""
- var phoneList: ArrayList? = null
- var status: String = ""
-
- init {
- phoneList = ArrayList()
- }
-
- fun setData(id: String, name: String, phoneList: ArrayList, status: String) {
- this.id = id
- this.name = name
- this.phoneList = phoneList
- this.status = status
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/HelpCommandModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/HelpCommandModel.kt
deleted file mode 100644
index 3f1871ab5e601ef58168d3aa51f91870e8774247..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/HelpCommandModel.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.matthaigh27.chatgptwrapper.models.common
-
-class HelpCommandModel {
- var mainCommandName: String = ""
- var assistCommandName: String = ""
-
- fun isMainCommand(): Boolean {
- return mainCommandName != "help"
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/HelpPromptModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/HelpPromptModel.kt
deleted file mode 100644
index 891cce0539ce69703f865fdbd3a0b8973a6e6f94..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/HelpPromptModel.kt
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.matthaigh27.chatgptwrapper.models.common
-
-import com.google.gson.Gson
-import com.google.gson.GsonBuilder
-
-class HelpPromptModel {
- var name: String = ""
- var description: String = ""
- var prompt: String = ""
- var tags: ArrayList? = null
-
- override fun toString(): String {
- val gson = Gson()
- val str = gson.toJson(this)
- return str
- }
-
- companion object {
- fun initModelWithString(strJson: String): HelpPromptModel {
- val gson = Gson()
- val model: HelpPromptModel = gson.fromJson(strJson, HelpPromptModel::class.java)
- return model
- }
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/ImagePromptModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/ImagePromptModel.kt
deleted file mode 100644
index 53c9e9350a40d6dca39afb083e9e5d12b49561f7..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/common/ImagePromptModel.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.matthaigh27.chatgptwrapper.models.common
-
-class ImagePromptModel {
- var id: String = ""
- var path: String = ""
-
- constructor(id: String, path: String) {
- this.id = id
- this.path = path
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/requestmodels/RequestBodyModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/requestmodels/RequestBodyModel.kt
deleted file mode 100644
index 7c5451d6118db9d1517513770a42000bf405814c..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/requestmodels/RequestBodyModel.kt
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.matthaigh27.chatgptwrapper.models.requestmodels
-
-import com.matthaigh27.chatgptwrapper.MyApplication
-import org.json.JSONException
-import org.json.JSONObject
-
-class RequestBodyModel(builder: Builder) {
-
- /** this identify request type
- * example: it will be 'message' when users send message, 'image' when users upload image
- */
- var type: String = ""
- var token: String = ""
- var message: String = ""
- var imageName: String = ""
- var uuid: String = ""
-
- init {
- this.token = MyApplication.appContext.getFCMToken()
- this.uuid = MyApplication.appContext.getUUID()
- this.message = builder.message
- this.imageName = builder.imageName
- }
-
- @Throws(JSONException::class)
- fun buildJsonObject(): JSONObject {
-
- val jsonObject = JSONObject()
- jsonObject.accumulate("type", type)
- jsonObject.accumulate("token", token)
- jsonObject.accumulate("message", message)
- jsonObject.accumulate("image_name", imageName)
- jsonObject.accumulate("uuid", uuid)
-
- return jsonObject
- }
-
- class Builder {
- var type: String = ""
- var token: String = ""
- var message: String = ""
- var imageName: String = ""
- var uuid: String = ""
-
- constructor() {
-
- }
-
- constructor(request: RequestBodyModel) {
- this.type = request.type
- this.token = request.token
- this.message = request.message
- this.imageName = request.imageName
- this.uuid = request.uuid
- }
-
- fun type(type: String): Builder {
- this.type = type
- return this
- }
-
- fun token(token: String): Builder {
- this.token = token
- return this
- }
-
- fun message(message: String): Builder {
- this.message = message
- return this
- }
-
- fun imageName(imageName: String): Builder {
- this.imageName = imageName
- return this
- }
-
- fun uuid(uuid: String): Builder {
- this.uuid = uuid
- return this
- }
-
- fun build(): RequestBodyModel {
- return RequestBodyModel(this)
- }
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/requestmodels/RequestTrainContactModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/requestmodels/RequestTrainContactModel.kt
deleted file mode 100644
index 9056f6ba0b7a76fa90736018e90a580bda36d2ff..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/requestmodels/RequestTrainContactModel.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.matthaigh27.chatgptwrapper.models.requestmodels
-
-import com.matthaigh27.chatgptwrapper.MyApplication
-import com.matthaigh27.chatgptwrapper.models.common.ContactModel
-import com.matthaigh27.chatgptwrapper.utils.Utils
-import org.json.JSONArray
-import org.json.JSONException
-import org.json.JSONObject
-
-class RequestTrainContactModel(builder: Builder) {
-
- /** this identify request type
- * example: it will be 'message' when users send message, 'image' when users upload image
- */
- var type: String = ""
- var token: String = ""
- var contacts = JSONArray()
- var uuid: String = ""
-
- init {
- this.token = MyApplication.appContext.getFCMToken()
- this.uuid = MyApplication.appContext.getUUID()
- this.contacts = builder.contacts
- }
-
- @Throws(JSONException::class)
- fun buildJsonObject(): JSONObject {
-
- val jsonObject = JSONObject()
- jsonObject.accumulate("type", type)
- jsonObject.accumulate("token", token)
- jsonObject.accumulate("contacts", contacts)
- jsonObject.accumulate("uuid", uuid)
-
- return jsonObject
- }
-
- class Builder {
- var type: String = ""
- var token: String = ""
- var contacts = JSONArray()
- var uuid: String = ""
-
- constructor() {
-
- }
-
- constructor(request: RequestTrainContactModel) {
- this.type = request.type
- this.token = request.token
- this.uuid = request.uuid
- this.contacts = request.contacts
- }
-
- fun type(type: String): Builder {
- this.type = type
- return this
- }
-
- fun token(token: String): Builder {
- this.token = token
- return this
- }
-
- fun contacts(contacts: ArrayList): Builder {
- this.contacts = Utils.instance.convertContactModelToJsonArray(contacts)
- return this
- }
-
- fun uuid(uuid: String): Builder {
- this.uuid = uuid
- return this
- }
-
- fun build(): RequestTrainContactModel {
- return RequestTrainContactModel(this)
- }
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/viewmodels/ChatMessageModel.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/viewmodels/ChatMessageModel.kt
deleted file mode 100644
index c6dd4655cd1d37264f9b06fde72d2cda751d66cc..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/models/viewmodels/ChatMessageModel.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.matthaigh27.chatgptwrapper.models.viewmodels
-
-import androidx.lifecycle.ViewModel
-
-/**
- * ChatModel for Chat RecyclerView
- */
-class ChatMessageModel: ViewModel() {
- var message: String = ""
- var isMe: Boolean = true
- var image: ByteArray? = null
- var imageName: String = ""
- var visibleFeedback = false
- var feedback = 0
- var isWidget: Boolean = false
- var widgetType = ""
- var widgetDescription = ""
-}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/MessageService.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/MessageService.kt
deleted file mode 100644
index 36f21bd2c15e97ef4f81ef42e58fe7b83c6d1759..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/MessageService.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.matthaigh27.chatgptwrapper.services
-
-import android.content.Intent
-import android.util.Log
-import com.google.firebase.messaging.FirebaseMessagingService
-import com.google.firebase.messaging.RemoteMessage
-import com.matthaigh27.chatgptwrapper.utils.Constants.TAG
-
-class MessageService : FirebaseMessagingService() {
-
- /**
- * this function is called when langchain server pushs notification into FCM
- * @param remoteMessage is sent by FCM when langchain server pushs notification
- */
- override fun onMessageReceived(remoteMessage: RemoteMessage) {
- super.onMessageReceived(remoteMessage)
- if (remoteMessage.notification != null) {
- Log.d(
- TAG, "Message Notification Body: " + remoteMessage.notification!!.body
- )
-
- /** intent for sending broadcast to ChatActivity */
- val intent = Intent()
- intent.action = "android.intent.action.MAIN"
- intent.putExtra("message", remoteMessage.notification!!.body)
-
- /** send broadcast to ChatActivity
- * So ChatActivity can receive remoteMessage from this service */
- sendBroadcast(intent)
- }
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/api/HttpClient.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/api/HttpClient.kt
deleted file mode 100644
index 35583f7b84dbfce6c53ce04fbe83144f1751e2fb..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/api/HttpClient.kt
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.matthaigh27.chatgptwrapper.services.api
-
-import android.util.Log
-import com.matthaigh27.chatgptwrapper.BuildConfig
-import com.matthaigh27.chatgptwrapper.models.common.ContactModel
-import com.matthaigh27.chatgptwrapper.models.requestmodels.RequestBodyModel
-import com.matthaigh27.chatgptwrapper.models.requestmodels.RequestTrainContactModel
-import com.matthaigh27.chatgptwrapper.utils.Constants
-import com.matthaigh27.chatgptwrapper.utils.Constants.GET
-import com.matthaigh27.chatgptwrapper.utils.Constants.POST
-import com.matthaigh27.chatgptwrapper.utils.ReqType
-import okhttp3.Call
-import okhttp3.Callback
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.RequestBody
-import okhttp3.Response
-import org.json.JSONException
-import org.json.JSONObject
-import java.io.IOException
-import java.util.concurrent.TimeUnit
-
-class HttpClient {
- /* Server URL and Api Endpoints */
- val SERVER_URL = BuildConfig.BASE_URL
- val SEND_NOTIFICATION_URL = SERVER_URL + "sendNotification"
- val IMAGE_RELATEDNESS = SERVER_URL + "image_relatedness"
- val UPLOAD_IMAGE = SERVER_URL + "uploadImage"
- val GET_ALL_HELP_COMMANDS = SERVER_URL + "commands"
- val TRAIN_CONTACTS = SERVER_URL + "train/contacts"
-
- var mCallback: HttpRisingInterface
-
- constructor(callback: HttpRisingInterface) {
- mCallback = callback
- }
-
- private fun sendOkHttpRequest(postBody: String, postUrl: String, method: String) {
- val body: RequestBody = RequestBody.create(Constants.JSON, postBody)
-
- /**
- * set okhttpclient timeout to 120s
- */
- var request: Request? = null
- if (method == POST) request = Request.Builder().url(postUrl).post(body).build()
- else request = Request.Builder().url(postUrl).get().build()
-
- val client =
- OkHttpClient.Builder().connectTimeout(Constants.CUSTOM_TIMEOUT, TimeUnit.SECONDS)
- .readTimeout(Constants.CUSTOM_TIMEOUT, TimeUnit.SECONDS)
- .writeTimeout(Constants.CUSTOM_TIMEOUT, TimeUnit.SECONDS).build()
-
- client.newCall(request).enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- /**
- * Handle failure
- */
- e.printStackTrace()
-
- mCallback.onFailureResult("Fail to send request to server. Please ask again.")
- }
-
- override fun onResponse(call: Call, response: Response) {
- val myResponse = response.body()!!.string()
- Log.d(Constants.TAG, myResponse)
-
- try {
- val json = JSONObject(myResponse)["result"].toString()
- mCallback.onSuccessResult(json)
- } catch (e: JSONException) {
- mCallback.onFailureResult(myResponse)
- e.printStackTrace()
- }
- }
- })
- }
-
- /* call sendNotification */
- fun callSendNotification(message: String) {
- sendOkHttpRequest(
- RequestBodyModel.Builder().message(message).type(ReqType.instance.MESSAGE).build()
- .buildJsonObject().toString(), SEND_NOTIFICATION_URL, POST
- )
- }
-
- /* call image_relatedness */
- fun callImageRelatedness(imageName: String) {
- sendOkHttpRequest(
- RequestBodyModel.Builder().imageName(imageName).type(ReqType.instance.MESSAGE).build()
- .buildJsonObject().toString(), IMAGE_RELATEDNESS, POST
- )
- }
-
- /* call image_upload */
- fun callImageUpload(imageName: String) {
- sendOkHttpRequest(
- RequestBodyModel.Builder().imageName(imageName).type(ReqType.instance.IMAGE_UPLOAD)
- .build().buildJsonObject().toString(), UPLOAD_IMAGE, POST
- )
- }
-
- fun getALlHelpPromptCommands() {
- sendOkHttpRequest(
- RequestBodyModel.Builder().build().buildJsonObject().toString(),
- GET_ALL_HELP_COMMANDS,
- GET
- )
- }
-
- fun trainContacts(contacts: ArrayList) {
- sendOkHttpRequest(
- RequestTrainContactModel.Builder().contacts(contacts).build().buildJsonObject().toString(),
- TRAIN_CONTACTS,
- POST
- )
- }
-}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/api/HttpRisingInterface.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/api/HttpRisingInterface.kt
deleted file mode 100644
index d01c29ce04878f508af5c2e5a20f7fdc6e2e30ff..0000000000000000000000000000000000000000
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/services/api/HttpRisingInterface.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.matthaigh27.chatgptwrapper.services.api;
-
-interface HttpRisingInterface {
- fun onSuccessResult(msg: String)
-
- fun onFailureResult(msg: String)
-}
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/base/BaseActivity.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/base/BaseActivity.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7af743f2f001182f5889ad4e7bc8e07192901b20
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/base/BaseActivity.kt
@@ -0,0 +1,18 @@
+package com.matthaigh27.chatgptwrapper.ui.base
+
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+
+open class BaseActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ // Hide the status bar (system toolbar)
+ window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_FULLSCREEN
+
+ // For hiding the action bar, if you have one
+ supportActionBar?.hide()
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/activites/HomeActivity.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/ChatActivity.kt
similarity index 67%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/activites/HomeActivity.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/ChatActivity.kt
index 0a11074e924944adcac75f71f65eaf8a4e31050a..50542830f45a3f6281aa86ace7824c01721dbe5e 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/activites/HomeActivity.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/ChatActivity.kt
@@ -1,39 +1,38 @@
-package com.matthaigh27.chatgptwrapper.activites
+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 android.util.Log
-import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
-import com.google.android.material.tabs.TabLayout.TabGravity
import com.matthaigh27.chatgptwrapper.R
-import com.matthaigh27.chatgptwrapper.dialogs.CommonConfirmDialog
-import com.matthaigh27.chatgptwrapper.fragments.ChatFragment
-import java.io.File
+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 HomeActivity : AppCompatActivity() {
+class ChatActivity : BaseActivity() {
private val PERMISSIONS_REQUEST_CODE = 1
-
private val PERMISSIONS = arrayOf(
Manifest.permission.SEND_SMS,
Manifest.permission.READ_CONTACTS,
Manifest.permission.CALL_PHONE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
+ 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_home)
+ setContentView(R.layout.activity_chat)
- requestPermission()
+ requestPermissions()
}
- private fun requestPermission() {
+ private fun requestPermissions() {
val notGrantedPermissions = PERMISSIONS.filter {
checkSelfPermission(it) != PackageManager.PERMISSION_GRANTED
}
@@ -41,10 +40,9 @@ class HomeActivity : AppCompatActivity() {
if (notGrantedPermissions.isNotEmpty()) {
if (shouldShowRequestPermissionRationale(notGrantedPermissions[0])) {
// show custom permission rationale
- val confirmDialog = CommonConfirmDialog(this)
- confirmDialog.setMessage("This app requires SMS, Contacts and Phone permissions to function properly. Please grant the necessary permissions.")
+ val confirmDialog = ConfirmDialog(this@ChatActivity)
confirmDialog.setOnClickListener(object :
- CommonConfirmDialog.OnConfirmButtonClickListener {
+ ConfirmDialog.OnDialogButtonClickListener {
override fun onPositiveButtonClick() {
requestPermissions(
notGrantedPermissions.toTypedArray(), PERMISSIONS_REQUEST_CODE
@@ -55,21 +53,19 @@ class HomeActivity : AppCompatActivity() {
finish()
}
})
+
confirmDialog.show()
+ confirmDialog.setMessage(CONFIRM_MESSAGE)
+
} else {
requestPermissions(notGrantedPermissions.toTypedArray(), PERMISSIONS_REQUEST_CODE)
}
} else {
// Permissions already granted, navigate to your desired fragment
- navigateToChatFragment()
+ navigateToChatMainFragment()
}
}
- private fun navigateToChatFragment() {
- val fragmentTransaction = supportFragmentManager.beginTransaction()
- fragmentTransaction.replace(R.id.frame_container, ChatFragment()).commit()
- }
-
@SuppressLint("MissingSuperCall")
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array, grantResults: IntArray
@@ -78,14 +74,19 @@ class HomeActivity : AppCompatActivity() {
PERMISSIONS_REQUEST_CODE -> {
if (grantResults.all { it == PackageManager.PERMISSION_GRANTED }) {
// Permissions granted, navigate to your desired fragment
- navigateToChatFragment()
+ navigateToChatMainFragment()
} else {
- requestPermission()
+ requestPermissions()
}
return
}
}
}
+
+ private fun navigateToChatMainFragment() {
+ val fragmentTransaction = supportFragmentManager.beginTransaction()
+ fragmentTransaction.replace(R.id.fl_container, ChatMainFragment()).commit()
+ }
}
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
new file mode 100644
index 0000000000000000000000000000000000000000..03deb5e800281637c07a1a8641ca31bb176f3f03
--- /dev/null
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/adapters/ChatMainAdapter.kt
@@ -0,0 +1,179 @@
+package com.matthaigh27.chatgptwrapper.ui.chat.view.adapters
+
+import android.content.Context
+import android.graphics.BitmapFactory
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.ImageView
+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.ui.chat.view.interfaces.ChatMessageInterface
+import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.SendSmsWidget
+import com.matthaigh27.chatgptwrapper.ui.chat.view.widgets.chatwidget.helpprompt.HelpPromptWidget
+import com.matthaigh27.chatgptwrapper.utils.Constants
+import com.matthaigh27.chatgptwrapper.utils.helpers.chat.ImageHelper
+
+class ChatMainAdapter(
+ context: Context, list: ArrayList, callbacks: ChatMessageInterface
+) : RecyclerView.Adapter() {
+
+ private val VIEW_TYPE_MSG_SENT = 0
+ private val VIEW_TYPE_MSG_RECEIVED = 1
+ private val VIEW_TYPE_CHAT_WIDGET = 2
+
+ private var context: Context
+ private var callbacks: ChatMessageInterface
+ private var chatMessageList: ArrayList = ArrayList()
+
+ init {
+ this.context = context
+ this.chatMessageList = list
+ this.callbacks = callbacks
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
+ val inflater = LayoutInflater.from(context)
+
+ return when (viewType) {
+ VIEW_TYPE_MSG_SENT -> {
+ SentMessageViewHolder(
+ inflater.inflate(
+ R.layout.item_container_sent_message, parent, false
+ )
+ )
+ }
+
+ VIEW_TYPE_MSG_RECEIVED -> {
+ ReceivedMessageViewHolder(
+ inflater.inflate(
+ R.layout.item_container_received_message, parent, false
+ )
+ )
+ }
+
+ else -> {
+ ChatWidgetViewHolder(
+ inflater.inflate(
+ R.layout.item_container_chat_widget, parent, false
+ )
+ )
+ }
+ }
+ }
+
+ override fun getItemCount(): Int {
+ return chatMessageList.size
+ }
+
+ override fun getItemViewType(position: Int): Int {
+ return chatMessageList[position].type
+ }
+
+ override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
+ 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)
+ }
+
+ else -> {
+ setMessageData(holder as ChatWidgetViewHolder, chatMessageModel)
+ }
+ }
+ }
+
+ private fun setMessageData(holder: SentMessageViewHolder, data: ChatMessageModel) {
+ holder.txtMessage.text = data.content
+ }
+
+ private fun setMessageData(holder: ReceivedMessageViewHolder, data: ChatMessageModel) {
+ if (data.hasImage) {
+ data.image?.let { image ->
+ val originBitmap = BitmapFactory.decodeByteArray(image, 0, image.size)
+ val radius = context.resources.getDimensionPixelSize(R.dimen.radius_small)
+ val bmp = ImageHelper.getRoundedCornerBitmap(originBitmap, radius)
+ holder.imgMessage.visibility = View.VISIBLE
+ holder.imgMessage.setImageBitmap(bmp)
+
+ data.content?.let { message ->
+ holder.txtMessage.text = message
+ } ?: run {
+ holder.txtMessage.visibility = View.GONE
+ }
+ }
+ } else {
+ holder.txtMessage.text = data.content
+ holder.imgMessage.visibility = View.GONE
+ holder.txtMessage.visibility = View.VISIBLE
+ }
+ }
+
+ private fun setMessageData(holder: ChatWidgetViewHolder, data: ChatMessageModel) {
+ when (data.content) {
+ Constants.TYPE_WIDGET_SMS -> {
+ val sendSmsWidget = SendSmsWidget(context).apply {
+ this.callback = callbacks
+ }
+ holder.itemLayout.addView(sendSmsWidget)
+ holder.itemLayout.visibility = View.VISIBLE
+ }
+
+ Constants.TYPE_WIDGET_HELP_PROMPT -> {
+// val helpPromptWidget = HelpPromptWidget(context)
+ }
+
+ Constants.TYPE_WIDGET_SEARCH_CONTACT -> {
+
+ }
+
+ Constants.TYPE_WIDGET_FEEDBACK -> {
+
+ }
+ }
+ }
+
+ inner class ReceivedMessageViewHolder internal constructor(itemView: View) :
+ RecyclerView.ViewHolder(itemView) {
+ var txtMessage: TextView
+ var imgMessage: ImageView
+ var itemLayout: ConstraintLayout
+
+ 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
+ }
+ }
+
+ inner class SentMessageViewHolder internal constructor(itemView: View) :
+ RecyclerView.ViewHolder(itemView) {
+ var txtMessage: TextView
+ var imgMessage: ImageView
+ var itemLayout: ConstraintLayout
+
+ 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
+ }
+ }
+
+ inner class ChatWidgetViewHolder internal constructor(itemView: View) :
+ RecyclerView.ViewHolder(itemView) {
+ var itemLayout: FrameLayout
+
+ init {
+ itemLayout = itemView.findViewById(R.id.fl_widget_message) as FrameLayout
+ }
+ }
+}
\ No newline at end of file
diff --git a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/dialogs/CommonConfirmDialog.kt b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/dialogs/ConfirmDialog.kt
similarity index 55%
rename from Android/app/src/main/java/com/matthaigh27/chatgptwrapper/dialogs/CommonConfirmDialog.kt
rename to Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/dialogs/ConfirmDialog.kt
index 5cea7908d29de7db5d74c6aeeaf97c84dddb558e..08608e8e12bf8fa267ad2d9b7c7f6f15b8776e47 100644
--- a/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/dialogs/CommonConfirmDialog.kt
+++ b/Android/app/src/main/java/com/matthaigh27/chatgptwrapper/ui/chat/view/dialogs/ConfirmDialog.kt
@@ -1,4 +1,4 @@
-package com.matthaigh27.chatgptwrapper.dialogs
+package com.matthaigh27.chatgptwrapper.ui.chat.view.dialogs
import android.app.Dialog
import android.content.Context
@@ -12,62 +12,59 @@ import android.widget.Button
import android.widget.TextView
import com.matthaigh27.chatgptwrapper.R
-class CommonConfirmDialog(context: Context) : Dialog(context), View.OnClickListener {
+class ConfirmDialog(context: Context) : Dialog(context), View.OnClickListener {
- private var mTvMessage: TextView? = null
- private var mMessage: String = ""
- private lateinit var mClickListener: OnConfirmButtonClickListener
+ private var txtMessage: TextView? = null
+ private lateinit var btnClickListener: OnDialogButtonClickListener
init {
setCancelable(false)
}
- fun setOnClickListener(listener: OnConfirmButtonClickListener) {
- mClickListener = listener
- }
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initView()
}
+ override fun onClick(view: View?) {
+ when (view?.id) {
+ R.id.btn_ok -> {
+ btnClickListener.onPositiveButtonClick()
+ }
+
+ R.id.btn_cancel -> {
+ btnClickListener.onNegativeButtonClick()
+ }
+ }
+ this.dismiss()
+ }
+
private fun initView() {
requestWindowFeature(Window.FEATURE_NO_TITLE)
- setContentView(R.layout.dialog_common_confirm)
+ setContentView(R.layout.dialog_confirm)
- window!!.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
- window!!.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
+ window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+ window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
findViewById