Advertisement
Guest User

Untitled

a guest
Nov 15th, 2019
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.33 KB | None | 0 0
  1. package com.example.kalam_android.view.activities
  2.  
  3. import android.app.Activity
  4. import android.content.Intent
  5. import android.os.Bundle
  6. import android.os.Handler
  7. import android.text.Editable
  8. import android.text.TextWatcher
  9. import android.view.View
  10. import androidx.databinding.DataBindingUtil
  11. import androidx.lifecycle.Observer
  12. import androidx.lifecycle.ViewModelProviders
  13. import androidx.recyclerview.widget.LinearLayoutManager
  14. import com.example.kalam_android.R
  15. import com.example.kalam_android.base.BaseActivity
  16. import com.example.kalam_android.base.MyApplication
  17. import com.example.kalam_android.callbacks.MessageTypingListener
  18. import com.example.kalam_android.callbacks.NewMessageListener
  19. import com.example.kalam_android.databinding.ActivityChatDetailBinding
  20. import com.example.kalam_android.repository.model.AudioResponse
  21. import com.example.kalam_android.repository.model.ChatData
  22. import com.example.kalam_android.repository.model.ChatMessagesResponse
  23. import com.example.kalam_android.repository.net.ApiResponse
  24. import com.example.kalam_android.repository.net.Status
  25. import com.example.kalam_android.util.*
  26. import com.example.kalam_android.view.adapter.ChatMessagesAdapter
  27. import com.example.kalam_android.viewmodel.ChatMessagesViewModel
  28. import com.example.kalam_android.viewmodel.factory.ViewModelFactory
  29. import com.example.kalam_android.wrapper.GlideDownloder
  30. import com.example.kalam_android.helper.MyMediaRecorder
  31. import com.example.kalam_android.wrapper.SocketIO
  32. import com.fxn.pix.Pix
  33. import com.github.nkzawa.socketio.client.Ack
  34. import com.google.gson.Gson
  35. import com.google.gson.JsonObject
  36. import id.zelory.compressor.Compressor
  37. import kotlinx.android.synthetic.main.layout_content_of_chat.view.*
  38. import okhttp3.MediaType
  39. import okhttp3.RequestBody
  40. import org.json.JSONObject
  41. import java.io.File
  42. import javax.inject.Inject
  43.  
  44. class ChatDetailActivity : BaseActivity(), View.OnClickListener,
  45. NewMessageListener, MessageTypingListener {
  46.  
  47. private val TAG = this.javaClass.simpleName
  48. @Inject
  49. lateinit var sharedPrefsHelper: SharedPrefsHelper
  50. private var chatId = -1
  51. private var receiverId: String? = null
  52. private var userRealName: String? = null
  53. @Inject
  54. lateinit var factory: ViewModelFactory
  55. lateinit var binding: ActivityChatDetailBinding
  56. lateinit var viewModel: ChatMessagesViewModel
  57. private val delay: Long = 1000
  58. private var lastTextEdit: Long = 0
  59. private var index = 0
  60. var handler = Handler()
  61. private var chatList1: ArrayList<ChatData> = ArrayList()
  62. private var profileImage: String = ""
  63. private var loading = false
  64. private var isFromChatFragment = false
  65. private var messageType = ""
  66. private var myMediaRecorder: MyMediaRecorder? = null
  67.  
  68. override fun onCreate(savedInstanceState: Bundle?) {
  69. super.onCreate(savedInstanceState)
  70. binding = DataBindingUtil.setContentView(this, R.layout.activity_chat_detail)
  71. MyApplication.getAppComponent(this).doInjection(this)
  72. viewModel = ViewModelProviders.of(this, factory).get(ChatMessagesViewModel::class.java)
  73. viewModel.allChatResponse().observe(this, Observer {
  74. consumeResponse(it)
  75. })
  76. viewModel.audioResponse().observe(this, Observer {
  77. consumeAudioResponse(it)
  78. })
  79. gettingChatId()
  80. setUserData()
  81. initAdapter()
  82. initListeners()
  83. checkSomeoneTyping()
  84. SocketIO.setListener(this)
  85. SocketIO.setTypingListener(this)
  86. myMediaRecorder = MyMediaRecorder.getInstance(this, binding)
  87. applyPagination()
  88. }
  89.  
  90. private fun initListeners() {
  91. binding.lvBottomChat.ivSend.setOnClickListener(this)
  92. binding.lvBottomChat.ivCamera.setOnClickListener(this)
  93. binding.header.rlBack.setOnClickListener(this)
  94. binding.lvBottomChat.ivMic.setOnClickListener(this)
  95. binding.header.tvName.setOnClickListener(this)
  96. }
  97.  
  98. private fun initAdapter() {
  99. val linearLayout = LinearLayoutManager(this)
  100. linearLayout.reverseLayout = true
  101. linearLayout.stackFromEnd = false
  102. binding.chatMessagesRecycler.layoutManager = linearLayout
  103. binding.chatMessagesRecycler.adapter =
  104. ChatMessagesAdapter(this, sharedPrefsHelper.getUser()?.id.toString())
  105. }
  106.  
  107. private fun applyPagination() {
  108.  
  109. binding.chatMessagesRecycler.addOnScrollListener(object :
  110. PaginationScrollListener(binding.chatMessagesRecycler.layoutManager as LinearLayoutManager) {
  111. override val isLastPage: Boolean
  112. get() = chatList1.size == 0
  113. override val isLoading: Boolean
  114. get() = loading
  115.  
  116. override fun loadMoreItems() {
  117. binding.pbHeader.visibility = View.VISIBLE
  118. loading = true
  119. index += 20
  120. hitAllChatApi(index)
  121. }
  122. })
  123. }
  124.  
  125. private fun gettingChatId() {
  126. isFromChatFragment = intent.getBooleanExtra(AppConstants.IS_FROM_CHAT_FRAGMENT, false)
  127. if (isFromChatFragment) {
  128. chatId = intent.getIntExtra(AppConstants.CHAT_ID, 0)
  129. hitAllChatApi(0)
  130. sharedPrefsHelper.put(AppConstants.IS_FROM_CONTACTS, 2)
  131. } else {
  132. receiverId = intent.getStringExtra(AppConstants.RECEIVER_ID)
  133. val jsonObject = JsonObject()
  134. jsonObject.addProperty("user_id", sharedPrefsHelper.getUser()?.id.toString())
  135. jsonObject.addProperty("receiver_id", receiverId)
  136. SocketIO.socket?.emit(AppConstants.START_CAHT, jsonObject, Ack {
  137. val chatId = it[0] as Int
  138. this.chatId = chatId
  139. runOnUiThread {
  140. hitAllChatApi(0)
  141. }
  142. })
  143. sharedPrefsHelper.put(AppConstants.IS_FROM_CONTACTS, 1)
  144. }
  145. }
  146.  
  147. fun hitAllChatApi(offset: Int) {
  148. val params = HashMap<String, String>()
  149. params["chat_id"] = this.chatId.toString()
  150. params["offset"] = offset.toString()
  151. viewModel.hitAllChatApi(sharedPrefsHelper.getUser()?.token.toString(), params)
  152. }
  153.  
  154. private fun setUserData() {
  155. userRealName = intent.getStringExtra(AppConstants.CHAT_USER_NAME)
  156. profileImage = intent.getStringExtra(AppConstants.CHAT_USER_PICTURE)
  157. binding.header.tvName.text = userRealName
  158. GlideDownloder.load(
  159. this,
  160. binding.header.ivProfileImage,
  161. profileImage,
  162. R.drawable.dummy_placeholder,
  163. R.drawable.dummy_placeholder
  164. )
  165. }
  166.  
  167. private fun consumeResponse(apiResponse: ApiResponse<ChatMessagesResponse>?) {
  168. when (apiResponse?.status) {
  169.  
  170. Status.LOADING -> {
  171. loading = true
  172. logE("Loading Chat Messages")
  173. }
  174. Status.SUCCESS -> {
  175. loading = false
  176. binding.pbCenter.visibility = View.GONE
  177. binding.pbHeader.visibility = View.GONE
  178. renderResponse(apiResponse.data as ChatMessagesResponse)
  179. logE("+${apiResponse.data}")
  180. }
  181. Status.ERROR -> {
  182. loading = false
  183. binding.pbCenter.visibility = View.GONE
  184. binding.pbHeader.visibility = View.GONE
  185. toast("Something went wrong please try again")
  186. logE("consumeResponse ERROR: " + apiResponse.error.toString())
  187. }
  188. else -> {
  189. }
  190. }
  191. }
  192.  
  193. private fun renderResponse(response: ChatMessagesResponse?) {
  194. logE("socketResponse: $response")
  195. response?.let { it ->
  196. it.data?.let {
  197. chatList1 = it
  198. logE("All Messages Api Called")
  199. (binding.chatMessagesRecycler.adapter as ChatMessagesAdapter).updateList(it)
  200. }
  201. }
  202. }
  203.  
  204. private fun consumeAudioResponse(apiResponse: ApiResponse<AudioResponse>?) {
  205. when (apiResponse?.status) {
  206.  
  207. Status.LOADING -> {
  208. logE("Loading Audio")
  209. }
  210. Status.SUCCESS -> {
  211. renderAudioResponse(apiResponse.data as AudioResponse)
  212. }
  213. Status.ERROR -> {
  214. toast("Something went wrong please try again")
  215. logE("consumeResponse ERROR: " + apiResponse.error.toString())
  216. }
  217. else -> {
  218. }
  219. }
  220. }
  221.  
  222. private fun renderAudioResponse(response: AudioResponse?) {
  223. logE("socketResponse: $response")
  224. response?.let {
  225. SocketIO.emitFileID(it.data?.file_id)
  226. (binding.chatMessagesRecycler.adapter as ChatMessagesAdapter).updateIdentifier(it.data?.identifier.toString())
  227. }
  228. }
  229.  
  230. private fun uploadMedia(identifier: String, file: String) {
  231. val params = HashMap<String, RequestBody>()
  232. params["identifier"] = RequestBody.create(MediaType.parse("text/plain"), identifier)
  233. viewModel.hitUploadAudioApi(
  234. sharedPrefsHelper.getUser()?.token, params,
  235. getFileBody(file, "file")
  236. )
  237. }
  238.  
  239. private fun sendMediaMessage(file: String, type: String, isImage: Boolean) {
  240. val identifier = System.currentTimeMillis().toString()
  241. createChatObject(
  242. AppConstants.DUMMY_STRING,
  243. file,
  244. type,
  245. identifier
  246. )
  247. if (isImage) {
  248. messageType = type
  249. logE("Before Conversion : ${getReadableFileSize(File(file).length())}")
  250. val convertedFile = Compressor(this).compressToFile(File(file))
  251. logE("After Conversion : ${getReadableFileSize(convertedFile.length())}")
  252. uploadMedia(identifier, convertedFile.absolutePath)
  253. logE("Image Api hit successfully")
  254. } else {
  255. messageType = type
  256. uploadMedia(identifier, file)
  257. logE("Audio Api hit successfully")
  258. }
  259. }
  260.  
  261. private val inputFinishChecker = Runnable {
  262. if (System.currentTimeMillis() > lastTextEdit + delay - 500) {
  263. logE("User Stops Typing")
  264. SocketIO.typingEvent(
  265. AppConstants.STOP_TYPING,
  266. sharedPrefsHelper.getUser()?.id.toString(),
  267. chatId.toString()
  268. )
  269. }
  270. }
  271.  
  272. private fun checkSomeoneTyping() {
  273. binding.lvBottomChat.editTextMessage.addTextChangedListener(object : TextWatcher {
  274. override fun afterTextChanged(s: Editable?) {
  275. if (s?.isNotEmpty() == true) {
  276. lastTextEdit = System.currentTimeMillis()
  277. handler.postDelayed(inputFinishChecker, delay)
  278. }
  279. }
  280.  
  281. override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
  282.  
  283. }
  284.  
  285. override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
  286. if (s?.isNotEmpty() == true) {
  287. logE("User is typing")
  288. SocketIO.typingEvent(
  289. AppConstants.START_TYPING,
  290. sharedPrefsHelper.getUser()?.id.toString(),
  291. chatId.toString()
  292. )
  293. handler.removeCallbacks(inputFinishChecker)
  294. logE("id: ${sharedPrefsHelper.getUser()?.id.toString()}, chatID: $chatId")
  295. }
  296. }
  297. })
  298. }
  299.  
  300. private fun sendMessage() {
  301. createChatObject(
  302. binding.lvBottomChat.editTextMessage.text.toString(), AppConstants.DUMMY_STRING,
  303. AppConstants.TEXT_MESSAGE, AppConstants.DUMMY_STRING
  304. )
  305. SocketIO.emitNewMessage(
  306. sharedPrefsHelper.getUser()?.id.toString(),
  307. chatId.toString(),
  308. binding.lvBottomChat.editTextMessage.text.toString(),
  309. AppConstants.TEXT_MESSAGE,
  310. sharedPrefsHelper.getUser()?.firstname.toString()
  311. + " " + sharedPrefsHelper.getUser()?.lastname.toString(),
  312. AppConstants.DUMMY_STRING,
  313. 0
  314. )
  315. logE("Message Emitted to socket")
  316. binding.lvBottomChat.editTextMessage.setText("")
  317. }
  318.  
  319. override fun socketResponse(jsonObject: JSONObject) {
  320. val gson = Gson()
  321. logE("New Message : $jsonObject")
  322. val data = gson.fromJson(jsonObject.toString(), ChatData::class.java)
  323. if (data.chat_id == chatId) {
  324. runOnUiThread {
  325. addMessage(data)
  326. }
  327. }
  328. }
  329.  
  330. override fun typingResponse(jsonObject: JSONObject, isTyping: Boolean) {
  331. logE("typing response: $jsonObject")
  332. val chatId1 = jsonObject.getString("chat_id")
  333. if (chatId1.toInt() == chatId) {
  334. runOnUiThread {
  335. if (isTyping) {
  336. val user: String? = jsonObject.getString("user")
  337. if (user.equals(userRealName)) {
  338. logE("Is Typing")
  339. binding.header.tvTyping.visibility = View.VISIBLE
  340. }
  341. } else {
  342. logE("Not Typing")
  343. binding.header.tvTyping.visibility = View.GONE
  344. }
  345. }
  346. }
  347. }
  348.  
  349. private fun createChatObject(message: String, file: String, type: String, identifier: String) {
  350. addMessage(
  351. ChatData(
  352. AppConstants.DUMMY_STRING,
  353. file,
  354. AppConstants.DUMMY_STRING,
  355. StringBuilder(sharedPrefsHelper.getUser()?.firstname.toString()).append(" ").append(
  356. sharedPrefsHelper.getUser()?.lastname.toString()
  357. ).toString(),
  358. AppConstants.DUMMY_DATA,
  359. chatId,
  360. sharedPrefsHelper.getUser()?.id,
  361. AppConstants.DUMMY_DATA,
  362. message,
  363. AppConstants.DUMMY_DATA,
  364. AppConstants.DUMMY_DATA,
  365. type,
  366. file,
  367. 0,
  368. 0,
  369. message, identifier
  370. )
  371. )
  372. }
  373.  
  374. private fun addMessage(chatData: ChatData) {
  375. (binding.chatMessagesRecycler.adapter as ChatMessagesAdapter).addMessage(chatData)
  376. binding.chatMessagesRecycler.scrollToPosition(0)
  377. }
  378.  
  379. override fun onClick(v: View?) {
  380. when (v?.id) {
  381. R.id.ivSend -> {
  382. if (myMediaRecorder?.fileOutput()?.isEmpty() == true && binding.lvBottomChat.editTextMessage.text.toString().isNotEmpty()) {
  383. sendMessage()
  384. logE("Text Message")
  385. } else {
  386. if (myMediaRecorder?.isFileReady() == true) {
  387. logE("Audio Message")
  388. sendMediaMessage(
  389. myMediaRecorder?.fileOutput().toString(),
  390. AppConstants.AUDIO_MESSAGE,
  391. false
  392. )
  393. myMediaRecorder?.hideRecorder()
  394. myMediaRecorder?.cancel(false)
  395. }
  396. }
  397. }
  398. R.id.rlBack -> {
  399. onBackPressed()
  400. }
  401. R.id.tvName -> {
  402. val intent = Intent(this@ChatDetailActivity, UserProfileActivity::class.java)
  403. intent.putExtra(AppConstants.CHAT_USER_NAME, userRealName)
  404. intent.putExtra(AppConstants.CHAT_USER_PICTURE, profileImage)
  405. startActivity(intent)
  406. }
  407. R.id.ivCamera -> {
  408. checkPixPermission(
  409. this@ChatDetailActivity,
  410. AppConstants.CHAT_IMAGE_CODE
  411. )
  412. }
  413. R.id.ivMic -> {
  414. myMediaRecorder?.initRecorderWithPermissions()
  415. }
  416. }
  417. }
  418.  
  419. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  420. super.onActivityResult(requestCode, resultCode, data)
  421. if (resultCode == Activity.RESULT_OK) {
  422. when (requestCode) {
  423. AppConstants.CHAT_IMAGE_CODE -> {
  424. val returnValue = data?.getStringArrayListExtra(Pix.IMAGE_RESULTS)
  425. logE("onActivityResult returnValue: $returnValue")
  426. sendMediaMessage(
  427. returnValue?.get(0).toString(),
  428. AppConstants.IMAGE_MESSAGE,
  429. true
  430. )
  431. }
  432. }
  433. }
  434. }
  435.  
  436. override fun onBackPressed() {
  437. setResult(Activity.RESULT_OK)
  438. finish()
  439. }
  440.  
  441. private fun logE(msg: String) {
  442. Debugger.e(TAG, msg)
  443. }
  444. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement