diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..fd45b12 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*.iml +.gradle +/local.properties +/.idea/caches/build_file_checksums.ser +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml new file mode 100755 index 0000000..f8dbc1f --- /dev/null +++ b/.idea/assetWizardSettings.xml @@ -0,0 +1,36 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100755 index 0000000..30aa626 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100755 index 0000000..7ac24c7 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100755 index 0000000..703e5d4 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100755 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100755 index 0000000..288b36b --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100755 index 0000000..6870378 --- /dev/null +++ b/README.md @@ -0,0 +1,110 @@ +
+
+
+

+ +

+
+
+
+
+
+ +CometChat Android Demo app (built using **CometChat Pro**) is a fully functional messaging app capable of **one-on-one** (private) and **group** messaging. The app enables users to send **text** and **multimedia messages like audio, video, images, documents.** + +[![Platform](https://img.shields.io/badge/Platform-Android-brightgreen.svg)](#) [![Platform](https://img.shields.io/badge/Language-Kotlin-yellowgreen.svg)](#) + +## Table of Contents + +1. [Screenshots ](#screenshots) + +2. [Installation ](#installtion) + +3. [Run the Sample App ](#run-the-sample-app) + +4. [Customizing the UI](#customizing-the-ui) + +5. [Integrating this sample into your own app](#integrating-this-sample-into-your-own-app) + +5. [Contribute](#contribute) + + + +## ScreenShots + + + +## Installtion + + Simply Clone the project from android-kotlin-chat-app repository and open in Android Studio. + Build the Demo App and it will be ready to Run + + + + +## Run the Sample App + + + + To Run to sample App you have to do the following changes by Adding **ApiKey** and **AppId** + + - Open the Project in Android Mode in Android Studio + + - Go to Under java --> com\inscripts\cometchatpulse--> StringContract + + - Under class `StringContract.kt` go to `class` named `AppDetails` + + - modify *APP_ID* and *API_KEY* with your own **ApiKey** and **AppId** + + `val APP_ID: String = "XXXXXXXXX"` + + `val API_KEY: String = "XXXXXXXXX"` + +## Note + + You can Obtain your *APP_ID* and *API_KEY* from [CometChat-Pulse Dashboard](https://app.cometchat.com/) + + For more information read [CometChat-Pro Android SDK](https://prodocs.cometchat.com/docs/android-quick-start) Documentation + + + + + ![Studio Guide](https://github.com/cometchat-pro/android-kotlin-chat-app/blob/master/ScreenShot/guide.png) + + ## Customizing the UI + + We have provided three themes with our sample app namely **PersianBlue, MountainMeadow, AzureRadiance**. To apply the themes: + + - Go to `Application` class `CometChatPro` + + - Create constructor of class `Appearance` and pass any of these three values + + 1.PERSIAN_BLUE + + 2.MOUNTAIN_MEADOW + + 3.AZURE_RADIANCE + + example `Appearance(Appearance.AppTheme.PERSIAN_BLUE)` + + To make your custom appearance go to `Appearance` class under package named Utils i.e + + Go to Under java --> com\inscripts\cometchatpulse--> Utils--> Appearance + +

+ +

+ + +## Integrating this sample into your own app + Copy sample app in your project + + remove login and add your own authentication method + + launch `MainActivity` and start using the app + +## Contribute + + + Feel free to make Pull Request. + diff --git a/ScreenShot/Screenshot_20190121-135306_CometChat Pro.jpg b/ScreenShot/Screenshot_20190121-135306_CometChat Pro.jpg new file mode 100755 index 0000000..57c3145 Binary files /dev/null and b/ScreenShot/Screenshot_20190121-135306_CometChat Pro.jpg differ diff --git a/ScreenShot/Screenshot_20190121-135314_CometChat Pro.jpg b/ScreenShot/Screenshot_20190121-135314_CometChat Pro.jpg new file mode 100755 index 0000000..7ca7bf3 Binary files /dev/null and b/ScreenShot/Screenshot_20190121-135314_CometChat Pro.jpg differ diff --git a/ScreenShot/Screenshot_20190121-135330_CometChat Pro.jpg b/ScreenShot/Screenshot_20190121-135330_CometChat Pro.jpg new file mode 100755 index 0000000..fe20001 Binary files /dev/null and b/ScreenShot/Screenshot_20190121-135330_CometChat Pro.jpg differ diff --git a/ScreenShot/Screenshot_20190121-142043_CometChat Pro.jpg b/ScreenShot/Screenshot_20190121-142043_CometChat Pro.jpg new file mode 100755 index 0000000..ab11da4 Binary files /dev/null and b/ScreenShot/Screenshot_20190121-142043_CometChat Pro.jpg differ diff --git a/ScreenShot/gib.gif b/ScreenShot/gib.gif new file mode 100755 index 0000000..c5bb3a8 Binary files /dev/null and b/ScreenShot/gib.gif differ diff --git a/ScreenShot/guide.png b/ScreenShot/guide.png new file mode 100755 index 0000000..46fd214 Binary files /dev/null and b/ScreenShot/guide.png differ diff --git a/app/.gitignore b/app/.gitignore new file mode 100755 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100755 index 0000000..6df34ed --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,99 @@ +apply plugin: 'com.android.application' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +apply plugin: 'kotlin-kapt' + + + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.inscripts.cometchatpulse" + minSdkVersion 21 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + resValue "string", "google_maps_key", (project.findProperty("GOOGLE_MAPS_API_KEY") ?: "") + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + ndk { + abiFilters "armeabi-v7a", "x86" + } + +// packagingOptions { +// exclude "lib/arm64-v8a/libgnustl_shared.so" +// } + + } + dataBinding { + enabled = true + } + + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.google.android.gms:play-services-maps:16.0.0' + compile 'com.google.android.gms:play-services-places:16.0.0' +// compile 'com.google.android.gms:play-services:12.0.1' + compile 'com.google.android.gms:play-services-location:16.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + + implementation 'com.android.support:design:28.0.0' + implementation 'com.android.support:support-v4:28.0.0' + implementation 'com.android.support:recyclerview-v7:28.0.0' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + implementation 'com.android.support:cardview-v7:28.0.0' + implementation 'com.android.support:support-emoji-appcompat:28.0.0' + implementation 'com.android.support:support-annotations:28.0.0' + + implementation 'com.github.bumptech.glide:glide:4.8.0' + + annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0' + + // ViewModel and LiveData + implementation "android.arch.lifecycle:extensions:1.1.1" + + + kapt "android.arch.lifecycle:compiler:1.1.1" + + + //cometchat sdk + implementation 'com.cometchat:pro-android-chat-sdk:1.2.0' + + + implementation 'com.google.firebase:firebase-core:16.+' + + implementation 'com.google.firebase:firebase-messaging:17.3.4' + + implementation 'com.facebook.shimmer:shimmer:0.4.0' + + + api "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0" + api "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.0" + + +} +apply plugin: 'com.google.gms.google-services' diff --git a/app/google-services.json b/app/google-services.json new file mode 100755 index 0000000..e51d617 --- /dev/null +++ b/app/google-services.json @@ -0,0 +1,55 @@ +{ + "project_info": { + "project_number": "122431658736", + "firebase_url": "https://pro-demo-229414.firebaseio.com", + "project_id": "pro-demo-229414", + "storage_bucket": "pro-demo-229414.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:122431658736:android:9701feb58d0de92f", + "android_client_info": { + "package_name": "com.inscripts.cometchatpulse" + } + }, + "oauth_client": [ + { + "client_id": "122431658736-850hjj22tfu85s0kskhvgbaej5ajoi0k.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.inscripts.cometchatpulse", + "certificate_hash": "b7ac951dadc69f508d5964100060ac97e6dfd595" + } + }, + { + "client_id": "122431658736-ab8npvt0hi9kb3fphce4v3546j5eq8m5.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyBZQBGyUgawKhekPGvys_KQzKBDpcJE3BE" + } + ], + "services": { + "analytics_service": { + "status": 1 + }, + "appinvite_service": { + "status": 2, + "other_platform_oauth_client": [ + { + "client_id": "122431658736-ab8npvt0hi9kb3fphce4v3546j5eq8m5.apps.googleusercontent.com", + "client_type": 3 + } + ] + }, + "ads_service": { + "status": 2 + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100755 index 0000000..308344d --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,24 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# ServiceLoader support +-keepnames class kotlinx.** { *; } \ No newline at end of file diff --git a/app/src/androidTest/java/com/inscripts/cometchatpulse/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/inscripts/cometchatpulse/ExampleInstrumentedTest.kt new file mode 100755 index 0000000..7fb69e6 --- /dev/null +++ b/app/src/androidTest/java/com/inscripts/cometchatpulse/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package com.inscripts.cometchatpulse + +import android.support.test.InstrumentationRegistry +import android.support.test.runner.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getTargetContext() + assertEquals("com.inscripts.cometchatpulse", appContext.packageName) + } +} diff --git a/app/src/debug/res/values/google_maps_api.xml b/app/src/debug/res/values/google_maps_api.xml new file mode 100755 index 0000000..4b23a1f --- /dev/null +++ b/app/src/debug/res/values/google_maps_api.xml @@ -0,0 +1,24 @@ + + + AIzaSyCFV_G9O00VZ61EFqun4y_l3XJq9KUcAXQ + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100755 index 0000000..5fd0fe9 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/Avenir_Next.ttf b/app/src/main/assets/Avenir_Next.ttf new file mode 100755 index 0000000..a059a49 Binary files /dev/null and b/app/src/main/assets/Avenir_Next.ttf differ diff --git a/app/src/main/assets/GoogleSans-Bold.ttf b/app/src/main/assets/GoogleSans-Bold.ttf new file mode 100755 index 0000000..8049766 Binary files /dev/null and b/app/src/main/assets/GoogleSans-Bold.ttf differ diff --git a/app/src/main/assets/GoogleSans-Medium.ttf b/app/src/main/assets/GoogleSans-Medium.ttf new file mode 100755 index 0000000..1543660 Binary files /dev/null and b/app/src/main/assets/GoogleSans-Medium.ttf differ diff --git a/app/src/main/assets/GoogleSans-Regular.ttf b/app/src/main/assets/GoogleSans-Regular.ttf new file mode 100755 index 0000000..ab605f9 Binary files /dev/null and b/app/src/main/assets/GoogleSans-Regular.ttf differ diff --git a/app/src/main/assets/HelveticaNeueBold.ttf b/app/src/main/assets/HelveticaNeueBold.ttf new file mode 100755 index 0000000..a918901 Binary files /dev/null and b/app/src/main/assets/HelveticaNeueBold.ttf differ diff --git a/app/src/main/assets/HelveticaNeueItalic.ttf b/app/src/main/assets/HelveticaNeueItalic.ttf new file mode 100755 index 0000000..6830ffc Binary files /dev/null and b/app/src/main/assets/HelveticaNeueItalic.ttf differ diff --git a/app/src/main/assets/HelveticaNeueMedium.ttf b/app/src/main/assets/HelveticaNeueMedium.ttf new file mode 100755 index 0000000..9a1e4cf Binary files /dev/null and b/app/src/main/assets/HelveticaNeueMedium.ttf differ diff --git a/app/src/main/assets/OpenSans-Regular.ttf b/app/src/main/assets/OpenSans-Regular.ttf new file mode 100755 index 0000000..db43334 Binary files /dev/null and b/app/src/main/assets/OpenSans-Regular.ttf differ diff --git a/app/src/main/assets/Product Sans Bold.ttf b/app/src/main/assets/Product Sans Bold.ttf new file mode 100755 index 0000000..d847195 Binary files /dev/null and b/app/src/main/assets/Product Sans Bold.ttf differ diff --git a/app/src/main/assets/Product Sans Italic.ttf b/app/src/main/assets/Product Sans Italic.ttf new file mode 100755 index 0000000..5fc56d4 Binary files /dev/null and b/app/src/main/assets/Product Sans Italic.ttf differ diff --git a/app/src/main/assets/Product Sans Regular.ttf b/app/src/main/assets/Product Sans Regular.ttf new file mode 100755 index 0000000..c0442ee Binary files /dev/null and b/app/src/main/assets/Product Sans Regular.ttf differ diff --git a/app/src/main/assets/Roboto-Medium.ttf b/app/src/main/assets/Roboto-Medium.ttf new file mode 100755 index 0000000..6a95133 Binary files /dev/null and b/app/src/main/assets/Roboto-Medium.ttf differ diff --git a/app/src/main/assets/Roboto-Regular.ttf b/app/src/main/assets/Roboto-Regular.ttf new file mode 100755 index 0000000..ddee473 Binary files /dev/null and b/app/src/main/assets/Roboto-Regular.ttf differ diff --git a/app/src/main/assets/RobotoCondensed-Regular.ttf b/app/src/main/assets/RobotoCondensed-Regular.ttf new file mode 100755 index 0000000..f0d3a81 Binary files /dev/null and b/app/src/main/assets/RobotoCondensed-Regular.ttf differ diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/CallActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/CallActivity.kt new file mode 100755 index 0000000..2a4d9a6 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/CallActivity.kt @@ -0,0 +1,163 @@ +package com.inscripts.cometchatpulse.Activities + +import android.app.Activity +import android.arch.lifecycle.ViewModelProviders +import android.content.pm.PackageManager +import android.databinding.DataBindingUtil +import android.media.RingtoneManager +import android.net.Uri +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.view.View +import android.widget.RelativeLayout +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.inscripts.cometchatpulse.Repository.MessageRepository +import com.inscripts.cometchatpulse.Helpers.CCPermissionHelper +import com.inscripts.cometchatpulse.Helpers.CometChatAudioHelper +import com.inscripts.cometchatpulse.Helpers.OutgoingAudioHelper +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.OnetoOneViewModel +import com.inscripts.cometchatpulse.databinding.ActivityCallBinding +import java.lang.NullPointerException + +class CallActivity : AppCompatActivity(), View.OnClickListener { + + private lateinit var name: String + + private lateinit var id: String + + lateinit var binding: ActivityCallBinding + + private var imageUrl: String? = null + + private var cometChatAudioHelper: CometChatAudioHelper? = null + + private lateinit var sessionID: String + + private lateinit var onetoOneViewModel: OnetoOneViewModel + + private lateinit var notification: Uri + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_call) + + binding = DataBindingUtil.setContentView(this, R.layout.activity_call) + CommonUtil.setStatusBarColor(this) + cometChatAudioHelper = CometChatAudioHelper(this) + cometChatAudioHelper?.initAudio() + notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE) + onetoOneViewModel = ViewModelProviders.of(this).get(OnetoOneViewModel::class.java) + + try { + + + if (intent?.action?.equals(CometChatConstants.CALL_TYPE_VIDEO)!!) { + if (!CCPermissionHelper.hasPermissions(this, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + CCPermissionHelper.requestPermissions(this, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VIDEO_CALL) + } + + } else if (intent?.action.equals(CometChatConstants.CALL_TYPE_AUDIO)) { + if (!CCPermissionHelper.hasPermissions(this, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + + CCPermissionHelper.requestPermissions(this, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VOICE_CALL) + } + } + } catch (e: NullPointerException) { + e.printStackTrace() + } + + if (intent.hasExtra(StringContract.IntentString.RECIVER_TYPE)) { + + if (intent.getStringExtra(StringContract.IntentString.RECIVER_TYPE).equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + + name = intent.getStringExtra(StringContract.IntentString.GROUP_NAME) + id = intent.getStringExtra(StringContract.IntentString.GROUP_ID) + imageUrl = intent?.getStringExtra(StringContract.IntentString.GROUP_ICON) + } else { + name = intent.getStringExtra(StringContract.IntentString.USER_NAME) + id = intent.getStringExtra(StringContract.IntentString.USER_ID) + imageUrl = intent?.getStringExtra(StringContract.IntentString.USER_AVATAR) + } + } + + if (intent?.type.equals(StringContract.IntentString.INCOMING)) { + binding.tvCallText.setText("Incoming call...") + cometChatAudioHelper?.startIncomingAudio(notification, true) + } else if (intent?.type.equals(StringContract.IntentString.OUTGOING)) { + cometChatAudioHelper?.startOutgoingAudio(OutgoingAudioHelper.Type.IN_COMMUNICATION) + val rl = RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, + RelativeLayout.LayoutParams.WRAP_CONTENT) + + rl.addRule(RelativeLayout.CENTER_HORIZONTAL) + rl.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM) + rl.bottomMargin = 56 + + binding.hangUp.layoutParams = rl + binding.acceptCall.visibility = View.GONE + binding.tvCallText.setText("Ringing...") + } + + binding.name = name + binding.image = imageUrl + + binding.acceptCall.setOnClickListener(this) + binding.hangUp.setOnClickListener(this) + + sessionID = intent.getStringExtra(StringContract.IntentString.SESSION_ID) + + + } + + override fun onStart() { + super.onStart() + onetoOneViewModel.addCallListener(this@CallActivity, StringContract.ListenerName.CALL_EVENT_LISTENER, binding.mainCallView) + } + + override fun onDestroy() { + super.onDestroy() + onetoOneViewModel.removeCallListener(StringContract.ListenerName.CALL_EVENT_LISTENER) + cometChatAudioHelper?.stop(false) + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + + when (requestCode) { + + StringContract.RequestCode.VOICE_CALL -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED) { + + } else { + Toast.makeText(this, "Voice call will behave inappropriately ", Toast.LENGTH_SHORT).show() + } + StringContract.RequestCode.VIDEO_CALL -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { + } else { + Toast.makeText(this, "Video call will behave inappropriately ", Toast.LENGTH_SHORT).show() + } + } + } + + override fun onClick(p0: View?) { + + when (p0?.id) { + + R.id.acceptCall -> { + cometChatAudioHelper?.stop(false) + onetoOneViewModel.acceptCall(sessionID, binding.mainCallView, this@CallActivity) + } + + R.id.hangUp -> { + cometChatAudioHelper?.stop(true) + onetoOneViewModel.rejectCall(sessionID, CometChatConstants.CALL_STATUS_REJECTED, this@CallActivity) + } + + } + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/CreateGroupActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/CreateGroupActivity.kt new file mode 100755 index 0000000..3ab6c7a --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/CreateGroupActivity.kt @@ -0,0 +1,206 @@ +package com.inscripts.cometchatpulse.Activities + +import android.arch.lifecycle.ViewModelProviders +import android.databinding.DataBindingUtil +import android.graphics.PorterDuff +import android.graphics.Typeface +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.text.Editable +import android.text.TextWatcher +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.widget.AdapterView +import android.widget.ArrayAdapter +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.models.Group +import com.inscripts.cometchatpulse.Extensions.setTitleTypeface +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.GroupChatViewModel +import com.inscripts.cometchatpulse.ViewModel.GroupViewModel +import com.inscripts.cometchatpulse.databinding.ActivityCreateGroupBinding + + +class CreateGroupActivity : AppCompatActivity(), AdapterView.OnItemSelectedListener { + + + private lateinit var binding: ActivityCreateGroupBinding + + private var groupType: String? = null + + private var guid: String? = null + + private var groupDescription:String?=null + + private var groupName: String? = null + + private var groupPassword: String? = null + + private lateinit var groupViewModel:GroupViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = DataBindingUtil.setContentView(this, R.layout.activity_create_group) + + setSupportActionBar(binding.createGroupToolbar) + supportActionBar!!.setDisplayHomeAsUpEnabled(true) + + supportActionBar?.title="Create Group" + + CommonUtil.setStatusBarColor(this) + + binding.createGroupToolbar.setTitleTypeface(StringContract.Font.title) + + + CommonUtil.setStatusBarColor(this) + + if (StringContract.AppDetails.theme==Appearance.AppTheme.AZURE_RADIANCE){ + binding.createGroupToolbar.setTitleTextColor(StringContract.Color.black) + } + else { + binding.createGroupToolbar.setTitleTextColor(StringContract.Color.white) + } + + binding.createGroupToolbar.setBackgroundColor(StringContract.Color.primaryColor) + + binding.createGroupToolbar.navigationIcon?.setColorFilter(StringContract.Color.iconTint,PorterDuff.Mode.SRC_ATOP) + + binding.spinner.onItemSelectedListener = this + + + groupViewModel=ViewModelProviders.of(this).get(GroupViewModel::class.java) + + val adapter = ArrayAdapter.createFromResource(this, + R.array.group_type, android.R.layout.simple_spinner_item) + + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) + binding.spinner.setAdapter(adapter) + binding.editTextGuid.addTextChangedListener(guidWatcher) + binding.editTextPassword.addTextChangedListener(passwordWatcher) + + //typeface + binding.tvName.typeface=StringContract.Font.status + binding.tvGuid.typeface=StringContract.Font.status + binding.tvDescription.typeface=StringContract.Font.status + binding.tvType.typeface=StringContract.Font.status + + binding.editTextDescription.typeface=StringContract.Font.name + binding.editTextPassword.typeface=StringContract.Font.name + binding.editTextName.typeface=StringContract.Font.name + binding.editTextGuid.typeface=StringContract.Font.name + + + } + + val guidWatcher:TextWatcher=object :TextWatcher{ + override fun afterTextChanged(p0: Editable?) { + + } + + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + + } + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + binding.editTextGuid.setError(null) + } + + } + + val passwordWatcher:TextWatcher=object :TextWatcher{ + override fun afterTextChanged(p0: Editable?) { + + } + + override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + + } + + override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) { + binding.editTextPassword.setError(null) + } + + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + + menuInflater.inflate(R.menu.create_menu, menu) + + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + + if (item?.itemId == R.id.menu_create_group) { + guid = binding.editTextGuid.text?.toString()?.trim() + groupPassword = binding.editTextPassword.text?.toString()?.trim() + groupDescription=binding.editTextDescription.text?.toString()?.trim() + groupName = binding.editTextName.text?.toString()?.trim() + + if (guid.isNullOrEmpty()) { + binding.editTextGuid.setError("GUID can't be empty") + + } + else if (groupType?.equals(CometChatConstants.GROUP_TYPE_PASSWORD, ignoreCase = true)!! + && groupPassword.isNullOrEmpty()) { + binding.editTextPassword.setError("Password is mandatory") + + } + else if (groupType?.equals("Select Group Type",ignoreCase = true)!!) + { + Toast.makeText(this,"Please select group type",Toast.LENGTH_SHORT).show() + } + + else if (guid != null && groupType != null && groupName != null) { + + if (groupType.equals(CometChatConstants.GROUP_TYPE_PASSWORD, ignoreCase = true)) { + + if (groupPassword != null) { + val group = Group(guid, groupName, groupType.toString().toLowerCase(), + groupPassword, null, groupDescription) + + groupViewModel.createGroup(this,group) + + } /*else { + chatroomPasswordField.setText(""); + chatroomPasswordField.setError(chatroomLang.get26()); + }*/ + } else { + val group = Group(guid, groupName, groupType.toString().toLowerCase(), null, + null, groupDescription) + groupViewModel.createGroup(this,group) + + + } + + + } + + } + return super.onOptionsItemSelected(item) + } + + fun showToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } + + override fun onNothingSelected(p0: AdapterView<*>?) { + } + + override fun onItemSelected(p0: AdapterView<*>?, p1: View?, p2: Int, p3: Long) { + + groupType = p0?.getSelectedItem() as String + + if (groupType.equals(CometChatConstants.GROUP_TYPE_PASSWORD, ignoreCase = true)) { + binding.llPasswordContainer.setVisibility(View.VISIBLE) + } else { + binding.llPasswordContainer.setVisibility(View.GONE) + } + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/GroupDetailActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/GroupDetailActivity.kt new file mode 100755 index 0000000..c400eea --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/GroupDetailActivity.kt @@ -0,0 +1,185 @@ +package com.inscripts.cometchatpulse.Activities + +import android.arch.lifecycle.ViewModelProviders +import android.databinding.DataBindingUtil +import android.graphics.PorterDuff +import android.support.v7.app.AppCompatActivity +import android.os.Bundle +import android.support.v4.content.ContextCompat +import android.support.v7.widget.LinearLayoutManager +import android.view.Menu +import android.view.MenuItem +import com.cometchat.pro.core.CometChat +import com.inscripts.cometchatpulse.Adapter.GroupOptionAdapter +import com.inscripts.cometchatpulse.Extensions.setTitleTypeface +import com.inscripts.cometchatpulse.Fragment.BanMemberFragment +import com.inscripts.cometchatpulse.Fragment.MemberFragment +import com.inscripts.cometchatpulse.Helpers.OnOptionClickListener +import com.inscripts.cometchatpulse.Pojo.GroupOption +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.GroupViewModel +import com.inscripts.cometchatpulse.databinding.ActivityGroupDetailBinding + +class GroupDetailActivity : AppCompatActivity() { + + private lateinit var binding: ActivityGroupDetailBinding + + private lateinit var groupId: String + + private lateinit var ownerUid: String + + private lateinit var layoutManager: LinearLayoutManager + + private lateinit var groupOptionAdapter: GroupOptionAdapter + + private var groupOptionList: MutableList = mutableListOf() + + private lateinit var groupViewModel: GroupViewModel + + private var groupOwner:String?=null + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + + binding = DataBindingUtil.setContentView(this, R.layout.activity_group_detail) + + CommonUtil.setStatusBarColor(this) + + groupOwner = intent?.getStringExtra(StringContract.IntentString.GROUP_OWNER) + + binding.groupName = intent?.getStringExtra(StringContract.IntentString.GROUP_NAME) + + binding.groupIcon = intent?.getStringExtra(StringContract.IntentString.GROUP_ICON) + + binding.description = intent?.getStringExtra(StringContract.IntentString.GROUP_DESCRIPTION) + + ownerUid = CometChat.getLoggedInUser().uid + + groupId = intent?.getStringExtra(StringContract.IntentString.GROUP_ID).toString() + + binding.tvDescription.typeface=StringContract.Font.name + binding.tvName.typeface=StringContract.Font.name + + + + groupViewModel = ViewModelProviders.of(this).get(GroupViewModel::class.java) + + layoutManager = LinearLayoutManager(this) + binding.rvGroupOptions.layoutManager = layoutManager + groupOptionAdapter = GroupOptionAdapter(this, GroupOptionItemList(), ownerUid, groupId,object :OnOptionClickListener(){ + + override fun OnOptionClick( position:Int){ + + when (position) { + + 0 -> { + val memberListFragment = MemberFragment().apply { + arguments = Bundle().apply { + putString(StringContract.IntentString.GROUP_ID, groupId) + putString(StringContract.IntentString.USER_ID, ownerUid) + } + } + supportFragmentManager.beginTransaction() + .replace(R.id.group_frame, memberListFragment).addToBackStack(null).commit() + } + + 1 -> { + val banMemberListFragment = BanMemberFragment().apply { + arguments = Bundle().apply { + putString(StringContract.IntentString.GROUP_ID, groupId) + putString(StringContract.IntentString.USER_ID, ownerUid) + } + } + supportFragmentManager.beginTransaction() + .replace(R.id.group_frame, banMemberListFragment).addToBackStack(null).commit() + } + 2 -> { + showDialog("Are you sure want to leave ? "+intent?.getStringExtra(StringContract.IntentString.GROUP_NAME), + "Leave Group",position) + } + + 3 -> { + showDialog("Are you sure want to delete ? "+intent?.getStringExtra(StringContract.IntentString.GROUP_NAME), + "Delete Group",position) + } + + } + } + + }) + binding.rvGroupOptions.adapter = groupOptionAdapter + + + setSupportActionBar(binding.toolbar) + supportActionBar!!.title="Group Details" + supportActionBar!!.elevation = 10f + supportActionBar!!.setDisplayHomeAsUpEnabled(true) + + + binding.toolbar.setTitleTypeface(StringContract.Font.title) + binding.toolbar.navigationIcon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + binding.tv30.setBackgroundColor(StringContract.Color.primaryDarkColor) + binding.toolbar.setTitleTextColor(StringContract.Color.black) + + } else { + binding.tv30.setBackgroundColor(StringContract.Color.primaryColor) + binding.toolbar.setTitleTextColor(StringContract.Color.white) + } + + } + + + private fun GroupOptionItemList(): MutableList { + + groupOptionList.add(GroupOption("View Members", ContextCompat.getDrawable(this, R.drawable.ic_person_black_24dp))) + groupOptionList.add(GroupOption("Unban Members", ContextCompat.getDrawable(this, R.drawable.ic_supervisor_account_black_24dp))) + groupOptionList.add(GroupOption("Leave Group", ContextCompat.getDrawable(this, R.drawable.ic_exit_to_app_black_24dp))) + if (ownerUid.equals(groupOwner)) { + groupOptionList.add(GroupOption("Delete Group", ContextCompat.getDrawable(this, R.drawable.ic_delete_black_24dp))) + } + return groupOptionList + } + + + fun showDialog(message: String, title: String, position: Int) { + val builder = android.support.v7.app.AlertDialog.Builder(this) + builder.setTitle(CommonUtil.setTitle(title, this)) + + .setMessage(message) + .setCancelable(true) + .setNegativeButton(CommonUtil.setTitle("Cancel", this)) { + dialogInterface, i -> dialogInterface.dismiss() } + .setPositiveButton(CommonUtil.setTitle("Yes", this)) { + dialogInterface, i -> when(position){ + + 2->{ + groupViewModel.leaveGroup(groupId, this@GroupDetailActivity) + } + + 3->{ + groupViewModel.deleteGroup(groupId,this@GroupDetailActivity) + } + } + }.show() + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + + if (item.itemId == android.R.id.home) { + onBackPressed() + } + return super.onOptionsItemSelected(item) + } + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/ImageViewActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/ImageViewActivity.kt new file mode 100755 index 0000000..fc1c360 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/ImageViewActivity.kt @@ -0,0 +1,29 @@ +package com.inscripts.cometchatpulse.Activities + +import android.databinding.DataBindingUtil +import android.support.v7.app.AppCompatActivity +import android.os.Bundle + +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.databinding.ActivityImageViewBinding + +class ImageViewActivity : AppCompatActivity() { + + private lateinit var binding:ActivityImageViewBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + CommonUtil.setStatusBarColor(this) + binding=DataBindingUtil.setContentView(this,R.layout.activity_image_view) + + binding.context=this + + binding.type=intent?.getStringExtra(StringContract.IntentString.FILE_TYPE) + + binding.url=intent?.getStringExtra(StringContract.IntentString.URL) + + CommonUtil.setStatusBarColor(this) + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/LocationActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/LocationActivity.kt new file mode 100755 index 0000000..499a603 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/LocationActivity.kt @@ -0,0 +1,292 @@ +package com.inscripts.cometchatpulse.Activities + +import android.content.pm.PackageManager +import android.location.Location +import android.location.LocationListener +import android.location.LocationManager +import android.os.Bundle +import android.support.v4.app.ActivityCompat +import android.support.v4.content.ContextCompat +import android.support.v7.app.AppCompatActivity +import android.util.Log +import android.view.View +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.models.TextMessage +import com.google.android.gms.common.api.Status +import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationRequest +import com.google.android.gms.location.LocationServices +import com.google.android.gms.location.places.GeoDataClient +import com.google.android.gms.location.places.Place +import com.google.android.gms.location.places.PlaceDetectionClient +import com.google.android.gms.location.places.ui.PlaceAutocompleteFragment +import com.google.android.gms.location.places.ui.PlaceSelectionListener +import com.google.android.gms.maps.CameraUpdateFactory +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.OnMapReadyCallback +import com.google.android.gms.maps.SupportMapFragment +import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.Marker +import com.google.android.gms.maps.model.MarkerOptions +import com.google.android.gms.maps.model.PolygonOptions +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.Repository.MessageRepository +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.CommonUtil +import kotlinx.android.synthetic.main.activity_location.* +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import org.json.JSONObject + + +class LocationActivity : AppCompatActivity(), OnMapReadyCallback, PlaceSelectionListener, View.OnClickListener { + + private var mMap: GoogleMap? = null + + private val DEFAULT_ZOOM: Float = 20f + + private var mDefaultLocation: LatLng = LatLng(-33.8523341, 151.2106085) + + private var markerLatLng: LatLng? = null + + private var mLastKnownLocation: Location? = null + + private lateinit var mFusedLocationProviderClient: FusedLocationProviderClient + + private lateinit var autocompleteFragment: PlaceAutocompleteFragment + + private lateinit var receiverId: String + + private var receiverType: String? = null + + private var marker: Marker? = null + + private lateinit var mLocationRequest:LocationRequest + + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_location) + CommonUtil.setStatusBarColor(this) + // Obtain the SupportMapFragment and get notified when the map is ready to be used. + val mapFragment = supportFragmentManager.findFragmentById(com.inscripts.cometchatpulse.R.id.map) as SupportMapFragment + mapFragment.getMapAsync(this) + + // Construct a FusedLocationProviderClient. + mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this@LocationActivity) + + + receiverId = intent.getStringExtra(StringContract.IntentString.ID) + receiverType = intent?.getStringExtra(StringContract.IntentString.RECIVER_TYPE) + + autocompleteFragment = fragmentManager.findFragmentById(R.id.place_autocomplete_fragment) as PlaceAutocompleteFragment + + autocompleteFragment.setOnPlaceSelectedListener(this) + + ivLocation.setOnClickListener(this) + + } + + + override fun onPlaceSelected(p0: Place?) { + mMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(p0?.latLng, DEFAULT_ZOOM)) + + try { + marker = mMap?.addMarker(p0?.latLng?.let { MarkerOptions().position(it).title(p0.name.toString()) })!! + markerLatLng = p0?.latLng + } catch (e: Exception) { + e.printStackTrace() + } + + + } + + override fun onError(p0: Status?) { + + } + + override fun onClick(p0: View?) { + + when (p0?.id) { + + R.id.ivLocation -> { + + try { + + val messageRepository: MessageRepository = MessageRepository() + + val jObject = JSONObject() + + jObject.put("lat", markerLatLng?.latitude) + jObject.put("logt", markerLatLng?.longitude) + + val textMessage = TextMessage(receiverId, "custom_location",CometChatConstants.MESSAGE_TYPE_TEXT, receiverType) + + textMessage.metadata = jObject + + messageRepository.sendTextMessage(textMessage, this@LocationActivity) + + + } catch (e: Exception) { + e.printStackTrace() + } + + } + + } + } + + + override fun onDestroy() { + super.onDestroy() + } + + + override fun onStop() { + super.onStop() + } + + /** + * Manipulates the map once available. + * This callback is triggered when the map is ready to be used. + * This is where we can add markers or lines, add listeners or move the camera. In this case, + * we just add a marker near Sydney, Australia. + * If Google Play services is not installed on the device, the user will be prompted to install + * it inside the SupportMapFragment. This method will only be triggered once the user has + * installed Google Play services and returned to the app. + */ + override fun onMapReady(googleMap: GoogleMap) { + mMap = googleMap + + // Add a marker in Sydney and move the camera + +// val sydney = LatLng(19.046865, 72.906995) +// mMap.addMarker(MarkerOptions().position(sydney).title("Marker in Inscripts")) +// mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney)) + getLocationPermission() + updateLocationUI() + getDeviceLocation() + + + + mMap?.setOnMapClickListener(object : GoogleMap.OnMapClickListener { + + override fun onMapClick(p0: LatLng?) { + + try { + marker?.remove() + markerLatLng = p0 + marker = mMap?.addMarker(p0?.let { MarkerOptions().position(it) }) + mMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(p0, DEFAULT_ZOOM)) + + } catch (e: Exception) { + e.printStackTrace() + } + + } + + }) + + mMap?.setOnMyLocationButtonClickListener(object :GoogleMap.OnMyLocationButtonClickListener{ + override fun onMyLocationButtonClick(): Boolean { + + return false + } + + }) + + } + + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + + when (requestCode) { + + StringContract.RequestCode.LOCATION -> { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + + } else { + + Toast.makeText(this, "Location permission denied, can't fetch location", Toast.LENGTH_SHORT).show() + } + + + } + } + + updateLocationUI() + } + + + private fun getDeviceLocation() { + + try { + if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + val locationResult = mFusedLocationProviderClient.lastLocation + locationResult.addOnCompleteListener(this) { p0 -> + if (p0.isSuccessful) { + try { + mLastKnownLocation = p0.result + mMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(mLastKnownLocation?.latitude!!, mLastKnownLocation?.longitude!!), DEFAULT_ZOOM)) + marker = mMap?.addMarker(MarkerOptions().position(LatLng(mLastKnownLocation?.latitude!!, mLastKnownLocation?.longitude!!)))!! + markerLatLng= mLastKnownLocation?.latitude?.let { LatLng(it, mLastKnownLocation?.longitude!!) } + } catch (e: Exception) { + + } + } else { + Log.d("MAP", "Current location is null. Using defaults.") + Log.e("MAp", "Exception: %s", p0.exception) + mMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM)) + } + } + + } else { + ActivityCompat.requestPermissions(this, + arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), StringContract.RequestCode.LOCATION) + + } + } catch (e: Exception) { + + } + + } + + private fun getLocationPermission() { + if (ContextCompat.checkSelfPermission(this.applicationContext, + android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + getDeviceLocation() + + } else { + ActivityCompat.requestPermissions(this, + arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION), StringContract.RequestCode.LOCATION) + } + } + + private fun updateLocationUI() { + + if (mMap == null) { + return + } + + try { + + if (ContextCompat.checkSelfPermission(this.applicationContext, + android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + mMap?.isMyLocationEnabled = true + mMap?.uiSettings?.isMyLocationButtonEnabled = true + + } else { + getLocationPermission() + mMap?.isMyLocationEnabled=false + + } + + + } catch (e: SecurityException) { + Log.e("Exception: %s", e.message) + } + + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/LoginActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/LoginActivity.kt new file mode 100755 index 0000000..23db88d --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/LoginActivity.kt @@ -0,0 +1,127 @@ +package com.inscripts.cometchatpulse.Activities + +import android.content.Context +import android.content.Intent +import android.content.res.ColorStateList +import android.databinding.DataBindingUtil +import android.graphics.PorterDuff +import android.graphics.PorterDuffColorFilter +import android.graphics.drawable.Drawable +import android.graphics.drawable.GradientDrawable +import android.graphics.drawable.ShapeDrawable +import android.graphics.drawable.StateListDrawable +import android.os.Bundle +import android.support.v4.content.ContextCompat +import android.support.v7.app.AppCompatActivity +import android.text.Html +import android.text.SpannableString +import android.text.TextUtils +import android.util.Log +import android.view.View +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.CometChat +import com.cometchat.pro.exceptions.CometChatException +import com.cometchat.pro.models.User +import com.google.firebase.messaging.FirebaseMessaging +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.databinding.ActivityLoginBinding + + +public class LoginActivity : AppCompatActivity() { + + private lateinit var binding: ActivityLoginBinding + private lateinit var context: Context + private val TAG="LoginActivity" + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + context = this + CommonUtil.setStatusBarColor(this) + if (CometChat.getLoggedInUser() != null) { + startActivity() + } + + else { + binding = DataBindingUtil.setContentView(this, R.layout.activity_login) + binding.login = this + + if (StringContract.AppDetails.theme==Appearance.AppTheme.PERSIAN_BLUE|| + StringContract.AppDetails.theme==Appearance.AppTheme.MOUNTAIN_MEADOW) { + binding.btLogin.setTextColor(StringContract.Color.white) + binding.rlBack.setBackgroundColor(StringContract.Color.primaryColor) + binding.progressHorizontal.progressTintList= ColorStateList.valueOf(StringContract.Color.primaryColor) + } + else{ + binding.progressHorizontal.progressTintList= ColorStateList.valueOf(StringContract.Color.iconTint) + binding.btLogin.setTextColor(StringContract.Color.black) + binding.rlBack.setBackgroundColor(StringContract.Color.primaryDarkColor) + } + + binding.editTextUid.typeface=StringContract.Font.name + binding.btLogin.typeface=StringContract.Font.status + val drawableUid=(binding.btLogin.background) + + drawableUid.setColorFilter(StringContract.Color.primaryColor,PorterDuff.Mode.SRC_ATOP) + for (drawable:Drawable? in binding.editTextUid.compoundDrawables) { + if (drawable != null) { + drawable.setColorFilter(PorterDuffColorFilter(ContextCompat.getColor(binding.editTextUid.getContext(), StringContract.Color.primaryColor), PorterDuff.Mode.SRC_ATOP)) + } + } + + } + + CommonUtil.setStatusBarColor(this) + + } + + fun onLoginClick(uid:String){ + + Log.d("Login", uid) + binding.progressHorizontal.visibility=View.VISIBLE + kotlin.run { + Toast.makeText(this@LoginActivity,"Please Wait",Toast.LENGTH_SHORT).show() + CometChat.login(uid.trim(), StringContract.AppDetails.API_KEY, object : CometChat.CallbackListener() { + override fun onSuccess(p0: User?) { + startActivity() + + FirebaseMessaging.getInstance().subscribeToTopic("user_${p0?.uid}") + } + + override fun onError(p0: CometChatException?) { + Toast.makeText(context, p0?.message, Toast.LENGTH_SHORT).show() + binding.progressHorizontal.visibility=View.GONE + Log.d(TAG,"onError:Login "+p0?.message) + + + } + + }) + +// CometChat.login("superhero11_3b34bb32bfc7f3a930c829b75d6ffeb579efbd0e",object :CometChat.CallbackListener(){ +// override fun onSuccess(p0: User?) { +// Log.d(TAG,"onSuccess: "+p0.toString()) +// binding.progressHorizontal.visibility=View.GONE +// startActivity() +// } +// +// override fun onError(p0: CometChatException?) { +// Log.d(TAG,"onError: "+p0?.message) +// binding.progressHorizontal.visibility=View.GONE +// } +// +// }) + } + + + } + + fun startActivity() { + startActivity(Intent(this, MainActivity::class.java)) + finish() + } +} + + diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/MainActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/MainActivity.kt new file mode 100755 index 0000000..4cc378c --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/MainActivity.kt @@ -0,0 +1,436 @@ +package com.inscripts.cometchatpulse.Activities + +import android.app.AlertDialog +import android.app.ProgressDialog +import android.arch.lifecycle.ViewModelProviders +import android.content.Context +import android.content.DialogInterface +import android.content.Intent +import android.content.res.ColorStateList +import android.graphics.PorterDuff +import android.graphics.Typeface +import android.os.Bundle +import android.support.design.widget.BottomNavigationView +import android.support.v4.app.Fragment +import android.support.v4.content.ContextCompat +import android.support.v7.app.AppCompatActivity +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.EditText +import android.widget.TextView +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.CometChat +import com.cometchat.pro.exceptions.CometChatException +import com.cometchat.pro.helpers.Logger +import com.cometchat.pro.models.Group +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Fragment.ContactListFragment +import com.inscripts.cometchatpulse.Fragment.GroupFragment +import com.inscripts.cometchatpulse.Fragment.GroupListFragment +import com.inscripts.cometchatpulse.Fragment.OneToOneFragment +import com.inscripts.cometchatpulse.Helpers.ChildClickListener +import com.inscripts.cometchatpulse.Helpers.CustomAlertDialogHelper +import com.inscripts.cometchatpulse.Helpers.OnAlertDialogButtonClickListener +import com.inscripts.cometchatpulse.Helpers.OnBackArrowClickListener +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.Repository.GroupRepository +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.GroupChatViewModel +import com.inscripts.cometchatpulse.ViewModel.GroupViewModel +import com.inscripts.cometchatpulse.ViewModel.OnetoOneViewModel +import kotlinx.android.synthetic.main.activity_main.* + + +class MainActivity : AppCompatActivity(), BottomNavigationView.OnNavigationItemSelectedListener, + ChildClickListener, OnBackArrowClickListener, OnAlertDialogButtonClickListener, GroupRepository.onGroupJoin { + + private var twoPane: Boolean = false + + private var position: Int = 0 + + private lateinit var progressDialog: ProgressDialog + + private lateinit var groupViewModel: GroupViewModel + + private lateinit var group: Group + + var resId: Int = 0 + + private lateinit var groupChatViewModel: GroupChatViewModel + + private lateinit var oneToOneChatViewModel: OnetoOneViewModel + + private val TAG="MainActivity" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + navigation.setOnNavigationItemSelectedListener(this) + + frame_container_detail + loadFragment(ContactListFragment()) + + groupViewModel = ViewModelProviders.of(this).get(GroupViewModel::class.java) + groupChatViewModel = ViewModelProviders.of(this).get(GroupChatViewModel::class.java) + oneToOneChatViewModel = ViewModelProviders.of(this).get(OnetoOneViewModel::class.java) + + + setSupportActionBar(toolbar) + supportActionBar?.title = "" + toolbar.title = "" + + toolbar.setBackgroundColor(StringContract.Color.primaryColor) + navigation.itemTextColor = getColorStateList() + + navigation.itemIconTintList = getColorStateList() + + overrideFont(this,navigation) + + + if (main_frame != null) { + main_frame.setBackgroundColor(StringContract.Color.primaryColor) + } + toolbar.overflowIcon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + toolbar_title?.setTypeface(StringContract.Font.title) + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + toolbar_title.setTextColor(StringContract.Color.black) + } else { + toolbar_title.setTextColor(StringContract.Color.white) + } + toolbar_title?.setText("Contact") + + if (frame_container_detail != null) { + + twoPane = true + } + CommonUtil.setStatusBarColor(this) + + for (i in 0..navigation.menu.size()) { + + } + + + } + + private fun overrideFont(context: Context, v: View) { + val typeface = StringContract.Font.status + try { + if (v is ViewGroup) { + for (i in 0..v.childCount) { + overrideFont(context, v.getChildAt(i)) + } + + } else if (v is TextView) { + v.typeface = typeface + } + } catch (e: Exception) { + + } + } + + override fun onCreateOptionsMenu(menu: Menu?): Boolean { + + menuInflater.inflate(R.menu.main_menu, menu) + + val menuDrawable = ContextCompat.getDrawable(this, R.drawable.ic_more) + menuDrawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + menu?.getItem(0)?.setIcon(menuDrawable) + + val menuItem = menu?.findItem(R.id.create_group)?.icon + + menuItem?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + + when (item?.itemId) { + + R.id.create_group -> { + startActivity(Intent(this, CreateGroupActivity::class.java)) + } + + R.id.logout_menu -> { + + CometChat.logout(object : CometChat.CallbackListener() { + override fun onSuccess(p0: String?) { + startActivity(Intent(this@MainActivity, LoginActivity::class.java)) + finish() + } + + override fun onError(p0: CometChatException?) { + } + + }) + + } + + R.id.view_menu -> { + val user = CometChat.getLoggedInUser() + val profilViewIntent = Intent(this, UserProfileViewActivity::class.java) + profilViewIntent.putExtra(StringContract.IntentString.USER_NAME, user.name) + profilViewIntent.putExtra(StringContract.IntentString.USER_ID, user.uid) + profilViewIntent.putExtra(StringContract.IntentString.USER_STATUS, user.status) + profilViewIntent.putExtra(StringContract.IntentString.USER_AVATAR, user.avatar) + startActivity(profilViewIntent) + } + } + return super.onOptionsItemSelected(item) + } + + private fun getColorStateList(): ColorStateList { + + val states = arrayOf( + intArrayOf(-android.R.attr.state_selected), intArrayOf(android.R.attr.state_selected) + ) + var colors = intArrayOf() + + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + colors = intArrayOf(StringContract.Color.inactiveColor, StringContract.Color.iconTint) + } else { + colors = intArrayOf(StringContract.Color.inactiveColor, StringContract.Color.primaryColor) + } + + + return ColorStateList(states, colors) + } + + + override fun onBackPressed() { + super.onBackPressed() + hideKeyboard() + + } + + fun hideKeyboard() { + val inputManager =getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + + // check if no view has focus: + val currentFocusedView = currentFocus + if (currentFocusedView != null) { + inputManager.hideSoftInputFromWindow(currentFocusedView.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); + } + } + + + override fun OnChildClick(t: Any) { + + + if (twoPane) { + resId = R.id.frame_container_detail + } else { + resId = R.id.main_frame + } + if (t is User) { + val oneToOneFragment = OneToOneFragment().apply { + arguments = Bundle().apply { + putString(StringContract.IntentString.USER_ID, t.uid) + putString(StringContract.IntentString.USER_NAME, t.name) + putString(StringContract.IntentString.USER_AVATAR, t.avatar) + putString(StringContract.IntentString.USER_STATUS, t.status) + putLong(StringContract.IntentString.LAST_ACTIVE, t.lastActiveAt) + + } + } + supportFragmentManager.beginTransaction() + .replace(resId, oneToOneFragment).addToBackStack(null).commit() + } else if (t is Group) { + group = t + initJoinGroup(group, resId) + } + + } + + fun startGroupChatFragment(t: Group, resId: Int) { + val groupChat = GroupFragment().apply { + arguments = Bundle().apply { + putString(StringContract.IntentString.GROUP_ID, t.guid) + putString(StringContract.IntentString.GROUP_NAME, t.name) + putString(StringContract.IntentString.GROUP_ICON, t.icon) + putString(StringContract.IntentString.GROUP_OWNER, t.owner) + putString(StringContract.IntentString.GROUP_DESCRIPTION, t.description) + } + } + supportFragmentManager.beginTransaction() + .replace(resId, groupChat).addToBackStack(null).commit() + + } + + private lateinit var groupPassword: String + + override fun onButtonClick(alertDialog: AlertDialog?, v: View?, which: Int, popupId: Int) { + + val groupPasswordInput = v?.findViewById(R.id.edittextDialogueInput) as EditText + if (which == DialogInterface.BUTTON_NEGATIVE) { // Cancel + + alertDialog?.dismiss() + } else if (which == DialogInterface.BUTTON_POSITIVE) { // Join + try { + progressDialog = ProgressDialog.show(this, "", getString(R.string.joining)) + progressDialog.setProgressStyle(StringContract.Color.primaryColor) + progressDialog.setCancelable(false) + groupPassword = groupPasswordInput.text.toString() + if (groupPassword.length == 0) { + groupPasswordInput.setText("") + groupPasswordInput.error = getString(R.string.incorrect_password) + + } else { + try { + alertDialog?.dismiss() + group.setPassword(groupPassword) + + groupViewModel.joinGroup(group, progressDialog, resId, this@MainActivity) + + } catch (e: Exception) { + Logger.error("Error at SHA1:UnsupportedEncodingException FOR PASSWORD " + e.localizedMessage) + e.printStackTrace() + } + + } + } catch (e: Exception) { + Logger.error("chatroomFragment.java onButtonClick() : Exception=" + e.localizedMessage) + e.printStackTrace() + } + + } + } + + + private fun initJoinGroup(group: Group, resId: Int) { + + if (CommonUtil.isConnected(this@MainActivity)) { + + if (group.groupType.equals(CometChatConstants.GROUP_TYPE_PUBLIC, ignoreCase = true) || + group.groupType.equals(CometChatConstants.GROUP_TYPE_PRIVATE, ignoreCase = true)) { + + if (group.isJoined) { + startGroupChatFragment(group, resId) + } else { + progressDialog = ProgressDialog.show(this, "", getString(R.string.joining)) + progressDialog.setCancelable(false) + groupViewModel.joinGroup(group, progressDialog, resId, this@MainActivity) + } + + } else { + if (group.isJoined) { + startGroupChatFragment(group, resId) + } else { + val dialogview = this.getLayoutInflater().inflate(R.layout.cc_custom_dialog, null) + val tvTitle = dialogview.findViewById(R.id.textViewDialogueTitle) as TextView + tvTitle.text = "" + CustomAlertDialogHelper(this, getString(R.string.group_password), dialogview, getString(R.string.enter), + "", getString(R.string.cancel), this, 1, false) + } + } + } else { + if (progressDialog.isShowing()) { + progressDialog.dismiss() + } + Toast.makeText(this, getString(R.string.warning), Toast.LENGTH_SHORT).show() + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + } + + override fun onBackClick() { + + if (twoPane) { + + if (list_container.visibility == View.VISIBLE) { + list_container.visibility = View.GONE + } else if (list_container.visibility == View.GONE) { + list_container.visibility = View.VISIBLE + } + } + } + + + override fun onSaveInstanceState(outState: Bundle?) { + super.onSaveInstanceState(outState) + + outState?.putInt(StringContract.IntentString.POSITION, position) + } + + override fun onRestoreInstanceState(savedInstanceState: Bundle?) { + super.onRestoreInstanceState(savedInstanceState) + + try { + supportActionBar?.title = "" + navigation.selectedItemId = savedInstanceState?.getInt(StringContract.IntentString.POSITION)!! + } catch (e: Exception) { + e.printStackTrace() + } + + } + + fun loadFragment(fragment: Fragment?): Boolean { + + if (fragment != null) { + supportFragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit() + return true + } else { + return false + } + + } + + + + override fun onResume() { + super.onResume() + Log.d(TAG,"onResume: ") + groupChatViewModel.addGroupEventListener(StringContract.ListenerName.GROUP_EVENT_LISTENER) + oneToOneChatViewModel.addCallListener(this, TAG, null) + } + + override fun onPause() { + super.onPause() + Log.d(TAG,"onPause: ") + groupChatViewModel.removeGroupEventListener(StringContract.ListenerName.GROUP_EVENT_LISTENER) + oneToOneChatViewModel.removeCallListener(TAG) + } + + override fun onJoined(group: Group, resId: Int) { + startGroupChatFragment(group, resId) + } + + + override fun onNavigationItemSelected(p0: MenuItem): Boolean { + + var fragment: Fragment? = null + + when (p0.itemId) { + + R.id.menu_contacts -> { + fragment = ContactListFragment() + toolbar_title?.setText("Contacts") + position = R.id.menu_contacts + + } + + R.id.menu_group -> { + + fragment = GroupListFragment() + toolbar_title?.setText("Groups") + position = R.id.menu_group + + } + + } + return loadFragment(fragment) + } + + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Activities/UserProfileViewActivity.kt b/app/src/main/java/com/inscripts/cometchatpulse/Activities/UserProfileViewActivity.kt new file mode 100755 index 0000000..d247b6f --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Activities/UserProfileViewActivity.kt @@ -0,0 +1,155 @@ +package com.inscripts.cometchatpulse.Activities + +import android.arch.lifecycle.ViewModelProviders +import android.content.pm.PackageManager +import android.databinding.DataBindingUtil +import android.graphics.PorterDuff +import android.os.Bundle +import android.support.v7.app.AppCompatActivity +import android.view.MenuItem +import android.view.View +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.CometChat +import com.inscripts.cometchatpulse.Helpers.CCPermissionHelper +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.OnetoOneViewModel +import com.inscripts.cometchatpulse.databinding.ActivityUserProfileViewBinding +import android.support.v4.content.ContextCompat +import android.graphics.PorterDuffColorFilter +import android.graphics.drawable.Drawable +import com.inscripts.cometchatpulse.Extensions.setTitleTypeface +import com.inscripts.cometchatpulse.Utils.Appearance + + +class UserProfileViewActivity : AppCompatActivity(), View.OnClickListener { + + private lateinit var binding: ActivityUserProfileViewBinding + + private var uid: String? = null + + private lateinit var oneToOneViewModel: OnetoOneViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + CommonUtil.setStatusBarColor(this) + binding = DataBindingUtil.setContentView(this, R.layout.activity_user_profile_view) + + binding.url = intent?.getStringExtra(StringContract.IntentString.USER_AVATAR) + + binding.status = intent?.getStringExtra(StringContract.IntentString.USER_STATUS) + + binding.name = intent?.getStringExtra(StringContract.IntentString.USER_NAME) + + uid = intent?.getStringExtra(StringContract.IntentString.USER_ID) + + oneToOneViewModel = ViewModelProviders.of(this).get(OnetoOneViewModel::class.java) + + setSupportActionBar(binding.toolbar) + + supportActionBar?.title=intent?.getStringExtra(StringContract.IntentString.USER_NAME) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + binding.toolbar.setTitleTypeface(StringContract.Font.title) + + binding.toolbar.navigationIcon?.setColorFilter(StringContract.Color.iconTint,PorterDuff.Mode.SRC_ATOP) + + binding.tv30.setTextColor(StringContract.Color.primaryColor) + + binding.toolbar.setTitle(intent?.getStringExtra(StringContract.IntentString.USER_NAME)) + + binding.toolbar.setBackgroundColor(StringContract.Color.primaryColor) + + binding.toolbar.setTitleTextColor(StringContract.Color.white) + + if (StringContract.AppDetails.theme== Appearance.AppTheme.AZURE_RADIANCE) { + binding.toolbar.setTitleTextColor(StringContract.Color.black) + binding.ivVideo.drawable.setColorFilter(StringContract.Color.iconTint,PorterDuff.Mode.SRC_ATOP) + binding.ivVoice.drawable.setColorFilter(StringContract.Color.iconTint,PorterDuff.Mode.SRC_ATOP) + + } + else{ + binding.ivVideo.drawable.setColorFilter(StringContract.Color.primaryColor,PorterDuff.Mode.SRC_ATOP) + binding.ivVoice.drawable.setColorFilter(StringContract.Color.primaryColor,PorterDuff.Mode.SRC_ATOP) + binding.toolbar.setTitleTextColor(StringContract.Color.white) + } + + binding.videoCall.setOnClickListener(this) + binding.voiceCall.setOnClickListener(this) + + + if (CometChat.getLoggedInUser().uid.equals(intent?.getStringExtra(StringContract.IntentString.USER_ID))) { + + binding.voiceCall.visibility = View.GONE + binding.videoCall.visibility = View.GONE + binding.cardViewCallContainer.visibility = View.GONE + binding.status="online" + + } + CommonUtil.setStatusBarColor(this) + + } + + override fun onClick(p0: View?) { + + when (p0?.id) { + + R.id.voice_call -> { + if (CCPermissionHelper.hasPermissions(this, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + + uid?.let { oneToOneViewModel.initCall(this, it, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_AUDIO) } + } else { + CCPermissionHelper.requestPermissions(this, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VOICE_CALL) + } + + } + + R.id.video_call -> { + if (CCPermissionHelper.hasPermissions(this, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + + uid?.let { oneToOneViewModel.initCall(this, it, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_VIDEO) } + } else { + CCPermissionHelper.requestPermissions(this, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VIDEO_CALL) + } + + + } + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + + when (requestCode) { + + StringContract.RequestCode.VOICE_CALL -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED) { + + uid?.let { oneToOneViewModel.initCall(this, it, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_AUDIO) } + + } else { + Toast.makeText(this, "Voice call will behave inappropriately ", Toast.LENGTH_SHORT).show() + } + StringContract.RequestCode.VIDEO_CALL -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + uid?.let { oneToOneViewModel.initCall(this, it, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_VIDEO) } + } else { + + Toast.makeText(this, "Video call will behave inappropriately ", Toast.LENGTH_SHORT).show() + } + } + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + + if (item?.itemId == android.R.id.home) { + onBackPressed() + } + return super.onOptionsItemSelected(item) + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Adapter/ContactListAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/ContactListAdapter.kt new file mode 100755 index 0000000..1cc7a2b --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/ContactListAdapter.kt @@ -0,0 +1,56 @@ +package com.inscripts.cometchatpulse.Adapter + +import android.content.Context +import android.databinding.DataBindingUtil +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.ViewGroup +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Helpers.ChildClickListener +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.ViewHolder.ContactViewHolder +import com.inscripts.cometchatpulse.databinding.ContactItemBinding +import com.inscripts.cometchatpulse.ViewModel.UserViewModel + + +class ContactListAdapter(val context: Context?) : RecyclerView.Adapter() { + + private var userList: MutableMap = mutableMapOf() + + override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ContactViewHolder { + + val layoutInflater:LayoutInflater = LayoutInflater.from(context) + + val binding:ContactItemBinding= DataBindingUtil.inflate(layoutInflater,R.layout.contact_item,p0,false) + + return ContactViewHolder(binding) + } + + override fun getItemCount(): Int { + return userList.size + } + + override fun onBindViewHolder(contactViewHolder: ContactViewHolder, p1: Int) { + + val user=userList.values.toMutableList().get(p1) + + contactViewHolder.binding.user=user + contactViewHolder.binding.childClick=context as ChildClickListener + contactViewHolder.binding.textviewUserName.typeface=StringContract.Font.name + contactViewHolder.binding.textviewUserStatus.typeface=StringContract.Font.status + contactViewHolder.binding.executePendingBindings() + contactViewHolder.binding.root.setTag(R.string.user,user) + contactViewHolder.binding.executePendingBindings() + + } + + internal fun setUser(users: MutableMap) { + this.userList = users + notifyDataSetChanged() + + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupChatAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupChatAdapter.kt new file mode 100755 index 0000000..92ebd98 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupChatAdapter.kt @@ -0,0 +1,1348 @@ +package com.inscripts.cometchatpulse.Adapter + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.databinding.DataBindingUtil +import android.graphics.Bitmap +import android.graphics.PorterDuff +import android.media.AudioManager +import android.media.MediaPlayer +import android.net.Uri +import android.os.AsyncTask +import android.os.Handler +import android.support.v4.util.LongSparseArray +import android.support.v7.widget.RecyclerView +import android.text.TextUtils +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.SeekBar +import android.widget.TextView +import com.bumptech.glide.Glide +import com.bumptech.glide.request.RequestOptions +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.Call +import com.cometchat.pro.models.* +import com.inscripts.cometchatpulse.Activities.ImageViewActivity +import com.inscripts.cometchatpulse.AsyncTask.DownloadFile +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.CustomView.StickyHeaderAdapter +import com.inscripts.cometchatpulse.Helpers.CCPermissionHelper +import com.inscripts.cometchatpulse.Helpers.OnClickEvent +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.DateUtil +import com.inscripts.cometchatpulse.Utils.FileUtil +import com.inscripts.cometchatpulse.ViewHolder.* +import com.inscripts.cometchatpulse.databinding.* +import java.io.File +import java.io.IOException +import java.util.* + +class GroupChatAdapter(val context: Context, val guid: String, val ownerId: String, val listener: OnClickEvent ) : + RecyclerView.Adapter(), StickyHeaderAdapter { + + + private var messagesList: MutableList = mutableListOf() + + lateinit var viewHolder: RecyclerView.ViewHolder + + private var currentPlayingSong: String? = null + private var timerRunnable: Runnable? = null + private val seekHandler = Handler() + private var onClickEvent: OnClickEvent + private var currentlyPlayingId = 0L + + private var downloadFile: DownloadFile? = null + + var player: MediaPlayer? = null + + init { + + if (player == null) { + player = MediaPlayer() + } + onClickEvent = listener + audioDurations = LongSparseArray() + videoThumbnails = LongSparseArray() + + } + + companion object { + private lateinit var audioDurations: LongSparseArray + private lateinit var videoThumbnails: LongSparseArray + } + + override fun onCreateViewHolder(p0: ViewGroup, p1: Int): RecyclerView.ViewHolder { + val layoutInflater: LayoutInflater = LayoutInflater.from(context) + + when (p1) { + + StringContract.ViewType.RIGHT_TEXT_MESSAGE -> { + val binding: RightTextBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_text, p0, false) + return RightTextMessageHolder(binding) + } + + StringContract.ViewType.LEFT_TEXT_MESSAGE -> { + val binding: LeftTextBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_text, p0, false) + return LeftTextMessageHolder(binding) + } + + StringContract.ViewType.RIGHT_IMAGE_MESSAGE -> { + val binding: CcImageVideoLayoutRightBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_right, p0, false) + return RightImageVideoMessageHolder(binding) + } + StringContract.ViewType.LEFT_IMAGE_MESSAGE -> { + val binding: CcImageVideoLayoutLeftBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_left, p0, false) + return LeftImageVideoMessageHolder(binding) + } + StringContract.ViewType.RIGHT_VIDEO_MESSAGE -> { + + val binding: CcImageVideoLayoutRightBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_right, p0, false) + return RightImageVideoMessageHolder(binding) + } + + StringContract.ViewType.LEFT_VIDEO_MESSAGE -> { + val binding: CcImageVideoLayoutLeftBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_left, p0, false) + return LeftImageVideoMessageHolder(binding) + } + + StringContract.ViewType.RIGHT_AUDIO_MESSAGE -> { + val binding: RightAudioBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_audio, p0, false) + return RightAudioMessageHolder(binding) + } + + StringContract.ViewType.LEFT_AUDIO_MESSAGE -> { + val binding: LeftAudioBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_audio, p0, false) + return LeftAudioMessageHolder(binding) + } + StringContract.ViewType.CALL_MESSAGE -> { + val binding: ListHeaderBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_header, p0, false) + return TextHeaderHolder(binding) + } + StringContract.ViewType.ACTION_MESSAGE -> { + val binding: ListHeaderBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_header, p0, false) + return TextHeaderHolder(binding) + } + StringContract.ViewType.RIGHT_FILE_MESSAGE -> { + val binding: RightFileBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_file, p0, false) + return RightFileViewHolder(binding) + } + + StringContract.ViewType.LEFT_FILE_MESSAGE -> { + val binding: LeftFileBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_file, p0, false) + return LeftFileViewHolder(binding) + } + + StringContract.ViewType.RIGHT_LOCATION_MESSAGE -> { + val binding: RightLocationBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_location, p0, false) + return RightLocationViewHolder(binding) + } + + StringContract.ViewType.LEFT_LOCATION_MESSAGE -> { + val binding: LeftLocationBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_location, p0, false) + return LeftLocationViewHolder(binding) + } + + StringContract.ViewType.RIGHT_TEXT_REPLY_MESSAGE -> { + + val binding: RightReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_reply, p0, false) + return RightReplyMessageHolder(binding) + } + + StringContract.ViewType.RIGHT_MEDIA_REPLY_MESSAGE -> { + + val binding: RightReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_reply, p0, false) + return RightReplyMessageHolder(binding) + } + + StringContract.ViewType.LEFT_TEXT_REPLY_MESSAGE -> { + + val binding: LeftReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_reply, p0, false) + return LeftReplyMessageHolder(binding) + } + + StringContract.ViewType.LEFT_MEDIA_REPLY_MESSAGE -> { + + val binding: LeftReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_reply, p0, false) + return LeftReplyMessageHolder(binding) + } + + + else -> { + Log.d(" onCreateViewHolder ", " Unknown View Type ") + val binding: RightTextBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_text, p0, false) + return RightTextMessageHolder(binding) + } + } + } + + + override fun getHeaderId(var1: Int): Long { + + return java.lang.Long.parseLong(DateUtil.getDateId(messagesList.get(var1).getSentAt() * 1000)) + } + + override fun onCreateHeaderViewHolder(var1: ViewGroup): TextHeaderHolder { + val layoutInflater: LayoutInflater = LayoutInflater.from(context) + val binding: ListHeaderBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_header, var1, false) + return TextHeaderHolder(binding) + } + + override fun onBindHeaderViewHolder(var1: TextHeaderHolder, var2: Int, var3: Long) { + val date = Date(messagesList.get(var2).getSentAt() * 1000) + + val formattedDate = DateUtil.getCustomizeDate(date.getTime()) + + var1.binding.txtMessageDate.setBackground(context.resources.getDrawable(R.drawable.cc_rounded_date_button)) + + var1.binding.txtMessageDate.setText(formattedDate) + } + + + fun setLongClick(view: View, baseMessage: BaseMessage) { + var message: Any? = null + if (baseMessage is TextMessage) + message = baseMessage + + if (baseMessage is MediaMessage) + message = baseMessage + + view.setOnLongClickListener { + message?.let { it1 -> onClickEvent.onClickRl(view, it1) } + true + } + } + + + override fun getItemCount(): Int { + return messagesList.size + } + + override fun onBindViewHolder(p0: RecyclerView.ViewHolder, p1: Int) { + val baseMessage = messagesList.get(p1) + val timeStampLong = messagesList.get(p1).sentAt + var message: String? = null + var mediaFile: String? = null + + var filePath: String? = null + if (baseMessage is MediaMessage) { + try { + if (baseMessage.metadata?.has("path")!!) + filePath = baseMessage.metadata.getString("path") + } catch (e: Exception) { + + } + + } + + if (baseMessage is Call) { + val user = baseMessage.callInitiator as User + + if (user.uid.equals(ownerId, ignoreCase = true)) { + message = "You initiated call " + } else { + message = user.name + " initiated call " + } + } + + if (baseMessage is MediaMessage) { + mediaFile = baseMessage.url + + } + + when (p0.itemViewType) { + + StringContract.ViewType.RIGHT_TEXT_MESSAGE -> { + val rightTextMessageHolder = p0 as RightTextMessageHolder + rightTextMessageHolder.binding.message = (baseMessage as TextMessage) + rightTextMessageHolder.binding.tvMessage.typeface = StringContract.Font.message + rightTextMessageHolder.binding.timestamp.typeface = StringContract.Font.status + rightTextMessageHolder.binding.tvMessage.background.setColorFilter(StringContract.Color.rightMessageColor, PorterDuff.Mode.SRC_ATOP) + setLongClick(rightTextMessageHolder.binding.root,baseMessage) + } + + StringContract.ViewType.LEFT_TEXT_MESSAGE -> { + val leftTextMessageHolder = p0 as LeftTextMessageHolder + leftTextMessageHolder.binding.message = (baseMessage as TextMessage) + leftTextMessageHolder.binding.tvMessage.typeface = StringContract.Font.message + leftTextMessageHolder.binding.senderName.typeface = StringContract.Font.status + leftTextMessageHolder.binding.timestamp.typeface = StringContract.Font.status + leftTextMessageHolder.binding.tvMessage.background.setColorFilter(StringContract.Color.leftMessageColor, PorterDuff.Mode.SRC_ATOP) + setLongClick(leftTextMessageHolder.binding.root,baseMessage) + + } + + StringContract.ViewType.LEFT_IMAGE_MESSAGE -> { + val leftImageVideoMessageHolder = p0 as LeftImageVideoMessageHolder + leftImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + leftImageVideoMessageHolder.binding.senderName.typeface = StringContract.Font.status + leftImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + + leftImageVideoMessageHolder.binding.imageMessage.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(leftImageVideoMessageHolder.binding.imageMessage,baseMessage) + + } + + StringContract.ViewType.RIGHT_IMAGE_MESSAGE -> { + val rightImageVideoMessageHolder = p0 as RightImageVideoMessageHolder + rightImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + rightImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + + rightImageVideoMessageHolder.binding.imageMessage.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(rightImageVideoMessageHolder.binding.imageMessage,baseMessage) + } + + StringContract.ViewType.RIGHT_FILE_MESSAGE -> { + try { + + val rightFileViewHolder = p0 as RightFileViewHolder + rightFileViewHolder.binding.message = baseMessage as MediaMessage + rightFileViewHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.rightMessageColor, + PorterDuff.Mode.SRC_ATOP) + val t = mediaFile?.substring(mediaFile.lastIndexOf("/"))?.split("_".toRegex())?.dropLastWhile({ it.isEmpty() })?.toTypedArray() + rightFileViewHolder.binding.fileName.setText(t?.get(2)) + rightFileViewHolder.binding.fileType.setText(mediaFile?.substring(mediaFile.lastIndexOf(".") + 1)) + rightFileViewHolder.binding.fileName.typeface = StringContract.Font.name + rightFileViewHolder.binding.fileType.typeface = StringContract.Font.name + rightFileViewHolder.binding.timeStamp.typeface = StringContract.Font.status + val finalMediaFile = mediaFile + setLongClick(rightFileViewHolder.binding.root,baseMessage) + rightFileViewHolder.binding.fileName.setOnClickListener(View.OnClickListener { context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(finalMediaFile))) }) + } catch (e: Exception) { + e.printStackTrace() + } + + } + + + StringContract.ViewType.RIGHT_LOCATION_MESSAGE -> { + val rightLocationViewHolder = p0 as RightLocationViewHolder + rightLocationViewHolder.binding.message = baseMessage as TextMessage + rightLocationViewHolder.binding.timestamp.typeface = StringContract.Font.status + rightLocationViewHolder.bindView(p1, messagesList) + + } + + StringContract.ViewType.LEFT_LOCATION_MESSAGE -> { + val leftLocationViewHolder = p0 as LeftLocationViewHolder + leftLocationViewHolder.binding.message = baseMessage as TextMessage + leftLocationViewHolder.binding.timestamp.typeface = StringContract.Font.status + leftLocationViewHolder.bindView(p1, messagesList) + } + + StringContract.ViewType.RIGHT_TEXT_REPLY_MESSAGE -> { + + val rightReplyMessageHolder = p0 as RightReplyMessageHolder + rightReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightReplyMessageHolder.binding.message = baseMessage + rightReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.rightMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is TextMessage) { + + rightReplyMessageHolder.binding.txtNewmsg.visibility = View.VISIBLE + rightReplyMessageHolder.binding.txtNewmsg.text = baseMessage.text + rightReplyMessageHolder.binding.txtNewmsg.typeface = StringContract.Font.message + rightReplyMessageHolder.binding.tvNameReply.typeface = StringContract.Font.name + rightReplyMessageHolder.binding.ivNewMessage.visibility = View.GONE + + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + rightReplyMessageHolder.binding.tvNameReply.text = "You" + + } else { + rightReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName"); + } + + when { + baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT) -> { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = + baseMessage.metadata?.getString("text") + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO) -> { + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.VISIBLE + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(rightReplyMessageHolder.binding.ivReplyImage) + + if (baseMessage.metadata.getString("type") == CometChatConstants.MESSAGE_TYPE_IMAGE) { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Photo" + } else { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Video" + } + + } + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO) -> { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE) -> { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + } + + } + + setLongClick(rightReplyMessageHolder.binding.root, baseMessage) + + } + + StringContract.ViewType.RIGHT_MEDIA_REPLY_MESSAGE -> { + + val rightReplyMessageHolder = p0 as RightReplyMessageHolder + rightReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightReplyMessageHolder.binding.message = baseMessage + rightReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.rightMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is MediaMessage) { + + + if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_IMAGE) + || baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + + rightReplyMessageHolder.binding.imageContainer.visibility = View.VISIBLE + + if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + rightReplyMessageHolder.binding.ivVideoPlay.visibility = View.VISIBLE + rightReplyMessageHolder.binding.ivVideoPlay.setOnClickListener { + startIntent(baseMessage) + } + } + rightReplyMessageHolder.binding.tvReplyTextMessage.visibility = View.VISIBLE + Glide.with(context).load(baseMessage.url) + .into(rightReplyMessageHolder.binding.ivNewMessage) + + } else if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + + rightReplyMessageHolder.binding.fileContainer.visibility = View.VISIBLE + + rightReplyMessageHolder.binding.fileName.text = FileUtil.getFileName(baseMessage.url) + rightReplyMessageHolder.binding.fileType.text = FileUtil.getFileExtension(baseMessage.url) + + rightReplyMessageHolder.binding.fileName.setOnClickListener { + + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(baseMessage.url))) + } + } else if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + rightReplyMessageHolder.binding.audioContainer.visibility = View.VISIBLE + rightReplyMessageHolder.binding.audioSeekBar.progress = 0 + rightReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightReplyMessageHolder.binding.audioLength.typeface = StringContract.Font.status + + try { + + if (GroupChatAdapter.audioDurations.get(timeStampLong) == null) { + player?.reset() + try { + player?.setDataSource(filePath) + player?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + val duration = player?.duration + GroupChatAdapter.audioDurations.put(timeStampLong, duration) + rightReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } else { + val duration = GroupChatAdapter.audioDurations.get(timeStampLong) + rightReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } + + } catch (e: Exception) { + e.printStackTrace() + } + + + rightReplyMessageHolder.binding.playButton.setOnClickListener { + + if (!TextUtils.isEmpty(filePath)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying()!!) { + player?.pause() + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow_black) + } else { + + player?.getCurrentPosition()?.let { player?.seekTo(it) } + player?.getCurrentPosition()?.let { rightReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + rightReplyMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { rightReplyMessageHolder.binding.audioSeekBar.setMax(it) } + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.getCurrentPosition() + pos?.let { rightReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + rightReplyMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + player?.let { + playAudio(filePath, timeStampLong, it, rightReplyMessageHolder.binding.playButton, + rightReplyMessageHolder.binding.audioLength, rightReplyMessageHolder.binding.audioSeekBar) + } + } + + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + + } + } + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + rightReplyMessageHolder.binding.tvNameReply.text = "You" + } else { + rightReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName"); + } + + if (baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = + baseMessage.metadata?.getString("text") + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.VISIBLE + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(rightReplyMessageHolder.binding.ivReplyImage) + + if (baseMessage.metadata.getString("type") == CometChatConstants.MESSAGE_TYPE_IMAGE) { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Photo" + } else { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Video" + } + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } + } + + setLongClick(rightReplyMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.LEFT_TEXT_REPLY_MESSAGE -> { + + val leftReplyMessageHolder = p0 as LeftReplyMessageHolder + leftReplyMessageHolder.binding.message = baseMessage + leftReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.leftMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is TextMessage) { + + leftReplyMessageHolder.binding.txtNewmsg.visibility = View.VISIBLE + leftReplyMessageHolder.binding.txtNewmsg.text = baseMessage.text + leftReplyMessageHolder.binding.txtNewmsg.typeface = StringContract.Font.message + leftReplyMessageHolder.binding.ivNewMessage.visibility = View.GONE + leftReplyMessageHolder.binding.tvNameReply.visibility=View.VISIBLE + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + leftReplyMessageHolder.binding.tvNameReply.text = "You" + } else { + leftReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName"); + } + + if (baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = baseMessage.metadata?.getString("text") + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.VISIBLE + + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(leftReplyMessageHolder.binding.ivReplyImage) + + leftReplyMessageHolder.binding.tvReplyTextMessage.visibility=View.VISIBLE + + if (baseMessage.metadata.getString("type") == CometChatConstants.MESSAGE_TYPE_IMAGE) { + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Photo" + } else { + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Video" + } + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + + } + + setLongClick(leftReplyMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.LEFT_MEDIA_REPLY_MESSAGE -> { + + val leftReplyMessageHolder = p0 as LeftReplyMessageHolder + leftReplyMessageHolder.binding.message = baseMessage + leftReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.leftMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is MediaMessage) { + + when { + baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_IMAGE) + || baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO) -> { + + leftReplyMessageHolder.binding.imageContainer.visibility = View.VISIBLE + + if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + leftReplyMessageHolder.binding.ivVideoPlay.visibility = View.VISIBLE + leftReplyMessageHolder.binding.ivVideoPlay.setOnClickListener { + startIntent(baseMessage) + } + + } + Glide.with(context).load(baseMessage.url) + .into(leftReplyMessageHolder.binding.ivNewMessage) + + } + baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_FILE) -> { + + leftReplyMessageHolder.binding.fileContainer.visibility = View.VISIBLE + leftReplyMessageHolder.binding.fileName.text = FileUtil.getFileName(baseMessage.url) + leftReplyMessageHolder.binding.fileType.text = FileUtil.getFileExtension(baseMessage.url) + leftReplyMessageHolder.binding.fileName.setOnClickListener { + + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(baseMessage.url))) + } + } + baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_AUDIO) -> { + + leftReplyMessageHolder.binding.audioContainer.visibility = View.VISIBLE + leftReplyMessageHolder.binding.audioSeekBar.progress = 0 + leftReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + leftReplyMessageHolder.binding.audioLength.typeface = StringContract.Font.status + + try { + + if (GroupChatAdapter.audioDurations.get(timeStampLong) == null) { + player?.reset() + try { + player?.setDataSource(baseMessage.url) + player?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + val duration = player?.duration + GroupChatAdapter.audioDurations.put(timeStampLong, duration) + leftReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } else { + val duration = GroupChatAdapter.audioDurations.get(timeStampLong) + leftReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } + + } catch (e: Exception) { + e.printStackTrace() + } + + leftReplyMessageHolder.binding.playButton.setOnClickListener { + + if (!TextUtils.isEmpty(baseMessage.url)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying()!!) { + player?.pause() + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow) + } else { + + player?.getCurrentPosition()?.let { player?.seekTo(it) } + player?.getCurrentPosition()?.let { leftReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + leftReplyMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { leftReplyMessageHolder.binding.audioSeekBar.setMax(it) } + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.getCurrentPosition() + pos?.let { leftReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + leftReplyMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler.removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + player?.let { + playAudio(baseMessage.url, timeStampLong, it, leftReplyMessageHolder.binding.playButton, + leftReplyMessageHolder.binding.audioLength, + leftReplyMessageHolder.binding.audioSeekBar) + } + } + + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + + } + } + } + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + leftReplyMessageHolder.binding.tvNameReply.text = "You" + } else { + leftReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName"); + } + + if (baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = + baseMessage.metadata?.getString("text") + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + leftReplyMessageHolder.binding.tvReplyTextMessage.visibility=View.VISIBLE + + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(leftReplyMessageHolder.binding.ivReplyImage) + + if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO)){ + leftReplyMessageHolder.binding.tvReplyTextMessage.text="Video" + } + else{ + leftReplyMessageHolder.binding.tvReplyTextMessage.text="Photo" + } + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + } + + setLongClick(leftReplyMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.LEFT_FILE_MESSAGE -> { + try { + + val leftFileViewHolder = p0 as LeftFileViewHolder + leftFileViewHolder.binding.message = baseMessage as MediaMessage + leftFileViewHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.leftMessageColor, PorterDuff.Mode.SRC_ATOP) + val t = mediaFile?.substring(mediaFile.lastIndexOf("/"))?.split("_".toRegex())?.dropLastWhile({ it.isEmpty() })?.toTypedArray() + leftFileViewHolder.binding.fileName.setText(t?.get(2)) + leftFileViewHolder.binding.fileType.setText(mediaFile?.substring(mediaFile.lastIndexOf(".") + 1)) + val finalMediaFile = mediaFile + leftFileViewHolder.binding.fileName.typeface = StringContract.Font.name + leftFileViewHolder.binding.fileType.typeface = StringContract.Font.name + leftFileViewHolder.binding.timeStamp.typeface = StringContract.Font.status + leftFileViewHolder.binding.senderName.typeface = StringContract.Font.status + setLongClick(leftFileViewHolder.binding.root,baseMessage) + leftFileViewHolder.binding.fileName.setOnClickListener({ context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(finalMediaFile))) }) + } catch (e: Exception) { + e.printStackTrace() + } + } + + StringContract.ViewType.LEFT_VIDEO_MESSAGE -> { + val leftImageVideoMessageHolder = p0 as LeftImageVideoMessageHolder + leftImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + leftImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + leftImageVideoMessageHolder.binding.senderName.typeface = StringContract.Font.status + + val requestOptions = RequestOptions() + .fitCenter() + .placeholder(R.drawable.ic_broken_image) + Glide.with(context) + .load(baseMessage.url) + .apply(requestOptions) + .into(leftImageVideoMessageHolder.binding.imageMessage) + + leftImageVideoMessageHolder.binding.btnPlayVideo.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(leftImageVideoMessageHolder.binding.root,baseMessage) + } + + StringContract.ViewType.RIGHT_VIDEO_MESSAGE -> { + val rightImageVideoMessageHolder = p0 as RightImageVideoMessageHolder + rightImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + rightImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + + val requestOptions = RequestOptions() + .fitCenter() + .placeholder(R.drawable.ic_broken_image) + Glide.with(context) + .load(baseMessage.url) + .apply(requestOptions) + .into(rightImageVideoMessageHolder.binding.imageMessage) + + + rightImageVideoMessageHolder.binding.btnPlayVideo.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(rightImageVideoMessageHolder.binding.root,baseMessage) + } + + + StringContract.ViewType.RIGHT_AUDIO_MESSAGE -> { + val rightAudioMessageHolder = p0 as RightAudioMessageHolder + rightAudioMessageHolder.binding.message = (baseMessage as MediaMessage) + rightAudioMessageHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.rightMessageColor, PorterDuff.Mode.SRC_ATOP) + rightAudioMessageHolder.binding.audioSeekBar.progress = 0 + rightAudioMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightAudioMessageHolder.binding.audioLength.typeface = StringContract.Font.status + setLongClick(rightAudioMessageHolder.binding.root, baseMessage) + + try { + + if (GroupChatAdapter.audioDurations.get(timeStampLong) == null) { + player?.reset() + try { + player?.setDataSource(filePath) + player?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + val duration = player?.duration + GroupChatAdapter.audioDurations.put(timeStampLong, duration) + rightAudioMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } else { + val duration = GroupChatAdapter.audioDurations.get(timeStampLong) + rightAudioMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } + + } catch (e: Exception) { + e.printStackTrace() + } + + rightAudioMessageHolder.binding.playButton.setOnClickListener(object : View.OnClickListener { + override fun onClick(v: View?) { + + if (!TextUtils.isEmpty(filePath)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying()!!) { + player?.pause() + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow) + } else { + + player?.currentPosition?.let { player?.seekTo(it) } + player?.currentPosition?.let { rightAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + rightAudioMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { rightAudioMessageHolder.binding.audioSeekBar.setMax(it) } + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.getCurrentPosition() + pos?.let { rightAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + rightAudioMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + player?.let { + playAudio(filePath, timeStampLong, it, rightAudioMessageHolder.binding.playButton, + rightAudioMessageHolder.binding.audioLength, rightAudioMessageHolder.binding.audioSeekBar) + } + } + + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + }) + + filePath?.let { Log.d("metaData", it) } + + } + + StringContract.ViewType.LEFT_AUDIO_MESSAGE -> { + + val leftAudioMessageHolder = p0 as LeftAudioMessageHolder + leftAudioMessageHolder.binding.message = (baseMessage as MediaMessage) + leftAudioMessageHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.leftMessageColor, PorterDuff.Mode.SRC_ATOP) + leftAudioMessageHolder.binding.audioSeekBar.progress = 0 + leftAudioMessageHolder.binding.audioLength.typeface = StringContract.Font.status + leftAudioMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + setLongClick(leftAudioMessageHolder.itemView, baseMessage) + leftAudioMessageHolder.binding.progress.visibility = View.GONE + + val audioPath: String = FileUtil.getPath(context, CometChatConstants.MESSAGE_TYPE_AUDIO) + + FileUtil.getFileName(baseMessage.url) + + val audioFile = File(audioPath) + + if (audioFile.exists()) { + + leftAudioMessageHolder.binding.progress.visibility = View.GONE + leftAudioMessageHolder.binding.download.visibility = View.GONE + leftAudioMessageHolder.binding.playButton.visibility = View.VISIBLE + + } else { + + leftAudioMessageHolder.binding.progress.visibility = View.GONE + leftAudioMessageHolder.binding.download.visibility = View.VISIBLE + leftAudioMessageHolder.binding.playButton.visibility = View.GONE + + } + + leftAudioMessageHolder.binding.download.setOnClickListener(object : View.OnClickListener { + override fun onClick(v: View?) { + + if (downloadFile?.status == AsyncTask.Status.RUNNING) { + + downloadFile?.cancel(true) + leftAudioMessageHolder.binding.download.setImageResource(R.drawable.ic_file_download) + leftAudioMessageHolder.binding.progress.visibility = View.GONE + leftAudioMessageHolder.binding.playButton.visibility = View.GONE + } else { + + if (CCPermissionHelper.hasPermissions(CometChatPro.applicationContext(), CCPermissionHelper.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE)) { + if (FileUtil.checkDirExistence(context, CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + downloadFile = DownloadFile(CometChatConstants.MESSAGE_TYPE_AUDIO, baseMessage.url, + leftAudioMessageHolder.binding) + + downloadFile?.execute() + + } + } else { + CCPermissionHelper.requestPermissions(context as Activity, + arrayOf(CCPermissionHelper.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE), StringContract.RequestCode.FILE_WRITE) + } + } + } + }) + + leftAudioMessageHolder.binding.playButton.setOnClickListener(object : View.OnClickListener { + override fun onClick(v: View?) { + + if (!TextUtils.isEmpty(baseMessage.url)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying!!) { + player?.pause() + + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow_black) + } else { + // player.setDataSource(message); + // player.prepare(); + player?.currentPosition?.let { player?.seekTo(it) } + player?.currentPosition?.let { leftAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + leftAudioMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { leftAudioMessageHolder.binding.audioSeekBar.setMax(it) } + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.currentPosition + pos?.let { leftAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + leftAudioMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + player?.let { + playAudio(if (audioFile.exists()) audioPath else baseMessage.url, timeStampLong, it, leftAudioMessageHolder.binding.playButton, + leftAudioMessageHolder.binding.audioLength, leftAudioMessageHolder.binding.audioSeekBar, true) + } + } + + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + }) + + filePath?.let { Log.d("metaData", it) } + + } + + + StringContract.ViewType.ACTION_MESSAGE -> { + + val actionHolder = p0 as TextHeaderHolder + + actionHolder.binding.txtMessageDate.setText((baseMessage as Action).message) + actionHolder.binding.txtMessageDate.setTextColor(StringContract.Color.black) + actionHolder.binding.txtMessageDate.typeface = StringContract.Font.status + + } + + StringContract.ViewType.CALL_MESSAGE -> { + val callHolder = p0 as TextHeaderHolder + callHolder.binding.txtMessageDate.setTextColor(StringContract.Color.black) + callHolder.binding.txtMessageDate.typeface = StringContract.Font.status + + message = "Call " + (baseMessage as Call).callStatus + + callHolder.binding.txtMessageDate.text = message + + } + + + + + } + } + + private fun startIntent(baseMessage: MediaMessage){ + + val imageIntent = Intent(context, ImageViewActivity::class.java) + imageIntent.putExtra(StringContract.IntentString.FILE_TYPE, baseMessage.type); + imageIntent.putExtra(StringContract.IntentString.URL, (baseMessage.url)) + context.startActivity(imageIntent) + } + + + fun stopPlayer(){ + try { + if (player!=null){ + player?.stop() + player=null + } + + }catch (e:Exception){ + + } + } + + fun playAudio(message: String?, sentTimeStamp: Long, player: MediaPlayer, playButton: ImageView, audioLength: TextView, audioSeekBar: SeekBar,isleft:Boolean=false) { + try { + currentPlayingSong = message + currentlyPlayingId = sentTimeStamp + if (timerRunnable != null) { + seekHandler.removeCallbacks(timerRunnable) + timerRunnable = null + } + // setBtnColor(viewtype, playBtn, false); + player.reset() + player.setAudioStreamType(AudioManager.STREAM_MUSIC) + player.setDataSource(currentPlayingSong) + player.prepare() + player.start() + + val duration = player.duration + audioSeekBar.max = duration + timerRunnable = object : Runnable { + override fun run() { + + val pos = player.currentPosition + audioSeekBar.progress = pos + + if (player.isPlaying && pos < duration) { + audioLength.setText(DateUtil.convertTimeStampToDurationTime(player.currentPosition.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + + player.setOnCompletionListener { mp -> + currentPlayingSong = "" + currentlyPlayingId = 0L + // setBtnColor(viewtype, playBtn, true); + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + mp.stop() + audioLength.setText(DateUtil.convertTimeStampToDurationTime(duration.toLong())) + audioSeekBar.progress = 0 + if (isleft) { + playButton.setImageResource(R.drawable.ic_play_arrow_black) + } + else{ + playButton.setImageResource(R.drawable.ic_play_arrow) + } + } + + } catch (e: Exception) { + e.printStackTrace() + } + + } + + override fun getItemViewType(position: Int): Int { + + if (messagesList.get(position).category.equals(CometChatConstants.CATEGORY_MESSAGE, ignoreCase = true)) { + + if (ownerId.equals(messagesList.get(position).sender.uid, ignoreCase = true)) { + + if ((messagesList.get(position) is TextMessage) + &&(messagesList[position] as TextMessage).metadata!=null + &&(messagesList[position] as TextMessage).metadata.has("reply")) { + + return StringContract.ViewType.RIGHT_TEXT_REPLY_MESSAGE + } + else if ((messagesList[position] is MediaMessage) + &&(messagesList[position] as MediaMessage).metadata!=null + &&(messagesList[position] as MediaMessage).metadata.has("reply")){ + return StringContract.ViewType.RIGHT_MEDIA_REPLY_MESSAGE + } + else { + when (messagesList.get(position).type) { + + CometChatConstants.MESSAGE_TYPE_TEXT -> { + if ((messagesList.get(position) as TextMessage).text.equals("custom_location")) { + return StringContract.ViewType.RIGHT_LOCATION_MESSAGE + } + return StringContract.ViewType.RIGHT_TEXT_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_IMAGE -> { + return StringContract.ViewType.RIGHT_IMAGE_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_AUDIO -> { + return StringContract.ViewType.RIGHT_AUDIO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_VIDEO -> { + return StringContract.ViewType.RIGHT_VIDEO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_FILE -> { + return StringContract.ViewType.RIGHT_FILE_MESSAGE + } + + } + } + } else { + + if ((messagesList[position] is TextMessage) + &&(messagesList[position] as TextMessage).metadata!=null + &&(messagesList[position] as TextMessage).metadata.has("reply")) { + + return StringContract.ViewType.LEFT_TEXT_REPLY_MESSAGE + } + else if ((messagesList[position] is MediaMessage) + &&(messagesList[position] as MediaMessage).metadata!=null + &&(messagesList[position] as MediaMessage).metadata.has("reply")){ + + return StringContract.ViewType.LEFT_MEDIA_REPLY_MESSAGE + } + + else { + when (messagesList.get(position).type) { + + CometChatConstants.MESSAGE_TYPE_TEXT -> { + + if ((messagesList.get(position) as TextMessage).text.equals("custom_location")) { + + return StringContract.ViewType.LEFT_LOCATION_MESSAGE + } + return StringContract.ViewType.LEFT_TEXT_MESSAGE + + } + + CometChatConstants.MESSAGE_TYPE_IMAGE -> { + return StringContract.ViewType.LEFT_IMAGE_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_AUDIO -> { + return StringContract.ViewType.LEFT_AUDIO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_VIDEO -> { + return StringContract.ViewType.LEFT_VIDEO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_FILE -> { + return StringContract.ViewType.LEFT_FILE_MESSAGE + } + + } + } + } + } else if (messagesList.get(position).category.equals(CometChatConstants.CATEGORY_ACTION, ignoreCase = true)) { + return StringContract.ViewType.ACTION_MESSAGE + + } else if (messagesList.get(position).category.equals(CometChatConstants.CATEGORY_CALL, ignoreCase = true)) { + return StringContract.ViewType.CALL_MESSAGE + } + return super.getItemViewType(position) + } + + fun setMessageList(messageList: MutableList) { + this.messagesList = messageList + + notifyDataSetChanged() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupListAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupListAdapter.kt new file mode 100755 index 0000000..cbc79cd --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupListAdapter.kt @@ -0,0 +1,55 @@ +package com.inscripts.cometchatpulse.Adapter + +import android.content.Context +import android.databinding.DataBindingUtil +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.ViewGroup +import com.cometchat.pro.models.Group +import com.inscripts.cometchatpulse.Helpers.ChildClickListener +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.databinding.GroupListItemBinding + + + +class GroupListAdapter(val context: Context?) : RecyclerView.Adapter() { + + private var groupList: MutableList = arrayListOf() + + override fun onCreateViewHolder(p0: ViewGroup, p1: Int): GroupHolder { + val layoutInflater:LayoutInflater = LayoutInflater.from(context) + + val binding: GroupListItemBinding = DataBindingUtil.inflate(layoutInflater,R.layout.group_list_item,p0,false) + + return GroupHolder(binding) + + } + + override fun getItemCount(): Int { + + return groupList.size + } + + override fun onBindViewHolder(groupHolder: GroupHolder, p1: Int) { + + val group = groupList[p1] + + groupHolder.binding.group=group + groupHolder.binding.childClick=context as ChildClickListener + groupHolder.binding.textViewGroupName.typeface=StringContract.Font.name + groupHolder.binding.textViewUsersOnlineMessage.typeface=StringContract.Font.status + groupHolder.binding.executePendingBindings() + groupHolder.binding.root.setTag(R.string.group,group) + + } + + fun setGroup(it: MutableList) { + this.groupList = it + notifyDataSetChanged() + } + + + class GroupHolder(val binding:GroupListItemBinding) : RecyclerView.ViewHolder(binding.root) + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupOptionAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupOptionAdapter.kt new file mode 100755 index 0000000..5389c35 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/GroupOptionAdapter.kt @@ -0,0 +1,58 @@ +package com.inscripts.cometchatpulse.Adapter + +import android.content.Context +import android.databinding.DataBindingUtil +import android.os.Bundle +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.inscripts.cometchatpulse.Fragment.MemberFragment +import com.inscripts.cometchatpulse.Helpers.OnOptionClickListener +import com.inscripts.cometchatpulse.Pojo.GroupOption +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.ViewHolder.GroupOptionViewHolder +import com.inscripts.cometchatpulse.databinding.GroupOptionItemBinding + + +class GroupOptionAdapter(val context:Context,val groupOptionList: MutableList, + val ownerId:String,val guid:String, onOptionClickListener: OnOptionClickListener): RecyclerView.Adapter() { + + private var onOptionClickListener:OnOptionClickListener + init { + this.onOptionClickListener=onOptionClickListener + } + + override fun onCreateViewHolder(p0: ViewGroup, p1: Int): GroupOptionViewHolder { + val layoutInflater: LayoutInflater = LayoutInflater.from(context) + + val binding: GroupOptionItemBinding =DataBindingUtil.inflate(layoutInflater, R.layout.group_option_item,p0,false) + + return GroupOptionViewHolder(binding) + } + + override fun getItemCount(): Int { + return groupOptionList.size + } + + override fun onBindViewHolder(p0: GroupOptionViewHolder, p1: Int) { + + val groupOption=groupOptionList.get(p1) + + p0.binding.groupOption=groupOption + + p0.binding.tvOption.typeface=StringContract.Font.name + + + p0.binding.root.setOnClickListener(object :View.OnClickListener{ + override fun onClick(v: View?) { + + onOptionClickListener.OnOptionClick(p0.adapterPosition) + + } + + }) + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Adapter/MemberListAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/MemberListAdapter.kt new file mode 100755 index 0000000..5899c36 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/MemberListAdapter.kt @@ -0,0 +1,69 @@ +package com.inscripts.cometchatpulse.Adapter + + +import android.databinding.DataBindingUtil +import android.support.v4.app.Fragment +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.cometchat.pro.models.GroupMember +import com.inscripts.cometchatpulse.Fragment.BanMemberFragment +import com.inscripts.cometchatpulse.Fragment.MemberFragment +import com.inscripts.cometchatpulse.Helpers.OnClickEvent +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.ViewHolder.GroupMemberHolder +import com.inscripts.cometchatpulse.databinding.ContactItemBinding +import com.inscripts.cometchatpulse.databinding.GroupMemberItemBinding + +class MemberListAdapter(val ownerId:String, val resId:Int,val listener: OnClickEvent): RecyclerView.Adapter() { + + private var groupMemberList:MutableList = mutableListOf() + + private var onClickevent:OnClickEvent = listener + + override fun onCreateViewHolder(p0: ViewGroup, p1: Int): GroupMemberHolder { + val layoutInflater: LayoutInflater = LayoutInflater.from(p0.context) + val binding: GroupMemberItemBinding = DataBindingUtil.inflate(layoutInflater,resId,p0,false) + + return GroupMemberHolder(binding) + } + + override fun getItemCount(): Int { + return groupMemberList.size + } + + override fun onBindViewHolder(p0: GroupMemberHolder, p1: Int) { + + val groupMember:GroupMember=groupMemberList.get(p1) + + p0.binding.memeber=groupMember + + p0.binding.textviewUserName.typeface=StringContract.Font.name + + p0.binding.textviewUserStatus.typeface=StringContract.Font.status + + p0.binding.root.setTag(R.string.user,groupMember.user) + + p0.binding.executePendingBindings() + + if (groupMember.uid.equals(ownerId)) + p0.binding.textviewUserName.text="You" + + + p0.itemView.setOnClickListener { + onClickevent.onClickRl(p0.itemView,groupMember.user) + } + + } + + internal fun setMemberList(memberlist: MutableList) { + this.groupMemberList=memberlist + notifyDataSetChanged() + + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Adapter/OneToOneAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/OneToOneAdapter.kt new file mode 100755 index 0000000..23f0097 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/OneToOneAdapter.kt @@ -0,0 +1,1369 @@ +package com.inscripts.cometchatpulse.Adapter + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.databinding.DataBindingUtil +import android.graphics.Bitmap +import android.graphics.PorterDuff +import android.media.AudioManager +import android.media.MediaPlayer +import android.net.Uri +import android.os.AsyncTask +import android.os.Handler +import android.support.v4.util.LongSparseArray +import android.support.v7.widget.RecyclerView +import android.text.TextUtils +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.SeekBar +import android.widget.TextView +import com.bumptech.glide.Glide +import com.bumptech.glide.request.RequestOptions +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.Call +import com.cometchat.pro.models.BaseMessage +import com.cometchat.pro.models.MediaMessage +import com.cometchat.pro.models.TextMessage +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Activities.ImageViewActivity +import com.inscripts.cometchatpulse.AsyncTask.DownloadFile +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.CustomView.StickyHeaderAdapter +import com.inscripts.cometchatpulse.Helpers.CCPermissionHelper +import com.inscripts.cometchatpulse.Helpers.OnClickEvent +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.DateUtil +import com.inscripts.cometchatpulse.Utils.FileUtil +import com.inscripts.cometchatpulse.ViewHolder.* +import com.inscripts.cometchatpulse.databinding.* +import org.json.JSONException +import java.io.File +import java.io.IOException +import java.util.* + +class OneToOneAdapter(val context: Context, val ownerId: String, + val listener: OnClickEvent) : RecyclerView.Adapter(), + StickyHeaderAdapter { + + + private lateinit var viewHolder: RecyclerView.ViewHolder + private var messagesList: MutableList = mutableListOf() + private var currentPlayingSong: String? = null + private var timerRunnable: Runnable? = null + private val seekHandler = Handler() + private var onClickEvent: OnClickEvent + private var currentlyPlayingId = 0L + var player: MediaPlayer? = null + + private var downloadFile: DownloadFile? = null + + init { + if (player == null) { + player = MediaPlayer() + } + onClickEvent = listener + audioDurations = LongSparseArray() + videoThumbnails = LongSparseArray() + } + + companion object { + private lateinit var audioDurations: LongSparseArray + private lateinit var videoThumbnails: LongSparseArray + } + + + override fun onCreateViewHolder(p0: ViewGroup, p1: Int): RecyclerView.ViewHolder { + + val layoutInflater: LayoutInflater = LayoutInflater.from(context) + + when (p1) { + + StringContract.ViewType.RIGHT_TEXT_MESSAGE -> { + val binding: RightTextBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_text, p0, false) + return RightTextMessageHolder(binding) + } + + StringContract.ViewType.LEFT_TEXT_MESSAGE -> { + val binding: LeftTextBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_text, p0, false) + return LeftTextMessageHolder(binding) + } + + StringContract.ViewType.RIGHT_IMAGE_MESSAGE -> { + val binding: CcImageVideoLayoutRightBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_right, p0, false) + return RightImageVideoMessageHolder(binding) + } + + StringContract.ViewType.LEFT_IMAGE_MESSAGE -> { + val binding: CcImageVideoLayoutLeftBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_left, p0, false) + return LeftImageVideoMessageHolder(binding) + + } + + StringContract.ViewType.RIGHT_VIDEO_MESSAGE -> { + + val binding: CcImageVideoLayoutRightBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_right, p0, false) + return RightImageVideoMessageHolder(binding) + } + + StringContract.ViewType.LEFT_VIDEO_MESSAGE -> { + val binding: CcImageVideoLayoutLeftBinding = DataBindingUtil.inflate(layoutInflater, R.layout.cc_image_video_layout_left, p0, false) + return LeftImageVideoMessageHolder(binding) + } + + StringContract.ViewType.RIGHT_AUDIO_MESSAGE -> { + val binding: RightAudioBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_audio, p0, false) + return RightAudioMessageHolder(binding) + } + + StringContract.ViewType.LEFT_AUDIO_MESSAGE -> { + val binding: LeftAudioBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_audio, p0, false) + return LeftAudioMessageHolder(binding) + } + + StringContract.ViewType.CALL_MESSAGE -> { + + val binding: ListHeaderBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_header, p0, false) + return TextHeaderHolder(binding) + } + + StringContract.ViewType.RIGHT_FILE_MESSAGE -> { + val binding: RightFileBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_file, p0, false) + return RightFileViewHolder(binding) + } + + StringContract.ViewType.LEFT_FILE_MESSAGE -> { + val binding: LeftFileBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_file, p0, false) + return LeftFileViewHolder(binding) + } + + StringContract.ViewType.RIGHT_LOCATION_MESSAGE -> { + val binding: RightLocationBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_location, p0, false) + return RightLocationViewHolder(binding) + } + + StringContract.ViewType.LEFT_LOCATION_MESSAGE -> { + val binding: LeftLocationBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_location, p0, false) + return LeftLocationViewHolder(binding) + } + + StringContract.ViewType.RIGHT_TEXT_REPLY_MESSAGE -> { + + val binding: RightReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_reply, p0, false) + return RightReplyMessageHolder(binding) + } + + StringContract.ViewType.RIGHT_MEDIA_REPLY_MESSAGE -> { + + val binding: RightReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.right_reply, p0, false) + return RightReplyMessageHolder(binding) + } + + StringContract.ViewType.LEFT_TEXT_REPLY_MESSAGE -> { + + val binding: LeftReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_reply, p0, false) + return LeftReplyMessageHolder(binding) + } + + StringContract.ViewType.LEFT_MEDIA_REPLY_MESSAGE -> { + + val binding: LeftReplyBinding = DataBindingUtil.inflate(layoutInflater, R.layout.left_reply, p0, false) + return LeftReplyMessageHolder(binding) + } + + else -> { + return viewHolder + } + } + + } + + override fun getHeaderId(var1: Int): Long { + return java.lang.Long.parseLong(DateUtil.getDateId(messagesList.get(var1).getSentAt() * 1000)) + } + + override fun onCreateHeaderViewHolder(var1: ViewGroup): TextHeaderHolder { + val layoutInflater: LayoutInflater = LayoutInflater.from(context) + val binding: ListHeaderBinding = DataBindingUtil.inflate(layoutInflater, R.layout.list_header, var1, false) + return TextHeaderHolder(binding) + + } + + override fun onBindHeaderViewHolder(var1: TextHeaderHolder, var2: Int, var3: Long) { + val date = Date(messagesList.get(var2).getSentAt() * 1000) + + val formattedDate = DateUtil.getCustomizeDate(date.getTime()) + + var1.binding.txtMessageDate.setBackground(context.resources.getDrawable(R.drawable.cc_rounded_date_button)) + + var1.binding.txtMessageDate.setText(formattedDate) + + } + + + override fun getItemCount(): Int { + + return messagesList.size + } + + override fun getItemViewType(position: Int): Int { + + if (messagesList[position].category.equals(CometChatConstants.CATEGORY_MESSAGE, ignoreCase = true)) { + + if (ownerId.equals(messagesList[position].sender.uid, ignoreCase = true)) { + + if ((messagesList.get(position) is TextMessage) + && (messagesList[position] as TextMessage).metadata != null + && (messagesList[position] as TextMessage).metadata.has("reply")) { + + return StringContract.ViewType.RIGHT_TEXT_REPLY_MESSAGE + + } else if ((messagesList[position] is MediaMessage) + && (messagesList[position] as MediaMessage).metadata != null + && (messagesList[position] as MediaMessage).metadata.has("reply")) { + + return StringContract.ViewType.RIGHT_MEDIA_REPLY_MESSAGE + + } else { + + when (messagesList.get(position).type) { + + CometChatConstants.MESSAGE_TYPE_TEXT -> { + + if ((messagesList[position] as TextMessage).text.equals("custom_location")) { + return StringContract.ViewType.RIGHT_LOCATION_MESSAGE + } + + return StringContract.ViewType.RIGHT_TEXT_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_IMAGE -> { + + return StringContract.ViewType.RIGHT_IMAGE_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_AUDIO -> { + + return StringContract.ViewType.RIGHT_AUDIO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_VIDEO -> { + + return StringContract.ViewType.RIGHT_VIDEO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_FILE -> { + + return StringContract.ViewType.RIGHT_FILE_MESSAGE + } + + } + } + } else { + + + if ((messagesList[position] is TextMessage) + && (messagesList[position] as TextMessage).metadata != null + && (messagesList[position] as TextMessage).metadata.has("reply")) { + + return StringContract.ViewType.LEFT_TEXT_REPLY_MESSAGE + } else if ((messagesList[position] is MediaMessage) + && (messagesList[position] as MediaMessage).metadata != null + && (messagesList[position] as MediaMessage).metadata.has("reply")) { + + return StringContract.ViewType.LEFT_MEDIA_REPLY_MESSAGE + } else { + when (messagesList[position].type) { + + CometChatConstants.MESSAGE_TYPE_TEXT -> { + + if ((messagesList[position] as TextMessage).text.equals("custom_location")) { + + return StringContract.ViewType.LEFT_LOCATION_MESSAGE + } + + return StringContract.ViewType.LEFT_TEXT_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_IMAGE -> { + + return StringContract.ViewType.LEFT_IMAGE_MESSAGE + + } + + CometChatConstants.MESSAGE_TYPE_AUDIO -> { + + return StringContract.ViewType.LEFT_AUDIO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_VIDEO -> { + + return StringContract.ViewType.LEFT_VIDEO_MESSAGE + } + + CometChatConstants.MESSAGE_TYPE_FILE -> { + + return StringContract.ViewType.LEFT_FILE_MESSAGE + } + + } + } + } + } else if (messagesList[position].category.equals(CometChatConstants.CATEGORY_CALL, ignoreCase = true)) { + return StringContract.ViewType.CALL_MESSAGE + } + + return super.getItemViewType(position) + } + + fun setMessageList(messageList: MutableList) { + this.messagesList = messageList + notifyDataSetChanged() + + } + + + fun setLongClick(view: View, baseMessage: BaseMessage) { + var message: Any? = null + if (baseMessage is TextMessage) + message = baseMessage + + if (baseMessage is MediaMessage) + message = baseMessage + + view.setOnLongClickListener { + message?.let { it1 -> onClickEvent.onClickRl(view, it1) } + true + } + } + + public fun stopPlayer() { + try { + if (player != null) { + player?.stop() + player = null + } + + } catch (e: Exception) { + + } + } + + + override fun onBindViewHolder(p0: RecyclerView.ViewHolder, p1: Int) { + + val baseMessage = messagesList[p1] + val timeStampLong = messagesList[p1].sentAt + var message: String? = null + var filePath: String? = null + var mediaFile: String? = null + + if (baseMessage is MediaMessage) { + if (baseMessage.metadata != null) { + try { + Log.d("metaAdapter", baseMessage.metadata.toString()) + + filePath = baseMessage.metadata.getString("path") + Log.d("OneToOneAdapter", filePath) + } catch (e: JSONException) { + e.printStackTrace() + } + } + mediaFile = baseMessage.url + + } + + if (baseMessage is Call) { + val user = baseMessage.callInitiator as User + val callReceiver = baseMessage.callReceiver as User + + if (user.uid.equals(ownerId, ignoreCase = true)) { + message = "You Call " + callReceiver.name + } else { + message = "You received call from " + user.name + } + } + + when (p0.itemViewType) { + + StringContract.ViewType.RIGHT_TEXT_MESSAGE -> { + val rightTextMessageHolder = p0 as RightTextMessageHolder + rightTextMessageHolder.binding.message = (baseMessage as TextMessage) + rightTextMessageHolder.binding.tvMessage.typeface = StringContract.Font.message + rightTextMessageHolder.binding.timestamp.typeface = StringContract.Font.status + rightTextMessageHolder.binding.tvMessage.background.setColorFilter(StringContract.Color.rightMessageColor, PorterDuff.Mode.SRC_ATOP) + setLongClick(rightTextMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.LEFT_TEXT_MESSAGE -> { + val leftTextMessageHolder = p0 as LeftTextMessageHolder + leftTextMessageHolder.binding.message = (baseMessage as TextMessage) + leftTextMessageHolder.binding.tvMessage.typeface = StringContract.Font.message + leftTextMessageHolder.binding.senderName.typeface = StringContract.Font.status + leftTextMessageHolder.binding.timestamp.typeface = StringContract.Font.status + leftTextMessageHolder.binding.tvMessage.background.setColorFilter(StringContract.Color.leftMessageColor, + PorterDuff.Mode.SRC_ATOP) + + setLongClick(leftTextMessageHolder.binding.root, baseMessage) + } + + + StringContract.ViewType.RIGHT_TEXT_REPLY_MESSAGE -> { + val rightReplyMessageHolder = p0 as RightReplyMessageHolder + rightReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightReplyMessageHolder.binding.message = baseMessage + rightReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.rightMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is TextMessage) { + + rightReplyMessageHolder.binding.txtNewmsg.visibility = View.VISIBLE + rightReplyMessageHolder.binding.txtNewmsg.text = baseMessage.text + rightReplyMessageHolder.binding.txtNewmsg.typeface = StringContract.Font.message + rightReplyMessageHolder.binding.tvNameReply.typeface = StringContract.Font.name + rightReplyMessageHolder.binding.ivNewMessage.visibility = View.GONE + + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + rightReplyMessageHolder.binding.tvNameReply.text = "You" + + } else { + rightReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName") + } + + when { + baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT) -> { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = + baseMessage.metadata?.getString("text") + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO) -> { + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.VISIBLE + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(rightReplyMessageHolder.binding.ivReplyImage) + + if (baseMessage.metadata.getString("type") == CometChatConstants.MESSAGE_TYPE_IMAGE) { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Photo" + } else { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Video" + } + + } + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO) -> { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE) -> { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + } + + } + + setLongClick(rightReplyMessageHolder.binding.root, baseMessage) + + } + + StringContract.ViewType.RIGHT_MEDIA_REPLY_MESSAGE -> { + + val rightReplyMessageHolder = p0 as RightReplyMessageHolder + rightReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightReplyMessageHolder.binding.message = baseMessage + rightReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.rightMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is MediaMessage) { + + + if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_IMAGE) + || baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + + rightReplyMessageHolder.binding.ivNewMessage.visibility = View.VISIBLE + + if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + rightReplyMessageHolder.binding.ivVideoPlay.visibility=View.VISIBLE + rightReplyMessageHolder.binding.ivVideoPlay.setOnClickListener { + startIntent(baseMessage) + } + + } + + Glide.with(context).load(baseMessage.url) + .into(rightReplyMessageHolder.binding.ivNewMessage) + } else if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + + rightReplyMessageHolder.binding.fileContainer.visibility = View.VISIBLE + + rightReplyMessageHolder.binding.fileName.text = FileUtil.getFileName(baseMessage.url) + rightReplyMessageHolder.binding.fileType.text = FileUtil.getFileExtension(baseMessage.url) + + rightReplyMessageHolder.binding.fileName.setOnClickListener { + + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(baseMessage.url))) + } + } else if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + rightReplyMessageHolder.binding.audioContainer.visibility = View.VISIBLE + rightReplyMessageHolder.binding.audioSeekBar.progress = 0 + rightReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightReplyMessageHolder.binding.audioLength.typeface = StringContract.Font.status + + try { + + if (audioDurations.get(timeStampLong) == null) { + player?.reset() + try { + player?.setDataSource(filePath) + player?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + val duration = player?.duration + audioDurations.put(timeStampLong, duration) + rightReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } else { + val duration = audioDurations.get(timeStampLong) + rightReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } + + } catch (e: Exception) { + e.printStackTrace() + } + + + rightReplyMessageHolder.binding.playButton.setOnClickListener { + + if (!TextUtils.isEmpty(filePath)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying()!!) { + player?.pause() + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow_black) + } else { + + player?.getCurrentPosition()?.let { player?.seekTo(it) } + player?.getCurrentPosition()?.let { rightReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + rightReplyMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { rightReplyMessageHolder.binding.audioSeekBar.setMax(it) } + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.getCurrentPosition() + pos?.let { rightReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + rightReplyMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + player?.let { + playAudio(filePath, timeStampLong, it, rightReplyMessageHolder.binding.playButton, + rightReplyMessageHolder.binding.audioLength, rightReplyMessageHolder.binding.audioSeekBar) + } + } + + rightReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + + } + } + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + rightReplyMessageHolder.binding.tvNameReply.text = "You" + } else { + rightReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName"); + } + + if (baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = + baseMessage.metadata?.getString("text") + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(rightReplyMessageHolder.binding.ivReplyImage) + + if (baseMessage.metadata.getString("type") == CometChatConstants.MESSAGE_TYPE_IMAGE) { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Photo" + } else { + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Video" + } + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + + rightReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + + rightReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } + } + + setLongClick(rightReplyMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.LEFT_TEXT_REPLY_MESSAGE -> { + + val leftReplyMessageHolder = p0 as LeftReplyMessageHolder + leftReplyMessageHolder.binding.message = baseMessage + leftReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.leftMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is TextMessage) { + + leftReplyMessageHolder.binding.txtNewmsg.visibility = View.VISIBLE + leftReplyMessageHolder.binding.txtNewmsg.text = baseMessage.text + leftReplyMessageHolder.binding.txtNewmsg.typeface = StringContract.Font.message + leftReplyMessageHolder.binding.ivNewMessage.visibility = View.GONE + leftReplyMessageHolder.binding.tvNameReply.visibility = View.VISIBLE + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + leftReplyMessageHolder.binding.tvNameReply.text = "You" + } else { + leftReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName"); + } + + if (baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = baseMessage.metadata?.getString("text") + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(leftReplyMessageHolder.binding.ivReplyImage) + + if (baseMessage.metadata.getString("type") == CometChatConstants.MESSAGE_TYPE_IMAGE) { + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Photo" + } else { + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Video" + } + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } else if (baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + + } + + setLongClick(leftReplyMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.LEFT_MEDIA_REPLY_MESSAGE -> { + + val leftReplyMessageHolder = p0 as LeftReplyMessageHolder + leftReplyMessageHolder.binding.message = baseMessage + leftReplyMessageHolder.binding.rlMain.background.setColorFilter(StringContract.Color.leftMessageColor, + PorterDuff.Mode.SRC_ATOP) + + if (baseMessage is MediaMessage) { + + when { + baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_IMAGE) + || baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO) -> { + + leftReplyMessageHolder.binding.ivNewMessage.visibility = View.VISIBLE + + Glide.with(context).load(baseMessage.url) + .into(leftReplyMessageHolder.binding.ivNewMessage) + + if (baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + leftReplyMessageHolder.binding.tvReplyTextMessage.visibility = View.VISIBLE; + leftReplyMessageHolder.binding.ivVideoPlay.setOnClickListener { + startIntent(baseMessage) + } + } + + } + baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_FILE) -> { + + leftReplyMessageHolder.binding.fileContainer.visibility = View.VISIBLE + leftReplyMessageHolder.binding.fileName.text = FileUtil.getFileName(baseMessage.url) + leftReplyMessageHolder.binding.fileType.text = FileUtil.getFileExtension(baseMessage.url) + leftReplyMessageHolder.binding.fileName.setOnClickListener { + + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(baseMessage.url))) + } + } + baseMessage.type.equals(CometChatConstants.MESSAGE_TYPE_AUDIO) -> { + + leftReplyMessageHolder.binding.audioContainer.visibility = View.VISIBLE + leftReplyMessageHolder.binding.audioSeekBar.progress = 0 + leftReplyMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + leftReplyMessageHolder.binding.audioLength.typeface = StringContract.Font.status + + try { + + if (audioDurations.get(timeStampLong) == null) { + player?.reset() + try { + player?.setDataSource(baseMessage.url) + player?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + val duration = player?.duration + audioDurations.put(timeStampLong, duration) + leftReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } else { + val duration = audioDurations.get(timeStampLong) + leftReplyMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } + + } catch (e: Exception) { + e.printStackTrace() + } + + leftReplyMessageHolder.binding.playButton.setOnClickListener { + + if (!TextUtils.isEmpty(baseMessage.url)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying()!!) { + player?.pause() + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow) + } else { + + player?.getCurrentPosition()?.let { player?.seekTo(it) } + player?.getCurrentPosition()?.let { leftReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + leftReplyMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { leftReplyMessageHolder.binding.audioSeekBar.setMax(it) } + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.getCurrentPosition() + pos?.let { leftReplyMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + leftReplyMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler.removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + player?.let { + playAudio(baseMessage.url, timeStampLong, it, leftReplyMessageHolder.binding.playButton, + leftReplyMessageHolder.binding.audioLength, + leftReplyMessageHolder.binding.audioSeekBar) + } + } + + leftReplyMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + + } + } + } + + if (baseMessage.metadata.has("senderUid") + && baseMessage.metadata.getString("senderUid").equals(ownerId)) { + + leftReplyMessageHolder.binding.tvNameReply.text = "You" + } else { + leftReplyMessageHolder.binding.tvNameReply.text = baseMessage.metadata.getString("senderName"); + } + + when { + baseMessage.metadata.getString("type") + .equals(CometChatConstants.MESSAGE_TYPE_TEXT) -> { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = + baseMessage.metadata?.getString("text") + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_VIDEO) -> { + + + Glide.with(context).load(baseMessage.metadata.getString("url")) + .into(leftReplyMessageHolder.binding.ivReplyImage) + + if (baseMessage.metadata.getString("type") == CometChatConstants.MESSAGE_TYPE_IMAGE) { + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Photo" + } else { + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Video" + } + + } + + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_AUDIO) -> { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "Audio Message" + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + + } + + baseMessage.metadata.getString("type").equals(CometChatConstants.MESSAGE_TYPE_FILE) -> { + + leftReplyMessageHolder.binding.tvReplyTextMessage.text = "File Message" + + leftReplyMessageHolder.binding.ivReplyImage.visibility = View.GONE + } + } + } + + setLongClick(leftReplyMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.LEFT_IMAGE_MESSAGE -> { + val leftImageVideoMessageHolder = p0 as LeftImageVideoMessageHolder + leftImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + leftImageVideoMessageHolder.binding.senderName.typeface = StringContract.Font.status + leftImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + leftImageVideoMessageHolder.binding.imageMessage.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(leftImageVideoMessageHolder.binding.imageMessage, baseMessage) + } + + StringContract.ViewType.RIGHT_IMAGE_MESSAGE -> { + val rightImageVideoMessageHolder = p0 as RightImageVideoMessageHolder + rightImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + rightImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightImageVideoMessageHolder.binding.imageMessage.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(rightImageVideoMessageHolder.binding.imageMessage, baseMessage) + + } + + StringContract.ViewType.RIGHT_LOCATION_MESSAGE -> { + val rightLocationViewHolder = p0 as RightLocationViewHolder + rightLocationViewHolder.binding.message = baseMessage as TextMessage + rightLocationViewHolder.binding.timestamp.typeface = StringContract.Font.status + rightLocationViewHolder.bindView(p1, messagesList) + } + + StringContract.ViewType.LEFT_LOCATION_MESSAGE -> { + val leftLocationViewHolder = p0 as LeftLocationViewHolder + leftLocationViewHolder.binding.message = baseMessage as TextMessage + leftLocationViewHolder.binding.timestamp.typeface = StringContract.Font.status + leftLocationViewHolder.bindView(p1, messagesList) + } + + StringContract.ViewType.RIGHT_FILE_MESSAGE -> { + try { + + val rightFileViewHolder = p0 as RightFileViewHolder + rightFileViewHolder.binding.message = baseMessage as MediaMessage + rightFileViewHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.rightMessageColor, PorterDuff.Mode.SRC_ATOP) + rightFileViewHolder.binding.fileName.text = FileUtil.getFileName(mediaFile) + rightFileViewHolder.binding.fileType.text = FileUtil.getFileExtension(mediaFile) + val finalMediaFile = mediaFile + rightFileViewHolder.binding.fileName.typeface = StringContract.Font.name + rightFileViewHolder.binding.fileType.typeface = StringContract.Font.name + rightFileViewHolder.binding.timeStamp.typeface = StringContract.Font.status + rightFileViewHolder.binding.fileName.setOnClickListener(View.OnClickListener { + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(finalMediaFile))) + }) + setLongClick(rightFileViewHolder.binding.root, baseMessage) + } catch (e: Exception) { + e.printStackTrace() + } + + } + + StringContract.ViewType.LEFT_FILE_MESSAGE -> { + + try { + val leftFileViewHolder = p0 as LeftFileViewHolder + leftFileViewHolder.binding.message = baseMessage as MediaMessage + leftFileViewHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.leftMessageColor, PorterDuff.Mode.SRC_ATOP) + leftFileViewHolder.binding.fileName.text = FileUtil.getFileName(mediaFile) + leftFileViewHolder.binding.fileType.text = FileUtil.getFileExtension(mediaFile) + val finalMediaFile = mediaFile + leftFileViewHolder.binding.fileName.typeface = StringContract.Font.name + leftFileViewHolder.binding.fileType.typeface = StringContract.Font.name + leftFileViewHolder.binding.timeStamp.typeface = StringContract.Font.status + leftFileViewHolder.binding.senderName.typeface = StringContract.Font.status + leftFileViewHolder.binding.fileName.setOnClickListener(View.OnClickListener { + context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(finalMediaFile))) + }) + setLongClick(leftFileViewHolder.binding.root, baseMessage) + + } catch (e: Exception) { + e.printStackTrace() + } + + } + + StringContract.ViewType.LEFT_VIDEO_MESSAGE -> { + val leftImageVideoMessageHolder = p0 as LeftImageVideoMessageHolder + leftImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + leftImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + + val requestOptions = RequestOptions() + .fitCenter() + .placeholder(R.drawable.ic_broken_image) + Glide.with(context) + .load(baseMessage.url) + .apply(requestOptions) + .into(leftImageVideoMessageHolder.binding.imageMessage) + + leftImageVideoMessageHolder.binding.btnPlayVideo.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(leftImageVideoMessageHolder.binding.root, baseMessage) + } + + StringContract.ViewType.CALL_MESSAGE -> { + val listHeaderItem = p0 as TextHeaderHolder + listHeaderItem.binding.txtMessageDate.setTextColor(StringContract.Color.black) + + message = "Call " + (baseMessage as Call).callStatus + + listHeaderItem.binding.txtMessageDate.text = message + } + + StringContract.ViewType.RIGHT_VIDEO_MESSAGE -> { + val rightImageVideoMessageHolder = p0 as RightImageVideoMessageHolder + rightImageVideoMessageHolder.binding.message = (baseMessage as MediaMessage) + rightImageVideoMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + + val requestOptions = RequestOptions() + .fitCenter() + .placeholder(R.drawable.ic_broken_image) + Glide.with(context) + .load(baseMessage.url) + .apply(requestOptions) + .into(rightImageVideoMessageHolder.binding.imageMessage) + + rightImageVideoMessageHolder.binding.btnPlayVideo.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + startIntent(baseMessage) + } + + }) + + setLongClick(rightImageVideoMessageHolder.binding.root, baseMessage) + + } + + StringContract.ViewType.RIGHT_AUDIO_MESSAGE -> { + val rightAudioMessageHolder = p0 as RightAudioMessageHolder + rightAudioMessageHolder.binding.message = (baseMessage as MediaMessage) + rightAudioMessageHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.rightMessageColor, PorterDuff.Mode.SRC_ATOP) + rightAudioMessageHolder.binding.audioSeekBar.progress = 0 + rightAudioMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + rightAudioMessageHolder.binding.audioLength.typeface = StringContract.Font.status + setLongClick(rightAudioMessageHolder.binding.root, baseMessage) + try { + + if (audioDurations.get(timeStampLong) == null) { + player?.reset() + try { + player?.setDataSource(filePath) + player?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + val duration = player?.duration + audioDurations.put(timeStampLong, duration) + rightAudioMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } else { + val duration = audioDurations.get(timeStampLong) + rightAudioMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } + + } catch (e: Exception) { + e.printStackTrace() + } + + rightAudioMessageHolder.binding.playButton.setOnClickListener(object : View.OnClickListener { + override fun onClick(v: View?) { + + if (!TextUtils.isEmpty(filePath)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying()!!) { + player?.pause() + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow) + } else { + + player?.currentPosition?.let { player?.seekTo(it) } + player?.currentPosition?.let { rightAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + rightAudioMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { rightAudioMessageHolder.binding.audioSeekBar.setMax(it) } + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.getCurrentPosition() + pos?.let { rightAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + rightAudioMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + player?.let { + playAudio(filePath, timeStampLong, it, rightAudioMessageHolder.binding.playButton, + rightAudioMessageHolder.binding.audioLength, rightAudioMessageHolder.binding.audioSeekBar) + } + } + + rightAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_white_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + }) + + filePath?.let { Log.d("metaData", it) } + + } + + StringContract.ViewType.LEFT_AUDIO_MESSAGE -> { + + val leftAudioMessageHolder = p0 as LeftAudioMessageHolder + leftAudioMessageHolder.binding.message = (baseMessage as MediaMessage) + leftAudioMessageHolder.binding.fileContainer.background.setColorFilter(StringContract.Color.leftMessageColor, PorterDuff.Mode.SRC_ATOP) + leftAudioMessageHolder.binding.audioSeekBar.progress = 0 + leftAudioMessageHolder.binding.audioLength.typeface = StringContract.Font.status + leftAudioMessageHolder.binding.timeStamp.typeface = StringContract.Font.status + setLongClick(leftAudioMessageHolder.itemView, baseMessage) + leftAudioMessageHolder.binding.progress.visibility = View.GONE + + val audioPath: String = FileUtil.getPath(context, CometChatConstants.MESSAGE_TYPE_AUDIO) + + FileUtil.getFileName(baseMessage.url) + + val audioFile = File(audioPath) + + if (audioFile.exists()) { + + leftAudioMessageHolder.binding.progress.visibility = View.GONE + leftAudioMessageHolder.binding.download.visibility = View.GONE + leftAudioMessageHolder.binding.playButton.visibility = View.VISIBLE + + try { + + if (audioDurations.get(timeStampLong) == null) { + player?.reset() + try { + player?.setDataSource(filePath) + player?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + val duration = player?.duration + audioDurations.put(timeStampLong, duration) + leftAudioMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } else { + val duration = audioDurations.get(timeStampLong) + leftAudioMessageHolder.binding.audioLength.setText(duration?.toLong()?.let + { DateUtil.convertTimeStampToDurationTime(it) }) + + } + + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + + leftAudioMessageHolder.binding.progress.visibility = View.GONE + leftAudioMessageHolder.binding.download.visibility = View.VISIBLE + leftAudioMessageHolder.binding.playButton.visibility = View.GONE + + } + + leftAudioMessageHolder.binding.download.setOnClickListener(object : View.OnClickListener { + override fun onClick(v: View?) { + + if (downloadFile?.status == AsyncTask.Status.RUNNING) { + + downloadFile?.cancel(true) + leftAudioMessageHolder.binding.download.setImageResource(R.drawable.ic_file_download) + leftAudioMessageHolder.binding.progress.visibility = View.GONE + leftAudioMessageHolder.binding.playButton.visibility = View.GONE + } else { + + if (CCPermissionHelper.hasPermissions(CometChatPro.applicationContext(), CCPermissionHelper.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE)) { + if (FileUtil.checkDirExistence(context, CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + downloadFile = DownloadFile(CometChatConstants.MESSAGE_TYPE_AUDIO, baseMessage.url, + leftAudioMessageHolder.binding) + + downloadFile?.execute() + + } + } else { + CCPermissionHelper.requestPermissions(context as Activity, + arrayOf(CCPermissionHelper.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE), StringContract.RequestCode.FILE_WRITE) + } + } + } + }) + + + leftAudioMessageHolder.binding.playButton.setOnClickListener(object : View.OnClickListener { + override fun onClick(v: View?) { + + if (!TextUtils.isEmpty(baseMessage.url)) { + + try { + if (baseMessage.sentAt == currentlyPlayingId) { + currentPlayingSong = "" + + try { + if (player?.isPlaying!!) { + player?.pause() + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_play_arrow_black) + } else { + // player.setDataSource(message); + // player.prepare(); + player?.currentPosition?.let { player?.seekTo(it) } + player?.currentPosition?.let { leftAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + leftAudioMessageHolder.binding.audioLength.setText(player?.getDuration()?.toLong()?.let { DateUtil.convertTimeStampToDurationTime(it) }) + player?.getDuration()?.let { leftAudioMessageHolder.binding.audioSeekBar.setMax(it) } + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + timerRunnable = object : Runnable { + override fun run() { + + val pos = player?.currentPosition + pos?.let { leftAudioMessageHolder.binding.audioSeekBar.setProgress(it) } + if (player?.isPlaying()!! && pos!! < player?.getDuration()!!) { + leftAudioMessageHolder.binding.audioLength.setText(DateUtil.convertTimeStampToDurationTime(player?.getCurrentPosition()!!.toLong())) + seekHandler.postDelayed(this, 250) + } else { + seekHandler + .removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + player!!.start() + } + } catch (e: Exception) { + e.printStackTrace() + } + + } else { + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + player?.let { + playAudio(if (audioFile.exists()) audioPath else baseMessage.url, timeStampLong, it, leftAudioMessageHolder.binding.playButton, + leftAudioMessageHolder.binding.audioLength, leftAudioMessageHolder.binding.audioSeekBar, true) + } + } + + leftAudioMessageHolder.binding.playButton.setImageResource(R.drawable.ic_pause_black_24dp) + + } catch (e: Exception) { + e.printStackTrace() + } + } + } + + }) + + filePath?.let { Log.d("metaData", it) } + + } + + } + } + + private fun startIntent(baseMessage: MediaMessage) { + + val imageIntent = Intent(context, ImageViewActivity::class.java) + imageIntent.putExtra(StringContract.IntentString.FILE_TYPE, baseMessage.type); + imageIntent.putExtra(StringContract.IntentString.URL, (baseMessage.url)) + context.startActivity(imageIntent) + + } + + fun playAudio(message: String?, sentTimeStamp: Long, player: MediaPlayer, + playButton: ImageView, audioLength: TextView, audioSeekBar: SeekBar, isLeft: Boolean = false) { + try { + currentPlayingSong = message + currentlyPlayingId = sentTimeStamp + if (timerRunnable != null) { + seekHandler.removeCallbacks(timerRunnable) + timerRunnable = null + } + // setBtnColor(viewtype, playBtn, false); + player.reset() + player.setAudioStreamType(AudioManager.STREAM_MUSIC) + player.setDataSource(currentPlayingSong) + player.prepare() + player.start() + + val duration = player.duration + audioSeekBar.max = duration + timerRunnable = object : Runnable { + override fun run() { + + val pos = player.currentPosition + audioSeekBar.progress = pos + + if (player.isPlaying && pos < duration) { + audioLength.text = DateUtil.convertTimeStampToDurationTime(player.currentPosition.toLong()) + seekHandler.postDelayed(this, 250) + } else { + seekHandler.removeCallbacks(timerRunnable) + timerRunnable = null + } + } + + } + seekHandler.postDelayed(timerRunnable, 100) + notifyDataSetChanged() + + player.setOnCompletionListener { mp -> + currentPlayingSong = "" + currentlyPlayingId = 0L + // setBtnColor(viewtype, playBtn, true); + seekHandler.removeCallbacks(timerRunnable) + timerRunnable = null + mp.stop() + audioLength.text = DateUtil.convertTimeStampToDurationTime(duration.toLong()) + audioSeekBar.progress = 0 + if (isLeft) { + playButton.setImageResource(R.drawable.ic_play_arrow_black) + } else { + playButton.setImageResource(R.drawable.ic_play_arrow) + } + } + + } catch (e: Exception) { + e.printStackTrace() + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Adapter/ViewPagerAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/ViewPagerAdapter.kt new file mode 100755 index 0000000..07f158e --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Adapter/ViewPagerAdapter.kt @@ -0,0 +1,31 @@ +package com.inscripts.cometchatpulse.Adapter + +import android.support.v4.app.Fragment +import android.support.v4.app.FragmentManager +import android.support.v4.app.FragmentPagerAdapter +import java.util.ArrayList + +class ViewPagerAdapter(manager: FragmentManager) : FragmentPagerAdapter(manager) { + + private val mFragmentList = ArrayList() + private val mFragmentTitleList = ArrayList() + + override fun getItem(position: Int): Fragment { + return mFragmentList[position] + + } + + override fun getCount(): Int { + return mFragmentList.size + } + + fun addFragment(fragment: Fragment, title: String) { + mFragmentList.add(fragment) + mFragmentTitleList.add(title) + } + + override fun getPageTitle(position: Int): CharSequence? { + return mFragmentTitleList[position] + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/AsyncTask/DownloadFile.kt b/app/src/main/java/com/inscripts/cometchatpulse/AsyncTask/DownloadFile.kt new file mode 100644 index 0000000..f26da97 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/AsyncTask/DownloadFile.kt @@ -0,0 +1,137 @@ +package com.inscripts.cometchatpulse.AsyncTask + +import android.os.AsyncTask +import android.view.View +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.Utils.FileUtil +import com.inscripts.cometchatpulse.databinding.LeftAudioBinding +import java.io.* +import java.net.HttpURLConnection +import java.net.URL + + +class DownloadFile() : AsyncTask() { + + private lateinit var mediaUrl: String + + private lateinit var leftAudioBinding: LeftAudioBinding + + private lateinit var type: String + + constructor(type: String, mediaUrl: String, leftAudioBinding: LeftAudioBinding) : this() { + this.mediaUrl = mediaUrl + this.leftAudioBinding = leftAudioBinding + this.type = type + } + + override fun onPreExecute() { + super.onPreExecute() + } + + override fun doInBackground(vararg params: String?): String? { + var inputStream: InputStream? = null + var outputStream: OutputStream? = null + var connection: HttpURLConnection? = null + var file: File? = null + try { + var url: URL = URL(mediaUrl) + connection = url.openConnection() as HttpURLConnection + connection.connect() + + if (connection.responseCode != HttpURLConnection.HTTP_OK) { + + return ("Server " + connection.responseCode + + " " + connection.responseMessage) + } + val fileLength = connection.contentLength + + inputStream = connection.inputStream + + + file = File(FileUtil.getPath(CometChatPro.applicationContext(), type) + + FileUtil.getFileName(mediaUrl)) + + outputStream = FileOutputStream(file) + + val data = ByteArray(4096) + + var total: Long = 0 + + var count = 0 + + do { + + count = inputStream.read(data) + + if (count != 1) { + + if (isCancelled) { + inputStream.close() + return null + + } + total += count + + if (fileLength > 0) { + publishProgress((total * 100 / fileLength).toInt()) + outputStream.write(data, 0, count) + } + } else { + break + } + + } while (count != -1) + + } catch (e: Exception) { + e.printStackTrace() + + } finally { + try { + if (outputStream != null) { + outputStream.close() + } + if (inputStream != null) { + inputStream.close() + } + + + } catch (io: IOException) { + + io.printStackTrace() + } + + if (connection != null) { + connection.disconnect() + } + } + return null + } + + override fun onProgressUpdate(vararg values: Int?) { + super.onProgressUpdate(*values) + try { + leftAudioBinding.progress.visibility = View.VISIBLE + leftAudioBinding.progress.max=100 + leftAudioBinding.download.setImageResource(R.drawable.ic_close_24dp) + leftAudioBinding.progress.progress = values[0]!! + leftAudioBinding.playButton.visibility = View.GONE + } catch (e: java.lang.Exception) { + e.printStackTrace() + } + + } + + override fun onPostExecute(result: String?) { + super.onPostExecute(result) + + try { + leftAudioBinding.progress.visibility = View.GONE + leftAudioBinding.download.visibility = View.GONE + leftAudioBinding.playButton.visibility = View.VISIBLE + } catch (e: Exception) { + e.printStackTrace() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CometChatPro.kt b/app/src/main/java/com/inscripts/cometchatpulse/CometChatPro.kt new file mode 100755 index 0000000..36aa7f6 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CometChatPro.kt @@ -0,0 +1,43 @@ +package com.inscripts.cometchatpulse + +import android.app.Application +import android.content.Context +import android.util.Log +import com.cometchat.pro.core.CometChat +import com.cometchat.pro.exceptions.CometChatException +import com.inscripts.cometchatpulse.Utils.Appearance + + +class CometChatPro : Application() { + + private val TAG="CometChatPro" + init { + instance = this + } + + companion object { + private var instance: CometChatPro? = null + + fun applicationContext(): Context { + return instance!!.applicationContext + } + } + + override fun onCreate() { + super.onCreate() + + Appearance(Appearance.AppTheme.PERSIAN_BLUE) + + CometChat.init(applicationContext, StringContract.AppDetails.APP_ID.trim(), object : CometChat.CallbackListener() { + override fun onSuccess(p0: String?) { + Log.d("INIT", "Initialization completed successfully"); + } + + override fun onError(p0: CometChatException?) { + Log.d(TAG,"onError: "+p0?.message) + } + }) + + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CustomBinder/CustomBinder.kt b/app/src/main/java/com/inscripts/cometchatpulse/CustomBinder/CustomBinder.kt new file mode 100755 index 0000000..92faee4 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CustomBinder/CustomBinder.kt @@ -0,0 +1,204 @@ +package com.inscripts.cometchatpulse.CustomBinder + +import android.annotation.SuppressLint +import android.content.Context +import android.databinding.BindingAdapter +import android.graphics.PorterDuff +import android.graphics.Typeface +import android.graphics.drawable.Drawable +import android.support.v4.content.ContextCompat +import android.support.v7.widget.Toolbar +import android.util.Log +import android.widget.ImageView +import android.widget.MediaController +import android.widget.TextView +import android.widget.VideoView +import com.bumptech.glide.Glide +import com.bumptech.glide.request.RequestOptions +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.helpers.Logger +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.CustomView.CircleImageView +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.DateUtil +import com.inscripts.cometchatpulse.Utils.MediaUtil +import java.sql.Timestamp + +@BindingAdapter(value = ["setTimeStamp"]) +fun setTimeStamp(timeView: TextView, timeLong: Long) { + + val dt = java.util.Date(timeLong * 1000) + val time = Timestamp(dt.getTime()) + Logger.debug("timestamp", time.toString() + "rime" + dt.getDate() + " inside") + val str = DateUtil.getMessageTime(time.toString(), "hh:mm a") + timeView.setText(str) +} + + +@BindingAdapter(value = ["setDeliveryStatus"]) +fun setDeliveryStatus(deliveryStatusView: CircleImageView, deliveryStatus: Int) { + + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + deliveryStatusView.circleBackgroundColor = StringContract.Color.iconTint + } else { + deliveryStatusView.circleBackgroundColor = StringContract.Color.primaryColor + } + + if (deliveryStatus == 0) { + deliveryStatusView.setImageDrawable(ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.ic_access_time_24dp)) + } else if (deliveryStatus == 1) { + deliveryStatusView.setImageDrawable(ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.ic_check_24dp)) + } + +} + + + +@BindingAdapter(value = ["setVideoMessage", "setContext"]) +fun setVideoMessage(videoVideoView: VideoView, url: String, context: Context) { + videoVideoView.setVideoPath(url) + videoVideoView.setMediaController(MediaController(context)) + videoVideoView.keepScreenOn = true + videoVideoView.start() +} + +@BindingAdapter(value = ["setOptionImage"]) +fun setOptionImage(ivOption: CircleImageView,drawable: Drawable) { + + try { + drawable.setColorFilter(StringContract.Color.white, PorterDuff.Mode.SRC_ATOP) + ivOption.setImageBitmap(MediaUtil.getPlaceholderImage(CometChatPro.applicationContext(),drawable)) + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + ivOption.circleBackgroundColor = StringContract.Color.primaryDarkColor + } else { + ivOption.circleBackgroundColor = StringContract.Color.primaryColor + } + + } catch (e: Exception) { + e.printStackTrace() + } + + +} + +@BindingAdapter(value = ["setGroupIcon"]) +fun setGroupIcon(view: CircleImageView, groupIcon: String?) { + val default: Drawable = ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.ic_group_default)!! + view.circleBackgroundColor = StringContract.Color.primaryColor + if (groupIcon != null) { + val requestOptions = RequestOptions() + requestOptions.placeholder(default) + Glide.with(CometChatPro.applicationContext()).applyDefaultRequestOptions(requestOptions) + .load(groupIcon).into(view) + } else { + try { + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + default.setColorFilter(StringContract.Color.primaryDarkColor, PorterDuff.Mode.SRC_ATOP) + } + view.setImageBitmap(MediaUtil.getPlaceholderImage(CometChatPro.applicationContext(), default)) + } catch (e: Exception) { + view.setImageBitmap(MediaUtil.getPlaceholderImage(CometChatPro.applicationContext(), default)) + } + } +} + +@BindingAdapter(value = ["setStatus", "setLastActive"]) +fun setStatus(tvStatus: TextView, status: String, lastActive: Long?) { + + if (status.equals(CometChatConstants.USER_STATUS_ONLINE, ignoreCase = true)) { + tvStatus.text = status + } else if (status.equals(CometChatConstants.USER_STATUS_OFFLINE, ignoreCase = true)) { + if (lastActive != null) { + tvStatus.text = DateUtil.getLastSeenDate(lastActive, CometChatPro.applicationContext()) + } else { + tvStatus.text = status + } + + } +} + +@BindingAdapter(value = ["setStatusIcon"]) +fun setStatusIcon(ivStatus: ImageView, status: String) { + + val statusDrawable: Drawable + + if (status.equals(CometChatConstants.USER_STATUS_ONLINE, ignoreCase = true)) { + statusDrawable = ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.cc_status_available)!! + } else { + statusDrawable = ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.cc_status_offline)!! + } + + ivStatus.setImageDrawable(statusDrawable) +} + +@SuppressLint("CheckResult") +@BindingAdapter(value = ["setImage"]) +fun setImage(imageView: ImageView, url: String?) { + + try { + if (url != null) { + Log.d("corner", "called") + val requestOptions = RequestOptions() + requestOptions.placeholder(ContextCompat.getDrawable(CometChatPro.applicationContext(), + R.drawable.ic_broken_image_black)) + requestOptions.centerCrop() + Glide.with(CometChatPro.applicationContext()) + .applyDefaultRequestOptions(requestOptions) + .load(url) + .into(imageView) + } + + + } catch (e: Exception) { + e.printStackTrace() + } + +} + +@BindingAdapter(value = ["groupDetailIcon"]) +fun setGroupDeatail(view: ImageView, url: String?) { + val default: Drawable = ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.ic_group_default)!! + try { + if (url != null) { + + val requestOptions = RequestOptions() + requestOptions.placeholder(default) + Glide.with(CometChatPro.applicationContext()).applyDefaultRequestOptions(requestOptions) + .load(url).into(view) + } + } catch (e: Exception) { + e.printStackTrace() + } +} + +@SuppressLint("CheckResult") +@BindingAdapter(value = ["setUserImage"]) +fun setImage(view: CircleImageView, avatar: String?) { + + val default: Drawable = ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.default_avatar)!! + if (avatar != null) { + val requestOptions = RequestOptions() + requestOptions.placeholder(default) + Glide.with(CometChatPro.applicationContext()).applyDefaultRequestOptions(requestOptions) + .load(avatar).into(view) + } else { + + try { + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + default.setColorFilter(StringContract.Color.primaryDarkColor, PorterDuff.Mode.SRC_ATOP) + } + view.circleBackgroundColor = StringContract.Color.primaryColor + view.setImageBitmap(MediaUtil.getPlaceholderImage(CometChatPro.applicationContext(), default)) + } catch (e: Exception) { + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + default.setColorFilter(StringContract.Color.primaryDarkColor, PorterDuff.Mode.SRC_ATOP) + } + view.circleBackgroundColor = StringContract.Color.primaryColor + view.setImageDrawable(ContextCompat.getDrawable(CometChatPro.applicationContext(), R.drawable.default_avatar)) + e.printStackTrace() + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CustomView/AttachmentTypeSelector.kt b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/AttachmentTypeSelector.kt new file mode 100755 index 0000000..3cdf258 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/AttachmentTypeSelector.kt @@ -0,0 +1,282 @@ +package com.inscripts.cometchatpulse.CustomView + +import android.animation.Animator +import android.annotation.TargetApi +import android.app.Activity +import android.content.Context +import android.graphics.PorterDuff +import android.graphics.Rect +import android.graphics.drawable.BitmapDrawable +import android.os.Build +import android.support.annotation.RequiresApi +import android.support.v4.content.ContextCompat +import android.view.* +import android.view.animation.* +import android.widget.LinearLayout +import android.widget.PopupWindow +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.StringContract.RequestCode.Companion.ADD_DOCUMENT +import com.inscripts.cometchatpulse.StringContract.RequestCode.Companion.ADD_GALLERY +import com.inscripts.cometchatpulse.StringContract.RequestCode.Companion.ADD_SOUND +import com.inscripts.cometchatpulse.StringContract.RequestCode.Companion.LOCATION +import com.inscripts.cometchatpulse.StringContract.RequestCode.Companion.TAKE_PHOTO +import com.inscripts.cometchatpulse.StringContract.RequestCode.Companion.TAKE_VIDEO +import com.inscripts.cometchatpulse.Utils.AnimUtil +import com.inscripts.cometchatpulse.Utils.Appearance +//import com.inscripts.cometchatpulse.R +//import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.Utils.MediaUtil + +class AttachmentTypeSelector(context: Context, private var listener: AttachmentClickedListener?) : PopupWindow() { +// + private val ANIMATION_DURATION = 300 + + private val TAG = AttachmentTypeSelector::class.java.simpleName + + private var imageButton: CircleImageView + + private var audioButton: CircleImageView + private var documentButton: CircleImageView + + private var cameraButton: CircleImageView + private var locationButton: CircleImageView + private var videoButton: CircleImageView + + + private var currentAnchor: View? = null + private var rect: Rect? = null + private var winHeight: Int = 0 + + init { + val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + val layout = inflater.inflate(R.layout.attachment_type_selector, null, true) as LinearLayout + + this.imageButton = CommonUtil.findById(layout, R.id.gallery_button) as CircleImageView + this.audioButton = CommonUtil.findById(layout, R.id.audio_button) as CircleImageView + this.documentButton = CommonUtil.findById(layout, R.id.document_button) as CircleImageView + this.cameraButton = CommonUtil.findById(layout, R.id.camera_button) as CircleImageView + this.locationButton = CommonUtil.findById(layout, R.id.close_button) as CircleImageView + this.videoButton = CommonUtil.findById(layout, R.id.video) as CircleImageView + + var color:Int? + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) + { + color=StringContract.Color.iconTint + } + else{ + color=StringContract.Color.primaryColor + } + + val imageDrawable = ContextCompat.getDrawable(context,R.drawable.ic_outline_image_24px) + val cameraDrawable = ContextCompat.getDrawable(context,R.drawable.ic_outline_add_a_photo_24px) + val audioDrawable = ContextCompat.getDrawable(context,R.drawable.ic_mic_24dp) + val videoDrawable = ContextCompat.getDrawable(context,R.drawable.ic_outline_videocam_24px) + val documentDrawable = ContextCompat.getDrawable(context,R.drawable.ic_outline_insert_drive_file_24px) + val locationDrawable = ContextCompat.getDrawable(context,R.drawable.ic_location_on_black_24dp) + + imageDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) + cameraDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) + audioDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) + videoDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) + documentDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) + locationDrawable?.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) + + this.imageButton.setImageBitmap(imageDrawable?.let { MediaUtil.getPlaceholderImage(context, it) }) + this.audioButton.setImageBitmap(audioDrawable?.let { MediaUtil.getPlaceholderImage(context, it) }) + this.documentButton.setImageBitmap(documentDrawable?.let { MediaUtil.getPlaceholderImage(context, it) }) + this.locationButton.setImageBitmap(locationDrawable?.let { MediaUtil.getPlaceholderImage(context, it) }) + this.cameraButton.setImageBitmap(cameraDrawable?.let { MediaUtil.getPlaceholderImage(context, it) }) + this.videoButton.setImageBitmap(videoDrawable?.let { MediaUtil.getPlaceholderImage(context, it) }) + + this.imageButton.setOnClickListener(PropagatingClickListener(ADD_GALLERY)) + this.audioButton.setOnClickListener(PropagatingClickListener(ADD_SOUND)) + this.documentButton.setOnClickListener(PropagatingClickListener(ADD_DOCUMENT)) + this.cameraButton.setOnClickListener(PropagatingClickListener(TAKE_PHOTO)) + this.videoButton.setOnClickListener(PropagatingClickListener(TAKE_VIDEO)) + this.locationButton.setOnClickListener(PropagatingClickListener(LOCATION)) + + + this.imageButton.borderColor=color + this.audioButton.borderColor=color + this.documentButton.borderColor=color + this.cameraButton.borderColor=color + this.videoButton.borderColor=color + this.locationButton.borderColor=color + + + + + contentView = layout + width = LinearLayout.LayoutParams.MATCH_PARENT + height = LinearLayout.LayoutParams.WRAP_CONTENT + setBackgroundDrawable(BitmapDrawable()) + animationStyle = 0 + isClippingEnabled = false + inputMethodMode = PopupWindow.INPUT_METHOD_NOT_NEEDED + isFocusable = true + isTouchable = true + } + + + + fun show(activity: Activity, anchor: View) { + + val y: Int +// if (KeyboardVisibilityEvent.isKeyboardVisible(activity)) { +// y = 0 +// val imm = activity.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager +// //Find the currently focused view, so we can grab the correct window token from it. +// imm.hideSoftInputFromWindow(activity.currentFocus!!.windowToken, 0) +// } else { +// rect = Rect() +// activity.window.decorView.getWindowVisibleDisplayFrame(rect) +// winHeight = activity.window.decorView.height +// y = winHeight - rect!!.bottom +// } + + rect = Rect() + activity.window.decorView.getWindowVisibleDisplayFrame(rect) + winHeight = activity.window.decorView.height + y = winHeight - rect!!.bottom + + + this.currentAnchor = anchor + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + isAttachedInDecor=false + } + + showAtLocation(anchor, Gravity.BOTTOM, 0,y) + + + contentView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + contentView.viewTreeObserver.removeOnGlobalLayoutListener(this) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + animateWindowInCircular(anchor, contentView) + } else { + animateWindowInTranslate(contentView) + } + } + }) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + animateButtonIn(imageButton, ANIMATION_DURATION / 2) + animateButtonIn(cameraButton, ANIMATION_DURATION / 2) + animateButtonIn(audioButton, ANIMATION_DURATION / 3) + animateButtonIn(videoButton, ANIMATION_DURATION / 3) + animateButtonIn(documentButton, ANIMATION_DURATION / 4) + animateButtonIn(locationButton, 0) + } + } + + override fun dismiss() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + animateWindowOutCircular(currentAnchor, contentView) + } else { + animateWindowOutTranslate(contentView) + } + } + + fun setListener(listener: AttachmentClickedListener?) { + this.listener = listener + } + + private fun animateButtonIn(button: View, delay: Int) { + val animation = AnimationSet(true) + val scale = ScaleAnimation(0.0f, 1.0f, 0.0f, 1.0f, + Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.0f) + + animation.addAnimation(scale) + animation.interpolator = OvershootInterpolator(1f) + animation.duration = ANIMATION_DURATION.toLong() + animation.startOffset = delay.toLong() + button.startAnimation(animation) + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private fun animateWindowInCircular(anchor: View?, contentView: View) { + val coordinates = AnimUtil.getClickOrigin(anchor, contentView) + val animator = ViewAnimationUtils.createCircularReveal(contentView, + coordinates.first, + coordinates.second, + 0f, + Math.max(contentView.width, contentView.height).toFloat()) + animator.duration = ANIMATION_DURATION.toLong() + animator.start() + } + + private fun animateWindowInTranslate(contentView: View) { + val animation = TranslateAnimation(0f, 0f, contentView.height.toFloat(), 0f) + animation.duration = ANIMATION_DURATION.toLong() + + getContentView().startAnimation(animation) + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + private fun animateWindowOutCircular(anchor: View?, contentView: View) { + val coordinates = AnimUtil.getClickOrigin(anchor, contentView) + val animator = ViewAnimationUtils.createCircularReveal(getContentView(), + coordinates.first, + coordinates.second, + Math.max(getContentView().width, getContentView().height).toFloat(), + 0f) + + animator.duration = ANIMATION_DURATION.toLong() + animator.addListener(object : Animator.AnimatorListener { + override fun onAnimationStart(animation: Animator) {} + + override fun onAnimationEnd(animation: Animator) { + super@AttachmentTypeSelector.dismiss() + } + + override fun onAnimationCancel(animation: Animator) {} + + override fun onAnimationRepeat(animation: Animator) {} + }) + + animator.start() + } + + private fun animateWindowOutTranslate(contentView: View) { + val animation = TranslateAnimation(0f, 0f, 0f, (contentView.top + contentView.height).toFloat()) + animation.duration = ANIMATION_DURATION.toLong() + animation.setAnimationListener(object : Animation.AnimationListener { + override fun onAnimationStart(animation: Animation) {} + + override fun onAnimationEnd(animation: Animation) { + super@AttachmentTypeSelector.dismiss() + } + + override fun onAnimationRepeat(animation: Animation) {} + }) + + getContentView().startAnimation(animation) + } + + + private inner class PropagatingClickListener (private val type: Int) : View.OnClickListener { + + override fun onClick(v: View) { + animateWindowOutTranslate(contentView) + + if (listener != null) listener!!.onClick(type) + } + + } + + private inner class CloseClickListener : View.OnClickListener { + override fun onClick(v: View) { + dismiss() + } + } + + interface AttachmentClickedListener { + fun onClick(type: Int) + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CustomView/CircleImageView.java b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/CircleImageView.java new file mode 100755 index 0000000..18cc3d1 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/CircleImageView.java @@ -0,0 +1,477 @@ +package com.inscripts.cometchatpulse.CustomView; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.ColorFilter; +import android.graphics.Matrix; +import android.graphics.Outline; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.net.Uri; +import android.os.Build; +import android.support.annotation.ColorInt; +import android.support.annotation.ColorRes; +import android.support.annotation.DrawableRes; +import android.support.annotation.RequiresApi; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewOutlineProvider; +import android.widget.ImageView; + +import com.inscripts.cometchatpulse.R; + +public class CircleImageView extends ImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 2; + + private static final int DEFAULT_BORDER_WIDTH = 0; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + private static final int DEFAULT_CIRCLE_BACKGROUND_COLOR = Color.TRANSPARENT; + private static final boolean DEFAULT_BORDER_OVERLAY = false; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + private final Paint mCircleBackgroundPaint = new Paint(); + + private int mBorderColor = DEFAULT_BORDER_COLOR; + private int mBorderWidth = DEFAULT_BORDER_WIDTH; + private int mCircleBackgroundColor = DEFAULT_CIRCLE_BACKGROUND_COLOR; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private ColorFilter mColorFilter; + + private boolean mReady; + private boolean mSetupPending; + private boolean mBorderOverlay; + private boolean mDisableCircularTransformation; + + public CircleImageView(Context context) { + super(context); + + init(); + } + + public CircleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); + + mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_civ_border_width, DEFAULT_BORDER_WIDTH); + mBorderColor = a.getColor(R.styleable.CircleImageView_civ_border_color, DEFAULT_BORDER_COLOR); + mBorderOverlay = a.getBoolean(R.styleable.CircleImageView_civ_border_overlay, DEFAULT_BORDER_OVERLAY); + + // Look for deprecated civ_fill_color if civ_circle_background_color is not set + if (a.hasValue(R.styleable.CircleImageView_civ_circle_background_color)) { + mCircleBackgroundColor = a.getColor(R.styleable.CircleImageView_civ_circle_background_color, + DEFAULT_CIRCLE_BACKGROUND_COLOR); + } else if (a.hasValue(R.styleable.CircleImageView_civ_fill_color)) { + mCircleBackgroundColor = a.getColor(R.styleable.CircleImageView_civ_fill_color, + DEFAULT_CIRCLE_BACKGROUND_COLOR); + } + + a.recycle(); + + init(); + } + + private void init() { + super.setScaleType(SCALE_TYPE); + mReady = true; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + setOutlineProvider(new OutlineProvider()); + } + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); + } + } + + @Override + public void setAdjustViewBounds(boolean adjustViewBounds) { + if (adjustViewBounds) { + throw new IllegalArgumentException("adjustViewBounds not supported."); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (mDisableCircularTransformation) { + super.onDraw(canvas); + return; + } + + if (mBitmap == null) { + return; + } + + if (mCircleBackgroundColor != Color.TRANSPARENT) { + canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mCircleBackgroundPaint); + } + canvas.drawCircle(mDrawableRect.centerX(), mDrawableRect.centerY(), mDrawableRadius, mBitmapPaint); + if (mBorderWidth > 0) { + canvas.drawCircle(mBorderRect.centerX(), mBorderRect.centerY(), mBorderRadius, mBorderPaint); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + @Override + public void setPadding(int left, int top, int right, int bottom) { + super.setPadding(left, top, right, bottom); + setup(); + } + + @Override + public void setPaddingRelative(int start, int top, int end, int bottom) { + super.setPaddingRelative(start, top, end, bottom); + setup(); + } + + public int getBorderColor() { + return mBorderColor; + } + + public void setBorderColor(@ColorInt int borderColor) { + if (borderColor == mBorderColor) { + return; + } + + mBorderColor = borderColor; + mBorderPaint.setColor(mBorderColor); + invalidate(); + } + + /** + * @deprecated Use {@link #setBorderColor(int)} instead + */ + @Deprecated + public void setBorderColorResource(@ColorRes int borderColorRes) { + setBorderColor(getContext().getResources().getColor(borderColorRes)); + } + + public int getCircleBackgroundColor() { + return mCircleBackgroundColor; + } + + public void setCircleBackgroundColor(@ColorInt int circleBackgroundColor) { + if (circleBackgroundColor == mCircleBackgroundColor) { + return; + } + + mCircleBackgroundColor = circleBackgroundColor; + mCircleBackgroundPaint.setColor(circleBackgroundColor); + invalidate(); + } + + public void setCircleBackgroundColorResource(@ColorRes int circleBackgroundRes) { + setCircleBackgroundColor(getContext().getResources().getColor(circleBackgroundRes)); + } + + /** + * Return the color drawn behind the circle-shaped drawable. + * + * @return The color drawn behind the drawable + * + * @deprecated Use {@link #getCircleBackgroundColor()} instead. + */ + @Deprecated + public int getFillColor() { + return getCircleBackgroundColor(); + } + + /** + * Set a color to be drawn behind the circle-shaped drawable. Note that + * this has no effect if the drawable is opaque or no drawable is set. + * + * @param fillColor The color to be drawn behind the drawable + * + * @deprecated Use {@link #setCircleBackgroundColor(int)} instead. + */ + @Deprecated + public void setFillColor(@ColorInt int fillColor) { + setCircleBackgroundColor(fillColor); + } + + /** + * Set a color to be drawn behind the circle-shaped drawable. Note that + * this has no effect if the drawable is opaque or no drawable is set. + * + * @param fillColorRes The color resource to be resolved to a color and + * drawn behind the drawable + * + * @deprecated Use {@link #setCircleBackgroundColorResource(int)} instead. + */ + @Deprecated + public void setFillColorResource(@ColorRes int fillColorRes) { + setCircleBackgroundColorResource(fillColorRes); + } + + public int getBorderWidth() { + return mBorderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth == mBorderWidth) { + return; + } + + mBorderWidth = borderWidth; + setup(); + } + + public boolean isBorderOverlay() { + return mBorderOverlay; + } + + public void setBorderOverlay(boolean borderOverlay) { + if (borderOverlay == mBorderOverlay) { + return; + } + + mBorderOverlay = borderOverlay; + setup(); + } + + public boolean isDisableCircularTransformation() { + return mDisableCircularTransformation; + } + + public void setDisableCircularTransformation(boolean disableCircularTransformation) { + if (mDisableCircularTransformation == disableCircularTransformation) { + return; + } + + mDisableCircularTransformation = disableCircularTransformation; + initializeBitmap(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + initializeBitmap(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + initializeBitmap(); + } + + @Override + public void setImageResource(@DrawableRes int resId) { + super.setImageResource(resId); + initializeBitmap(); + } + + @Override + public void setImageURI(Uri uri) { + super.setImageURI(uri); + initializeBitmap(); + } + + @Override + public void setColorFilter(ColorFilter cf) { + if (cf == mColorFilter) { + return; + } + + mColorFilter = cf; + applyColorFilter(); + invalidate(); + } + + @Override + public ColorFilter getColorFilter() { + return mColorFilter; + } + + private void applyColorFilter() { + if (mBitmapPaint != null) { + mBitmapPaint.setColorFilter(mColorFilter); + } + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private void initializeBitmap() { + if (mDisableCircularTransformation) { + mBitmap = null; + } else { + mBitmap = getBitmapFromDrawable(getDrawable()); + } + setup(); + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (getWidth() == 0 && getHeight() == 0) { + return; + } + + if (mBitmap == null) { + invalidate(); + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + mBorderPaint.setColor(mBorderColor); + mBorderPaint.setStrokeWidth(mBorderWidth); + + mCircleBackgroundPaint.setStyle(Paint.Style.FILL); + mCircleBackgroundPaint.setAntiAlias(true); + mCircleBackgroundPaint.setColor(mCircleBackgroundColor); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(calculateBounds()); + mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2.0f, (mBorderRect.width() - mBorderWidth) / 2.0f); + + mDrawableRect.set(mBorderRect); + if (!mBorderOverlay && mBorderWidth > 0) { + mDrawableRect.inset(mBorderWidth - 1.0f, mBorderWidth - 1.0f); + } + mDrawableRadius = Math.min(mDrawableRect.height() / 2.0f, mDrawableRect.width() / 2.0f); + + applyColorFilter(); + updateShaderMatrix(); + invalidate(); + } + + private RectF calculateBounds() { + int availableWidth = getWidth() - getPaddingLeft() - getPaddingRight(); + int availableHeight = getHeight() - getPaddingTop() - getPaddingBottom(); + + int sideLength = Math.min(availableWidth, availableHeight); + + float left = getPaddingLeft() + (availableWidth - sideLength) / 2f; + float top = getPaddingTop() + (availableHeight - sideLength) / 2f; + + return new RectF(left, top, left + sideLength, top + sideLength); + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) + mDrawableRect.left, (int) (dy + 0.5f) + mDrawableRect.top); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return inTouchableArea(event.getX(), event.getY()) && super.onTouchEvent(event); + } + + private boolean inTouchableArea(float x, float y) { + return Math.pow(x - mBorderRect.centerX(), 2) + Math.pow(y - mBorderRect.centerY(), 2) <= Math.pow(mBorderRadius, 2); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private class OutlineProvider extends ViewOutlineProvider { + + @Override + public void getOutline(View view, Outline outline) { + Rect bounds = new Rect(); + mBorderRect.roundOut(bounds); + outline.setRoundRect(bounds, bounds.width() / 2.0f); + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CustomView/RecordAudio.kt b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/RecordAudio.kt new file mode 100755 index 0000000..f47e1ac --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/RecordAudio.kt @@ -0,0 +1,392 @@ +package com.inscripts.cometchatpulse.CustomView + +import android.app.Activity +import android.content.Context +import android.graphics.PorterDuff +import android.media.MediaPlayer +import android.os.SystemClock +import android.support.v7.content.res.AppCompatResources +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.widget.* +import com.inscripts.cometchatpulse.Helpers.CCPermissionHelper +import com.inscripts.cometchatpulse.Helpers.RecordListener +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.AnimUtil +import com.inscripts.cometchatpulse.Utils.CommonUtil +import java.io.IOException + +class RecordAudio : RelativeLayout { + + private var recordMic: ImageView? = null + + private var counterTime: Chronometer? = null + + private var slideToCancel: TextView? = null + + private var arrow: ImageView? = null + + private var initialX: Float = 0.toFloat() + private var difX = 0f + + private var cancelOffset = DEFAULT_CANCEL_OFFSET.toFloat() + + private var startTime: Long = 0 + private var elapsedTime: Long = 0 + + private var recordListener: RecordListener? = null + + private var isSwiped: Boolean = false + private var isLessThanSecondAllowed = false + + private var isSoundEnabled = true + + private var RECORD_START = R.raw.record_start + + private var RECORD_FINISHED = R.raw.record_finished + + private var RECORD_ERROR = R.raw.record_error + + private var player: MediaPlayer? = null + + private val animUtil: AnimUtil? = null + + private var slideToCancelLayout: FrameLayout? = null + + + constructor(context: Context) : super(context) { + initViewComponent(context, null, -1, -1) + } + + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + + initViewComponent(context, attrs, -1, -1) + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + + initViewComponent(context, attrs, defStyleAttr, -1) + } + + private fun initViewComponent(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) { + val view = View.inflate(context, R.layout.record_audio, null) + addView(view) + + val viewGroup = view.parent as ViewGroup + viewGroup.clipChildren = false + + arrow = view.findViewById(R.id.left_arrow) + slideToCancel = view.findViewById(R.id.slide_to_cancel_text) + counterTime = view.findViewById(R.id.record_time) + recordMic = view.findViewById(R.id.record_mic) + slideToCancelLayout = view.findViewById(R.id.slide_to_cancel_Layout) + + recordMic?.drawable?.setColorFilter(StringContract.Color.primaryColor,PorterDuff.Mode.SRC_ATOP) + arrow?.drawable?.setColorFilter(StringContract.Color.primaryColor,PorterDuff.Mode.SRC_ATOP) + + hideViews(true) + + + if (attrs != null && defStyleAttr == -1 && defStyleRes == -1) { + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordAudio, + defStyleAttr, defStyleRes) + + val slideArrowResource = typedArray.getResourceId(R.styleable.RecordAudio_slide_to_cancel_arrow, -1) + val slideToCancelText = typedArray.getString(R.styleable.RecordAudio_slide_to_cancel_text) + val slideMarginRight = typedArray.getDimension(R.styleable.RecordAudio_slide_to_cancel_margin_right, 30f).toInt() + val counterTimeColor = typedArray.getColor(R.styleable.RecordAudio_counter_time_color, -1) + val arrowColor = typedArray.getColor(R.styleable.RecordAudio_slide_to_cancel_arrow_color, -1) + + + val cancelBounds = typedArray.getDimensionPixelSize(R.styleable.RecordAudio_slide_to_cancel_bounds, -1) + + if (cancelBounds != -1) + setCancelOffset(cancelBounds.toFloat(), false) + + + if (slideArrowResource != -1) { + val slideArrow = AppCompatResources.getDrawable(getContext(), slideArrowResource) + arrow!!.setImageDrawable(slideArrow) + } + + if (slideToCancelText != null) + slideToCancel!!.text = slideToCancelText + + if (counterTimeColor != -1) + setCounterTimeColor(counterTimeColor) + + + if (arrowColor != -1) + setSlideToCancelArrowColor(arrowColor) + + + + setMarginRight(slideMarginRight, true) + + typedArray.recycle() + } + + } + + + private fun hideViews(hideSmallMic: Boolean) { + slideToCancelLayout!!.visibility = View.GONE + counterTime!!.visibility = View.GONE + if (hideSmallMic) + recordMic!!.visibility = View.GONE + } + + private fun showViews() { + slideToCancelLayout!!.visibility = View.VISIBLE + recordMic!!.visibility = View.VISIBLE + counterTime!!.visibility = View.VISIBLE + } + + + private fun isLessThanOneSecond(time: Long): Boolean { + return time <= 1000 + } + + + private fun playSound(soundRes: Int) { + + if (isSoundEnabled) { + if (soundRes == 0) + return + + try { + player = MediaPlayer() + val afd = context!!.resources.openRawResourceFd(soundRes) ?: return + player!!.setDataSource(afd.fileDescriptor, afd.startOffset, afd.length) + afd.close() + player!!.prepare() + player!!.start() + player!!.setOnCompletionListener { mp -> mp.release() } + player!!.isLooping = false + } catch (e: IOException) { + e.printStackTrace() + } + + } + + + } + + + fun onActionDown(recordMicButton: RecordMicButton, context: Context) { + + if (recordListener != null) { + if (CCPermissionHelper.hasPermissions(context, *StringContract.RequestPermission.RECORD_PERMISSION)) { + recordListener!!.onRecordStart() + } else { + CCPermissionHelper.requestPermissions(context as Activity, StringContract.RequestPermission.RECORD_PERMISSION, + StringContract.RequestCode.RECORD_CODE) + } + } + + AnimUtil.setStartRecorded(true) + AnimUtil.resetSmallMic(recordMic!!) + + + recordMicButton.startScale() + + initialX = recordMicButton.getX() + + playSound(RECORD_START) + + showViews() + + AnimUtil.animateMic(recordMic!!) + + counterTime!!.base = SystemClock.elapsedRealtime() + + startTime = System.currentTimeMillis() + + counterTime!!.start() + isSwiped = false + + } + + + fun onActionMove(recordMicButton: RecordMicButton, motionEvent: MotionEvent) { + + + val time = System.currentTimeMillis() - startTime + + if (!isSwiped) { + + //Swipe To Cancel + val slideX = slideToCancelLayout!!.x + val right = counterTime!!.right + + if (slideX != 0f && slideX <= right + cancelOffset) { + + //if the time was less than one second then do not start basket animation + if (isLessThanOneSecond(time)) { + hideViews(true) + recordMic?.let { AnimUtil.clearAlphaAnimation(false, it) } + + } else { + hideViews(true) + recordMic?.let { AnimUtil.clearAlphaAnimation(true, it) } + } + + AnimUtil.moveSlideToCancel(recordMicButton, slideToCancelLayout!!, initialX, difX) + counterTime!!.stop() + isSwiped = true + + AnimUtil.setStartRecorded(false) + if (recordListener != null) { + + recordListener!!.onRecordCancel() + } + + + } else { + + if (motionEvent.getRawX() < initialX) { + recordMicButton.animate() + .x(motionEvent.getRawX()) + .setDuration(0) + .start() + + if (difX == 0f) + difX = initialX - slideToCancelLayout!!.x + + + slideToCancelLayout!!.animate() + .x(motionEvent.getRawX() - difX) + .setDuration(0) + .start() + + } + + + } + + } + } + + fun onActionUp(recordMicButton: RecordMicButton) { + + elapsedTime = System.currentTimeMillis() - startTime + + if (!isLessThanSecondAllowed && isLessThanOneSecond(elapsedTime) && !isSwiped) { + if (recordListener != null) + recordListener!!.onRecordLessTime() + AnimUtil.setStartRecorded(false) + playSound(RECORD_ERROR) + + + } else { + if (recordListener != null && !isSwiped) + recordListener!!.onRecordFinish(elapsedTime) + + AnimUtil.setStartRecorded(false) + + if (!isSwiped) + playSound(RECORD_FINISHED) + + } + + + //if user has swiped then do not hide SmallMic since it will be hidden after swipe Animation + hideViews(!isSwiped) + + + if (!isSwiped) + recordMic?.let { AnimUtil.clearAlphaAnimation(true, it) } + + slideToCancelLayout?.let { AnimUtil.moveSlideToCancel(recordMicButton, it, initialX, difX) } + counterTime!!.stop() + + + } + + + private fun setMarginRight(marginRight: Int, convertToDp: Boolean) { + val layoutParams = slideToCancelLayout!!.layoutParams as RelativeLayout.LayoutParams + if (convertToDp) { + layoutParams.rightMargin = CommonUtil.dpToPx(context, marginRight.toFloat()).toInt() + } else + layoutParams.rightMargin = marginRight + + slideToCancelLayout!!.layoutParams = layoutParams + } + + + fun setOnRecordListener(recrodListener: RecordListener) { + this.recordListener = recrodListener + } + + + fun setSoundEnabled(isEnabled: Boolean) { + isSoundEnabled = isEnabled + } + + fun setLessThanSecondAllowed(isAllowed: Boolean) { + isLessThanSecondAllowed = isAllowed + } + + fun setSlideToCancelText(text: String) { + slideToCancel!!.text = text + } + + fun setSlideToCancelTextColor(color: Int) { + slideToCancel!!.setTextColor(color) + } + + fun setSmallMicColor(color: Int) { + recordMic!!.setColorFilter(color) + } + + fun setSmallMicIcon(icon: Int) { + recordMic!!.setImageResource(icon) + } + + fun setSlideMarginRight(marginRight: Int) { + setMarginRight(marginRight, true) + } + + + fun setCustomSounds(startSound: Int, finishedSound: Int, errorSound: Int) { + //0 means do not play sound + RECORD_START = startSound + RECORD_FINISHED = finishedSound + RECORD_ERROR = errorSound + } + + fun getCancelOffset(): Float { + return cancelOffset + } + + fun setCancelOffset(cancelBounds: Float) { + setCancelOffset(cancelBounds, true) + } + + //set Chronometer color + fun setCounterTimeColor(color: Int) { + counterTime!!.setTextColor(color) + } + + fun setSlideToCancelArrowColor(color: Int) { + arrow!!.setColorFilter(color) + } + + + private fun setCancelOffset(cancelBounds: Float, DpToPixel: Boolean) { + val bounds = if (DpToPixel) CommonUtil.dpToPx(context, cancelBounds) else cancelBounds + this.cancelOffset = bounds + } + + companion object { + + val DEFAULT_CANCEL_OFFSET = 8 + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CustomView/RecordMicButton.kt b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/RecordMicButton.kt new file mode 100755 index 0000000..2325c79 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/RecordMicButton.kt @@ -0,0 +1,132 @@ +package com.inscripts.cometchatpulse.CustomView + +import android.content.Context +import android.support.v7.content.res.AppCompatResources +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import com.inscripts.cometchatpulse.Helpers.OnRecordClickListener +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.Utils.AnimUtil + + +class RecordMicButton : android.support.v7.widget.AppCompatImageView, View.OnTouchListener, View.OnClickListener { + + private var scaleView: View? = null + + var isRecord = true + + + private var onRecordClickListener: OnRecordClickListener? = null + + private var recordAudio: RecordAudio? = null + + fun setRecordAudio(recordAudio: RecordAudio?) { + this.recordAudio = recordAudio + + } + + constructor(context: Context) : super(context) { + initViewComponent(context, null) + + } + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { + initViewComponent(context, attrs) + + } + + constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { + initViewComponent(context, attrs) + + } + + + private fun initViewComponent(context: Context, attrs: AttributeSet?) { + if (attrs != null) { + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordMic) + + val imageResource = typedArray.getResourceId(R.styleable.RecordMic_mic_icon, -1) + + + if (imageResource != -1) { + setImage(imageResource) + } + + scaleView = this + + + typedArray.recycle() + } + + this.setOnTouchListener(this) + this.setOnClickListener(this) + + } + + + private fun setImage(imageResource: Int) { + val image = AppCompatResources.getDrawable(getContext(), imageResource) + setImageDrawable(image) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + setClip(this) + } + + fun setClip(v: View) { + if (v.parent == null) { + return + } + + if (v is ViewGroup) { + v.clipChildren = false + v.clipToPadding = false + } + + if (v.parent is View) { + setClip(v.parent as View) + } + } + + fun startScale() { + scaleView?.let { AnimUtil.start(it) } + } + + fun stopScale() { + scaleView?.let { AnimUtil.stop(it) } + } + + fun setListenForRecord(listenForRecord: Boolean) { + this.isRecord = listenForRecord + + } + + fun setOnRecordClickListener(onRecordClickListener: OnRecordClickListener) { + this.onRecordClickListener = onRecordClickListener + } + + + override fun onClick(view: View) { + if (onRecordClickListener != null) + onRecordClickListener!!.onRecordClick(view) + + } + + override fun onTouch(view: View, motionEvent: MotionEvent): Boolean { + if (isRecord) { + when (motionEvent.action) { + + MotionEvent.ACTION_DOWN ->{ recordAudio!!.onActionDown(view as RecordMicButton, context)} + + MotionEvent.ACTION_MOVE -> {recordAudio!!.onActionMove(view as RecordMicButton, motionEvent)} + + MotionEvent.ACTION_UP -> {recordAudio!!.onActionUp(view as RecordMicButton)} + } + + } + return isRecord + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CustomView/StickyHeaderAdapter.kt b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/StickyHeaderAdapter.kt new file mode 100755 index 0000000..ad16e38 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/StickyHeaderAdapter.kt @@ -0,0 +1,13 @@ +package com.inscripts.cometchatpulse.CustomView + +import android.support.v7.widget.RecyclerView +import android.view.ViewGroup + +interface StickyHeaderAdapter { + + fun getHeaderId(var1: Int): Long + + fun onCreateHeaderViewHolder(var1: ViewGroup): T + + fun onBindHeaderViewHolder(var1: T, var2: Int, var3: Long) +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/CustomView/StickyHeaderDecoration.kt b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/StickyHeaderDecoration.kt new file mode 100755 index 0000000..5559c7b --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/CustomView/StickyHeaderDecoration.kt @@ -0,0 +1,147 @@ +package com.inscripts.cometchatpulse.CustomView + +import android.graphics.Canvas +import android.graphics.Rect +import android.support.v4.view.ViewCompat +import android.support.v7.widget.RecyclerView +import android.view.View +import android.view.ViewGroup +import com.inscripts.cometchatpulse.ViewHolder.TextHeaderHolder +import java.util.HashMap + +class StickyHeaderDecoration constructor(private val mAdapter: StickyHeaderAdapter + ) : RecyclerView.ItemDecoration() { + + private val mHeaderCache: MutableMap + private val mRenderInline: Boolean = false + init { + this.mHeaderCache = HashMap() + } + + override fun getItemOffsets(var1: Rect, var2: View, var3: RecyclerView, var4: RecyclerView.State) { + val var5 = var3.getChildAdapterPosition(var2) + var var6 = 0 + if (var5 != -1 && this.hasHeader(var5) && this.showHeaderAboveItem(var5)) { + val var7 = this.getHeader(var3, var5).itemView + var6 = this.getHeaderHeightForLayout(var7) + } + + var1.set(0, var6, 0, 0) + } + + private fun showHeaderAboveItem(var1: Int): Boolean { + return if (var1 == 0) { + true + } else { + this.mAdapter.getHeaderId(var1 - 1) !== this.mAdapter.getHeaderId(var1) + } + } + + fun clearHeaderCache() { + this.mHeaderCache.clear() + } + + fun findHeaderViewUnder(var1: Float, var2: Float): View? { + val var3 = this.mHeaderCache.values.iterator() + + var var5: View + var var6: Float + var var7: Float + do { + if (!var3.hasNext()) { + return null + } + + var5 = var3.next().itemView + var6 = ViewCompat.getTranslationX(var5) + var7 = ViewCompat.getTranslationY(var5) + } while (var1 < var5.left.toFloat() + var6 || var1 > var5.right.toFloat() + var6 || var2 < var5.top.toFloat() + var7 || var2 > var5.bottom.toFloat() + var7) + + return var5 + } + + private fun hasHeader(var1: Int): Boolean { + return this.mAdapter.getHeaderId(var1) !== -1L + } + + private fun getHeader(var1: RecyclerView, var2: Int): RecyclerView.ViewHolder { + val var3 = this.mAdapter.getHeaderId(var2) + if (this.mHeaderCache.containsKey(var3)) { + return this.mHeaderCache[var3] as RecyclerView.ViewHolder + } else { + val var5 = this.mAdapter.onCreateHeaderViewHolder(var1) + val var6 = var5.itemView + this.mAdapter.onBindHeaderViewHolder(var5, var2, var3) + val var7 = View.MeasureSpec.makeMeasureSpec(var1.measuredWidth, 1073741824) + val var8 = View.MeasureSpec.makeMeasureSpec(var1.measuredHeight, 0) + val var9 = ViewGroup.getChildMeasureSpec(var7, var1.paddingLeft + var1.paddingRight, var6.getLayoutParams().width) + val var10 = ViewGroup.getChildMeasureSpec(var8, var1.paddingTop + var1.paddingBottom, var6.getLayoutParams().height) + var6.measure(var9, var10) + var6.layout(0, 0, var6.getMeasuredWidth(), var6.getMeasuredHeight()) + this.mHeaderCache[var3] = var5 + return var5 + } + } + + override fun onDrawOver(var1: Canvas, var2: RecyclerView, var3: RecyclerView.State) { + val var4 = var2.childCount + var var5 = -1L + + for (var7 in 0 until var4) { + val var8 = var2.getChildAt(var7) + val var9 = var2.getChildAdapterPosition(var8) + if (var9 != -1 && this.hasHeader(var9)) { + val var10 = this.mAdapter.getHeaderId(var9) + if (var10 != var5) { + var5 = var10 + val var12 = this.getHeader(var2, var9).itemView + var1.save() + val var13 = var8.left + val var14 = this.getHeaderTop(var2, var8, var12, var9, var7) + var1.translate(var13.toFloat(), var14.toFloat()) + var12.translationX = var13.toFloat() + var12.translationY = var14.toFloat() + var12.draw(var1) + var1.restore() + } + } + } + + } + + private fun getHeaderTop(var1: RecyclerView, var2: View, var3: View, var4: Int, var5: Int): Int { + val var6 = this.getHeaderHeightForLayout(var3) + var var7 = var2.y.toInt() - var6 + if (var5 == 0) { + val var8 = var1.childCount + val var9 = this.mAdapter.getHeaderId(var4) + + for (var11 in 1 until var8) { + val var12 = var1.getChildAdapterPosition(var1.getChildAt(var11)) + if (var12 != -1) { + val var13 = this.mAdapter.getHeaderId(var12) + if (var13 != var9) { + val var15 = var1.getChildAt(var11) + val var16 = var15.y.toInt() - (var6 + this.getHeader(var1, var12).itemView.height) + if (var16 < 0) { + return var16 + } + break + } + } + } + + var7 = Math.max(0, var7) + } + + return var7 + } + + private fun getHeaderHeightForLayout(var1: View): Int { + return if (this.mRenderInline) 0 else var1.height + } + + companion object { + val NO_HEADER_ID = -1L + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Extensions/Extentions.kt b/app/src/main/java/com/inscripts/cometchatpulse/Extensions/Extentions.kt new file mode 100755 index 0000000..4df5d75 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Extensions/Extentions.kt @@ -0,0 +1,18 @@ +package com.inscripts.cometchatpulse.Extensions + +import android.graphics.Typeface +import android.support.v7.widget.Toolbar +import android.widget.TextView + + +fun Toolbar.setTitleTypeface(typeface: Typeface){ + + for (i in 0 until childCount) + { + val view=getChildAt(i) + if (view is TextView && view.text==title){ + view.typeface=typeface + break + } + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Fcm/FirebaseService.kt b/app/src/main/java/com/inscripts/cometchatpulse/Fcm/FirebaseService.kt new file mode 100755 index 0000000..cdb5851 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Fcm/FirebaseService.kt @@ -0,0 +1,65 @@ +package com.inscripts.cometchatpulse.Fcm + +import android.app.PendingIntent +import android.content.Intent +import android.support.v4.app.NotificationCompat +import android.support.v4.app.NotificationManagerCompat +import android.support.v4.content.ContextCompat +import android.util.Log +import com.google.firebase.messaging.FirebaseMessaging +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage +import com.inscripts.cometchatpulse.Activities.MainActivity +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import org.json.JSONObject + +class FirebaseService : FirebaseMessagingService() { + + private val TAG="FirebaseService" + + private val CHANNEL_ID:String="1" + + private lateinit var json:JSONObject + + private var REQUEST_CODE:Int=2 + +// private lateinit var senderUid + + override fun onNewToken(p0: String?) { + Log.d(TAG, "Refreshed token: $p0") + } + + override fun onMessageReceived(p0: RemoteMessage?) { + Log.d(TAG, "From: ${p0?.from}") + Log.d(TAG, "RemoteMessage: ${p0?.data}") + + json =JSONObject(p0?.data) + + Log.d(TAG,"onMessageReceived: "+json.toString()) + + val intent=Intent(this,MainActivity::class.java).apply { + flags=Intent.FLAG_ACTIVITY_NEW_TASK + } + val pendingIntent=PendingIntent.getActivity(this,REQUEST_CODE,intent,0) + + showNotification(pendingIntent) + + } + + private fun showNotification(pendingIntent: PendingIntent){ + val builder=NotificationCompat.Builder(this,CHANNEL_ID) + .setSmallIcon(R.drawable.cc_small) + .setContentText(json.getString("alert")) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setBadgeIconType(R.drawable.cc_small) + .setColor(StringContract.Color.primaryColor) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + + with(NotificationManagerCompat.from(this)){ + notify(json.getString("id").toInt(),builder.build()) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Fragment/BanMemberFragment.kt b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/BanMemberFragment.kt new file mode 100755 index 0000000..7f0e49a --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/BanMemberFragment.kt @@ -0,0 +1,167 @@ +package com.inscripts.cometchatpulse.Fragment + + +import android.arch.lifecycle.Observer +import android.arch.lifecycle.ViewModelProviders +import android.graphics.PorterDuff +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.PopupMenu +import android.support.v7.widget.RecyclerView +import android.view.* +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Adapter.MemberListAdapter +import com.inscripts.cometchatpulse.Extensions.setTitleTypeface +import com.inscripts.cometchatpulse.Helpers.OnClickEvent +import com.inscripts.cometchatpulse.Helpers.RecyclerviewTouchListener + +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.GroupChatViewModel +import kotlinx.android.synthetic.main.fragment_ban_member.view.* +import kotlinx.android.synthetic.main.fragment_home.view.* +import kotlinx.coroutines.* +import java.lang.Exception + + +// TODO: Rename parameter arguments, choose names that match +// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER +private const val ARG_PARAM1 = "param1" +private const val ARG_PARAM2 = "param2" + +/** + * A simple [Fragment] subclass. + * + */ +class BanMemberFragment : Fragment() { + + + private lateinit var guid: String + + private lateinit var ownerId: String + + private lateinit var linearLayoutManager: LinearLayoutManager + + private lateinit var groupChatViewModel: GroupChatViewModel + + private lateinit var memberListAdapter: MemberListAdapter + + private lateinit var member: User + + lateinit var my: View + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + my = inflater.inflate(R.layout.fragment_ban_member, container, false) + + groupChatViewModel = ViewModelProviders.of(this).get(GroupChatViewModel::class.java) + + guid = arguments?.getString(StringContract.IntentString.GROUP_ID).toString() + + ownerId = arguments?.getString(StringContract.IntentString.USER_ID).toString() + + (activity as AppCompatActivity).setSupportActionBar(my.banmember_toolbar) + (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) + my.banmember_toolbar.title = "Banned Members" + my.banmember_toolbar.setTitleTypeface(StringContract.Font.title) + + my.banmember_toolbar.navigationIcon?.setColorFilter(StringContract.Color.iconTint, + PorterDuff.Mode.SRC_ATOP) + + if (StringContract.AppDetails.theme== Appearance.AppTheme.AZURE_RADIANCE){ + my.banmember_toolbar.setTitleTextColor(StringContract.Color.black) + } + else{ + my.banmember_toolbar.setTitleTextColor(StringContract.Color.white) + } + + my.banmember_toolbar.setBackgroundColor(StringContract.Color.primaryColor) + + linearLayoutManager = LinearLayoutManager(context) + my.rv_ban_member.setLayoutManager(linearLayoutManager) + try { + memberListAdapter = MemberListAdapter(ownerId,R.layout.group_member_item, object : OnClickEvent { + override fun onClickRl(item: View, user: Any) { + + if (user is User) { + member = user + if (ownerId != user.getUid()) { + val popup = context?.let { PopupMenu(it, item) } + //Inflating the Popup using xml file + popup?.getMenuInflater()?.inflate(R.menu.menu_group_action, popup.getMenu()) + + popup?.setOnMenuItemClickListener(object : PopupMenu.OnMenuItemClickListener { + override fun onMenuItemClick(p0: MenuItem?): Boolean { + + when (p0!!.itemId) { + + R.id.menu_item_Reinstate -> { + groupChatViewModel.unbanMember(member.uid, guid) + } + + } + + return true + } + + }) + + popup?.show() + } + } + } + + }) + } catch (e: Exception) { + e.printStackTrace() + } + my.rv_ban_member.adapter = memberListAdapter + + + Thread { + groupChatViewModel.getBanedMember(guid, LIMIT = 10) + }.start() + + + + groupChatViewModel.banMemberList.observe(this, Observer { groupMember -> + groupMember?.let { + memberListAdapter.setMemberList(it) + } + }) + + + my.rv_ban_member.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + + if (!recyclerView.canScrollVertically(1)) { + groupChatViewModel.getBanedMember(guid, LIMIT = 10) + } + } + + }) + + return my + } + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + + when(item?.itemId){ + + android.R.id.home->{ + activity?.onBackPressed() + } + } + + return true + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Fragment/ContactListFragment.kt b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/ContactListFragment.kt new file mode 100755 index 0000000..05afc66 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/ContactListFragment.kt @@ -0,0 +1,134 @@ +package com.inscripts.cometchatpulse.Fragment + + +import android.arch.lifecycle.Observer +import android.arch.lifecycle.ViewModelProviders +import android.content.Context +import android.content.res.Configuration +import android.graphics.PorterDuff +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v4.content.ContextCompat +import android.support.v7.widget.DefaultItemAnimator +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.support.v7.widget.helper.ItemTouchHelper +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Adapter.ContactListAdapter +import com.inscripts.cometchatpulse.Helpers.CardItemTouchHelper +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.UserViewModel +import kotlinx.android.synthetic.main.fragment_contact_list.view.* + +// TODO: Rename parameter arguments, choose names that match +// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER +private const val ARG_PARAM1 = "param1" +private const val ARG_PARAM2 = "param2" + + +class ContactListFragment : Fragment() { + + companion object { + private val TAG = this::class.java.simpleName + } + + lateinit var userViewModel: UserViewModel + + lateinit var contactListAdapter: ContactListAdapter + + private lateinit var linearLayoutManager: LinearLayoutManager + + private lateinit var user:User + + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + + + val view: View = layoutInflater.inflate(R.layout.fragment_contact_list, container, false) + val config: Configuration = activity?.resources?.configuration!! + if (config.smallestScreenWidthDp < 600) { + CommonUtil.setCardView(view.contact_cardview) + } + + userViewModel = ViewModelProviders.of(this).get(UserViewModel::class.java) + linearLayoutManager = LinearLayoutManager(activity) + view.contact_recycler.layoutManager = linearLayoutManager + view.contact_recycler.itemAnimator=DefaultItemAnimator() + contactListAdapter = ContactListAdapter(activity) + view.contact_recycler.adapter = contactListAdapter + + try { + + val icon = context?.let { ContextCompat.getDrawable(it, R.drawable.ic_outline_video_call_white_24px) } + icon?.setColorFilter(StringContract.Color.white,PorterDuff.Mode.SRC_ATOP) + val color = StringContract.Color.primaryDarkColor + val helper = object : CardItemTouchHelper(context!!,icon!!, color) { + override fun onSwiped(p0: RecyclerView.ViewHolder, p1: Int) { + contactListAdapter.notifyDataSetChanged() + user = (p0.itemView.getTag( R.string.user) as User) + showDialog("Are you sure you want to call ","Please Confirm",user.name,context) + } + } + + val itemTouchHelper = ItemTouchHelper(helper) + + itemTouchHelper.attachToRecyclerView(view.contact_recycler) + + } catch (e: Exception) { + e.printStackTrace() + } + + + userViewModel.fetchUser(LIMIT = 30,shimmer = view.contact_shimmer) + + + userViewModel.userList.observe(this, Observer { users -> + users?.let { contactListAdapter.setUser(it) } + }) + + + view.contact_recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + + if (!recyclerView.canScrollVertically(1)) { + userViewModel.fetchUser(LIMIT = 30,shimmer = view.contact_shimmer) + } + } + + }) + + return view + } + + override fun onStart() { + super.onStart() + userViewModel.addPresenceListener(StringContract.ListenerName.USER_LISTENER) + } + + override fun onDestroy() { + super.onDestroy() + userViewModel.removeUserListener(StringContract.ListenerName.USER_LISTENER) + } + + fun showDialog(message: String, title: String, contactName: String, context: Context) { + val builder = android.support.v7.app.AlertDialog.Builder(context) + builder.setTitle(CommonUtil.setTitle(title, context)) + + .setMessage(message + contactName) + .setCancelable(true) + .setNegativeButton(CommonUtil.setTitle("Cancel", context)) { + dialogInterface, i -> dialogInterface.dismiss() } + .setPositiveButton(CommonUtil.setTitle("Yes", context), { + dialogInterface, i -> userViewModel.initCall(context,user) + }).show() + } + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Fragment/GroupFragment.kt b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/GroupFragment.kt new file mode 100755 index 0000000..3fa844e --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/GroupFragment.kt @@ -0,0 +1,818 @@ +package com.inscripts.cometchatpulse.Fragment + + +import android.app.Activity +import android.arch.lifecycle.Observer +import android.arch.lifecycle.ViewModelProviders +import android.content.Intent +import android.content.pm.PackageManager +import android.content.res.ColorStateList +import android.content.res.Configuration +import android.databinding.DataBindingUtil +import android.graphics.PorterDuff +import android.media.MediaRecorder +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v4.app.FragmentActivity +import android.support.v4.content.ContextCompat +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.util.Log +import android.view.* +import android.widget.TextView +import android.widget.Toast +import com.bumptech.glide.Glide +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.CometChat +import com.cometchat.pro.helpers.Logger +import com.cometchat.pro.models.GroupMember +import com.cometchat.pro.models.MediaMessage +import com.cometchat.pro.models.TextMessage +import com.inscripts.cometchatpulse.Activities.GroupDetailActivity +import com.inscripts.cometchatpulse.Activities.LocationActivity +import com.inscripts.cometchatpulse.Adapter.GroupChatAdapter +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.CustomView.AttachmentTypeSelector +import com.inscripts.cometchatpulse.CustomView.StickyHeaderDecoration +import com.inscripts.cometchatpulse.Helpers.* +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.Utils.FileUtil +import com.inscripts.cometchatpulse.ViewModel.GroupChatViewModel +import com.inscripts.cometchatpulse.ViewModel.GroupViewModel +import com.inscripts.cometchatpulse.databinding.FragmentGroupBinding +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import org.json.JSONObject +import java.io.File +import java.io.IOException +import kotlin.coroutines.CoroutineContext + +// TODO: Rename parameter arguments, choose names that match +// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER + +private const val ARG_PARAM1 = "param1" +private const val ARG_PARAM2 = "param2" +private val TAG="GroupFragment" + +/** + * A simple [Fragment] subclass. + * + */ +class GroupFragment : Fragment(), View.OnClickListener, RecordListener,ActionMode.Callback,OnClickEvent { + + private lateinit var binding: FragmentGroupBinding + + private lateinit var guid: String + + private lateinit var groupChatViewModel: GroupChatViewModel + + private lateinit var config: Configuration + + private lateinit var groupViewModel: GroupViewModel + + private var audioFileNamewithPath: String? = null + + private lateinit var clickListener: OnBackArrowClickListener + + private var groupDescription: String? = null + + var mediaRecorder: MediaRecorder? = null + + private lateinit var linearLayoutManager: LinearLayoutManager + + private lateinit var groupChatAdapter: GroupChatAdapter + + private lateinit var groupName: String + + private var attachmentTypeSelector: AttachmentTypeSelector? = null + + private var parentJob = Job() + + private val coroutineContext: CoroutineContext + get() = parentJob + Dispatchers.Main + + private val scope = CoroutineScope(coroutineContext) + + var scrollFlag: Boolean = true + + private lateinit var any: Any + + private var mode: ActionMode? = null + + companion object { + + var isReply: Boolean = false + var metaData: JSONObject?= JSONObject() + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + + binding = DataBindingUtil.inflate(layoutInflater, R.layout.fragment_group, + container, false) + + setHasOptionsMenu(true) + + guid = arguments?.getString(StringContract.IntentString.GROUP_ID).toString() + + groupName = arguments?.getString(StringContract.IntentString.GROUP_NAME).toString() + + binding.name = arguments?.getString(StringContract.IntentString.GROUP_NAME) + + binding.icon = arguments?.getString(StringContract.IntentString.GROUP_ICON) + + groupDescription = arguments?.getString(StringContract.IntentString.GROUP_DESCRIPTION) + + groupChatViewModel = ViewModelProviders.of(this).get(GroupChatViewModel::class.java) + + groupViewModel = ViewModelProviders.of(this).get(GroupViewModel::class.java) + + config = activity?.resources?.configuration!! + + clickListener = context as OnBackArrowClickListener + + linearLayoutManager = LinearLayoutManager(activity) + binding.recycler.layoutManager = linearLayoutManager + + + binding.recycler.getItemAnimator()?.changeDuration = 0 + groupChatAdapter = GroupChatAdapter(context!!, guid, CometChat.getLoggedInUser().uid,this) + binding.recycler.adapter = groupChatAdapter + + binding.recycler.addItemDecoration(StickyHeaderDecoration(groupChatAdapter)) + + (activity as AppCompatActivity).setSupportActionBar(binding.cometchatToolbar) + (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) + binding.cometchatToolbar.title = "" + + binding.cometchatToolbar.setBackgroundColor(StringContract.Color.primaryColor) + + binding.title.typeface = StringContract.Font.name + binding.subTitle.typeface = StringContract.Font.status + + binding.messageBox?.buttonSendMessage?.setOnClickListener(this) + binding.messageBox?.ivAttchment?.setOnClickListener(this) + binding.rlTitlecontainer.setOnClickListener(this) + + binding.messageBox?.recordButton?.setListenForRecord(true) + + binding.messageBox?.recordAudioView?.setCancelOffset(8.toFloat()) + + binding.messageBox?.recordAudioView?.setLessThanSecondAllowed(false) + + binding.messageBox?.recordAudioView?.setSlideToCancelText(getString(R.string.slide_to_cancel)) + + binding.messageBox?.recordAudioView?.setCustomSounds(R.raw.record_start, + R.raw.record_finished, R.raw.record_error) + + binding.messageBox?.recordButton?.setRecordAudio(binding.messageBox?.recordAudioView) + + binding.messageBox?.recordAudioView?.setOnRecordListener(this) + + binding.cometchatToolbar.setBackgroundColor(StringContract.Color.primaryColor) + + binding.cometchatToolbar.navigationIcon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + binding.messageBox?.buttonSendMessage?.backgroundTintList = + ColorStateList.valueOf(StringContract.Color.primaryColor) + + + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + binding.title.setTextColor(StringContract.Color.black) + binding.subTitle.setTextColor(StringContract.Color.black) + binding.messageBox?.buttonSendMessage?.drawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.ivAttchment?.drawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.recordButton?.drawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + } else { + binding.messageBox?.buttonSendMessage?.drawable?.setColorFilter(StringContract.Color.primaryColor, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.ivAttchment?.drawable?.setColorFilter(StringContract.Color.primaryColor, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.recordButton?.drawable?.setColorFilter(StringContract.Color.primaryColor, PorterDuff.Mode.SRC_ATOP) + binding.title.setTextColor(StringContract.Color.white) + binding.subTitle.setTextColor(StringContract.Color.white) + binding.messageBox?.buttonSendMessage?.drawable?.setColorFilter(StringContract.Color.white, PorterDuff.Mode.SRC_ATOP) + } + binding.contactPic.borderColor = StringContract.Color.white + binding.contactPic.borderWidth = 2 + + binding.cometchatToolbar.overflowIcon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + Thread { + groupChatViewModel.fetchMessage(LIMIT = 30, guid = guid) + + }.start() + + + Thread { + groupViewModel.fetchGroupMemeber(LIMIT = 30, guid = guid) + }.start() + + + groupChatViewModel.messageList.observe(this, Observer { messages -> + messages?.let { + groupChatAdapter.setMessageList(it) + if (scrollFlag) { + scrollBottom() + scrollFlag = false + } + } + }) + + groupViewModel.groupMemberList.observe(this, Observer { groupMemeberList -> + groupMemeberList?.let { + setGroupMemberList(it, binding.subTitle) + + } + }) + + binding.recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + + binding.cometchatToolbar.isSelected = binding.recycler.canScrollVertically(-1) + + if (!recyclerView.canScrollVertically(-1)) { + groupChatViewModel.fetchMessage(LIMIT = 30, guid = guid) + + + } + + } + + }) + + binding.rlGroup.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { + override fun onGlobalLayout() { + try { + val heightDiff = binding.rlGroup.rootView.height - binding.rlGroup.height + if (heightDiff > CommonUtil.dpToPx(CometChatPro.applicationContext(), 200f)) { + binding.recycler.scrollToPosition(groupChatAdapter.itemCount - 1) + } + } catch (e: Exception) { + e.printStackTrace() + } + + } + + }) + + + + return binding.root + } + + private fun scrollBottom() { + binding.recycler.scrollToPosition(groupChatAdapter.itemCount - 1) + } + + override fun onRecordCancel() { + binding.messageBox?.editTextChatMessage?.setHint(getString(R.string.type_your_message)) + stopRecording(true) + } + + override fun onRecordFinish(time: Long) { + binding.messageBox?.editTextChatMessage?.setHint(getString(R.string.type_your_message)) + stopRecording(false) + + if (audioFileNamewithPath != null) { + Logger.error("audioFileNamewithPath", audioFileNamewithPath) + groupChatViewModel.sendMediaMessage(audioFileNamewithPath, + CometChatConstants.MESSAGE_TYPE_AUDIO, guid,this) + + } + + } + + override fun onRecordLessTime() { + binding.messageBox?.editTextChatMessage?.setHint(getString(R.string.type_your_message)) + stopRecording(true) + } + + override fun onRecordStart() { + binding.messageBox?.editTextChatMessage?.setHint("") + startRecording() + } + + + private fun startRecording() { + try { + mediaRecorder = MediaRecorder() + mediaRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC) + mediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) + mediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) + audioFileNamewithPath = FileUtil.getOutputMediaFile(context).toString() + mediaRecorder?.setOutputFile(audioFileNamewithPath) + + try { + mediaRecorder?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + mediaRecorder?.start() + } catch (e: Exception) { + e.printStackTrace() + } + + } + + private fun stopRecording(isCancel: Boolean) { + try { + if (mediaRecorder != null) { + mediaRecorder?.stop() + mediaRecorder?.release() + mediaRecorder = null + if (isCancel) { + File(audioFileNamewithPath).delete() + } + } + } catch (e: Exception) { + e.printStackTrace() + } + + } + + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + menu?.clear() + inflater?.inflate(R.menu.option_menu, menu) + + val audioCall = menu?.findItem(R.id.voice_call) + val videoCall = menu?.findItem(R.id.video_call) + + val leaveMenu = menu?.findItem(R.id.menu_leave) + leaveMenu?.setVisible(true) + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + val drawable = context?.let { ContextCompat.getDrawable(it, R.drawable.ic_more_vert) } + drawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + leaveMenu?.setIcon(drawable) + } + + audioCall?.icon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + videoCall?.icon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + super.onCreateOptionsMenu(menu, inflater) + + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + + when (item?.itemId) { + + android.R.id.home -> { + + if (config.smallestScreenWidthDp >= 600) { + clickListener.onBackClick() + } else { + activity?.onBackPressed() + } + } + R.id.voice_call -> { + + if (CCPermissionHelper.hasPermissions(activity, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + + groupViewModel.initCall(context, guid, CometChatConstants.RECEIVER_TYPE_GROUP, CometChatConstants.CALL_TYPE_AUDIO) + } else { + CCPermissionHelper.requestPermissions(activity as Activity, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VOICE_CALL) + } + } + + R.id.video_call -> { + + if (CCPermissionHelper.hasPermissions(activity, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + + groupViewModel.initCall(context, guid, CometChatConstants.RECEIVER_TYPE_GROUP, CometChatConstants.CALL_TYPE_VIDEO) + + } else { + CCPermissionHelper.requestPermissions(activity as Activity, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VIDEO_CALL) + } + + } + + R.id.menu_leave -> { + + groupViewModel.leaveGroup(guid, activity) + } + + + + + } + return true + } + + + override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { + mode?.finish() + + when (item?.itemId) { + + R.id.reply -> { + + GroupFragment.isReply = true + GroupFragment.metaData =null + GroupFragment.metaData =JSONObject() + GroupFragment.metaData?.put("reply", "reply") + + binding.messageBox?.replyLayout?.rlMain?.visibility = View.VISIBLE + + if (any is TextMessage) { + binding.messageBox?.replyLayout?.tvNameReply?.text = (any as TextMessage).sender.name + binding.messageBox?.replyLayout?.tvTextMessage?.text = (any as TextMessage).text + GroupFragment.metaData?.put("senderName", (any as TextMessage).sender.name) + GroupFragment.metaData?.put("senderUid", (any as TextMessage).sender.uid) + GroupFragment.metaData?.put("type", (any as TextMessage).type) + GroupFragment.metaData?.put("id", (any as TextMessage).id) + GroupFragment.metaData?.put("text", (any as TextMessage).text) + + Log.d(TAG, "onActionItemClicked: " + OneToOneFragment.metaData?.toString()) + + } + + if (any is MediaMessage) { + + binding.messageBox?.replyLayout?.tvNameReply?.text = (any as MediaMessage).sender.name + GroupFragment.metaData?.put("senderName", (any as MediaMessage).sender.name) + GroupFragment.metaData?.put("url", (any as MediaMessage).url) + GroupFragment.metaData?.put("id", (any as MediaMessage).id) + GroupFragment.metaData?.put("senderUid", (any as MediaMessage).sender.uid) + val type = (any as MediaMessage).type + GroupFragment.metaData?.put("type", type) + + if (type == CometChatConstants.MESSAGE_TYPE_IMAGE + || type == CometChatConstants.MESSAGE_TYPE_VIDEO) { + + binding.messageBox?.replyLayout?.ivReplyImage?.visibility = View.VISIBLE + + binding.messageBox?.replyLayout?.ivReplyImage?.let { Glide.with(this).load((any as MediaMessage).url).into(it) } + + } else if (type.equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + binding.messageBox?.replyLayout?.tvTextMessage?.text = "Audio message" + + GroupFragment.metaData?.put("senderName", (any as MediaMessage).sender.name) + GroupFragment.metaData?.put("url", (any as MediaMessage).url) + GroupFragment.metaData?.put("id", (any as MediaMessage).id) + + } else if (type == CometChatConstants.MESSAGE_TYPE_FILE) { + + GroupFragment.metaData?.put("senderName", (any as MediaMessage).sender.name) + GroupFragment.metaData?.put("url", (any as MediaMessage).url) + GroupFragment.metaData?.put("id", (any as MediaMessage).id) +// metaData.put("fileName",(any as MediaMessage).file.name) + + binding.messageBox?.replyLayout?.tvTextMessage?.text = "File message" + } + + } + } + } + + return true + } + + override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { + mode?.menuInflater?.inflate(R.menu.action_bar, menu) + this.mode = mode + + mode?.title = groupName + + return true + } + + override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { + return false + } + + override fun onDestroyActionMode(mode: ActionMode?) { + this.mode=null + } + + override fun onClickRl(item: View, any: Any) { + binding.cometchatToolbar.startActionMode(this) + this.any = any + } + + fun hideReplyContainer(){ + isReply = false + metaData =null + metaData =JSONObject() + binding.messageBox?.replyLayout?.rlMain?.visibility = View.GONE + } + override fun onClick(p0: View?) { + + when (p0?.id) { + R.id.buttonSendMessage -> { + + val messageText: String? = binding.messageBox?.editTextChatMessage?.text.toString().trim() + + if (messageText != null && !messageText.isEmpty()) { + + val textMessage = TextMessage(guid, messageText, CometChatConstants.MESSAGE_TYPE_TEXT, + CometChatConstants.RECEIVER_TYPE_GROUP) + + binding.messageBox?.editTextChatMessage?.setText("") + + if (GroupFragment.isReply) { + binding.messageBox?.replyLayout?.rlMain?.visibility = View.GONE + textMessage.metadata = GroupFragment.metaData + GroupFragment.metaData =null + GroupFragment.metaData = JSONObject() + } + + groupChatViewModel.sendTextMessage(textMessage) + scrollFlag = true + } + } + + R.id.iv_attchment -> { + showPopUp() + } + + R.id.rl_titlecontainer -> { + val groupDetailIntent = Intent(context, GroupDetailActivity::class.java) + groupDetailIntent.putExtra(StringContract.IntentString.GROUP_ID, guid) + groupDetailIntent.putExtra(StringContract.IntentString.GROUP_ICON, + arguments?.getString(StringContract.IntentString.GROUP_ICON)) + groupDetailIntent.putExtra(StringContract.IntentString.GROUP_OWNER, + arguments?.getString(StringContract.IntentString.GROUP_OWNER)) + + groupDetailIntent.putExtra(StringContract.IntentString.GROUP_DESCRIPTION + , groupDescription) + + groupDetailIntent.putExtra(StringContract.IntentString.GROUP_NAME, + arguments?.getString(StringContract.IntentString.GROUP_NAME)) + startActivity(groupDetailIntent) + + } + } + } + + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, + grantResults: IntArray) { + + when (requestCode) { + StringContract.RequestCode.ADD_DOCUMENT -> + + if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + AttachmentHelper.selectMedia(activity, "*/*", StringContract.IntentString.EXTRA_MIME_DOC) + } else { + showToast() + } + + StringContract.RequestCode.ADD_GALLERY -> + + if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + + val intent = AttachmentHelper.selectMedia(activity, "*/*", + StringContract.IntentString.EXTRA_MIME_TYPE) + + startActivityForResult(intent, StringContract.RequestCode.ADD_GALLERY) + } else { + showToast() + } + + StringContract.RequestCode.TAKE_PHOTO -> + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + val intent = AttachmentHelper.captureImage() + startActivityForResult(intent, StringContract.RequestCode.TAKE_PHOTO) + + } else { + showToast() + } + + StringContract.RequestCode.TAKE_VIDEO -> + + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + val intent = AttachmentHelper.captureVideo() + + startActivityForResult(intent, StringContract.RequestCode.TAKE_VIDEO) + + } else { + showToast() + } + + StringContract.RequestCode.RECORD_CODE -> + + if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + } else { + showToast() + } + + StringContract.RequestCode.ADD_SOUND -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED) { + + AttachmentHelper.selectMedia(activity, StringContract.IntentString.AUDIO_TYPE, null) + } else { + showToast() + } + StringContract.RequestCode.VOICE_CALL -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED) { + + groupViewModel.initCall(context, guid, CometChatConstants.RECEIVER_TYPE_GROUP, CometChatConstants.CALL_TYPE_AUDIO) + + } else { + showToast() + } + StringContract.RequestCode.VIDEO_CALL -> if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED + && grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + groupViewModel.initCall(context, guid, + CometChatConstants.RECEIVER_TYPE_GROUP, CometChatConstants.CALL_TYPE_VIDEO) + + } else { + showToast() + } + + } + + } + + private fun showToast() { + Toast.makeText(context, "PERMISSION NOT GRANTED", Toast.LENGTH_SHORT).show() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + + if (resultCode == Activity.RESULT_OK && data != null) { + + when (requestCode) { + + StringContract.RequestCode.ADD_GALLERY -> { + val filePath = AttachmentHelper.handleFile(context, data) + groupChatViewModel.sendMediaMessage(filePath[0], filePath[1], guid,this) + scrollFlag = true + } + StringContract.RequestCode.TAKE_PHOTO -> { + val filePath = AttachmentHelper.handleCameraImage(context, data) + groupChatViewModel.sendMediaMessage(filePath, CometChatConstants.MESSAGE_TYPE_IMAGE, guid,this) + scrollFlag = true + } + + StringContract.RequestCode.TAKE_VIDEO -> { + val filePath = AttachmentHelper.handleCameraVideo(context, data) + groupChatViewModel.sendMediaMessage(filePath, CometChatConstants.MESSAGE_TYPE_VIDEO, guid,this) + scrollFlag = true + } + + StringContract.RequestCode.ADD_SOUND -> { + val filePath = AttachmentHelper.handleFile(context, data) + groupChatViewModel.sendMediaMessage(filePath[0], CometChatConstants.MESSAGE_TYPE_AUDIO, guid,this) + scrollFlag = true + } + + StringContract.RequestCode.ADD_DOCUMENT -> { + val filePath = AttachmentHelper.handleFile(context, data) + groupChatViewModel.sendMediaMessage(filePath[0], filePath[1], guid,this) + scrollFlag = true + + } + } + } + + } + + + private fun showPopUp() { + + try { + if (attachmentTypeSelector == null) { + attachmentTypeSelector = AttachmentTypeSelector(context!!, AttachmentTypeListener()) + } + attachmentTypeSelector!!.show(activity as Activity, binding.messageBox?.ivAttchment as View) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private inner class AttachmentTypeListener : AttachmentTypeSelector.AttachmentClickedListener { + override fun onClick(type: Int) { + addAttachment(type, activity) + } + } + + fun addAttachment(type: Int, activity: FragmentActivity?) { + when (type) { + StringContract.RequestCode.ADD_GALLERY -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.STORAGE_PERMISSION)) { + + val intent = AttachmentHelper.selectMedia(activity, "*/*", + StringContract.IntentString.EXTRA_MIME_TYPE) + + startActivityForResult(intent, StringContract.RequestCode.ADD_GALLERY) + + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.STORAGE_PERMISSION, StringContract.RequestCode.ADD_GALLERY) + } + StringContract.RequestCode.ADD_DOCUMENT -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.STORAGE_PERMISSION)) { + + val intent = AttachmentHelper.selectMedia(activity, "*/*", + StringContract.IntentString.DOCUMENT_TYPE) + + startActivityForResult(intent, StringContract.RequestCode.ADD_DOCUMENT) + + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.STORAGE_PERMISSION, + StringContract.RequestCode.ADD_DOCUMENT) + } + StringContract.RequestCode.ADD_SOUND -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.STORAGE_PERMISSION)) { + + val intent = AttachmentHelper.selectMedia(activity, StringContract.IntentString.AUDIO_TYPE, + null) + + startActivityForResult(intent, StringContract.RequestCode.ADD_SOUND) + + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.STORAGE_PERMISSION, StringContract.RequestCode.ADD_SOUND) + } + + StringContract.RequestCode.TAKE_PHOTO -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.CAMERA_PERMISSION)) { + + val intent = AttachmentHelper.captureImage() + + startActivityForResult(intent, StringContract.RequestCode.TAKE_PHOTO) + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.CAMERA_PERMISSION, StringContract.RequestCode.TAKE_PHOTO) + } + StringContract.RequestCode.TAKE_VIDEO -> + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.CAMERA_PERMISSION)) { + val intent = AttachmentHelper.captureVideo() + startActivityForResult(intent, StringContract.RequestCode.TAKE_VIDEO) + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.CAMERA_PERMISSION, StringContract.RequestCode.TAKE_VIDEO) + + } + + StringContract.RequestCode.LOCATION -> + locationIntent() + + } + } + + + private fun locationIntent() { + val locationIntent = Intent(context, LocationActivity::class.java) + locationIntent.putExtra(StringContract.IntentString.ID, guid) + locationIntent.putExtra(StringContract.IntentString.RECIVER_TYPE, CometChatConstants.RECEIVER_TYPE_GROUP) + startActivity(locationIntent) + } + + + private fun setGroupMemberList(list: MutableList, subtitle: TextView) { + val builder = StringBuilder() + + for (member in list) { + + builder.append(member.user.name) + builder.append(",") + + } + val memeberList = builder.deleteCharAt(builder.length - 1).toString() + Logger.errorLong("LISTMEMBER", memeberList) + subtitle.text = memeberList + } + + + override fun onResume() { + super.onResume() + Log.d(TAG,"onResume: ") + groupChatViewModel.addGroupEventListener(StringContract.ListenerName.GROUP_EVENT_LISTENER) + groupChatViewModel.addGroupMessageListener(StringContract.ListenerName.MESSAGE_LISTENER, CometChat.getLoggedInUser().uid) + } + + + override fun onPause() { + super.onPause() + Log.d(TAG,"onPause: ") + stopRecording(false) + groupChatViewModel.removeGroupEventListener(StringContract.ListenerName.GROUP_EVENT_LISTENER) + groupChatViewModel.removeMessageListener(StringContract.ListenerName.MESSAGE_LISTENER) + groupChatAdapter.stopPlayer() + + } + + override fun onStop() { + super.onStop() + stopRecording(false) + } + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Fragment/GroupListFragment.kt b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/GroupListFragment.kt new file mode 100755 index 0000000..3b65d25 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/GroupListFragment.kt @@ -0,0 +1,91 @@ +package com.inscripts.cometchatpulse.Fragment + + +import android.app.ProgressDialog +import android.arch.lifecycle.Observer +import android.arch.lifecycle.ViewModelProviders +import android.content.Intent +import android.content.res.Configuration +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.models.Group +import com.inscripts.cometchatpulse.Adapter.GroupListAdapter +import com.inscripts.cometchatpulse.Helpers.RecyclerviewTouchListener +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.GroupViewModel +import kotlinx.android.synthetic.main.fragment_group_list.view.* +import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext + +// TODO: Rename parameter arguments, choose names that match +// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER +private const val ARG_PARAM1 = "param1" +private const val ARG_PARAM2 = "param2" + +/** + * A simple [Fragment] subclass. + * + */ +class GroupListFragment : Fragment() { + + private lateinit var linearLayoutManager: LinearLayoutManager + + private lateinit var groupListAdapter: GroupListAdapter + + private lateinit var groupViewModel:GroupViewModel + + private var twoPane: Boolean=false + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + val view:View= inflater.inflate(R.layout.fragment_group_list, container, false) + + val config: Configuration = activity?.resources?.configuration!! + if(config.smallestScreenWidthDp <600 ) { + CommonUtil.setCardView(view.group_Card) + } + //recycler view setup + linearLayoutManager= LinearLayoutManager(context) + view.group_recycler.layoutManager=linearLayoutManager + groupListAdapter= GroupListAdapter(context) + view.group_recycler.adapter=groupListAdapter + + groupViewModel=ViewModelProviders.of(this).get(GroupViewModel::class.java) + + + groupViewModel.fetchGroups(LIMIT = 30,shimmerFrameLayout= view.contact_shimmer) + + + groupViewModel.groupList.observe(this, Observer { groups -> + groups?.let { groupListAdapter.setGroup(it) } + }) + + view.group_recycler.addOnScrollListener(object :RecyclerView.OnScrollListener(){ + + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + + if (!recyclerView.canScrollVertically(1)) { + + groupViewModel.fetchGroups(LIMIT = 30,shimmerFrameLayout= view.contact_shimmer) + + } + } + }) + + + return view + } + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Fragment/MemberFragment.kt b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/MemberFragment.kt new file mode 100755 index 0000000..96b348b --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/MemberFragment.kt @@ -0,0 +1,196 @@ +package com.inscripts.cometchatpulse.Fragment + + +import android.arch.lifecycle.Observer +import android.arch.lifecycle.ViewModelProvider +import android.arch.lifecycle.ViewModelProviders +import android.content.Intent +import android.content.res.Configuration +import android.os.Bundle +import android.support.v4.app.Fragment +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.view.* +import android.widget.LinearLayout +import android.widget.Toast +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Adapter.MemberListAdapter +import com.inscripts.cometchatpulse.Helpers.OnClickEvent +import com.inscripts.cometchatpulse.Helpers.RecyclerviewTouchListener + +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.ViewModel.GroupChatViewModel +import kotlinx.android.synthetic.main.fragment_ban_member.view.* +import kotlinx.android.synthetic.main.fragment_contact_list.view.* +import kotlinx.android.synthetic.main.fragment_home.view.* +import kotlinx.coroutines.* +import java.lang.Exception +import android.R.attr.button +import android.graphics.PorterDuff +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.PopupMenu +import com.cometchat.pro.constants.CometChatConstants +import com.inscripts.cometchatpulse.Activities.MainActivity +import com.inscripts.cometchatpulse.Extensions.setTitleTypeface +import com.inscripts.cometchatpulse.Utils.Appearance + + +// TODO: Rename parameter arguments, choose names that match +// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER +private const val ARG_PARAM1 = "param1" +private const val ARG_PARAM2 = "param2" + +/** + * A simple [Fragment] subclass. + * + */ +class MemberFragment : Fragment() { + + + private lateinit var guid: String + + private lateinit var ownerId: String + + private lateinit var linearLayoutManager: LinearLayoutManager + + private lateinit var groupChatViewModel: GroupChatViewModel + + private lateinit var memberListAdapter: MemberListAdapter + + private lateinit var member: User + + private lateinit var myView: View + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + myView = inflater.inflate(R.layout.fragment_home, container, false) + + + guid = arguments?.getString(StringContract.IntentString.GROUP_ID).toString() + + ownerId = arguments?.getString(StringContract.IntentString.USER_ID).toString() + + (activity as AppCompatActivity).setSupportActionBar(myView.member_toolbar) + (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) + myView.member_toolbar.title = "Group Members" + + myView.member_toolbar.setTitleTypeface(StringContract.Font.title) + + myView.member_toolbar.navigationIcon?.setColorFilter(StringContract.Color.iconTint, + PorterDuff.Mode.SRC_ATOP) + + myView.member_toolbar.setBackgroundColor(StringContract.Color.primaryColor) + + + if (StringContract.AppDetails.theme== Appearance.AppTheme.AZURE_RADIANCE){ + myView.member_toolbar.setTitleTextColor(StringContract.Color.black) + } + else{ + myView.member_toolbar.setTitleTextColor(StringContract.Color.white) + } + + groupChatViewModel = ViewModelProviders.of(this).get(GroupChatViewModel::class.java) + + linearLayoutManager = LinearLayoutManager(context) + myView.rv_member.layoutManager = linearLayoutManager + try { + + memberListAdapter = MemberListAdapter(ownerId,R.layout.group_member_item, object : OnClickEvent { + override fun onClickRl(item: View, user: Any) { + + if (user is User) { + member = user + if (ownerId != user.getUid()) { + + val popup = context?.let { PopupMenu(it, item) } + //Inflating the Popup using xml file + popup?.menuInflater?.inflate(R.menu.member_menu, popup.getMenu()) + + popup?.setOnMenuItemClickListener(object : PopupMenu.OnMenuItemClickListener { + override fun onMenuItemClick(p0: MenuItem?): Boolean { + + when (p0!!.itemId) { + R.id.menu_item_outcast -> { + groupChatViewModel.banMember(user.uid, guid) + } + R.id.menu_item_kick -> { + groupChatViewModel.kickMember(user.uid, guid) + } + + R.id.menu_admin->{ + groupChatViewModel.updateScope(this@MemberFragment,user.uid,guid,CometChatConstants.SCOPE_ADMIN) + } + + R.id.menu_moderator->{ + groupChatViewModel.updateScope(this@MemberFragment,user.uid,guid,CometChatConstants.SCOPE_MODERATOR) + } + R.id.menu_participant->{ + groupChatViewModel.updateScope(this@MemberFragment,user.uid,guid,CometChatConstants.SCOPE_PARTICIPANT) + } + + + + } + + return true + } + + }) + + popup?.show() +// + } + } + } + + }) + } catch (e: Exception) { + e.printStackTrace() + } + myView.rv_member.adapter = memberListAdapter + registerForContextMenu(myView.rv_member) + groupChatViewModel.getMembers(guid, LIMIT = 10) + + + groupChatViewModel.groupMemberList.observe(this, Observer { groupMember -> + groupMember?.let { + memberListAdapter.setMemberList(it) + } + }) + + + myView.rv_member.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + + if (!recyclerView.canScrollVertically(1)) { + groupChatViewModel.getMembers(guid, LIMIT = 10) + } + } + + }) + + return myView + } + + + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + + when(item?.itemId){ + + android.R.id.home->{ + activity?.onBackPressed() + } + } + + return true + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Fragment/OneToOneFragment.kt b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/OneToOneFragment.kt new file mode 100755 index 0000000..e1ef3dc --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Fragment/OneToOneFragment.kt @@ -0,0 +1,831 @@ +package com.inscripts.cometchatpulse.Fragment + + +import android.app.Activity +import android.app.Activity.RESULT_OK +import android.app.Application +import android.arch.lifecycle.Observer +import android.content.Intent +import android.content.pm.PackageManager +import android.content.res.ColorStateList +import android.content.res.Configuration +import android.databinding.DataBindingUtil +import android.graphics.PorterDuff +import android.media.MediaRecorder +import android.os.Bundle +import android.os.Environment +import android.provider.Settings +import android.support.v4.app.Fragment +import android.support.v4.app.FragmentActivity +import android.support.v7.app.AppCompatActivity +import android.support.v7.widget.LinearLayoutManager +import android.support.v7.widget.RecyclerView +import android.util.Log +import android.view.* +import android.widget.Toast +import com.bumptech.glide.Glide +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.CometChat +import com.cometchat.pro.helpers.Logger +import com.cometchat.pro.models.MediaMessage +import com.cometchat.pro.models.TextMessage +import com.inscripts.cometchatpulse.Activities.LocationActivity +import com.inscripts.cometchatpulse.Activities.UserProfileViewActivity +import com.inscripts.cometchatpulse.Adapter.OneToOneAdapter +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.CustomView.AttachmentTypeSelector +import com.inscripts.cometchatpulse.CustomView.StickyHeaderDecoration +import com.inscripts.cometchatpulse.Helpers.* +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract +import com.inscripts.cometchatpulse.StringContract.IntentString.Companion.EXTRA_MIME_DOC +import com.inscripts.cometchatpulse.Utils.Appearance +import com.inscripts.cometchatpulse.Utils.CommonUtil +import com.inscripts.cometchatpulse.Utils.FileUtil +import com.inscripts.cometchatpulse.ViewModel.OnetoOneViewModel +import com.inscripts.cometchatpulse.databinding.FragmentContactDetailBinding +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import org.json.JSONObject +import java.io.File +import java.io.IOException +import kotlin.coroutines.CoroutineContext +import kotlin.random.Random + + +class OneToOneFragment : Fragment(), View.OnClickListener, RecordListener, ActionMode.Callback, OnClickEvent { + + + companion object { + const val ARG_PARAM1 = "param1" + const val ARG_PARAM2 = "param2" + private val TAG = "OneToOneFragment" + var isReply: Boolean = false + var metaData: JSONObject? = JSONObject() + + } + + private lateinit var linearLayoutManager: LinearLayoutManager + + private lateinit var oneToOneAdapter: OneToOneAdapter + + private var ownerId: String + + lateinit var binding: FragmentContactDetailBinding + + private lateinit var userId: String + + private lateinit var config: Configuration + + private var status: String? = null + + private var name: String? = null + + private var avatar: String? = null + + private var uid: String? = null + + private lateinit var onetoOneViewModel: OnetoOneViewModel + + private var audioFileNamewithPath: String? = null + + private var parentJob = Job() + + private lateinit var clickListener: OnBackArrowClickListener + + var mediaRecorder: MediaRecorder? = null + + var count: Int = 0 + + private var attachmentTypeSelector: AttachmentTypeSelector? = null + + private val coroutineContext: CoroutineContext + get() = parentJob + Dispatchers.Main + + private val scope = CoroutineScope(coroutineContext) + + var currentScrollPosition = 0 + + var scrollFlag: Boolean = true + + private var mode: ActionMode? = null + + private var menuResId: Int? = null + + private lateinit var any: Any + + init { + ownerId = CometChat.getLoggedInUser().uid + + } + + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // Inflate the layout for this fragment + binding = DataBindingUtil.inflate(layoutInflater, R.layout.fragment_contact_detail, + container, false) + + setHasOptionsMenu(true) + + name = arguments?.getString(StringContract.IntentString.USER_NAME) + + status = arguments?.getString(StringContract.IntentString.USER_STATUS) + + avatar = arguments?.getString(StringContract.IntentString.USER_AVATAR) + + uid = arguments?.getString(StringContract.IntentString.USER_ID) + + binding.name = name + + binding.status = status + + binding.avatar = avatar + + binding.lastActive = arguments?.getLong(StringContract.IntentString.LAST_ACTIVE) + + userId = arguments?.getString(StringContract.IntentString.USER_ID)!! + + onetoOneViewModel = OnetoOneViewModel(CometChatPro.applicationContext() as Application) + + binding.messageBox?.recordButton?.setListenForRecord(true) + + binding.messageBox?.recordAudioView?.setCancelOffset(16.toFloat()) + + binding.messageBox?.recordAudioView?.setLessThanSecondAllowed(false) + + binding.messageBox?.recordAudioView?.setSlideToCancelText(getString(R.string.slide_to_cancel)) + + binding.messageBox?.recordAudioView?.setCustomSounds(R.raw.record_start, R.raw.record_finished, R.raw.record_error) + + binding.messageBox?.recordButton?.setRecordAudio(binding.messageBox?.recordAudioView) + + binding.messageBox?.recordAudioView?.setOnRecordListener(this) + + config = activity?.resources?.configuration!! + + clickListener = context as OnBackArrowClickListener + + linearLayoutManager = LinearLayoutManager(activity) + binding.recycler.layoutManager = linearLayoutManager + + binding.title.typeface = StringContract.Font.name + binding.subTitle.typeface = StringContract.Font.status + + binding.recycler.itemAnimator?.changeDuration = 0 + oneToOneAdapter = OneToOneAdapter(context!!, CometChat.getLoggedInUser().uid, this) + binding.recycler.addItemDecoration(StickyHeaderDecoration(oneToOneAdapter)) + binding.recycler.setRecyclerListener(RecycleListenerHelper()) + + binding.recycler.adapter = oneToOneAdapter + + + (activity as AppCompatActivity).setSupportActionBar(binding.cometchatToolbar) + (activity as AppCompatActivity).supportActionBar?.setDisplayHomeAsUpEnabled(true) + + binding.cometchatToolbar.title = "" + + binding.cometchatToolbar.setBackgroundColor(StringContract.Color.primaryColor) + + binding.cometchatToolbar.navigationIcon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + binding.subTitle.isSelected = true + + binding.contactPic.borderColor = StringContract.Color.white + binding.contactPic.borderWidth = 2 + + binding.messageBox?.buttonSendMessage?.setOnClickListener(this) + binding.messageBox?.ivAttchment?.setOnClickListener(this) + binding.rlTitlecontainer.setOnClickListener(this) + + binding.rlMain.viewTreeObserver.addOnGlobalLayoutListener { + val heightDiff = binding.rlMain.rootView.height - binding.rlMain.height + try { + + if (heightDiff > CommonUtil.dpToPx(CometChatPro.applicationContext(), 200f)) { + binding.recycler.scrollToPosition(oneToOneAdapter.itemCount - 1) + } + } catch (e: Exception) { + e.printStackTrace() + } + } + + + binding.messageBox?.replyLayout?.ivClose?.setOnClickListener(object : View.OnClickListener { + override fun onClick(p0: View?) { + hideReplyContainer() + } + + }) + + + if (StringContract.AppDetails.theme == Appearance.AppTheme.AZURE_RADIANCE) { + binding.title.setTextColor(StringContract.Color.black) + binding.subTitle.setTextColor(StringContract.Color.black) + binding.messageBox?.buttonSendMessage?.drawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.ivAttchment?.drawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.recordButton?.drawable?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + } else { + binding.messageBox?.buttonSendMessage?.drawable?.setColorFilter(StringContract.Color.primaryColor, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.ivAttchment?.drawable?.setColorFilter(StringContract.Color.primaryColor, PorterDuff.Mode.SRC_ATOP) + binding.messageBox?.recordButton?.drawable?.setColorFilter(StringContract.Color.primaryColor, PorterDuff.Mode.SRC_ATOP) + binding.title.setTextColor(StringContract.Color.white) + binding.subTitle.setTextColor(StringContract.Color.white) + binding.messageBox?.buttonSendMessage?.drawable?.setColorFilter(StringContract.Color.white, PorterDuff.Mode.SRC_ATOP) + } + + binding.cometchatToolbar.overflowIcon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + binding.messageBox?.buttonSendMessage?.backgroundTintList = ColorStateList.valueOf(StringContract.Color.primaryColor) + + + scope.launch(Dispatchers.IO) { + onetoOneViewModel.fetchMessage(LIMIT = 30, userId = userId) + + } + + + + onetoOneViewModel.messageList.observe(this, Observer { messages -> + messages?.let { + oneToOneAdapter.setMessageList(it) + if (scrollFlag) { + scrollBottom() + scrollFlag = false + } + } + }) + + onetoOneViewModel.user.observe(this, Observer { user -> + user?.let { + if (user.uid.equals(userId)) { + binding.lastActive = it.lastActiveAt + binding.status = it.status + } + } + }) + + binding.recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + + binding.cometchatToolbar.isSelected = binding.recycler.canScrollVertically(-1) + + if (!recyclerView.canScrollVertically(-1)) { + onetoOneViewModel.fetchMessage(LIMIT = 30, userId = userId) + scrollFlag = false + } + } + + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + + } + + }) + + return binding.root + } + + + fun hideReplyContainer() { + isReply = false + metaData = null + metaData = JSONObject() + binding.messageBox?.replyLayout?.rlMain?.visibility = View.GONE + } + + + override fun onActionItemClicked(p0: ActionMode?, p1: MenuItem?): Boolean { + + p0?.finish() + + when (p1?.itemId) { + R.id.reply -> { + + isReply = true + metaData = null + metaData = JSONObject() + metaData?.put("reply", "reply") + + binding.messageBox?.replyLayout?.rlMain?.visibility = View.VISIBLE + + if (any is TextMessage) { + binding.messageBox?.replyLayout?.tvNameReply?.text = (any as TextMessage).sender.name + binding.messageBox?.replyLayout?.tvTextMessage?.text = (any as TextMessage).text + metaData?.put("senderName", (any as TextMessage).sender.name) + metaData?.put("senderUid", (any as TextMessage).sender.uid) + metaData?.put("type", (any as TextMessage).type) + metaData?.put("id", (any as TextMessage).id) + metaData?.put("text", (any as TextMessage).text) + + Log.d(TAG, "onActionItemClicked: " + metaData?.toString()) + + } + + if (any is MediaMessage) { + + metaData?.put("senderUid", (any as MediaMessage).sender.uid) + binding.messageBox?.replyLayout?.tvNameReply?.text = (any as MediaMessage).sender.name + metaData?.put("senderName", (any as MediaMessage).sender.name) + metaData?.put("url", (any as MediaMessage).url) + metaData?.put("id", (any as MediaMessage).id) + val type = (any as MediaMessage).type + metaData?.put("type", type) + + if (type == CometChatConstants.MESSAGE_TYPE_IMAGE + || type == CometChatConstants.MESSAGE_TYPE_VIDEO) { + + binding.messageBox?.replyLayout?.ivReplyImage?.visibility = View.VISIBLE + + binding.messageBox?.replyLayout?.ivReplyImage?.let { Glide.with(this).load((any as MediaMessage).url).into(it) } + + } else if (type.equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + + binding.messageBox?.replyLayout?.tvTextMessage?.text = "Audio Message" + + + } else if (type == CometChatConstants.MESSAGE_TYPE_FILE) { + + binding.messageBox?.replyLayout?.tvTextMessage?.text = "File Message" + } + + } + } + } + + return true + } + + override fun onCreateActionMode(p0: ActionMode?, p1: Menu?): Boolean { + + p0?.menuInflater?.inflate(R.menu.action_bar, p1) + mode = p0 + + mode?.title = name + mode?.subtitle = status + + return true + } + + override fun onPrepareActionMode(p0: ActionMode?, p1: Menu?): Boolean { + return false + } + + override fun onDestroyActionMode(p0: ActionMode?) { + mode = null + } + + fun scrollBottom() { + binding.recycler.scrollToPosition(oneToOneAdapter.itemCount - 1) + } + + override fun onClickRl(item: View, any: Any) { + binding.cometchatToolbar.startActionMode(this) + this.any = any + } + + + override fun onRecordCancel() { + binding.messageBox?.editTextChatMessage?.hint = getString(R.string.type_your_message) + stopRecording(true) + } + + override fun onRecordFinish(time: Long) { + binding.messageBox?.editTextChatMessage?.hint = getString(R.string.type_your_message) + stopRecording(false) + + if (audioFileNamewithPath != null) { + Logger.error("audioFileNamewithPath", audioFileNamewithPath) + onetoOneViewModel.sendMediaMessage(audioFileNamewithPath, CometChatConstants.MESSAGE_TYPE_AUDIO, userId, this) + + } + + } + + override fun onRecordLessTime() { + binding.messageBox?.editTextChatMessage?.hint = getString(R.string.type_your_message) + stopRecording(true) + } + + override fun onRecordStart() { + binding.messageBox?.editTextChatMessage?.hint = "" + startRecording() + } + + + private fun startRecording() { + try { + mediaRecorder = MediaRecorder() + mediaRecorder?.setAudioSource(MediaRecorder.AudioSource.MIC) + mediaRecorder?.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) + mediaRecorder?.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB) + audioFileNamewithPath = FileUtil.getOutputMediaFile(context).toString() + mediaRecorder?.setOutputFile(audioFileNamewithPath) + + try { + mediaRecorder?.prepare() + } catch (e: IOException) { + e.printStackTrace() + } + + mediaRecorder?.start() + } catch (e: Exception) { + e.printStackTrace() + } + + } + + private fun stopRecording(isCancel: Boolean) { + try { + if (mediaRecorder != null) { + mediaRecorder?.stop() + mediaRecorder?.reset() + mediaRecorder?.release() + mediaRecorder = null + if (isCancel) { + File(audioFileNamewithPath).delete() + } + } + } catch (e: Exception) { + e.printStackTrace() + } + + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + (activity as AppCompatActivity).supportActionBar?.title = "" + } + + + override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { + + menu?.clear() + inflater?.inflate(R.menu.option_menu, menu) + + val audioCall = menu?.findItem(R.id.voice_call) + val videoCall = menu?.findItem(R.id.video_call) + + menu?.findItem(R.id.menu_leave)?.setVisible(false) + + audioCall?.icon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + videoCall?.icon?.setColorFilter(StringContract.Color.iconTint, PorterDuff.Mode.SRC_ATOP) + + super.onCreateOptionsMenu(menu, inflater) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + + when (item?.itemId) { + + android.R.id.home -> { + + if (config.smallestScreenWidthDp >= 600) { + clickListener.onBackClick() + } else { + activity?.onBackPressed() + } + } + R.id.voice_call -> { + if (CCPermissionHelper.hasPermissions(activity, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + + onetoOneViewModel.initCall(context!!, userId, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_AUDIO) + } else { + CCPermissionHelper.requestPermissions(activity as Activity, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VOICE_CALL) + } + + } + + R.id.video_call -> { + if (CCPermissionHelper.hasPermissions(activity, *arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO))) { + + onetoOneViewModel.initCall(context!!, userId, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_VIDEO) + } else { + CCPermissionHelper.requestPermissions(activity as Activity, arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO), + StringContract.RequestCode.VIDEO_CALL) + } + + + } + } + return true + } + + + override fun onClick(p0: View?) { + + when (p0?.id) { + + + R.id.buttonSendMessage -> { + + val messageText: String? = binding.messageBox?.editTextChatMessage?.text.toString().trim() + + if (messageText != null && !messageText.isEmpty()) { + + + val textMessage = TextMessage(userId, messageText, CometChatConstants.MESSAGE_TYPE_TEXT, CometChatConstants.RECEIVER_TYPE_USER) + + binding.messageBox?.editTextChatMessage?.setText("") + + if (isReply) { + binding.messageBox?.replyLayout?.rlMain?.visibility = View.GONE + textMessage.metadata = metaData + metaData = null + metaData = JSONObject() + } + + onetoOneViewModel.sendTextMessage(textMessage) + + } + + scrollFlag = true + + } + + R.id.rl_titlecontainer -> { + + val profilViewIntent = Intent(context, UserProfileViewActivity::class.java) + profilViewIntent.putExtra(StringContract.IntentString.USER_NAME, name) + profilViewIntent.putExtra(StringContract.IntentString.USER_ID, uid) + profilViewIntent.putExtra(StringContract.IntentString.USER_STATUS, status) + profilViewIntent.putExtra(StringContract.IntentString.USER_AVATAR, avatar) + startActivity(profilViewIntent) + + } + + R.id.iv_attchment -> { + showPopUp() + } + } + + } + + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + when (requestCode) { + StringContract.RequestCode.ADD_DOCUMENT -> + + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + AttachmentHelper.selectMedia(activity, "", EXTRA_MIME_DOC) + } else { + showToast() + } + + StringContract.RequestCode.ADD_GALLERY -> + + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + + val intent = AttachmentHelper.selectMedia(activity, "", StringContract.IntentString.EXTRA_MIME_TYPE) + + startActivityForResult(intent, StringContract.RequestCode.ADD_GALLERY) + + } else { + showToast() + } + + StringContract.RequestCode.TAKE_PHOTO -> + if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + val intent = AttachmentHelper.captureImage() + startActivityForResult(intent, StringContract.RequestCode.TAKE_PHOTO) + + } else { + showToast() + } + + StringContract.RequestCode.TAKE_VIDEO -> + + if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + val intent = AttachmentHelper.captureVideo() + + startActivityForResult(intent, StringContract.RequestCode.TAKE_VIDEO) + + } else { + showToast() + } + + StringContract.RequestCode.RECORD_CODE -> + + if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + } else { + showToast() + } + + StringContract.RequestCode.ADD_SOUND -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED) { + + AttachmentHelper.selectMedia(activity, StringContract.IntentString.AUDIO_TYPE, null) + } else { + showToast() + } + StringContract.RequestCode.VOICE_CALL -> if (grantResults.size > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED) { + + context?.let { onetoOneViewModel.initCall(it, userId, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_AUDIO) } + + } else { + showToast() + } + StringContract.RequestCode.VIDEO_CALL -> if (grantResults.isNotEmpty() && grantResults[0] == + PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { + + context?.let { onetoOneViewModel.initCall(it, userId, CometChatConstants.RECEIVER_TYPE_USER, CometChatConstants.CALL_TYPE_VIDEO) } + } else { + showToast() + } + + StringContract.RequestCode.FILE_WRITE -> if (grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + + FileUtil.makeDirectory(context,CometChatConstants.MESSAGE_TYPE_AUDIO) + } + + + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + + if (resultCode == RESULT_OK && data != null) { + + when (requestCode) { + + StringContract.RequestCode.ADD_GALLERY -> { + val filePath = AttachmentHelper.handleFile(context, data) + onetoOneViewModel.sendMediaMessage(filePath[0], filePath[1], userId, this) + scrollFlag = true + } + StringContract.RequestCode.TAKE_PHOTO -> { + val filePath = AttachmentHelper.handleCameraImage(context, data) + scrollFlag = true + onetoOneViewModel.sendMediaMessage(filePath, CometChatConstants.MESSAGE_TYPE_IMAGE, userId, this) + + } + + StringContract.RequestCode.TAKE_VIDEO -> { + val filePath = AttachmentHelper.handleCameraVideo(context, data) + onetoOneViewModel.sendMediaMessage(filePath, CometChatConstants.MESSAGE_TYPE_VIDEO, userId, this) + scrollFlag = true + + } + + StringContract.RequestCode.ADD_SOUND -> { + val filePath = AttachmentHelper.handleFile(context, data) + onetoOneViewModel.sendMediaMessage(filePath[0], CometChatConstants.MESSAGE_TYPE_AUDIO, userId, this) + scrollFlag = true + } + + StringContract.RequestCode.ADD_DOCUMENT -> { + val filePath = AttachmentHelper.handleFile(context, data) + onetoOneViewModel.sendMediaMessage(filePath[0], filePath[1], userId, this) + scrollFlag = true + + } + } + } + + } + + + private fun showToast() { + Toast.makeText(context, "PERMISSION NOT GRANTED", Toast.LENGTH_SHORT).show() + } + + private fun showPopUp() { + + try { + if (attachmentTypeSelector == null) { + attachmentTypeSelector = AttachmentTypeSelector(context!!, AttachmentTypeListener()) + } + attachmentTypeSelector!!.show(activity as Activity, binding.messageBox?.ivAttchment as View) + } catch (e: Exception) { + e.printStackTrace() + } + } + + private inner class AttachmentTypeListener : AttachmentTypeSelector.AttachmentClickedListener { + override fun onClick(type: Int) { + addAttachment(type, activity) + } + } + + + fun addAttachment(type: Int, activity: FragmentActivity?) { + when (type) { + StringContract.RequestCode.ADD_GALLERY -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.STORAGE_PERMISSION)) { + + val intent = AttachmentHelper.selectMedia(activity, "*/*", StringContract.IntentString.EXTRA_MIME_TYPE) + + startActivityForResult(intent, StringContract.RequestCode.ADD_GALLERY) + + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.STORAGE_PERMISSION, StringContract.RequestCode.ADD_GALLERY) + } + StringContract.RequestCode.ADD_DOCUMENT -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.STORAGE_PERMISSION)) { + + val intent = AttachmentHelper.selectMedia(activity, "*/*", StringContract.IntentString.DOCUMENT_TYPE) + + startActivityForResult(intent, StringContract.RequestCode.ADD_DOCUMENT) + + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.STORAGE_PERMISSION, StringContract.RequestCode.ADD_DOCUMENT) + } + StringContract.RequestCode.ADD_SOUND -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.STORAGE_PERMISSION)) { + + val intent = AttachmentHelper.selectMedia(activity, StringContract.IntentString.AUDIO_TYPE, + null) + + startActivityForResult(intent, StringContract.RequestCode.ADD_SOUND) + + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.STORAGE_PERMISSION, StringContract.RequestCode.ADD_SOUND) + } + + StringContract.RequestCode.TAKE_PHOTO -> + + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.CAMERA_PERMISSION)) { + + val intent = AttachmentHelper.captureImage() + + startActivityForResult(intent, StringContract.RequestCode.TAKE_PHOTO) + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.CAMERA_PERMISSION, StringContract.RequestCode.TAKE_PHOTO) + } + StringContract.RequestCode.TAKE_VIDEO -> + if (CCPermissionHelper.hasPermissions(activity, *StringContract.RequestPermission.CAMERA_PERMISSION)) { + val intent = AttachmentHelper.captureVideo() + startActivityForResult(intent, StringContract.RequestCode.TAKE_VIDEO) + } else { + CCPermissionHelper.requestPermissions(activity as Activity, StringContract.RequestPermission.CAMERA_PERMISSION, StringContract.RequestCode.TAKE_VIDEO) + + } + + StringContract.RequestCode.LOCATION -> { + + try { + + if (CommonUtil.checkPermission(context!!)) { + val locationIntent = Intent(context, LocationActivity::class.java) + locationIntent.putExtra(StringContract.IntentString.ID, userId) + locationIntent.putExtra(StringContract.IntentString.RECIVER_TYPE, + CometChatConstants.RECEIVER_TYPE_USER) + startActivity(locationIntent) + } else { + showDialog("App requires to access your location", "Enable Location") + } + + } catch (e: Exception) { + + } + } + } + } + + + private fun showDialog(message: String, title: String) { + val builder = context?.let { android.support.v7.app.AlertDialog.Builder(it) } + builder?.setTitle(context?.let { CommonUtil.setTitle(title, it) })?.setMessage(message) + ?.setCancelable(true) + ?.setNegativeButton(context?.let { CommonUtil.setTitle("Cancel", it) }) { dialogInterface, i -> dialogInterface.dismiss() } + ?.setPositiveButton(context?.let { CommonUtil.setTitle("Go to settings to enable", it) }) { dialogInterface, i -> + startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)) + }?.show() + } + + override fun onStart() { + super.onStart() + + } + + + override fun onResume() { + super.onResume() + Log.d(TAG, "onResume: ") + onetoOneViewModel.receiveMessageListener(StringContract.ListenerName.MESSAGE_LISTENER, ownerId) + onetoOneViewModel.addPresenceListener(StringContract.ListenerName.USER_LISTENER) + } + + override fun onPause() { + super.onPause() + Log.d(TAG, "onPause: ") + parentJob.cancel() + onetoOneViewModel.removeMessageListener(StringContract.ListenerName.MESSAGE_LISTENER) + onetoOneViewModel.removePresenceListener(StringContract.ListenerName.USER_LISTENER) + stopRecording(false) + oneToOneAdapter.stopPlayer() + } + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/AttachmentHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/AttachmentHelper.kt new file mode 100755 index 0000000..286419b --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/AttachmentHelper.kt @@ -0,0 +1,138 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.app.Activity +import android.content.ActivityNotFoundException +import android.content.Context +import android.content.Intent +import android.graphics.Bitmap +import android.os.Build +import android.provider.MediaStore +import android.support.v4.app.FragmentActivity +import android.util.Log +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.helpers.Logger +import com.inscripts.cometchatpulse.Utils.FileUtil +import com.inscripts.cometchatpulse.Utils.FileUtil.Companion.getPath +import com.inscripts.cometchatpulse.Utils.MediaUtil +import java.io.File +import java.lang.Exception +import java.net.URISyntaxException + +class AttachmentHelper { + + companion object { + + fun selectMedia(activity: FragmentActivity?, type: String, + extraMimeType: Array?):Intent { + + val intent = Intent() + intent.type = type + + if (extraMimeType != null && Build.VERSION.SDK_INT >= 19) { + intent.putExtra(Intent.EXTRA_MIME_TYPES, extraMimeType) + } + + intent.action = Intent.ACTION_OPEN_DOCUMENT + + intent.action = Intent.ACTION_GET_CONTENT + + return intent + + } + + fun captureImage():Intent { + val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) + return intent + } + + fun captureVideo():Intent { + val intent = Intent(MediaStore.ACTION_VIDEO_CAPTURE) + intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 0) + intent.putExtra(MediaStore.EXTRA_SIZE_LIMIT, 15000000L) + + return intent + + } + + fun handleCameraImage(context: Context?, data: Intent):String { + var filePath: String="" + try { + Logger.error("uri", data.data?.toString()) + val bitmap = data.extras!!.get("data") as Bitmap + val fileUri = FileUtil.getImageUri(context!!, bitmap) + + Logger.error("", "fileUri: $fileUri") + filePath= FileUtil.ImagePath(fileUri, context) + + }catch (e:Exception){ + e.printStackTrace() + } + + return filePath + } + + fun handleCameraVideo(context: Context?, data: Intent): String? { + val path = context?.let { FileUtil.getVideoPath(data.data, it) } + Logger.debug("handleCameraVideo", " Video Path $path") + return path + + } + + fun handleFile(context: Context?, data: Intent): Array { + + var filePath: Array = arrayOfNulls(3) + +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { +// val uri = data.data +// val file = File(uri!!.path)//create path from uri +// val split = file.path.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()//split the path. +// for (string in split){ +// Log.d("handleFile",string) +// } +// val path=split[0] +// Log.d("File",split[1]) +// var messageType:String="" +// try { +// Log.d("filetype",context?.contentResolver?.getType(uri)) +// val type: String? =context?.contentResolver?.getType(uri)?.toLowerCase() +// +// if (type!=null) { +// if (type.contains("image")||type.contains("picture")||type.contains("photo")){ +// messageType=CometChatConstants.MESSAGE_TYPE_IMAGE +// } +// else if (type.contains("video")||type.contains("mp4")||type.contains("avi")|| +// type.contains("flv")){ +// messageType=CometChatConstants.MESSAGE_TYPE_VIDEO +// } +// else if (type.contains("aac")||type.contains("m4a")||type.contains("amr") +// ||type.contains("opus")||type.contains("mp3")){ +// +// messageType=CometChatConstants.MESSAGE_TYPE_AUDIO +// } +// else{ +// messageType=CometChatConstants.MESSAGE_TYPE_FILE +// } +// } +// +// }catch (e:Exception){ +// e.printStackTrace() +// } +// +// +// filePath= arrayOf(path,messageType) +// +// } else { + try { + filePath = getPath(context!!, data.data) + } catch (e: URISyntaxException) { + e.printStackTrace() + } + +// } + + return filePath + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CCPermissionHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CCPermissionHelper.kt new file mode 100755 index 0000000..c3ce8b9 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CCPermissionHelper.kt @@ -0,0 +1,63 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.Manifest +import android.app.Activity +import android.content.Context +import android.content.pm.PackageManager +import android.os.Build +import android.support.v4.app.ActivityCompat +import com.cometchat.pro.helpers.Logger + + +class CCPermissionHelper { + + + companion object { + + + + private val TAG = CCPermissionHelper::class.java.simpleName + + + // requested permissions + val REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE = Manifest.permission.WRITE_EXTERNAL_STORAGE + val REQUEST_PERMISSION_RECORD_AUDIO = Manifest.permission.RECORD_AUDIO + val REQUEST_PERMISSION_CAMERA = Manifest.permission.CAMERA + val REQUEST_PERMISSION_HARDWARE_LOCATION=Manifest.permission.LOCATION_HARDWARE + val REQUEST_PERMISSION_COARSE_LOCATION=Manifest.permission.ACCESS_COARSE_LOCATION + val REQUEST_PERMISSION_FINE_LOCATION=Manifest.permission.ACCESS_FINE_LOCATION + val REQUEST_PERMISSION_READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE + + /** + * method to check whether the permissions has been granted to the app + * @param context the context_menu of the requesting component + * @param permissions list of permissions requested + * @return boolean whether app has permission or not + */ + fun hasPermissions(context: Context?, vararg permissions: String): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context != null + && permissions != null) { + for (permission in permissions) { + Logger.error(TAG, " hasPermissions() : Permission : " + permission + + "checkSelfPermission : " + ActivityCompat.checkSelfPermission(context, permission)) + if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) { + return false + } + } + } + return true + } + + /** + * method to request permissions + * @param activity the activity requesting permissions + * @param permission list of the requested permissions + * @param requestCode int request code + */ + fun requestPermissions(activity: Activity, permission: Array, requestCode: Int) { + ActivityCompat.requestPermissions(activity, permission, requestCode) + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CardItemTouchHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CardItemTouchHelper.kt new file mode 100755 index 0000000..9d34c01 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CardItemTouchHelper.kt @@ -0,0 +1,72 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.content.Context +import android.graphics.* +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.support.v7.widget.RecyclerView +import android.support.v7.widget.helper.ItemTouchHelper + + + +open class CardItemTouchHelper(val context: Context,val icon: Drawable, val backgroundColor:Int) + : ItemTouchHelper.SimpleCallback(0,ItemTouchHelper.LEFT) { + override fun onSwiped(p0: RecyclerView.ViewHolder, p1: Int) { + + } + + private val intrinsicWidth:Int + private val intrinsicHeight:Int + private val background:ColorDrawable + private val clearPaint:Paint + + init { + intrinsicWidth = icon.intrinsicWidth + intrinsicHeight = icon.intrinsicHeight + background=ColorDrawable() + clearPaint = Paint() + } + + + override fun onMove(p0: RecyclerView, p1: RecyclerView.ViewHolder, p2: RecyclerView.ViewHolder): Boolean { + return false + } + + + override fun onChildDraw(c: Canvas, recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, dX: Float, dY: Float, actionState: Int, isCurrentlyActive: Boolean) { + + val itemView = viewHolder.itemView + val itemHeight = itemView.bottom - itemView.top + val isCanceled = dX == 0f && !isCurrentlyActive + + if (isCanceled) { + clearCanvas(c, itemView.right + dX, itemView.top.toFloat(), itemView.right.toFloat(), itemView.bottom.toFloat()) + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + return + } + + background.color = backgroundColor + background.setBounds(itemView.right + dX.toInt(), itemView.top, itemView.right, itemView.bottom) + background.draw(c) + + // Calculate position of icon + val IconTop = itemView.top + (itemHeight - intrinsicHeight) / 2 + val IconMargin = (itemHeight - intrinsicHeight) / 2 + val IconLeft = itemView.right - IconMargin - intrinsicWidth + val IconRight = itemView.right -IconMargin + val IconBottom = IconTop + intrinsicHeight + + // Draw the icon + icon.setBounds(IconLeft, IconTop, IconRight, IconBottom) + icon.draw(c) + + super.onChildDraw(c, recyclerView, viewHolder, dX/2.5f, dY, actionState, isCurrentlyActive) + } + + + private fun clearCanvas(c: Canvas?, left: Float, top: Float, right: Float, bottom: Float) { + c?.drawRect(left, top, right, bottom, clearPaint) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/ChildClickListener.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/ChildClickListener.kt new file mode 100755 index 0000000..dbd3c91 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/ChildClickListener.kt @@ -0,0 +1,5 @@ +package com.inscripts.cometchatpulse.Helpers + +interface ChildClickListener { + fun OnChildClick(t:Any) +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CometChatAudioHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CometChatAudioHelper.kt new file mode 100755 index 0000000..263a7f4 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CometChatAudioHelper.kt @@ -0,0 +1,107 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.content.Context +import android.media.AudioManager +import android.media.SoundPool +import android.net.Uri +import android.os.Build +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.Utils.CommonUtil + +class CometChatAudioHelper(private val context: Context) { + + private val incomingAudioHelper: IncomingAudioHelper + + private val outgoingAudioHelper: OutgoingAudioHelper + + private val soundPool: SoundPool + + private val disconnectedSoundId: Int + + init { + this.incomingAudioHelper = IncomingAudioHelper(context) + this.outgoingAudioHelper = OutgoingAudioHelper(context) + this.soundPool = SoundPool(1, AudioManager.STREAM_VOICE_CALL, 0) + this.disconnectedSoundId = this.soundPool.load(context, R.raw.beep2, 1) + } + + fun initAudio() { + val audioManager = CommonUtil.getAudioManager(context) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + audioManager.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) + } else { + audioManager.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) + } + } + + fun startIncomingAudio(ringtone: Uri, isVibarte: Boolean) { + val audioManager = CommonUtil.getAudioManager(context) + val speaker = !audioManager.isWiredHeadsetOn() && !audioManager.isBluetoothScoOn() + + audioManager.setMode(AudioManager.MODE_RINGTONE) + audioManager.setMicrophoneMute(false) + audioManager.setSpeakerphoneOn(speaker) + + incomingAudioHelper.start(ringtone, isVibarte) + } + + fun startOutgoingAudio(type: OutgoingAudioHelper.Type) { + val audioManager = CommonUtil.getAudioManager(context) + audioManager.setMicrophoneMute(false) + + if (type === OutgoingAudioHelper.Type.IN_COMMUNICATION) { + audioManager.setSpeakerphoneOn(false) + } + + audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION) + + outgoingAudioHelper.start(type) + } + + fun silenceIncomingRinger() { + incomingAudioHelper.stop() + } + + fun startCall(preserveSpeakerphone: Boolean) { + val audioManager = CommonUtil.getAudioManager(context) + + incomingAudioHelper.stop() + outgoingAudioHelper.stop() + + audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION) + + if (!preserveSpeakerphone) { + audioManager.setSpeakerphoneOn(false) + } + + } + + fun stop(playDisconnected: Boolean) { + val audioManager = CommonUtil.getAudioManager(context) + audioManager.setSpeakerphoneOn(false) + audioManager.setMicrophoneMute(false) + audioManager.setMode(AudioManager.MODE_NORMAL) + audioManager.abandonAudioFocus(null) + incomingAudioHelper.stop() + outgoingAudioHelper.stop() + + if (playDisconnected) { + soundPool.play(disconnectedSoundId, 1.0f, 1.0f, 0, 0, 1.0f) + } + + if (audioManager.isBluetoothScoOn()) { + audioManager.setBluetoothScoOn(false) + audioManager.stopBluetoothSco() + } + + + } + + companion object { + + private val TAG = "CometChatAudioHelper" + } + + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CustomAlertDialogHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CustomAlertDialogHelper.kt new file mode 100755 index 0000000..e65105c --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/CustomAlertDialogHelper.kt @@ -0,0 +1,83 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface +import android.view.View +import com.cometchat.pro.helpers.Logger +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract + +class CustomAlertDialogHelper: View.OnClickListener { + + private val TAG = CustomAlertDialogHelper::class.java.simpleName + + private lateinit var onAlertDialogButtonClick: OnAlertDialogButtonClickListener + + private var view: View? = null + + private lateinit var alertDialogCreater: AlertDialog + + private var popupId: Int = 0 + private var colorPrimary: Int = 0 + + // cc cometChat; + constructor(context: Context, title: String, view: View, positiveTitle: String, neutralTitle: String, + negativeTitle: String, onAlertDialogButton: OnAlertDialogButtonClickListener, popUpId: Int, isCancelable: Boolean) { + onAlertDialogButtonClick = onAlertDialogButton + // LayoutInflater inflater = (LayoutInflater) + // context_menu.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + this.view = view + val builder = AlertDialog.Builder(context) + + //todo get color from cc Sdk + // cometChat = cc.getInstance(context_menu); + colorPrimary = StringContract.Color.primaryDarkColor + // colorPrimary = (int) cometChat.getCCSetting(new CCSettingMapper(SettingType.UI_SETTINGS, SettingSubType.COLOR_PRIMARY)); + builder.setView(view) + builder.setCancelable(isCancelable) + if (title != "") { + builder.setTitle(title) + } + + Logger.error(TAG, "ACTION_SEND title : $title") + Logger.error(TAG, "ACTION_SEND positiveTitle : $positiveTitle") + Logger.error(TAG, "ACTION_SEND negativeTitle : $negativeTitle") + + if (positiveTitle != "") { + builder.setPositiveButton(positiveTitle, null) + } + if (negativeTitle != "") { + builder.setNegativeButton(negativeTitle, null) + } + if (neutralTitle != "") { + builder.setNeutralButton(neutralTitle, null) + } + + alertDialogCreater = builder.create() + alertDialogCreater.show() + + this.popupId = popUpId + + val positiveButton = alertDialogCreater.getButton(DialogInterface.BUTTON_POSITIVE) + positiveButton.id = DialogInterface.BUTTON_POSITIVE + positiveButton.setTextColor(colorPrimary) + positiveButton.setOnClickListener(this) + + val negativeButton = alertDialogCreater.getButton(DialogInterface.BUTTON_NEGATIVE) + negativeButton.id = DialogInterface.BUTTON_NEGATIVE + negativeButton.setTextColor(colorPrimary) + negativeButton.setOnClickListener(this) + + val neutralButton = alertDialogCreater.getButton(DialogInterface.BUTTON_NEUTRAL) + neutralButton.id = DialogInterface.BUTTON_NEUTRAL + neutralButton.setTextColor(colorPrimary) + neutralButton.setOnClickListener(this) + } + + + override fun onClick(v: View) { + onAlertDialogButtonClick.onButtonClick(alertDialogCreater, view, v.id, popupId) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/IncomingAudioHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/IncomingAudioHelper.kt new file mode 100755 index 0000000..6c8ad85 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/IncomingAudioHelper.kt @@ -0,0 +1,138 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.annotation.TargetApi +import android.content.Context +import android.media.AudioManager +import android.media.MediaPlayer +import android.net.Uri +import android.os.Build +import android.os.Vibrator +import com.cometchat.pro.helpers.Logger +import com.inscripts.cometchatpulse.Utils.CommonUtil +import java.io.IOException + + +class IncomingAudioHelper constructor(context: Context) { + + private val context: Context + private val vibrator: Vibrator + + private var player: MediaPlayer? = null + + init { + this.context = context.applicationContext + this.vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + } + + fun start(uri: Uri?, vibrate: Boolean) { + val audioManager = CommonUtil.getAudioManager(context) + + if (player != null) player!!.release() + if (uri != null) player = createPlayer(uri) + + val ringerMode = audioManager.getRingerMode() + + if (shouldVibrate(context, player, ringerMode, vibrate)) { + Logger.error(TAG, "Starting vibration") + vibrator.vibrate(VIBRATE_PATTERN, 1) + } + + if (player != null && ringerMode == AudioManager.RINGER_MODE_NORMAL) { + try { + if (!player!!.isPlaying) { + player!!.prepare() + player!!.start() + Logger.error(TAG, "Playing ringtone now...") + } else { + Logger.error(TAG, "Ringtone is already playing, declining to restart.") + } + } catch (e: IllegalStateException) { + Logger.error(TAG, e.message) + player = null + } catch (e: IOException) { + Logger.error(TAG, e.message) + player = null + } + + } else { + Logger.error(TAG, "Not ringing, mode: $ringerMode") + } + } + + fun stop() { + if (player != null) { + Logger.error(TAG, "Stopping ringer") + player!!.release() + player = null + } + + Logger.error(TAG, "Cancelling vibrator") + vibrator.cancel() + } + + private fun shouldVibrate(context: Context, player: MediaPlayer?, ringerMode: Int, vibrate: Boolean): Boolean { + if (player == null) { + return true + } + + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + shouldVibrateNew(context, ringerMode, vibrate) + } else { + shouldVibrateOld(context, vibrate) + } + } + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + private fun shouldVibrateNew(context: Context, ringerMode: Int, vibrate: Boolean): Boolean { + val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator + + if (vibrator == null || !vibrator.hasVibrator()) { + return false + } + + return if (vibrate) { + ringerMode != AudioManager.RINGER_MODE_SILENT + } else { + ringerMode == AudioManager.RINGER_MODE_VIBRATE + } + } + + private fun shouldVibrateOld(context: Context, vibrate: Boolean): Boolean { + val audioManager = CommonUtil.getAudioManager(context) + return vibrate && audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER) + } + + private fun createPlayer(ringtoneUri: Uri): MediaPlayer? { + try { + val mediaPlayer = MediaPlayer() + + mediaPlayer.setOnErrorListener(MediaPlayerErrorListener()) + mediaPlayer.setDataSource(context, ringtoneUri) + mediaPlayer.isLooping = true + mediaPlayer.setAudioStreamType(AudioManager.STREAM_RING) + + return mediaPlayer + } catch (e: IOException) { + Logger.error(TAG, "Failed to create player for incoming call ringer") + return null + } + + } + + + private inner class MediaPlayerErrorListener : MediaPlayer.OnErrorListener { + override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean { + Logger.error(TAG, "onError($mp, $what, $extra") + player = null + return false + } + } + + companion object { + + private val TAG = "IncomingAudioHelper" + + private val VIBRATE_PATTERN = longArrayOf(0, 1000, 1000) + } + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnAlertDialogButtonClickListener.java b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnAlertDialogButtonClickListener.java new file mode 100755 index 0000000..77bbdde --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnAlertDialogButtonClickListener.java @@ -0,0 +1,8 @@ +package com.inscripts.cometchatpulse.Helpers; + +import android.app.AlertDialog; +import android.view.View; + +public interface OnAlertDialogButtonClickListener { + public void onButtonClick(AlertDialog alertDialog, View v, int which, int popupId); +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnBackArrowClickListener.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnBackArrowClickListener.kt new file mode 100755 index 0000000..16f7581 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnBackArrowClickListener.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.Helpers + +interface OnBackArrowClickListener { + + fun onBackClick() +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnClickEvent.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnClickEvent.kt new file mode 100755 index 0000000..15308a8 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnClickEvent.kt @@ -0,0 +1,8 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.view.View +import com.cometchat.pro.models.User + +interface OnClickEvent { + fun onClickRl(item:View,any: Any) +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnOptionClickListener.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnOptionClickListener.kt new file mode 100755 index 0000000..c58ccdb --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnOptionClickListener.kt @@ -0,0 +1,10 @@ +package com.inscripts.cometchatpulse.Helpers + +abstract class OnOptionClickListener { + open fun OnOptionClick(position:Int){ + + } + open fun OnOptionClick( values:Array){ + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnRecordClickListener.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnRecordClickListener.kt new file mode 100755 index 0000000..e744a68 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OnRecordClickListener.kt @@ -0,0 +1,9 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.view.View + +interface OnRecordClickListener { + + fun onRecordClick(v: View) + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OutgoingAudioHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OutgoingAudioHelper.kt new file mode 100755 index 0000000..0097154 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/OutgoingAudioHelper.kt @@ -0,0 +1,70 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.content.Context +import android.media.AudioManager +import android.media.MediaPlayer +import android.net.Uri +import com.cometchat.pro.helpers.Logger +import com.inscripts.cometchatpulse.R +import java.io.IOException + +class OutgoingAudioHelper(private val context: Context) { + + private var type: Type? = null + + private val handler = android.os.Handler() + + private var mediaPlayer: MediaPlayer? = null + + enum class Type { + IN_COMMUNICATION, + RINGING + } + + fun start(type: Type) { + val soundId: Int + this.type = type + if (type == Type.IN_COMMUNICATION || type == Type.RINGING) + soundId = R.raw.ring + else + throw IllegalArgumentException("Not a valid sound type") + + if (mediaPlayer != null) { + mediaPlayer!!.release() + } + mediaPlayer = MediaPlayer() + mediaPlayer!!.setAudioStreamType(AudioManager.STREAM_VOICE_CALL) + mediaPlayer!!.isLooping = true + val packageName = context.packageName + val dataUri = Uri.parse("android.resource://$packageName/$soundId") + + try { + mediaPlayer!!.setDataSource(context, dataUri) + mediaPlayer!!.prepare() + + mediaPlayer!!.start() + + } catch (e: IllegalArgumentException) { + Logger.error(TAG, e.message) + } catch (e: SecurityException) { + Logger.error(TAG, e.message) + } catch (e: IllegalStateException) { + Logger.error(TAG, e.message) + } catch (e: IOException) { + Logger.error(TAG, e.message) + } + + } + + fun stop() { + if (mediaPlayer == null) return + mediaPlayer!!.stop() + mediaPlayer!!.release() + mediaPlayer = null + } + + companion object { + + private val TAG = "OutgoingAudioHelper" + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecordListener.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecordListener.kt new file mode 100755 index 0000000..9e797d5 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecordListener.kt @@ -0,0 +1,10 @@ +package com.inscripts.cometchatpulse.Helpers + +interface RecordListener { + + fun onRecordStart() + fun onRecordCancel() + fun onRecordFinish(time: Long) + fun onRecordLessTime() + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecycleListenerHelper.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecycleListenerHelper.kt new file mode 100755 index 0000000..533da1c --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecycleListenerHelper.kt @@ -0,0 +1,22 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.support.v7.widget.RecyclerView +import com.google.android.gms.maps.GoogleMap +import com.inscripts.cometchatpulse.ViewHolder.LeftLocationViewHolder +import com.inscripts.cometchatpulse.ViewHolder.RightLocationViewHolder + +class RecycleListenerHelper :RecyclerView.RecyclerListener { + + + override fun onViewRecycled(p0: RecyclerView.ViewHolder) { + + if (p0 is RightLocationViewHolder){ + p0.googleMap?.clear() + p0.googleMap?.mapType=GoogleMap.MAP_TYPE_NONE + } + if (p0 is LeftLocationViewHolder){ + p0.googleMap?.clear() + p0.googleMap?.mapType=GoogleMap.MAP_TYPE_NONE + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecyclerviewTouchListener.kt b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecyclerviewTouchListener.kt new file mode 100755 index 0000000..c36fec2 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Helpers/RecyclerviewTouchListener.kt @@ -0,0 +1,47 @@ +package com.inscripts.cometchatpulse.Helpers + +import android.content.Context +import android.support.v7.widget.RecyclerView +import android.view.GestureDetector +import android.view.MotionEvent +import android.view.View + +class RecyclerviewTouchListener(var1: Context, var2: RecyclerView, private val clickListener: ClickListener?) : + RecyclerView.OnItemTouchListener { + + private val gestureDetector: GestureDetector + + init { + this.gestureDetector = GestureDetector(var1, object : GestureDetector.SimpleOnGestureListener() { + override fun onSingleTapUp(var1: MotionEvent): Boolean { + return true + } + + override fun onLongPress(var1: MotionEvent) { + val var2x = var2.findChildViewUnder(var1.x, var1.y) + if (var2x != null && clickListener != null) { + clickListener!!.onLongClick(var2x, var2.getChildPosition(var2x)) + } + + } + }) + } + + override fun onInterceptTouchEvent(var1: RecyclerView, var2: MotionEvent): Boolean { + val var3 = var1.findChildViewUnder(var2.x, var2.y) + if (var3 != null && this.clickListener != null && this.gestureDetector.onTouchEvent(var2)) { + this.clickListener.onClick(var3, var1.getChildPosition(var3)) + } + + return false + } + + override fun onTouchEvent(var1: RecyclerView, var2: MotionEvent) {} + + override fun onRequestDisallowInterceptTouchEvent(var1: Boolean) {} + + interface ClickListener { + fun onClick(var1: View, var2: Int) + fun onLongClick(var1: View?, var2: Int) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Pojo/GroupOption.kt b/app/src/main/java/com/inscripts/cometchatpulse/Pojo/GroupOption.kt new file mode 100755 index 0000000..fc89016 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Pojo/GroupOption.kt @@ -0,0 +1,9 @@ +package com.inscripts.cometchatpulse.Pojo + +import android.graphics.drawable.Drawable + +data class GroupOption( + + var name:String, + var icon: Drawable? +) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Repository/GroupRepository.kt b/app/src/main/java/com/inscripts/cometchatpulse/Repository/GroupRepository.kt new file mode 100755 index 0000000..a7f7568 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Repository/GroupRepository.kt @@ -0,0 +1,318 @@ +package com.inscripts.cometchatpulse.Repository + + +import android.app.ProgressDialog +import android.arch.lifecycle.MutableLiveData +import android.content.Context +import android.content.Intent +import android.support.annotation.WorkerThread +import android.support.v4.app.FragmentActivity +import android.util.Log +import android.view.View +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.CometChat +import com.cometchat.pro.exceptions.CometChatException +import com.cometchat.pro.core.* +import com.cometchat.pro.models.Group +import com.cometchat.pro.models.GroupMember +import com.facebook.shimmer.ShimmerFrameLayout +import com.inscripts.cometchatpulse.Activities.CreateGroupActivity +import com.inscripts.cometchatpulse.Activities.GroupDetailActivity +import com.inscripts.cometchatpulse.Activities.MainActivity +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.Fragment.MemberFragment + + +class GroupRepository { + + var groupList: MutableLiveData> = MutableLiveData() + + var group: MutableLiveData = MutableLiveData() + + var groupListMutable = mutableListOf() + + var groupMemberList = mutableListOf() + + var banGroupMemberList= mutableListOf() + + var groupMemberLiveData:MutableLiveData> = MutableLiveData() + + var banMemberLiveData:MutableLiveData> = MutableLiveData() + + var groupRequest: GroupsRequest? = null + + var groupMemberRequest: GroupMembersRequest? = null + + var groupBanMemberRequest:BannedGroupMembersRequest?=null + + private lateinit var groupJoin:onGroupJoin + + + @WorkerThread + fun fetchGroup(LIMIT: Int,shimmerFrameLayout: ShimmerFrameLayout?) { + + if (groupRequest == null) { + + groupRequest = GroupsRequest.GroupsRequestBuilder().setLimit(LIMIT).build() + + groupRequest!!.fetchNext(object : CometChat.CallbackListener>() { + override fun onSuccess(p0: List?) { + p0?.let { groupListMutable.addAll(it) } + groupList.value = groupListMutable + + shimmerFrameLayout?.stopShimmer() + shimmerFrameLayout?.visibility=View.GONE + } + + + override fun onError(p0: CometChatException?) { + Toast.makeText(CometChatPro.applicationContext(),p0?.message,Toast.LENGTH_SHORT).show() + shimmerFrameLayout?.stopShimmer() + shimmerFrameLayout?.visibility=View.GONE + } + + }) + } else { + groupRequest!!.fetchNext(object : CometChat.CallbackListener>() { + override fun onSuccess(p0: List?) { + p0?.let { groupListMutable.addAll(it) } + groupList.value = groupListMutable + } + + override fun onError(p0: CometChatException?) { + p0?.printStackTrace() + } + + }) + } + } + + @WorkerThread + fun getGroup(guid: String) { + CometChat.getGroup(guid, object : CometChat.CallbackListener() { + override fun onSuccess(p0: Group?) { + + Log.d("onSuccess",p0?.toString()) + + } + + override fun onError(p0: CometChatException?) { + + } + }) + } + + @WorkerThread + fun unBanMember(guid: String,uid: String){ + + CometChat.unbanGroupMember(uid,guid,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: String?) { + + showToast("Successfully unbanned Member") + } + + override fun onError(p0: CometChatException?) { + p0?.message?.let { showToast(it) } + } + + }) + } + + + @WorkerThread + fun getBannedMember(guid: String,LIMIT: Int){ + if (groupBanMemberRequest==null){ + + groupBanMemberRequest=BannedGroupMembersRequest.BannedGroupMembersRequestBuilder(guid).setLimit(LIMIT).build() + + groupBanMemberRequest?.fetchNext(object :CometChat.CallbackListener>(){ + override fun onSuccess(p0: List?) { + + p0?.let { banGroupMemberList.addAll(it) } + banMemberLiveData.value=banGroupMemberList + + } + + override fun onError(p0: CometChatException?) { + + } + + }) + } + else{ + groupBanMemberRequest?.fetchNext(object :CometChat.CallbackListener>(){ + override fun onSuccess(p0: List?) { + p0?.let { banGroupMemberList.addAll(it) } + banMemberLiveData.value=banGroupMemberList + } + + override fun onError(p0: CometChatException?) { + + } + + }) + } + } + @WorkerThread + fun getGroupMember(guid: String, LIMIT: Int){ + + if (groupMemberRequest==null) { + + groupMemberRequest = GroupMembersRequest.GroupMembersRequestBuilder(guid).setLimit(LIMIT).build() + + groupMemberRequest?.fetchNext(object : CometChat.CallbackListener>() { + override fun onSuccess(p0: List?) { + + p0?.let { groupMemberList.addAll(it) } + + groupMemberLiveData.value=groupMemberList + } + + override fun onError(p0: CometChatException?) { + + } + + }) + } + else{ + groupMemberRequest?.fetchNext(object : CometChat.CallbackListener>() { + override fun onSuccess(p0: List?) { + + p0?.let { groupMemberList.addAll(it) } + groupMemberLiveData.value=groupMemberList + } + + override fun onError(p0: CometChatException?) { + p0?.printStackTrace() + } + + + }) + } + + } + + @WorkerThread + fun clearjob() { + + } + + @WorkerThread + fun joinGroup(group: Group, progressDialog: ProgressDialog?,resId:Int,context:Context) { + + groupJoin=context as onGroupJoin + + CometChat.joinGroup(group.guid,group.groupType,group.password,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: String?) { + progressDialog?.dismiss() + group.setHasJoined(true) + groupJoin.onJoined(group,resId) + } + + override fun onError(p0: CometChatException?) { + progressDialog?.dismiss() + Toast.makeText(CometChatPro.applicationContext(),p0?.message,Toast.LENGTH_SHORT).show() + } + + }) + } + @WorkerThread + fun createGroup(context: Context,group: Group) { + CometChat.createGroup(group,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: Group?) { + + (context as CreateGroupActivity).finish() + Toast.makeText(CometChatPro.applicationContext(),p0?.groupType+" group created ",Toast.LENGTH_SHORT).show() + } + + override fun onError(p0: CometChatException?) { + Toast.makeText(CometChatPro.applicationContext()," group creation failed ",Toast.LENGTH_SHORT).show() + } + + }) + } + @WorkerThread + fun banMember(uid: String, guid: String) { + CometChat.banGroupMember(uid,guid,object :CometChat.CallbackListener(){ + + override fun onSuccess(p0: String?) { + showToast("Successfully banned Member") + } + override fun onError(p0: CometChatException?) { + showToast(p0?.message.toString()) + } + + }) + + } + + fun showToast(msg:String){ + Toast.makeText(CometChatPro.applicationContext(), msg, Toast.LENGTH_SHORT).show() + } + @WorkerThread + fun kickMember(uid: String, guid: String) { + CometChat.kickGroupMember(uid,guid,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: String?) { + showToast("Successfully kicked Member") + } + + override fun onError(p0: CometChatException?) { + p0?.message?.let { showToast(it) } + } + + }) + } + @WorkerThread + fun leaveGroup(guid: String,activity: FragmentActivity?) { + CometChat.leaveGroup(guid,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: String?) { + showToast("Successfully left group") + + activity?.onBackPressed() + } + + override fun onError(p0: CometChatException?) { + Toast.makeText(CometChatPro.applicationContext(),p0?.message,Toast.LENGTH_SHORT).show() + } + + }) + } + + fun deleteGroup(groupId: String,context: Context) { + + CometChat.deleteGroup(groupId,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: String?) { + context.startActivity(Intent(context,MainActivity::class.java)) + (context as GroupDetailActivity).finish() + } + + override fun onError(p0: CometChatException?) { + Toast.makeText(CometChatPro.applicationContext(),p0?.message,Toast.LENGTH_SHORT).show() + } + + }) + } + + fun updateScope(fragment:MemberFragment,uid: String, guid: String,scope:String) { + + CometChat.updateGroupMemberScope(uid,guid,scope,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: String?) { + Toast.makeText(CometChatPro.applicationContext(),"Success",Toast.LENGTH_SHORT).show() + + + + } + + override fun onError(p0: CometChatException?) { + Toast.makeText(CometChatPro.applicationContext(),p0?.message,Toast.LENGTH_SHORT).show() + } + + }) + } + + + interface onGroupJoin{ + fun onJoined(group: Group,resId: Int) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Repository/MessageRepository.kt b/app/src/main/java/com/inscripts/cometchatpulse/Repository/MessageRepository.kt new file mode 100755 index 0000000..6b086aa --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Repository/MessageRepository.kt @@ -0,0 +1,534 @@ +package com.inscripts.cometchatpulse.Repository + +import android.app.Activity +import android.arch.lifecycle.MutableLiveData +import android.content.Context +import android.support.annotation.WorkerThread +import android.util.Log +import android.widget.RelativeLayout +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.Call +import com.cometchat.pro.core.CometChat +import com.cometchat.pro.core.MessagesRequest +import com.cometchat.pro.exceptions.CometChatException +import com.cometchat.pro.models.* +import com.inscripts.cometchatpulse.Activities.CallActivity +import com.inscripts.cometchatpulse.Activities.LocationActivity +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.Utils.CommonUtil + +class MessageRepository { + + var ownerId: String + + var messageRequest: MessagesRequest? = null + + var groupMessageRequest: MessagesRequest? = null + + var user: MutableLiveData = MutableLiveData() + + init { + ownerId = CometChat.getLoggedInUser().uid + } + + var onetoOneMessageList: MutableLiveData> = MutableLiveData() + + var groupMessageList: MutableLiveData> = MutableLiveData() + + var mutableOneToOneMessageList = mutableListOf() + + var mutableGroupMessageList = mutableListOf() + + private val TAG = "MessageRepository" + + + @WorkerThread + fun fetchMessage(LIMIT: Int, userId: String) { + + try { + if (messageRequest == null) { + messageRequest = MessagesRequest.MessagesRequestBuilder().setUID(userId).setLimit(LIMIT).build() + + messageRequest!!.fetchPrevious(object : CometChat.CallbackListener>() { + override fun onSuccess(p0: List?) { + + p0?.let { mutableOneToOneMessageList.addAll(0, it) } + onetoOneMessageList.value = mutableOneToOneMessageList + + Log.d(TAG, "messageRequest onSuccess: ${p0?.size}") + +// for (baseMessage in p0!!){ +// Log.d(TAG,"onSuccess: "+baseMessage.id) +// } + } + + override fun onError(p0: CometChatException?) { + Log.d(TAG, "messageRequest onError: ${p0?.message}") + } + + + }) + + } else { + messageRequest!!.fetchPrevious(object : CometChat.CallbackListener>() { + override fun onError(p0: CometChatException?) { + + } + + override fun onSuccess(p0: List?) { + + Log.d(TAG, "messageRequest 1 onSuccess: ${p0?.size}") + + p0?.let { mutableOneToOneMessageList.addAll(0, it) } + onetoOneMessageList.value = mutableOneToOneMessageList + + } + + }) + } + } catch (e: NullPointerException) { + e.printStackTrace() + } + + } + + @WorkerThread + fun fetchGroupMessage(guid: String, LIMIT: Int) { + if (groupMessageRequest == null) { + + groupMessageRequest = MessagesRequest.MessagesRequestBuilder().setGUID(guid).setLimit(LIMIT).build() + + groupMessageRequest!!.fetchPrevious(object : CometChat.CallbackListener>() { + override fun onSuccess(p0: List?) { + p0?.let { mutableGroupMessageList.addAll(0, it) } + groupMessageList.value = mutableGroupMessageList + + } + + override fun onError(p0: CometChatException?) { + Log.d(TAG, "fetchGroupMessageonError: " + p0?.message) + } + + + }) + } else { + + groupMessageRequest!!.fetchPrevious(object : CometChat.CallbackListener>() { + override fun onSuccess(p0: List?) { + p0?.let { mutableGroupMessageList.addAll(0, it) } + groupMessageList.value = mutableGroupMessageList + + } + + override fun onError(p0: CometChatException?) { + + } + }) + } + } + + @WorkerThread + fun sendTextMessage(textMessage: TextMessage, context: Context? = null) { + + CometChat.sendMessage(textMessage, object : CometChat.CallbackListener() { + override fun onSuccess(p0: TextMessage?) { + if (p0 != null) { + Log.d("messageDao", " " + p0.toString()) + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + + } + + if (context != null) { + if (context is LocationActivity) + context.finish() + } + + } + + } + + override fun onError(p0: CometChatException?) { + Toast.makeText(CometChatPro.applicationContext(), p0?.details, Toast.LENGTH_SHORT).show() + + } + + + }) + } + + + fun addGroupListener(group_event_listener: String) { + CometChat.addGroupListener(group_event_listener, object : CometChat.GroupListener() { + override fun onGroupMemberKicked(action: Action?, kickedUser: User?, kickedBy: User?, kickedFrom: Group?) { + action?.let { mutableGroupMessageList.add(it) } + groupMessageList.value = mutableGroupMessageList + + } + + override fun onGroupMemberScopeChanged(action: Action?, user: User?, scopeChangedTo: String?, scopeChangedFrom: String?, group: Group?) { + action?.let { mutableGroupMessageList.add(it) } + groupMessageList.value = mutableGroupMessageList + } + + override fun onGroupMemberUnbanned(action: Action?, unbannedUser: User?, unbannedBy: User?, unbannedFrom: Group?) { + action?.let { mutableGroupMessageList.add(it) } + groupMessageList.value = mutableGroupMessageList + } + + override fun onGroupMemberBanned(action: Action?, bannedUser: User?, bannedBy: User?, bannedFrom: Group?) { + action?.let { mutableGroupMessageList.add(it) } + groupMessageList.value = mutableGroupMessageList + + } + + override fun onGroupMemberLeft(action: Action?, joinedUser: User?, joinedGroup: Group?) { + action?.let { mutableGroupMessageList.add(it) } + groupMessageList.value = mutableGroupMessageList + + } + + override fun onGroupMemberJoined(action: Action?, joinedUser: User?, joinedGroup: Group?) { + action?.let { mutableGroupMessageList.add(it) } + groupMessageList.value = mutableGroupMessageList + + } + + }) + } + + + @WorkerThread + fun messageReceiveListener(listener: String, ownerId: String) { + + CometChat.addMessageListener(listener, object : CometChat.MessageListener() { + override fun onTextMessageReceived(p0: TextMessage?) { + if (p0 != null) { + +// if (!ownerId.equals(p0.sender.uid)) { + + if (!p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } +// } + + + } + } + + override fun onMediaMessageReceived(p0: MediaMessage?) { + if (p0 != null) { + + if (!ownerId.equals(p0.sender.uid)) { + + if (!p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + } + } + } + + }) + } + + @WorkerThread + fun removeMessageListener(listener: String) { + CometChat.removeMessageListener(listener) + + } + + @WorkerThread + fun addPresenceListener(listener: String) { + + CometChat.addUserListener(listener, object : CometChat.UserListener() { + override fun onUserOffline(p0: com.cometchat.pro.models.User?) { + + if (p0 != null) { + user.value = p0 + } + } + + override fun onUserOnline(p0: com.cometchat.pro.models.User?) { + if (p0 != null) { + user.value = p0 + } + } + + }) + } + + + @WorkerThread + fun removePresenceListener(listener: String) { + CometChat.removeUserListener(listener) + } + + @WorkerThread + fun sendMediaMessage(mediaMessage: MediaMessage) { + + CometChat.sendMediaMessage(mediaMessage, object : CometChat.CallbackListener() { + override fun onSuccess(p0: MediaMessage?) { + + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + + } + Log.d("MediaMessage", "baseMessage") + } + + override fun onError(p0: CometChatException?) { + p0?.printStackTrace() + } + + }) + } + + + fun removeGroupListener(group_event_listener: String) { + CometChat.removeGroupListener(group_event_listener) + } + + fun addCallListener(context: Context, call_event_listener: String, view: RelativeLayout?) { + + CometChat.addCallListener(call_event_listener, object : CometChat.CallListener() { + + override fun onIncomingCallCancelled(p0: Call?) { + Log.d(TAG, "onIncomingCallCancelled " + p0.toString()) + + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + } + + if (context is CallActivity) { + + context.finish() + } + } + + override fun onOutgoingCallAccepted(p0: Call?) { + + Log.d(TAG, "onOutgoingCallAccepted: " + p0?.toString()) + + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + } + p0?.sessionId?.let { + if (view != null) { + CometChat.startCall(context as Activity, it, view, object : CometChat.OngoingCallListener { + + override fun onUserJoined(p0: User?) { + Log.d(TAG, "onUserJoined: " + p0?.toString()) + } + + override fun onUserLeft(p0: User?) { + Log.d(TAG, "onUserLeft: " + p0?.toString()) + } + + override fun onError(p0: CometChatException?) { + Log.d(TAG, "CallonError: " + p0?.message) + } + + override fun onCallEnded(p0: Call?) { + + Log.d(TAG, "onCallEnded " + "onOutgoingCallAccepted " + p0.toString()) + + if (context is CallActivity) { + + context.finish() + } + } + + }) + } + } + } + + override fun onIncomingCallReceived(p0: Call?) { + + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + } + + Log.d(TAG, "onIncomingCallReceived: " + p0.toString()) + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + + CommonUtil.startCallIntent(CometChatConstants.RECEIVER_TYPE_USER, context, + p0.callInitiator as User, p0.type, false, p0.sessionId) + + } else if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + CommonUtil.startCallIntent(CometChatConstants.RECEIVER_TYPE_GROUP, context, + p0.callReceiver as Group, p0.type, false, p0.sessionId) + } + } + } + + override fun onOutgoingCallRejected(p0: Call?) { + + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + } + + Log.d(TAG, "onOutgoingCallRejected: " + p0?.toString()) + if (context is CallActivity) { + + context.finish() + } + } + + }) + + } + + fun removeCallListener(call_event_listener: String) { + CometChat.removeCallListener(call_event_listener) + } + + fun acceptCall(sessionID: String, view: RelativeLayout, activity: Activity) { + + + CometChat.acceptCall(sessionID, object : CometChat.CallbackListener() { + override fun onSuccess(p0: Call?) { + + + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + } + + p0?.sessionId?.let { + CometChat.startCall(activity, it, view, object : CometChat.OngoingCallListener { + override fun onUserJoined(p0: User?) { + Log.d(TAG, "onUserJoined: " + p0?.toString()) + } + + override fun onUserLeft(p0: User?) { + Log.d(TAG, "onUserLeft: " + p0?.toString()) + } + + override fun onError(p0: CometChatException?) { + } + + override fun onCallEnded(p0: Call?) { + Log.d(TAG, "onCallEnded: " + p0.toString()) + + activity.finish() + } + + }) + } + } + + override fun onError(p0: CometChatException?) { + + } + + }) + } + + fun rejectCall(sessionID: String, call_status_rejected: String, activity: Activity) { + CometChat.rejectCall(sessionID, call_status_rejected, object : CometChat.CallbackListener() { + override fun onSuccess(p0: Call?) { + Log.d(TAG, "onSuccess: " + p0?.toString()) + activity.finish() + if (p0 != null) { + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + } + } + + override fun onError(p0: CometChatException?) { + + } + + }) + + } + + fun initiateCall(call: Call, context: Context) { + CometChat.initiateCall(call, object : CometChat.CallbackListener() { + override fun onSuccess(p0: Call?) { + Log.d(TAG, "onSuccess: " + p0?.toString()) + if (p0 != null) { + + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + mutableOneToOneMessageList.add(p0) + onetoOneMessageList.value = mutableOneToOneMessageList + } else { + mutableGroupMessageList.add(p0) + groupMessageList.value = mutableGroupMessageList + } + if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + CommonUtil.startCallIntent(CometChatConstants.RECEIVER_TYPE_USER, context, p0.callReceiver as User, p0.type, true, p0.sessionId) + } else if (p0.receiverType.equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + CommonUtil.startCallIntent(CometChatConstants.RECEIVER_TYPE_GROUP, context, p0.callReceiver as Group, p0.type, true, p0.sessionId) + } + } + + } + + override fun onError(p0: CometChatException?) { + + } + + }) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Repository/UserRepository.kt b/app/src/main/java/com/inscripts/cometchatpulse/Repository/UserRepository.kt new file mode 100755 index 0000000..2312051 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Repository/UserRepository.kt @@ -0,0 +1,156 @@ +package com.inscripts.cometchatpulse.Repository + + +import android.app.Activity +import android.arch.lifecycle.MutableLiveData +import android.content.Context +import android.support.annotation.WorkerThread +import android.util.Log +import android.view.View +import android.widget.RelativeLayout +import android.widget.Toast +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.* +import com.cometchat.pro.exceptions.CometChatException +import com.cometchat.pro.models.* +import com.facebook.shimmer.Shimmer +import com.facebook.shimmer.ShimmerFrameLayout +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.Utils.CommonUtil + + + +class UserRepository() { + + var usersList = MutableLiveData>() + + var user = MutableLiveData() + + var mutableUserList = mutableMapOf() + + var userRequest: UsersRequest? = null + + + + + @WorkerThread + fun getUser(uid: String) { + + CometChat.getUser(uid, object : CometChat.CallbackListener() { + override fun onError(p0: CometChatException?) { + + } + + override fun onSuccess(p0: User?) { + user.value = p0 + } + + }) + } + + @WorkerThread + fun fetchUsers(LIMIT: Int,shimmer: ShimmerFrameLayout?) { + + if (userRequest == null) { + + userRequest = UsersRequest.UsersRequestBuilder().setLimit(LIMIT).build() + + userRequest?.fetchNext(object : CometChat.CallbackListener>() { + + override fun onError(p0: CometChatException?) { + Toast.makeText(CometChatPro.applicationContext(),p0?.message,Toast.LENGTH_SHORT).show() + shimmer?.stopShimmer() + shimmer?.visibility=View.GONE + } + + override fun onSuccess(p0: List?) { + if (p0 != null) { + Log.d("UsersRequest", " " + p0.size) + for (user:User in p0){ + mutableUserList.put(user.uid,user) + } + shimmer?.stopShimmer() + shimmer?.visibility= View.GONE + usersList.value = mutableUserList + } + } + + + }) + + + } else { + + userRequest?.fetchNext(object : CometChat.CallbackListener>() { + + override fun onSuccess(p0: List?) { + Log.d("UsersRequest", " " + p0?.size) + if (p0!=null) { + for (user: User in p0) { + mutableUserList.put(user.uid, user) + } + usersList.value = mutableUserList + } + + } + + override fun onError(p0: CometChatException?) { + Log.d("fetchNext","UsersRequest onError: ${p0?.message}") + } + + }) + + } + + } + + + @WorkerThread + fun addPresenceListener(listener: String) { + + CometChat.addUserListener(listener, object : CometChat.UserListener() { + override fun onUserOnline(p0: com.cometchat.pro.models.User?) { + + if (p0 != null) { + mutableUserList.put(p0.uid,p0) + usersList.value=mutableUserList + } + } + + override fun onUserOffline(p0: com.cometchat.pro.models.User?) { + if (p0 != null) { + mutableUserList.put(p0.uid,p0) + usersList.value=mutableUserList + } + } + + }) + + } + + @WorkerThread + fun clearjob() { + + } + + fun removeUserListener(listener: String) { + CometChat.removeUserListener(listener) + + } + + fun initCall(context:Context,call: Call) { + CometChat.initiateCall(call,object :CometChat.CallbackListener(){ + override fun onSuccess(p0: Call?) { + + CommonUtil.startCallIntent(CometChatConstants.RECEIVER_TYPE_USER,context, p0?.callReceiver as User, p0.type, true, p0.sessionId) + } + + override fun onError(p0: CometChatException?) { + + } + + }) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/StringContract.kt b/app/src/main/java/com/inscripts/cometchatpulse/StringContract.kt new file mode 100755 index 0000000..bca277c --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/StringContract.kt @@ -0,0 +1,246 @@ +package com.inscripts.cometchatpulse + +import android.graphics.Typeface +import com.inscripts.cometchatpulse.Helpers.CCPermissionHelper +import com.inscripts.cometchatpulse.Utils.Appearance + +class StringContract { + + class AppDetails { + + companion object { + + const val APP_ID: String = "XXXXXXXXXXXXXX" + + const val API_KEY: String = "XXXXXXXXXXXXX" + + + lateinit var theme: Appearance.AppTheme + + } + } + + class IntentString { + + companion object { + + val USER_ID: String = "user_id" + + val USER_NAME: String = "user_name" + + val USER_AVATAR: String = "user_avatar" + + val USER_STATUS: String = "user_status" + + val LAST_ACTIVE: String = "last_user" + + val GROUP_ID: String = "group_id" + + val GROUP_NAME: String = "group_name" + + val GROUP_ICON: String = "group_icon" + + val GROUP_OWNER: String = "group_owner" + + val IMAGE_TYPE = "image/*" + + val AUDIO_TYPE = "audio/*" + + val DOCUMENT_TYPE = arrayOf("*/*") + + val EXTRA_MIME_TYPE = arrayOf("image/*", "video/*") + + val EXTRA_MIME_DOC = arrayOf("text/plane", "text/html", "application/pdf", "application/msword", + "application/vnd.ms.excel", "application/mspowerpoint", "application/zip") + + val TITLE: String = "title" + + val POSITION: String = "position" + + val SESSION_ID: String = "session_id" + + val OUTGOING: String = "outgoing" + + val INCOMING: String = "incoming" + + val RECIVER_TYPE: String = "receiver_type" + + val URL: String = "image" + + val FILE_TYPE: String = "file_type" + + val ID: String = "id" + + val GROUP_DESCRIPTION:String="description" + + + } + } + + class ViewType { + + companion object { + + const val RIGHT_TEXT_MESSAGE = 334 + + const val LEFT_TEXT_MESSAGE = 734 + + const val LEFT_IMAGE_MESSAGE = 528 + + const val RIGHT_IMAGE_MESSAGE = 834 + + const val LEFT_VIDEO_MESSAGE = 580 + + const val RIGHT_VIDEO_MESSAGE = 797 + + const val RIGHT_AUDIO_MESSAGE = 70 + + const val LEFT_AUDIO_MESSAGE = 79 + + const val LEFT_FILE_MESSAGE = 24 + + const val RIGHT_FILE_MESSAGE = 55 + + const val CALL_MESSAGE = 84 + + const val ACTION_MESSAGE = 99 + + const val RIGHT_LOCATION_MESSAGE = 58 + + const val LEFT_LOCATION_MESSAGE = 59 + + const val RIGHT_MEDIA_REPLY_MESSAGE =345 + + const val RIGHT_TEXT_REPLY_MESSAGE=346 + + const val LEFT_MEDIA_REPLY_MESSAGE =756 + + const val LEFT_TEXT_REPLY_MESSAGE=748 + + } + } + + + class Font { + + + companion object { + + lateinit var title: Typeface + + lateinit var name: Typeface + + lateinit var status: Typeface + + lateinit var message: Typeface + + } + + } + + class Color { + + companion object { + var primaryColor: Int = 0; + + var primaryDarkColor: Int = 0 + + var accentColor: Int = 0 + + var rightMessageColor = 0 + + var leftMessageColor = 0 + + var iconTint = 0 + + var white: Int = android.graphics.Color.parseColor("#ffffff") + + var black: Int = android.graphics.Color.parseColor("#000000") + + var grey: Int = android.graphics.Color.parseColor("#CACACC") + + var inactiveColor = android.graphics.Color.parseColor("#9e9e9e"); + + } + + } + + class Dimensions { + + companion object { + + var marginStart: Int = 16 + + var marginEnd: Int = 16 + + var cardViewCorner: Float = 24f + + var cardViewElevation: Float = 8f + } + } + + class ListenerName { + + companion object { + + val MESSAGE_LISTENER = "message_listener" + + val USER_LISTENER = "user_listener" + + val GROUP_EVENT_LISTENER = "group_event_listener" + + val CALL_EVENT_LISTENER = "call_event_listener" + } + + + } + + + class RequestPermission { + + companion object { + val RECORD_PERMISSION = arrayOf(CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO, + CCPermissionHelper.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE) + + val CAMERA_PERMISSION = arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, + CCPermissionHelper.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE) + + val VIDEO_CALL_PERMISSION = arrayOf(CCPermissionHelper.REQUEST_PERMISSION_CAMERA, + CCPermissionHelper.REQUEST_PERMISSION_RECORD_AUDIO) + + val STORAGE_PERMISSION = arrayOf(CCPermissionHelper.REQUEST_PERMISSION_WRITE_EXTERNAL_STORAGE) + +// val LOCATION_PERMISSION= arrayOf(CCPermissionHelper.L) + } + } + + class RequestCode { + + companion object { + + val ADD_GALLERY = 1 + + val ADD_DOCUMENT = 2 + + val ADD_SOUND = 3 + + val TAKE_PHOTO = 5 + + val LOCATION = 15 + + val TAKE_VIDEO = 7 + + val LEFT = 8 + + val RECORD_CODE = 10 + + val VIDEO_CALL = 12 + + val VOICE_CALL = 24 + + val FILE_WRITE =25 + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Utils/AnimUtil.kt b/app/src/main/java/com/inscripts/cometchatpulse/Utils/AnimUtil.kt new file mode 100755 index 0000000..cc40e17 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Utils/AnimUtil.kt @@ -0,0 +1,126 @@ +package com.inscripts.cometchatpulse.Utils + +import android.animation.AnimatorSet +import android.animation.ObjectAnimator +import android.animation.ValueAnimator +import android.util.Pair +import android.view.View +import android.view.animation.AccelerateDecelerateInterpolator +import android.view.animation.AlphaAnimation +import android.view.animation.Animation +import android.widget.FrameLayout +import android.widget.ImageView +import com.inscripts.cometchatpulse.CustomView.RecordMicButton + +class AnimUtil { + + companion object { + + private lateinit var alphaAnimation: AlphaAnimation + + private var isStartRecorded: Boolean = false + + fun start(view: View) { + val set = AnimatorSet() + val scaleY = ObjectAnimator.ofFloat(view, "scaleY", 2.0f) + val scaleX = ObjectAnimator.ofFloat(view, "scaleX", 2.0f) + set.duration = 150 + set.interpolator = AccelerateDecelerateInterpolator() + set.playTogether(scaleY, scaleX) + set.start() + } + + fun stop(view: View) { + val set = AnimatorSet() + val scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f) + + val scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f) + set.duration = 150 + set.interpolator = AccelerateDecelerateInterpolator() + set.playTogether(scaleY, scaleX) + set.start() + } + + fun getClickOrigin(anchor: View?, contentView: View): Pair { + if (anchor == null) return Pair(0, 0) + + val anchorCoordinates = IntArray(2) + anchor.getLocationOnScreen(anchorCoordinates) + anchorCoordinates[0] += anchor.width / 2 + anchorCoordinates[1] += anchor.height / 2 + + val contentCoordinates = IntArray(2) + contentView.getLocationOnScreen(contentCoordinates) + + val x = anchorCoordinates[0] - contentCoordinates[0] + val y = anchorCoordinates[1] - contentCoordinates[1] + + return Pair(x, y) + } + + + fun animateMic(recordMic: ImageView) { + alphaAnimation = AlphaAnimation(0.0f, 1.0f) + alphaAnimation.setDuration(500) + alphaAnimation.setRepeatMode(Animation.REVERSE) + alphaAnimation.setRepeatCount(Animation.INFINITE) + recordMic.startAnimation(alphaAnimation) + } + + fun resetSmallMic(recordMic: ImageView) { + recordMic.alpha = 1.0f + recordMic.scaleX = 1.0f + recordMic.scaleY = 1.0f + } + + + fun getShakeAnimation(target: View) { +// val animator = ObjectAnimator.ofFloat(target, target.translationX, 0, 25, -25, 25, -25, 15, -15, 6, -6, 0) +// animator.setDuration(500) +// animator.start() + + } + + fun moveSlideToCancel(recordMicButton: RecordMicButton, layout: FrameLayout, initialX: Float, difX: Float) { + + val positionAnimator = ValueAnimator.ofFloat(recordMicButton.getX(), initialX) + + positionAnimator.interpolator = AccelerateDecelerateInterpolator() + positionAnimator.addUpdateListener { animation -> + val x = animation.animatedValue as Float + recordMicButton.setX(x) + } + + recordMicButton.stopScale() + positionAnimator.duration = 0 + positionAnimator.start() + + + // if the move event was not called ,then the difX will still 0 and there is no need to move it back + if (difX != 0f) { + val x = initialX - difX + layout.animate() + .x(x) + .setDuration(0) + .start() + } + + + } + + fun clearAlphaAnimation(hideView: Boolean, recordMic: ImageView) { + alphaAnimation.cancel() + alphaAnimation.reset() + recordMic.clearAnimation() + if (hideView) { + recordMic.visibility = View.GONE + } + } + + + fun setStartRecorded(startRecorded: Boolean) { + isStartRecorded = startRecorded + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Utils/Appearance.kt b/app/src/main/java/com/inscripts/cometchatpulse/Utils/Appearance.kt new file mode 100755 index 0000000..ebd397f --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Utils/Appearance.kt @@ -0,0 +1,156 @@ +package com.inscripts.cometchatpulse.Utils + +import android.graphics.Color +import android.graphics.Typeface +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.StringContract + +class Appearance(appearance: AppTheme) { + + + var appearance: AppTheme + + enum class AppTheme { + AZURE_RADIANCE, + MOUNTAIN_MEADOW, + PERSIAN_BLUE + } + + + init { + this.appearance = appearance + + StringContract.AppDetails.theme = appearance + + when (this.appearance) { + + AppTheme.PERSIAN_BLUE -> { + + //fonts + + StringContract.Font.title = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "GoogleSans-Bold.ttf") + + StringContract.Font.message = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "GoogleSans-Regular.ttf") + + StringContract.Font.name = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "GoogleSans-Regular.ttf") + + StringContract.Font.status = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "GoogleSans-Medium.ttf") + + //Dimensions + + StringContract.Dimensions.cardViewCorner = 32f + + StringContract.Dimensions.cardViewElevation = 8f + + StringContract.Dimensions.marginEnd = 24 + + StringContract.Dimensions.marginStart = 24 + + //color + + StringContract.Color.primaryColor = Color.parseColor("#2636be") + + StringContract.Color.primaryDarkColor = Color.parseColor("#000f8c") + + StringContract.Color.accentColor = Color.parseColor("#6861f2") + + StringContract.Color.leftMessageColor = Color.parseColor("#eaeaea") + + StringContract.Color.rightMessageColor = StringContract.Color.primaryColor + + StringContract.Color.iconTint = StringContract.Color.white + + + } + + AppTheme.MOUNTAIN_MEADOW -> { + //fonts + StringContract.Font.title = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "HelveticaNeueBold.ttf") + + StringContract.Font.message = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "OpenSans-Regular.ttf") + + StringContract.Font.name = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "HelveticaNeueMedium.ttf") + + StringContract.Font.status = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "HelveticaNeueMedium.ttf") + + //Dimensions + + StringContract.Dimensions.cardViewCorner = 0f + + StringContract.Dimensions.cardViewElevation = 0f + + StringContract.Dimensions.marginEnd = 0 + + StringContract.Dimensions.marginStart = 0 + + //color + + StringContract.Color.primaryColor = Color.parseColor("#25d366") + + StringContract.Color.primaryDarkColor = Color.parseColor("#00a038") + + StringContract.Color.accentColor = Color.parseColor("#6bff96") + + StringContract.Color.leftMessageColor = Color.parseColor("#eaeaea") + + StringContract.Color.rightMessageColor = StringContract.Color.primaryColor + + StringContract.Color.iconTint = StringContract.Color.white + + + } + + AppTheme.AZURE_RADIANCE -> { + + StringContract.Font.title = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "Avenir_Next.ttf") + + StringContract.Font.message = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "OpenSans-Regular.ttf") + + StringContract.Font.name = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "Roboto-Medium.ttf") + + StringContract.Font.status = Typeface.createFromAsset(CometChatPro.applicationContext().assets, + "RobotoCondensed-Regular.ttf") + + //Dimensions + + StringContract.Dimensions.cardViewCorner = 0f + + StringContract.Dimensions.cardViewElevation = 0f + + StringContract.Dimensions.marginEnd = 0 + + StringContract.Dimensions.marginStart = 0 + + //color + + StringContract.Color.primaryColor = Color.parseColor("#ffffff") + + StringContract.Color.primaryDarkColor = Color.parseColor("#a8a9ab") + + StringContract.Color.accentColor = Color.parseColor("#ffffff") + + StringContract.Color.leftMessageColor = Color.parseColor("#eaeaea") + + StringContract.Color.rightMessageColor = Color.parseColor("#0084ff") + + StringContract.Color.iconTint = Color.parseColor("#0084ff") + + + } + + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Utils/ColorUtil.kt b/app/src/main/java/com/inscripts/cometchatpulse/Utils/ColorUtil.kt new file mode 100755 index 0000000..cd749aa --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Utils/ColorUtil.kt @@ -0,0 +1,40 @@ +package com.inscripts.cometchatpulse.Utils + +import android.content.Context +import android.graphics.Color +import com.inscripts.cometchatpulse.R +import java.util.concurrent.ThreadLocalRandom + +class ColorUtil{ + + + companion object { + + fun getMaterialColor(context: Context): Int { + var materialColor = 0 + try { + + + materialColor = Color.WHITE + + val colors = context.resources.obtainTypedArray(R.array.material_color) + + materialColor = colors.getColor(getRandomIndex(), Color.WHITE) + colors.recycle() + + return materialColor + + } catch (se: StringIndexOutOfBoundsException) { + + return context.resources.getColor(R.color.primaryColor) + } + + } + + public fun getRandomIndex(): Int { + return ThreadLocalRandom.current().nextInt(0, 80 + 1) + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Utils/CommonUtil.kt b/app/src/main/java/com/inscripts/cometchatpulse/Utils/CommonUtil.kt new file mode 100755 index 0000000..2b695a9 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Utils/CommonUtil.kt @@ -0,0 +1,150 @@ +package com.inscripts.cometchatpulse.Utils + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.graphics.Typeface +import android.location.LocationManager +import android.media.AudioManager +import android.net.ConnectivityManager +import android.os.Build +import android.support.annotation.IdRes +import android.support.v7.widget.CardView +import android.support.v7.widget.Toolbar +import android.text.SpannableString +import android.text.Spanned +import android.text.style.ForegroundColorSpan +import android.util.DisplayMetrics +import android.view.View +import android.widget.LinearLayout +import android.widget.RelativeLayout +import android.widget.TextView +import com.cometchat.pro.models.Group +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Activities.CallActivity +import com.inscripts.cometchatpulse.Activities.LocationActivity +import com.inscripts.cometchatpulse.R +import com.inscripts.cometchatpulse.StringContract + +class CommonUtil { + + companion object { + + var cm: ConnectivityManager?=null + + fun setCardView(cardView: CardView) { + cardView.cardElevation = StringContract.Dimensions.cardViewElevation + cardView.radius = StringContract.Dimensions.cardViewCorner + val param = cardView.layoutParams as RelativeLayout.LayoutParams + param.marginEnd = StringContract.Dimensions.marginEnd + param.marginStart = StringContract.Dimensions.marginStart + cardView.layoutParams = param + + } + + + + + fun checkPermission (context: Context):Boolean{ + + return (context.getSystemService(Context.LOCATION_SERVICE) as LocationManager) + .isProviderEnabled(LocationManager.GPS_PROVIDER) + } + + fun startCallIntent(receiverType:String,context: Context, user: User, type: String, + isOutgoing: Boolean, sessionId: String) { + val callIntent = Intent(context, CallActivity::class.java) + callIntent.putExtra(StringContract.IntentString.USER_NAME, user.name) + callIntent.putExtra(StringContract.IntentString.USER_ID, user.uid) + callIntent.putExtra(StringContract.IntentString.SESSION_ID, sessionId) + callIntent.putExtra(StringContract.IntentString.USER_AVATAR, user.avatar) + callIntent.putExtra(StringContract.IntentString.RECIVER_TYPE, receiverType) + callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + callIntent.action = type + + if (isOutgoing) { + callIntent.type = StringContract.IntentString.OUTGOING + } else { + callIntent.type = StringContract.IntentString.INCOMING + } + context.startActivity(callIntent) + } + + + fun getAudioManager(context: Context): AudioManager { + return context.getSystemService(Context.AUDIO_SERVICE) as AudioManager + } + + fun startCallIntent(receiverType:String,context: Context, group: Group, type: String, + isOutgoing: Boolean, sessionId: String) { + val callIntent = Intent(context, CallActivity::class.java) + callIntent.putExtra(StringContract.IntentString.GROUP_NAME, group.name) + callIntent.putExtra(StringContract.IntentString.GROUP_ID, group.guid) + callIntent.putExtra(StringContract.IntentString.SESSION_ID, sessionId) + callIntent.putExtra(StringContract.IntentString.GROUP_ICON, group.icon) + callIntent.putExtra(StringContract.IntentString.RECIVER_TYPE, receiverType) + callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + callIntent.action = type + + if (isOutgoing) { + callIntent.type = StringContract.IntentString.OUTGOING + } else { + callIntent.type = StringContract.IntentString.INCOMING + } + context.startActivity(callIntent) + } + + fun isConnected(context: Context): Boolean { + + if (cm == null) { + cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + } + + val var0 = cm!!.getActiveNetworkInfo() + return null != var0 && var0!!.isConnectedOrConnecting() + } + + + fun setTitle(title: String, context: Context): SpannableString { + val ss = SpannableString(title) + + var color:Int + + if (StringContract.AppDetails.theme==Appearance.AppTheme.AZURE_RADIANCE){ + color=StringContract.Color.iconTint + } + else{ + color=StringContract.Color.primaryColor + } + ss.setSpan(ForegroundColorSpan(color), 0, title.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + + return ss + } + + + fun dpToPx(context: Context, valueInDp: Float): Float { + val resources = context.resources + val metrics = resources.displayMetrics + return valueInDp * (metrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT) + } + + + fun findById(parent: View, @IdRes resId: Int): Any { + return parent.findViewById(resId) as Any + } + + fun setStatusBarColor(var0: Activity) { + try { + if (Build.VERSION.SDK_INT >= 21) { + val var2 = var0.window + var2.addFlags((-2147483648).toInt()) + var2.statusBarColor = StringContract.Color.primaryDarkColor + } + } catch (var3: Exception) { + var3.printStackTrace() + } + + } + + } +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Utils/DateUtil.kt b/app/src/main/java/com/inscripts/cometchatpulse/Utils/DateUtil.kt new file mode 100755 index 0000000..5ef85ba --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Utils/DateUtil.kt @@ -0,0 +1,73 @@ +package com.inscripts.cometchatpulse.Utils + +import android.content.Context +import android.text.format.DateFormat +import com.inscripts.cometchatpulse.R +import java.text.SimpleDateFormat +import java.util.* + +class DateUtil { + + companion object { + + + fun getLastSeenDate(timeStamp: Long, context: Context): String { + + val lastSeenTime = java.text.SimpleDateFormat("HH:mm a").format(java.util.Date(timeStamp)) + val lastSeenDate = java.text.SimpleDateFormat("dd/MM/yyyy").format(java.util.Date(timeStamp)) + + val currentTimeStamp = System.currentTimeMillis() + + val diffTimeStamp = (currentTimeStamp - timeStamp) / 1000 + + return if (diffTimeStamp < 24 * 60 * 60) { + + context.getString(R.string.today_last_seen) + " " + lastSeenTime + + } else if (diffTimeStamp < 48 * 60 * 60) { + + context.getString(R.string.yesterday_last_seen) + " " + lastSeenTime + } else { + "Last seen at $lastSeenDate on $lastSeenTime" + } + + } + + fun getDateId(var0: Long): String { + val var2 = Calendar.getInstance(Locale.ENGLISH) + var2.timeInMillis = var0 + return DateFormat.format("ddMMyyyy", var2).toString() + } + + fun getCustomizeDate(time: Long): String { + val monthNames = arrayOf("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December") + + var date = "" + val cal = Calendar.getInstance() + cal.timeInMillis = time + val day = cal.get(Calendar.DAY_OF_MONTH) + val month = cal.get(Calendar.MONTH) + val year = cal.get(Calendar.YEAR) + + date = day.toString() + " " + monthNames[month] + ", " + year + + return date + } + + + fun convertTimeStampToDurationTime(var0: Long): String { + val var2 = var0 / 1000L + val var4 = var2 / 60L % 60L + val var6 = var2 / 60L / 60L % 24L + return if (var6 == 0L) String.format(Locale.getDefault(), "%02d:%02d", var4, var2 % 60L) else String.format(Locale.getDefault(), "%02d:%02d:%02d", var6, var4, var2 % 60L) + } + + fun getMessageTime(time: String, dateFormat: String): String { + val format = SimpleDateFormat(dateFormat) + val timestamp = java.sql.Timestamp.valueOf(time) + return format.format(timestamp) + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Utils/FileUtil.kt b/app/src/main/java/com/inscripts/cometchatpulse/Utils/FileUtil.kt new file mode 100755 index 0000000..33abe70 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Utils/FileUtil.kt @@ -0,0 +1,231 @@ +package com.inscripts.cometchatpulse.Utils + +import android.content.ContentUris +import android.content.Context +import android.database.Cursor +import android.graphics.Bitmap +import android.net.Uri +import android.os.Build +import android.os.Environment +import android.provider.DocumentsContract +import android.provider.MediaStore +import com.cometchat.pro.constants.CometChatConstants +import com.inscripts.cometchatpulse.R +import java.io.ByteArrayOutputStream +import java.io.File +import java.net.URISyntaxException +import java.text.SimpleDateFormat +import java.util.* + +class FileUtil { + + companion object { + + @Throws(URISyntaxException::class) + fun getPath(context: Context, uri: Uri?): Array { + var uri = uri + val needToCheckUri = Build.VERSION.SDK_INT >= 19 + var selection: String? = null + var selectionArgs: Array? = null + var ar: Array = arrayOf() + var type: String? = null + // Uri is different in versions after KITKAT (Android 4.4), we need to + // deal with different Uris. + if (needToCheckUri && DocumentsContract.isDocumentUri(context.applicationContext, uri)) { + if (isExternalStorageDocument(uri!!)) { + val docId = DocumentsContract.getDocumentId(uri) + val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + ar = arrayOf(Environment.getExternalStorageDirectory().toString() + "/" + split[1], CometChatConstants.MESSAGE_TYPE_FILE) + return ar + } else if (isDownloadsDocument(uri)) { + val id = DocumentsContract.getDocumentId(uri) + uri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)) + } else if (isMediaDocument(uri)) { + val docId = DocumentsContract.getDocumentId(uri) + val split = docId.split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + type = split[0] + if ("image".equals(type)) { + type = CometChatConstants.MESSAGE_TYPE_IMAGE + uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI + } else if ("video".equals(type)) { + uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI + type = CometChatConstants.MESSAGE_TYPE_VIDEO + } else if ("audio".equals(type)) { + uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI + type = CometChatConstants.MESSAGE_TYPE_AUDIO + } + selection = "_id=?" + selectionArgs = arrayOf(split[1]) + } + } + if ("content".equals(uri!!.scheme!!, ignoreCase = true)) { + val projection = arrayOf(MediaStore.Images.Media.DATA) + var cursor: Cursor? = null + try { + cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null) + val column_index = cursor!!.getColumnIndexOrThrow(MediaStore.Images.Media.DATA) + type = context.contentResolver?.getType(uri)?.toLowerCase() + if (type != null) { + if (type.contains("jpeg") || type.contains("jpg") || type.contains("png") || type.contains("image") + || type.contains("picture") || type.contains("photo")) { + type = CometChatConstants.MESSAGE_TYPE_IMAGE + } else if (type.contains("video") || type.contains("mp4") + || type.contains("avi") || + type.contains("flv")) { + type = CometChatConstants.MESSAGE_TYPE_VIDEO + } else if (type.contains("aac") || type.contains("m4a") || type.contains("amr") + || type.contains("opus") || type.contains("mp3")) { + + type = CometChatConstants.MESSAGE_TYPE_AUDIO + } else { + type = CometChatConstants.MESSAGE_TYPE_FILE + } + } + if (cursor.moveToFirst()) { + ar = arrayOf(cursor.getString(column_index), type) + return ar + } + } catch (e: Exception) { + } + + } else if ("file".equals(uri.scheme!!, ignoreCase = true)) { + ar = arrayOf(uri.path, CometChatConstants.MESSAGE_TYPE_FILE) + return ar + } + return ar; + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + fun isExternalStorageDocument(uri: Uri): Boolean { + return "com.android.externalstorage.documents" == uri.authority + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + fun isDownloadsDocument(uri: Uri): Boolean { + return "com.android.providers.downloads.documents" == uri.authority + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + fun isMediaDocument(uri: Uri): Boolean { + return "com.android.providers.media.documents" == uri.authority + } + + fun getImageUri(inContext: Context, inImage: Bitmap): Uri { + val bytes = ByteArrayOutputStream() + inImage.compress(Bitmap.CompressFormat.JPEG, 100, bytes) + val path = MediaStore.Images.Media.insertImage(inContext.contentResolver, inImage, "Title", null) + return Uri.parse(path) + } + + fun ImagePath(uri: Uri, context: Context): String { + var path = "" + if (context.contentResolver != null) { + val cursor = context.contentResolver.query(uri, null, null, null, null) + if (cursor != null) { + cursor.moveToFirst() + val idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA) + path = cursor.getString(idx) + cursor.close() + } + } + return path + } + + fun getVideoPath(uri: Uri, context: Context): String { + var path = "" + if (context.contentResolver != null) { + val cursor = context.contentResolver.query(uri, null, null, null, null) + if (cursor != null) { + cursor.moveToFirst() + val idx = cursor.getColumnIndex(MediaStore.Video.VideoColumns.DATA) + path = cursor.getString(idx) + cursor.close() + } + } + return path + } + + fun checkDirExistence(context: Context?,type: String): Boolean { + + val audioDir = File( Environment.getExternalStorageDirectory().toString() + "/" + + context?.resources?.getString(R.string.app_name) + "/" + type + "/") + + if (audioDir.isDirectory) { + return true + } + + return false + } + + fun checkFileExistence(path: String): Boolean { + + val filepath = File(path) + + if (filepath.exists()) { + + return true + } + + return false + } + + fun getPath(context: Context, folder: String): String { + + val path = Environment.getExternalStorageDirectory().toString() + "/" + + context.resources?.getString(R.string.app_name) + "/" + folder + "/" + + return path + } + + fun getFileName(mediaFile: String?): String? { + + val t = mediaFile?.substring(mediaFile.lastIndexOf("/"))?.split("_".toRegex())?.dropLastWhile({ it.isEmpty() })?.toTypedArray() + + return t?.get(2) + } + + fun getFileExtension(mediaFile: String?): String? { + + return mediaFile?.substring(mediaFile.lastIndexOf(".") + 1) + } + + + fun getOutputMediaFile(context: Context?): String? { + val var0 = File(Environment.getExternalStorageDirectory(), context?.resources?.getString(R.string.app_name)) + if (!var0.exists() && !var0.mkdirs()) { + return null + } else { + val var1 = (Environment.getExternalStorageDirectory().toString() + "/" + + context?.resources?.getString(R.string.app_name) + "/" +"audio/") + createDirectory(var1) + return var1 + SimpleDateFormat("yyyyMMddHHmmss").format(Date()) + ".mp3" + } + } + + fun createDirectory(var0: String) { + if (!File(var0).exists()) { + File(var0).mkdirs() + } + + } + + fun makeDirectory(context: Context?,type:String) { + + val audioDir = Environment.getExternalStorageDirectory().toString() + "/" + + context?.resources?.getString(R.string.app_name) + "/" + type + "/" + + createDirectory(audioDir) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/Utils/MediaUtil.kt b/app/src/main/java/com/inscripts/cometchatpulse/Utils/MediaUtil.kt new file mode 100755 index 0000000..c6e2b1c --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/Utils/MediaUtil.kt @@ -0,0 +1,37 @@ +package com.inscripts.cometchatpulse.Utils + +import android.content.Context +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.drawable.Drawable + +class MediaUtil { + + + companion object { + + fun getPlaceholderImage(context: Context, drawable: Drawable): Bitmap { + var bitmap = getBitmapFromDrawable( drawable) + + val outputImage = Bitmap.createBitmap(bitmap.getWidth() + 80, bitmap.getHeight() + 80, Bitmap.Config.ARGB_8888) + val canvas = Canvas(outputImage) + canvas.drawARGB(0, 0, 0, 0) + canvas.drawBitmap(bitmap, 40f, 40f, null) + bitmap = outputImage + + return bitmap + } + + private fun getBitmapFromDrawable(drawable: Drawable): Bitmap { + val bitmap: Bitmap + + bitmap = Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888) + + val canvas = Canvas(bitmap) + drawable.setBounds(0, 0, canvas.width, canvas.height) + drawable.draw(canvas) + + return bitmap + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/ContactViewHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/ContactViewHolder.kt new file mode 100755 index 0000000..2433960 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/ContactViewHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.ContactItemBinding + +class ContactViewHolder(val binding:ContactItemBinding) : RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/GroupMemberHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/GroupMemberHolder.kt new file mode 100755 index 0000000..31ab20e --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/GroupMemberHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.GroupMemberItemBinding + +class GroupMemberHolder( val binding:GroupMemberItemBinding) :RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/GroupOptionViewHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/GroupOptionViewHolder.kt new file mode 100755 index 0000000..ae395fa --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/GroupOptionViewHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView + +class GroupOptionViewHolder(val binding: com.inscripts.cometchatpulse.databinding.GroupOptionItemBinding) :RecyclerView.ViewHolder(binding.root) { +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftAudioMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftAudioMessageHolder.kt new file mode 100755 index 0000000..f0ab076 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftAudioMessageHolder.kt @@ -0,0 +1,7 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.LeftAudioBinding +import com.inscripts.cometchatpulse.databinding.RightAudioBinding + +class LeftAudioMessageHolder(val binding: LeftAudioBinding):RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftFileViewHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftFileViewHolder.kt new file mode 100755 index 0000000..4858c29 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftFileViewHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.LeftFileBinding + +class LeftFileViewHolder(val binding:LeftFileBinding):RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftImageVideoMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftImageVideoMessageHolder.kt new file mode 100755 index 0000000..9968e0c --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftImageVideoMessageHolder.kt @@ -0,0 +1,7 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.CcImageVideoLayoutLeftBinding +import com.inscripts.cometchatpulse.databinding.LeftTextBinding + +class LeftImageVideoMessageHolder(val binding: CcImageVideoLayoutLeftBinding): RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftLocationViewHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftLocationViewHolder.kt new file mode 100755 index 0000000..943980e --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftLocationViewHolder.kt @@ -0,0 +1,71 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.cometchat.pro.models.BaseMessage +import com.cometchat.pro.models.TextMessage +import com.google.android.gms.maps.CameraUpdateFactory +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.MapsInitializer +import com.google.android.gms.maps.OnMapReadyCallback +import com.google.android.gms.maps.model.LatLng +import com.google.android.gms.maps.model.MarkerOptions +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.databinding.LeftLocationBinding +import java.lang.Exception + +class LeftLocationViewHolder(val binding:LeftLocationBinding):RecyclerView.ViewHolder(binding.root),OnMapReadyCallback { + + var googleMap: GoogleMap? = null + + init { + + binding.map.onCreate(null) + binding.map.getMapAsync(this) + } + + + override fun onMapReady(p0: GoogleMap?) { + MapsInitializer.initialize(CometChatPro.applicationContext()) + googleMap=p0 + setMapLocation() + } + + fun bindView(pos:Int,messageList:MutableList){ + val item =messageList[pos] + binding.root.tag=this + binding.map.tag=item + setMapLocation() + + } + + private fun setMapLocation() { + + try { + + + if (googleMap == null) return + + val data: BaseMessage? = binding.map.tag as BaseMessage + + if (data==null){ + return + } + + // Add a marker for this item and set the camera + val metadata=(data as TextMessage).metadata + val lat=metadata.getString("lat").toDouble() + val longt=metadata.getString("logt").toDouble() + + googleMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(lat,longt), 20f)) + googleMap?.addMarker(MarkerOptions().position(LatLng(lat,longt))) + + + // Set the map type back to normal. + googleMap?.mapType= GoogleMap.MAP_TYPE_NORMAL + + }catch (e:Exception){ + + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftReplyMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftReplyMessageHolder.kt new file mode 100755 index 0000000..d4b36b1 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftReplyMessageHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.LeftReplyBinding + +class LeftReplyMessageHolder(val binding:LeftReplyBinding):RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftTextMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftTextMessageHolder.kt new file mode 100755 index 0000000..9db63dc --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/LeftTextMessageHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.LeftTextBinding + +class LeftTextMessageHolder(val binding: LeftTextBinding):RecyclerView.ViewHolder(binding.root) diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightAudioMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightAudioMessageHolder.kt new file mode 100755 index 0000000..8f84087 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightAudioMessageHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.RightAudioBinding + +class RightAudioMessageHolder(val binding: RightAudioBinding):RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightFileViewHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightFileViewHolder.kt new file mode 100755 index 0000000..5b59ee3 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightFileViewHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.RightFileBinding + +class RightFileViewHolder(val binding:RightFileBinding) :RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightImageVideoMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightImageVideoMessageHolder.kt new file mode 100755 index 0000000..b2010d6 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightImageVideoMessageHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.CcImageVideoLayoutRightBinding + +class RightImageVideoMessageHolder (val binding: CcImageVideoLayoutRightBinding): RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightLocationViewHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightLocationViewHolder.kt new file mode 100755 index 0000000..e657118 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightLocationViewHolder.kt @@ -0,0 +1,78 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import android.view.View +import com.google.android.gms.maps.GoogleMap +import com.google.android.gms.maps.MapsInitializer +import com.google.android.gms.maps.OnMapReadyCallback +import com.inscripts.cometchatpulse.CometChatPro +import com.inscripts.cometchatpulse.databinding.RightLocationBinding +import android.widget.TextView +import com.cometchat.pro.models.BaseMessage +import com.cometchat.pro.models.MediaMessage +import com.cometchat.pro.models.TextMessage +import com.google.android.gms.maps.MapView +import com.google.android.gms.maps.model.MarkerOptions +import com.google.android.gms.maps.CameraUpdateFactory +import com.google.android.gms.maps.model.LatLng + + +class RightLocationViewHolder(val binding: RightLocationBinding): + RecyclerView.ViewHolder(binding.root),OnMapReadyCallback{ + + + var googleMap: GoogleMap? = null + + init { + + binding.map.onCreate(null) + binding.map.getMapAsync(this) + } + + + override fun onMapReady(p0: GoogleMap?) { + MapsInitializer.initialize(CometChatPro.applicationContext()) + googleMap=p0 + setMapLocation() + } + + fun bindView(pos:Int,messageList:MutableList){ + val item =messageList[pos] + binding.root.tag=this + binding.map.tag=item + setMapLocation() + + } + + private fun setMapLocation() { + + try { + + + if (googleMap == null) return + + val data:BaseMessage? = binding.map.tag as BaseMessage + + if (data==null){ + return + } + + // Add a marker for this item and set the camera + val metadata=(data as TextMessage).metadata + val lat=metadata.getString("lat").toDouble() + val longt=metadata.getString("logt").toDouble() + + googleMap?.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(lat,longt), 20f)) + googleMap?.addMarker(MarkerOptions().position(LatLng(lat,longt))) + + + // Set the map type back to normal. + googleMap?.mapType=GoogleMap.MAP_TYPE_NORMAL + }catch (e:Exception){ + + } + } + + + +} diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightReplyMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightReplyMessageHolder.kt new file mode 100755 index 0000000..07d72bf --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightReplyMessageHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.RightReplyBinding + +class RightReplyMessageHolder(val binding:RightReplyBinding):RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightTextMessageHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightTextMessageHolder.kt new file mode 100755 index 0000000..8175707 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/RightTextMessageHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.RightTextBinding + +class RightTextMessageHolder(val binding:RightTextBinding):RecyclerView.ViewHolder(binding.root) diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/TextHeaderHolder.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/TextHeaderHolder.kt new file mode 100755 index 0000000..6f51542 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewHolder/TextHeaderHolder.kt @@ -0,0 +1,6 @@ +package com.inscripts.cometchatpulse.ViewHolder + +import android.support.v7.widget.RecyclerView +import com.inscripts.cometchatpulse.databinding.ListHeaderBinding + +class TextHeaderHolder(val binding:ListHeaderBinding): RecyclerView.ViewHolder(binding.root) \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/GroupChatViewModel.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/GroupChatViewModel.kt new file mode 100755 index 0000000..786f715 --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/GroupChatViewModel.kt @@ -0,0 +1,116 @@ +package com.inscripts.cometchatpulse.ViewModel + +import android.app.Application +import android.arch.lifecycle.AndroidViewModel +import android.arch.lifecycle.MutableLiveData +import android.content.Context +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.models.* +import com.inscripts.cometchatpulse.Fragment.GroupFragment +import com.inscripts.cometchatpulse.Fragment.MemberFragment +import com.inscripts.cometchatpulse.Fragment.OneToOneFragment +import com.inscripts.cometchatpulse.Repository.GroupRepository +import com.inscripts.cometchatpulse.Repository.MessageRepository +import com.inscripts.cometchatpulse.StringContract +import org.json.JSONObject +import java.io.File + + +class GroupChatViewModel(application: Application) : AndroidViewModel(application) { + + private val groupRepository: GroupRepository + + private val messageRepository: MessageRepository + + val messageList: MutableLiveData> + + val groupMemberList: MutableLiveData> + + val banMemberList: MutableLiveData> + + + init { + groupRepository = GroupRepository() + messageRepository = MessageRepository() + banMemberList = groupRepository.banMemberLiveData + messageList = messageRepository.groupMessageList + groupMemberList = groupRepository.groupMemberLiveData + } + + fun fetchMessage(LIMIT: Int, guid: String) { + messageRepository.fetchGroupMessage(guid, LIMIT) + } + + override fun onCleared() { + super.onCleared() + + } + + fun sendTextMessage(textMessage: TextMessage) { + messageRepository.sendTextMessage(textMessage) + } + + fun addGroupEventListener(group_event_listener: String) { + messageRepository.addGroupListener(group_event_listener) + } + + fun sendMediaMessage(path: String?, type: String?, guid: String,groupFragment:GroupFragment) { + val mediaMessage = MediaMessage(guid, File(path), type, CometChatConstants.RECEIVER_TYPE_GROUP) + val jObject = JSONObject() + jObject.put("path", path) + mediaMessage.metadata = jObject + + if (GroupFragment.isReply){ + GroupFragment.isReply=false + mediaMessage.metadata= GroupFragment.metaData?.put("path",path) + groupFragment.hideReplyContainer() + } + else{ + mediaMessage.metadata=jObject + } + messageRepository.sendMediaMessage(mediaMessage) + } + + fun removeGroupEventListener(group_event_listener: String) { + messageRepository.removeGroupListener(group_event_listener) + } + + + + fun getMembers(guid: String, LIMIT: Int) { + groupRepository.getGroupMember(guid, LIMIT) + } + + fun getBanedMember(guid: String, LIMIT: Int) { + groupRepository.getBannedMember(guid, LIMIT) + } + + fun banMember(uid: String?, guid: String) { + uid?.let { groupRepository.banMember(it, guid) } + } + + fun kickMember(uid: String?, guid: String) { + uid?.let { groupRepository.kickMember(it, guid) } + } + + fun unbanMember(uid: String?, guid: String) { + uid?.let { groupRepository.unBanMember(guid, it) } + } + + fun addGroupMessageListener(message_listener: String,ownerId:String) { + messageRepository.messageReceiveListener(message_listener,ownerId) + } + + fun removeMessageListener(message_listener: String) { + messageRepository.removeMessageListener(message_listener) + } + + fun removeCallListener(call_event_listener: String) { + messageRepository.removeCallListener(call_event_listener) + } + + fun updateScope(fragment:MemberFragment,uid: String, guid: String,scope:String) { + groupRepository.updateScope(fragment,uid,guid,scope) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/GroupViewModel.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/GroupViewModel.kt new file mode 100755 index 0000000..1b9bd6e --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/GroupViewModel.kt @@ -0,0 +1,82 @@ +package com.inscripts.cometchatpulse.ViewModel + +import android.app.Application +import android.app.ProgressDialog +import android.arch.lifecycle.AndroidViewModel +import android.arch.lifecycle.MutableLiveData +import android.content.Context +import android.support.v4.app.FragmentActivity +import android.widget.RelativeLayout +import com.cometchat.pro.core.Call +import com.cometchat.pro.models.Group +import com.cometchat.pro.models.GroupMember +import com.facebook.shimmer.ShimmerFrameLayout +import com.inscripts.cometchatpulse.Repository.MessageRepository +import com.inscripts.cometchatpulse.Repository.GroupRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlin.coroutines.CoroutineContext + +class GroupViewModel(application: Application) : AndroidViewModel(application) { + + private val groupRepository: GroupRepository + + private val messageRepository:MessageRepository + + val groupList:MutableLiveData> + + val groupMemberList:MutableLiveData> + + + + init { + groupRepository= GroupRepository() + messageRepository= MessageRepository() + groupList=groupRepository.groupList + groupMemberList=groupRepository.groupMemberLiveData + + } + + fun fetchGroups(LIMIT:Int,shimmerFrameLayout: ShimmerFrameLayout?){ + groupRepository.fetchGroup(LIMIT,shimmerFrameLayout) + } + + override fun onCleared() { + super.onCleared() + groupRepository.clearjob() + + } + + fun createGroup(context: Context, group: Group) { + groupRepository.createGroup(context, group) + } + + fun fetchGroupMemeber(LIMIT: Int,guid: String) { + groupRepository.getGroupMember(guid,LIMIT) + } + + fun joinGroup(group: Group, progressDialog: ProgressDialog?,resId:Int,context: Context) { + groupRepository.joinGroup(group,progressDialog,resId,context) + } + + fun initCall(context: Context?, guid: String, receiver_type: String, call_type: String) { + val call= Call(guid,receiver_type,call_type) + context?.let { messageRepository.initiateCall(call, it) } + } + + fun leaveGroup(guid: String,activity: FragmentActivity?) { + groupRepository.leaveGroup(guid,activity) + } + + fun deleteGroup(groupId: String,context: Context) { + groupRepository.deleteGroup(groupId,context) + } + + fun addCallListener(applicationContext: Context, calL_EVENT_LISTENER: String, relative: RelativeLayout?) { + messageRepository.addCallListener(applicationContext,calL_EVENT_LISTENER,relative) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/OnetoOneViewModel.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/OnetoOneViewModel.kt new file mode 100755 index 0000000..a94b11e --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/OnetoOneViewModel.kt @@ -0,0 +1,116 @@ +package com.inscripts.cometchatpulse.ViewModel + +import android.app.Activity +import android.app.Application +import android.arch.lifecycle.AndroidViewModel +import android.arch.lifecycle.MutableLiveData +import android.content.Context +import android.util.Log +import android.widget.RelativeLayout +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.Call +import com.cometchat.pro.models.BaseMessage +import com.cometchat.pro.models.MediaMessage +import com.cometchat.pro.models.TextMessage +import com.cometchat.pro.models.User +import com.inscripts.cometchatpulse.Fragment.OneToOneFragment +import com.inscripts.cometchatpulse.Repository.MessageRepository +import org.json.JSONObject +import java.io.File + +class OnetoOneViewModel constructor(application: Application) : AndroidViewModel(application) { + + private val messageRepository: MessageRepository + + val messageList: MutableLiveData> + + var user:MutableLiveData + + + + init { + messageRepository = MessageRepository() + messageList = messageRepository.onetoOneMessageList + user=messageRepository.user + + } + + fun fetchMessage(LIMIT: Int,userId: String) { + messageRepository.fetchMessage(LIMIT, userId) + } + + + override fun onCleared() { + super.onCleared() + + } + + fun sendTextMessage(textMessage: TextMessage) { + messageRepository.sendTextMessage(textMessage) + } + + + fun receiveMessageListener(listener:String,ownerId: String) { + messageRepository.messageReceiveListener(listener,ownerId) + } + + fun removeMessageListener(listener: String) { + messageRepository.removeMessageListener(listener) + } + + fun addPresenceListener(listener: String) { + messageRepository.addPresenceListener(listener) + } + + fun removePresenceListener(listener: String) { + messageRepository.removePresenceListener(listener) + } + + fun sendMediaMessage(filePath:String?,type:String?,userId: String,oneToOneFragment:OneToOneFragment) { + + val path = File(filePath) + Log.d("MediaMessage", " " + path.exists()) + + val mediaMessage = MediaMessage(userId, path, type, CometChatConstants.RECEIVER_TYPE_USER) + val jObject= JSONObject() + jObject.put("path",filePath) + + Log.d("meta",jObject.toString()) + + if (OneToOneFragment.isReply){ + OneToOneFragment.isReply=false + mediaMessage.metadata= OneToOneFragment.metaData?.put("path",filePath) + oneToOneFragment.hideReplyContainer() + } + else{ + mediaMessage.metadata=jObject + } + + messageRepository.sendMediaMessage(mediaMessage) + } + + fun addCallListener(context: Context,call_event_listener: String,view:RelativeLayout?) { + messageRepository.addCallListener(context,call_event_listener, view) + } + + fun removeCallListener(call_event_listener: String) { + messageRepository.removeCallListener(call_event_listener) + } + + fun acceptCall(sessionID: String,view:RelativeLayout,activity: Activity) { + messageRepository.acceptCall(sessionID,view,activity) + } + + fun rejectCall(sessionID: String, call_status_rejected: String,activity: Activity) { + messageRepository.rejectCall(sessionID,call_status_rejected,activity) + } + + fun initCall(context: Context,userId: String, receiver_type: String, callType: String) { + val call=Call(userId,receiver_type,callType) + messageRepository.initiateCall(call,context) + } + + + + + } \ No newline at end of file diff --git a/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/UserViewModel.kt b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/UserViewModel.kt new file mode 100755 index 0000000..dcd244a --- /dev/null +++ b/app/src/main/java/com/inscripts/cometchatpulse/ViewModel/UserViewModel.kt @@ -0,0 +1,58 @@ +package com.inscripts.cometchatpulse.ViewModel + +import android.app.Application +import android.arch.lifecycle.AndroidViewModel +import android.arch.lifecycle.LiveData +import android.arch.lifecycle.MutableLiveData +import android.content.Context +import com.cometchat.pro.constants.CometChatConstants +import com.cometchat.pro.core.Call +import com.cometchat.pro.models.User +import com.facebook.shimmer.Shimmer +import com.facebook.shimmer.ShimmerFrameLayout +import com.inscripts.cometchatpulse.Repository.UserRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.launch +import kotlin.coroutines.CoroutineContext + +class UserViewModel(application: Application) : AndroidViewModel(application) { + + private val userRepository: UserRepository + + val userList: MutableLiveData> + + val user:MutableLiveData + + + init { + userRepository = UserRepository() + userList = userRepository.usersList + user=userRepository.user + } + + fun fetchUser(LIMIT: Int,shimmer: ShimmerFrameLayout?){ + userRepository.fetchUsers(LIMIT,shimmer) + + } + + override fun onCleared() { + super.onCleared() + userRepository.clearjob() + } + + fun addPresenceListener(listener: String) { + userRepository.addPresenceListener(listener) + } + + fun removeUserListener(listener: String) { + userRepository.removeUserListener(listener) + } + + fun initCall(context: Context, user: User) { + val call= Call(user.uid,CometChatConstants.RECEIVER_TYPE_USER,CometChatConstants.CALL_TYPE_VIDEO) + userRepository.initCall(context,call) + } +} + diff --git a/app/src/main/res/animator/toolbar_elevation.xml b/app/src/main/res/animator/toolbar_elevation.xml new file mode 100755 index 0000000..20e342d --- /dev/null +++ b/app/src/main/res/animator/toolbar_elevation.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/cc_border.xml b/app/src/main/res/drawable-v21/cc_border.xml new file mode 100755 index 0000000..2a15350 --- /dev/null +++ b/app/src/main/res/drawable-v21/cc_border.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/cc_custom_left_bubble.xml b/app/src/main/res/drawable-v21/cc_custom_left_bubble.xml new file mode 100755 index 0000000..53550c9 --- /dev/null +++ b/app/src/main/res/drawable-v21/cc_custom_left_bubble.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-v21/cc_custom_right_bubble.xml b/app/src/main/res/drawable-v21/cc_custom_right_bubble.xml new file mode 100755 index 0000000..db1436c --- /dev/null +++ b/app/src/main/res/drawable-v21/cc_custom_right_bubble.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable-v21/cc_status_available.xml b/app/src/main/res/drawable-v21/cc_status_available.xml new file mode 100755 index 0000000..3e4ece1 --- /dev/null +++ b/app/src/main/res/drawable-v21/cc_status_available.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/cc_status_offline.xml b/app/src/main/res/drawable-v21/cc_status_offline.xml new file mode 100755 index 0000000..d2fc195 --- /dev/null +++ b/app/src/main/res/drawable-v21/cc_status_offline.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/edit_background.xml b/app/src/main/res/drawable-v21/edit_background.xml new file mode 100755 index 0000000..5d58305 --- /dev/null +++ b/app/src/main/res/drawable-v21/edit_background.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/edit_text_round.xml b/app/src/main/res/drawable-v21/edit_text_round.xml new file mode 100755 index 0000000..e88b48f --- /dev/null +++ b/app/src/main/res/drawable-v21/edit_text_round.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-v21/ic_attach_file_red_24dp.xml b/app/src/main/res/drawable-v21/ic_attach_file_red_24dp.xml new file mode 100755 index 0000000..bd1adeb --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_attach_file_red_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_chevron_left_24dp.xml b/app/src/main/res/drawable-v21/ic_chevron_left_24dp.xml new file mode 100755 index 0000000..b5f2815 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_chevron_left_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_keyboard_arrow_down_black_24dp.xml b/app/src/main/res/drawable-v21/ic_keyboard_arrow_down_black_24dp.xml new file mode 100755 index 0000000..ce5f669 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_keyboard_arrow_down_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_lock_outline_red_24dp.xml b/app/src/main/res/drawable-v21/ic_lock_outline_red_24dp.xml new file mode 100755 index 0000000..4396162 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_lock_outline_red_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_mic_24dp.xml b/app/src/main/res/drawable-v21/ic_mic_24dp.xml new file mode 100755 index 0000000..28e8dbf --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_mic_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_outline_add_a_photo_24px.xml b/app/src/main/res/drawable-v21/ic_outline_add_a_photo_24px.xml new file mode 100755 index 0000000..926eb2d --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_outline_add_a_photo_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_outline_call_24px.xml b/app/src/main/res/drawable-v21/ic_outline_call_24px.xml new file mode 100755 index 0000000..62b2ac7 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_outline_call_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_outline_image_24px.xml b/app/src/main/res/drawable-v21/ic_outline_image_24px.xml new file mode 100755 index 0000000..6e630ae --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_outline_image_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_outline_insert_drive_file_24px.xml b/app/src/main/res/drawable-v21/ic_outline_insert_drive_file_24px.xml new file mode 100755 index 0000000..32d5406 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_outline_insert_drive_file_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_outline_video_call_24px.xml b/app/src/main/res/drawable-v21/ic_outline_video_call_24px.xml new file mode 100755 index 0000000..b217fc7 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_outline_video_call_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_outline_videocam_24px.xml b/app/src/main/res/drawable-v21/ic_outline_videocam_24px.xml new file mode 100755 index 0000000..e4214db --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_outline_videocam_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_perm_24dp.xml b/app/src/main/res/drawable-v21/ic_perm_24dp.xml new file mode 100755 index 0000000..696aba3 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_perm_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100755 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/button_background.xml b/app/src/main/res/drawable/button_background.xml new file mode 100755 index 0000000..d6c08a4 --- /dev/null +++ b/app/src/main/res/drawable/button_background.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cc_custom_left_bubble.xml b/app/src/main/res/drawable/cc_custom_left_bubble.xml new file mode 100755 index 0000000..c9646f5 --- /dev/null +++ b/app/src/main/res/drawable/cc_custom_left_bubble.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/cc_custom_right_bubble.xml b/app/src/main/res/drawable/cc_custom_right_bubble.xml new file mode 100755 index 0000000..c0e457d --- /dev/null +++ b/app/src/main/res/drawable/cc_custom_right_bubble.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/cc_play_video_button.png b/app/src/main/res/drawable/cc_play_video_button.png new file mode 100755 index 0000000..c0be7c1 Binary files /dev/null and b/app/src/main/res/drawable/cc_play_video_button.png differ diff --git a/app/src/main/res/drawable/cc_rounded_date_button.xml b/app/src/main/res/drawable/cc_rounded_date_button.xml new file mode 100755 index 0000000..761ec4e --- /dev/null +++ b/app/src/main/res/drawable/cc_rounded_date_button.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cc_small.png b/app/src/main/res/drawable/cc_small.png new file mode 100755 index 0000000..d66848a Binary files /dev/null and b/app/src/main/res/drawable/cc_small.png differ diff --git a/app/src/main/res/drawable/cc_status_available.xml b/app/src/main/res/drawable/cc_status_available.xml new file mode 100755 index 0000000..10d4283 --- /dev/null +++ b/app/src/main/res/drawable/cc_status_available.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cc_status_offline.xml b/app/src/main/res/drawable/cc_status_offline.xml new file mode 100755 index 0000000..af6414e --- /dev/null +++ b/app/src/main/res/drawable/cc_status_offline.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/cometchat.png b/app/src/main/res/drawable/cometchat.png new file mode 100755 index 0000000..1024993 Binary files /dev/null and b/app/src/main/res/drawable/cometchat.png differ diff --git a/app/src/main/res/drawable/default_avatar.xml b/app/src/main/res/drawable/default_avatar.xml new file mode 100755 index 0000000..3e661e8 --- /dev/null +++ b/app/src/main/res/drawable/default_avatar.xml @@ -0,0 +1,12 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/edit_background.xml b/app/src/main/res/drawable/edit_background.xml new file mode 100755 index 0000000..1c1e885 --- /dev/null +++ b/app/src/main/res/drawable/edit_background.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/edit_text_round.xml b/app/src/main/res/drawable/edit_text_round.xml new file mode 100755 index 0000000..6b6c59f --- /dev/null +++ b/app/src/main/res/drawable/edit_text_round.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_access_time_24dp.xml b/app/src/main/res/drawable/ic_access_time_24dp.xml new file mode 100755 index 0000000..87e8fda --- /dev/null +++ b/app/src/main/res/drawable/ic_access_time_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_artboard.xml b/app/src/main/res/drawable/ic_artboard.xml new file mode 100644 index 0000000..c9ea996 --- /dev/null +++ b/app/src/main/res/drawable/ic_artboard.xml @@ -0,0 +1,24 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_attach_file_red_24dp.xml b/app/src/main/res/drawable/ic_attach_file_red_24dp.xml new file mode 100755 index 0000000..260f227 --- /dev/null +++ b/app/src/main/res/drawable/ic_attach_file_red_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_broken_image.xml b/app/src/main/res/drawable/ic_broken_image.xml new file mode 100755 index 0000000..39d7e9b --- /dev/null +++ b/app/src/main/res/drawable/ic_broken_image.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/ic_broken_image_black.xml b/app/src/main/res/drawable/ic_broken_image_black.xml new file mode 100755 index 0000000..88157dd --- /dev/null +++ b/app/src/main/res/drawable/ic_broken_image_black.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/src/main/res/drawable/ic_call_24dp.xml b/app/src/main/res/drawable/ic_call_24dp.xml new file mode 100755 index 0000000..7e6f97c --- /dev/null +++ b/app/src/main/res/drawable/ic_call_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_call_end_24dp.xml b/app/src/main/res/drawable/ic_call_end_24dp.xml new file mode 100755 index 0000000..edca9bf --- /dev/null +++ b/app/src/main/res/drawable/ic_call_end_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_chat_bubble_outline_black_24dp.xml b/app/src/main/res/drawable/ic_chat_bubble_outline_black_24dp.xml new file mode 100755 index 0000000..880a1b1 --- /dev/null +++ b/app/src/main/res/drawable/ic_chat_bubble_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_chats.xml b/app/src/main/res/drawable/ic_chats.xml new file mode 100755 index 0000000..8b33d2a --- /dev/null +++ b/app/src/main/res/drawable/ic_chats.xml @@ -0,0 +1,6 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_24dp.xml b/app/src/main/res/drawable/ic_check_24dp.xml new file mode 100755 index 0000000..17aca2a --- /dev/null +++ b/app/src/main/res/drawable/ic_check_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_check_black_24dp.xml b/app/src/main/res/drawable/ic_check_black_24dp.xml new file mode 100755 index 0000000..17aca2a --- /dev/null +++ b/app/src/main/res/drawable/ic_check_black_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_chevron_left_24dp.xml b/app/src/main/res/drawable/ic_chevron_left_24dp.xml new file mode 100755 index 0000000..748786a --- /dev/null +++ b/app/src/main/res/drawable/ic_chevron_left_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_close_24dp.xml b/app/src/main/res/drawable/ic_close_24dp.xml new file mode 100755 index 0000000..a8cce60 --- /dev/null +++ b/app/src/main/res/drawable/ic_close_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_contacts.xml b/app/src/main/res/drawable/ic_contacts.xml new file mode 100644 index 0000000..7f4f035 --- /dev/null +++ b/app/src/main/res/drawable/ic_contacts.xml @@ -0,0 +1,18 @@ + + + + diff --git a/app/src/main/res/drawable/ic_createbutton.xml b/app/src/main/res/drawable/ic_createbutton.xml new file mode 100644 index 0000000..3e2c896 --- /dev/null +++ b/app/src/main/res/drawable/ic_createbutton.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_delete_black_24dp.xml b/app/src/main/res/drawable/ic_delete_black_24dp.xml new file mode 100755 index 0000000..39e64d6 --- /dev/null +++ b/app/src/main/res/drawable/ic_delete_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_description_black_24dp.xml b/app/src/main/res/drawable/ic_description_black_24dp.xml new file mode 100755 index 0000000..74f6fc1 --- /dev/null +++ b/app/src/main/res/drawable/ic_description_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml b/app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml new file mode 100755 index 0000000..6f40d77 --- /dev/null +++ b/app/src/main/res/drawable/ic_exit_to_app_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_file_download.xml b/app/src/main/res/drawable/ic_file_download.xml new file mode 100644 index 0000000..84db281 --- /dev/null +++ b/app/src/main/res/drawable/ic_file_download.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_group_default.xml b/app/src/main/res/drawable/ic_group_default.xml new file mode 100755 index 0000000..3f6027b --- /dev/null +++ b/app/src/main/res/drawable/ic_group_default.xml @@ -0,0 +1,19 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_groups.xml b/app/src/main/res/drawable/ic_groups.xml new file mode 100644 index 0000000..4f9b63a --- /dev/null +++ b/app/src/main/res/drawable/ic_groups.xml @@ -0,0 +1,30 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_info_outline_24dp.xml b/app/src/main/res/drawable/ic_info_outline_24dp.xml new file mode 100755 index 0000000..20ae39f --- /dev/null +++ b/app/src/main/res/drawable/ic_info_outline_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_insert_drive_file_24dp.xml b/app/src/main/res/drawable/ic_insert_drive_file_24dp.xml new file mode 100755 index 0000000..a431a5e --- /dev/null +++ b/app/src/main/res/drawable/ic_insert_drive_file_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_insert_drive_file_black_24dp.xml b/app/src/main/res/drawable/ic_insert_drive_file_black_24dp.xml new file mode 100755 index 0000000..7a6d094 --- /dev/null +++ b/app/src/main/res/drawable/ic_insert_drive_file_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml b/app/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml new file mode 100755 index 0000000..7879b24 --- /dev/null +++ b/app/src/main/res/drawable/ic_keyboard_arrow_down_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_keyboard_arrow_right_24dp.xml b/app/src/main/res/drawable/ic_keyboard_arrow_right_24dp.xml new file mode 100755 index 0000000..0789c22 --- /dev/null +++ b/app/src/main/res/drawable/ic_keyboard_arrow_right_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100755 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_location_on_black_24dp.xml b/app/src/main/res/drawable/ic_location_on_black_24dp.xml new file mode 100755 index 0000000..e3291a9 --- /dev/null +++ b/app/src/main/res/drawable/ic_location_on_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock_outline_black_24dp.xml b/app/src/main/res/drawable/ic_lock_outline_black_24dp.xml new file mode 100755 index 0000000..9a14b68 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock_outline_grey_24dp.xml b/app/src/main/res/drawable/ic_lock_outline_grey_24dp.xml new file mode 100755 index 0000000..520ef53 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_outline_grey_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_lock_outline_red_24dp.xml b/app/src/main/res/drawable/ic_lock_outline_red_24dp.xml new file mode 100755 index 0000000..76d5d79 --- /dev/null +++ b/app/src/main/res/drawable/ic_lock_outline_red_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_mic_24dp.xml b/app/src/main/res/drawable/ic_mic_24dp.xml new file mode 100755 index 0000000..d652f36 --- /dev/null +++ b/app/src/main/res/drawable/ic_mic_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_more.xml b/app/src/main/res/drawable/ic_more.xml new file mode 100755 index 0000000..7553fe4 --- /dev/null +++ b/app/src/main/res/drawable/ic_more.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_more_vert.xml b/app/src/main/res/drawable/ic_more_vert.xml new file mode 100755 index 0000000..c097d3e --- /dev/null +++ b/app/src/main/res/drawable/ic_more_vert.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_my_location_24dp.xml b/app/src/main/res/drawable/ic_my_location_24dp.xml new file mode 100755 index 0000000..1d28825 --- /dev/null +++ b/app/src/main/res/drawable/ic_my_location_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_account_circle_24px.xml b/app/src/main/res/drawable/ic_outline_account_circle_24px.xml new file mode 100755 index 0000000..0c9a104 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_account_circle_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_add_a_photo_24px.xml b/app/src/main/res/drawable/ic_outline_add_a_photo_24px.xml new file mode 100755 index 0000000..8333e3c --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_add_a_photo_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_call_24px.xml b/app/src/main/res/drawable/ic_outline_call_24px.xml new file mode 100755 index 0000000..e316545 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_call_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_group_add_24px.xml b/app/src/main/res/drawable/ic_outline_group_add_24px.xml new file mode 100755 index 0000000..e8e9897 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_group_add_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_home_24px.xml b/app/src/main/res/drawable/ic_outline_home_24px.xml new file mode 100755 index 0000000..ad6065c --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_home_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_image_24px.xml b/app/src/main/res/drawable/ic_outline_image_24px.xml new file mode 100755 index 0000000..97d080d --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_image_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_insert_drive_file_24px.xml b/app/src/main/res/drawable/ic_outline_insert_drive_file_24px.xml new file mode 100755 index 0000000..c803616 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_insert_drive_file_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_video_call_24px.xml b/app/src/main/res/drawable/ic_outline_video_call_24px.xml new file mode 100755 index 0000000..444aeb9 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_video_call_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_video_call_white_24px.xml b/app/src/main/res/drawable/ic_outline_video_call_white_24px.xml new file mode 100755 index 0000000..b706c24 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_video_call_white_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_outline_videocam_24px.xml b/app/src/main/res/drawable/ic_outline_videocam_24px.xml new file mode 100755 index 0000000..67b6f19 --- /dev/null +++ b/app/src/main/res/drawable/ic_outline_videocam_24px.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_pause_black_24dp.xml b/app/src/main/res/drawable/ic_pause_black_24dp.xml new file mode 100755 index 0000000..bb28a6c --- /dev/null +++ b/app/src/main/res/drawable/ic_pause_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_pause_white_24dp.xml b/app/src/main/res/drawable/ic_pause_white_24dp.xml new file mode 100755 index 0000000..1696640 --- /dev/null +++ b/app/src/main/res/drawable/ic_pause_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_people_outline_black_24dp.xml b/app/src/main/res/drawable/ic_people_outline_black_24dp.xml new file mode 100755 index 0000000..ecdc122 --- /dev/null +++ b/app/src/main/res/drawable/ic_people_outline_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_perm_24dp.xml b/app/src/main/res/drawable/ic_perm_24dp.xml new file mode 100755 index 0000000..d2d1693 --- /dev/null +++ b/app/src/main/res/drawable/ic_perm_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_person_add_black_24dp.xml b/app/src/main/res/drawable/ic_person_add_black_24dp.xml new file mode 100755 index 0000000..225ae0a --- /dev/null +++ b/app/src/main/res/drawable/ic_person_add_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_person_black_24dp.xml b/app/src/main/res/drawable/ic_person_black_24dp.xml new file mode 100755 index 0000000..b2cb337 --- /dev/null +++ b/app/src/main/res/drawable/ic_person_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_play_arrow.xml b/app/src/main/res/drawable/ic_play_arrow.xml new file mode 100755 index 0000000..5f18c23 --- /dev/null +++ b/app/src/main/res/drawable/ic_play_arrow.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_play_arrow_black.xml b/app/src/main/res/drawable/ic_play_arrow_black.xml new file mode 100755 index 0000000..a95b173 --- /dev/null +++ b/app/src/main/res/drawable/ic_play_arrow_black.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_play_circle.xml b/app/src/main/res/drawable/ic_play_circle.xml new file mode 100755 index 0000000..41bec11 --- /dev/null +++ b/app/src/main/res/drawable/ic_play_circle.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_reply_24dp.xml b/app/src/main/res/drawable/ic_reply_24dp.xml new file mode 100755 index 0000000..3aff3f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_reply_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_black_24dp.xml b/app/src/main/res/drawable/ic_search_black_24dp.xml new file mode 100755 index 0000000..affc7ba --- /dev/null +++ b/app/src/main/res/drawable/ic_search_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_send_24dp.xml b/app/src/main/res/drawable/ic_send_24dp.xml new file mode 100755 index 0000000..33efc5c --- /dev/null +++ b/app/src/main/res/drawable/ic_send_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_supervisor_account_black_24dp.xml b/app/src/main/res/drawable/ic_supervisor_account_black_24dp.xml new file mode 100755 index 0000000..8aa9c18 --- /dev/null +++ b/app/src/main/res/drawable/ic_supervisor_account_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/login.png b/app/src/main/res/drawable/login.png new file mode 100755 index 0000000..8252773 Binary files /dev/null and b/app/src/main/res/drawable/login.png differ diff --git a/app/src/main/res/drawable/login_button.xml b/app/src/main/res/drawable/login_button.xml new file mode 100755 index 0000000..c676111 --- /dev/null +++ b/app/src/main/res/drawable/login_button.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/password_background.xml b/app/src/main/res/drawable/password_background.xml new file mode 100755 index 0000000..c5d376c --- /dev/null +++ b/app/src/main/res/drawable/password_background.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/reply_container_border.xml b/app/src/main/res/drawable/reply_container_border.xml new file mode 100755 index 0000000..6ccc05e --- /dev/null +++ b/app/src/main/res/drawable/reply_container_border.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/reply_left.xml b/app/src/main/res/drawable/reply_left.xml new file mode 100755 index 0000000..26c89aa --- /dev/null +++ b/app/src/main/res/drawable/reply_left.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shimmer_status.xml b/app/src/main/res/drawable/shimmer_status.xml new file mode 100755 index 0000000..4571223 --- /dev/null +++ b/app/src/main/res/drawable/shimmer_status.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp/activity_main.xml b/app/src/main/res/layout-sw600dp/activity_main.xml new file mode 100755 index 0000000..3dc9a56 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/activity_main.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-sw600dp/fragment_contact_list.xml b/app/src/main/res/layout-sw600dp/fragment_contact_list.xml new file mode 100755 index 0000000..3e1d976 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/fragment_contact_list.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp/fragment_group_list.xml b/app/src/main/res/layout-sw600dp/fragment_group_list.xml new file mode 100755 index 0000000..c729bc4 --- /dev/null +++ b/app/src/main/res/layout-sw600dp/fragment_group_list.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_call.xml b/app/src/main/res/layout/activity_call.xml new file mode 100755 index 0000000..92ec8ea --- /dev/null +++ b/app/src/main/res/layout/activity_call.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_create_group.xml b/app/src/main/res/layout/activity_create_group.xml new file mode 100755 index 0000000..46b8c3d --- /dev/null +++ b/app/src/main/res/layout/activity_create_group.xml @@ -0,0 +1,238 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_group_chat.xml b/app/src/main/res/layout/activity_group_chat.xml new file mode 100755 index 0000000..4fa8ff3 --- /dev/null +++ b/app/src/main/res/layout/activity_group_chat.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_group_detail.xml b/app/src/main/res/layout/activity_group_detail.xml new file mode 100755 index 0000000..f460b6e --- /dev/null +++ b/app/src/main/res/layout/activity_group_detail.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_image_view.xml b/app/src/main/res/layout/activity_image_view.xml new file mode 100755 index 0000000..5faeb1a --- /dev/null +++ b/app/src/main/res/layout/activity_image_view.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_location.xml b/app/src/main/res/layout/activity_location.xml new file mode 100755 index 0000000..a3aab47 --- /dev/null +++ b/app/src/main/res/layout/activity_location.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + +