Merge pull request #2355 from nextcloud/chrore/fix-warnings-in-chatController

Fix warnings in ChatController
This commit is contained in:
Tim Krüger 2022-09-07 15:41:14 +02:00 committed by GitHub
commit 7deb8bef8d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -238,32 +238,32 @@ class ChatController(args: Bundle) :
var roomToken: String? = null var roomToken: String? = null
val conversationUser: User? val conversationUser: User?
val roomPassword: String private val roomPassword: String
var credentials: String? = null var credentials: String? = null
var currentConversation: Conversation? = null var currentConversation: Conversation? = null
var inConversation = false var inConversation = false
var historyRead = false private var historyRead = false
var globalLastKnownFutureMessageId = -1 private var globalLastKnownFutureMessageId = -1
var globalLastKnownPastMessageId = -1 private var globalLastKnownPastMessageId = -1
var adapter: TalkMessagesListAdapter<ChatMessage>? = null var adapter: TalkMessagesListAdapter<ChatMessage>? = null
var mentionAutocomplete: Autocomplete<*>? = null private var mentionAutocomplete: Autocomplete<*>? = null
var layoutManager: LinearLayoutManager? = null var layoutManager: LinearLayoutManager? = null
var pullChatMessagesPending = false var pullChatMessagesPending = false
var lookingIntoFuture = false private var lookingIntoFuture = false
var newMessagesCount = 0 var newMessagesCount = 0
var startCallFromNotification: Boolean? = null var startCallFromNotification: Boolean? = null
val roomId: String val roomId: String
val voiceOnly: Boolean val voiceOnly: Boolean
var isFirstMessagesProcessing = true var isFirstMessagesProcessing = true
var emojiPopup: EmojiPopup? = null private var emojiPopup: EmojiPopup? = null
var myFirstMessage: CharSequence? = null var myFirstMessage: CharSequence? = null
var checkingLobbyStatus: Boolean = false var checkingLobbyStatus: Boolean = false
var conversationInfoMenuItem: MenuItem? = null private var conversationInfoMenuItem: MenuItem? = null
var conversationVoiceCallMenuItem: MenuItem? = null private var conversationVoiceCallMenuItem: MenuItem? = null
var conversationVideoMenuItem: MenuItem? = null private var conversationVideoMenuItem: MenuItem? = null
var conversationSharedItemsItem: MenuItem? = null private var conversationSharedItemsItem: MenuItem? = null
var magicWebSocketInstance: MagicWebSocketInstance? = null var magicWebSocketInstance: MagicWebSocketInstance? = null
@ -271,8 +271,8 @@ class ChatController(args: Bundle) :
var pastPreconditionFailed = false var pastPreconditionFailed = false
var futurePreconditionFailed = false var futurePreconditionFailed = false
val filesToUpload: MutableList<String> = ArrayList() private val filesToUpload: MutableList<String> = ArrayList()
var sharedText: String private var sharedText: String
var isVoiceRecordingInProgress: Boolean = false var isVoiceRecordingInProgress: Boolean = false
var currentVoiceRecordFile: String = "" var currentVoiceRecordFile: String = ""
@ -280,7 +280,7 @@ class ChatController(args: Bundle) :
var mediaPlayer: MediaPlayer? = null var mediaPlayer: MediaPlayer? = null
lateinit var mediaPlayerHandler: Handler lateinit var mediaPlayerHandler: Handler
var currentlyPlayedVoiceMessage: ChatMessage? = null private var currentlyPlayedVoiceMessage: ChatMessage? = null
var hasChatPermission: Boolean = false var hasChatPermission: Boolean = false
@ -306,10 +306,10 @@ class ChatController(args: Bundle) :
this.roomPassword = args.getString(BundleKeys.KEY_CONVERSATION_PASSWORD, "") this.roomPassword = args.getString(BundleKeys.KEY_CONVERSATION_PASSWORD, "")
if (conversationUser?.userId == "?") { credentials = if (conversationUser?.userId == "?") {
credentials = null null
} else { } else {
credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token) ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token)
} }
if (args.containsKey(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) { if (args.containsKey(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
@ -329,7 +329,7 @@ class ChatController(args: Bundle) :
val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1)) val apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1))
val startNanoTime = System.nanoTime() val startNanoTime = System.nanoTime()
Log.d(TAG, "getRoomInfo - getRoom - calling: " + startNanoTime) Log.d(TAG, "getRoomInfo - getRoom - calling: $startNanoTime")
ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, conversationUser.baseUrl, roomToken)) ncApi.getRoom(credentials, ApiUtils.getUrlForRoom(apiVersion, conversationUser.baseUrl, roomToken))
?.subscribeOn(Schedulers.io()) ?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread()) ?.observeOn(AndroidSchedulers.mainThread())
@ -340,7 +340,7 @@ class ChatController(args: Bundle) :
@Suppress("Detekt.TooGenericExceptionCaught") @Suppress("Detekt.TooGenericExceptionCaught")
override fun onNext(roomOverall: RoomOverall) { override fun onNext(roomOverall: RoomOverall) {
Log.d(TAG, "getRoomInfo - getRoom - got response: " + startNanoTime) Log.d(TAG, "getRoomInfo - getRoom - got response: $startNanoTime")
currentConversation = roomOverall.ocs!!.data currentConversation = roomOverall.ocs!!.data
Log.d( Log.d(
TAG, TAG,
@ -367,7 +367,7 @@ class ChatController(args: Bundle) :
} }
} catch (npe: NullPointerException) { } catch (npe: NullPointerException) {
// view binding can be null // view binding can be null
// since this is called asynchrously and UI might have been destroyed in the meantime // since this is called asynchronously and UI might have been destroyed in the meantime
Log.i(TAG, "UI destroyed - view binding already gone") Log.i(TAG, "UI destroyed - view binding already gone")
} }
} }
@ -377,7 +377,7 @@ class ChatController(args: Bundle) :
} }
override fun onComplete() { override fun onComplete() {
Log.d(TAG, "getRoomInfo - getRoom - onComplete: " + startNanoTime) Log.d(TAG, "getRoomInfo - getRoom - onComplete: $startNanoTime")
if (shouldRepeat) { if (shouldRepeat) {
if (lobbyTimerHandler == null) { if (lobbyTimerHandler == null) {
lobbyTimerHandler = Handler() lobbyTimerHandler = Handler()
@ -582,14 +582,13 @@ class ChatController(args: Bundle) :
this this
) )
var senderId = "" val senderId = if (!conversationUser.userId.equals("?")) {
if (!conversationUser?.userId.equals("?")) { "users/" + conversationUser.userId
senderId = "users/" + conversationUser?.userId
} else { } else {
senderId = currentConversation?.actorType + "/" + currentConversation?.actorId currentConversation?.actorType + "/" + currentConversation?.actorId
} }
Log.d(TAG, "Initialize TalkMessagesListAdapter with senderId: " + senderId) Log.d(TAG, "Initialize TalkMessagesListAdapter with senderId: $senderId")
adapter = TalkMessagesListAdapter( adapter = TalkMessagesListAdapter(
senderId, senderId,
@ -618,7 +617,7 @@ class ChatController(args: Bundle) :
R.id.playPauseBtn R.id.playPauseBtn
) { view, message -> ) { view, message ->
val filename = message.selectedIndividualHashMap!!["name"] val filename = message.selectedIndividualHashMap!!["name"]
val file = File(context!!.cacheDir, filename!!) val file = File(context.cacheDir, filename!!)
if (file.exists()) { if (file.exists()) {
if (message.isPlayingVoiceMessage) { if (message.isPlayingVoiceMessage) {
pausePlayback(message) pausePlayback(message)
@ -638,11 +637,10 @@ class ChatController(args: Bundle) :
binding.popupBubbleView.setPopupBubbleListener { context -> binding.popupBubbleView.setPopupBubbleListener { context ->
if (newMessagesCount != 0) { if (newMessagesCount != 0) {
val scrollPosition: Int val scrollPosition = if (newMessagesCount - 1 < 0) {
if (newMessagesCount - 1 < 0) { 0
scrollPosition = 0
} else { } else {
scrollPosition = newMessagesCount - 1 newMessagesCount - 1
} }
Handler().postDelayed( Handler().postDelayed(
{ {
@ -676,7 +674,7 @@ class ChatController(args: Bundle) :
}) })
val filters = arrayOfNulls<InputFilter>(1) val filters = arrayOfNulls<InputFilter>(1)
val lengthFilter = CapabilitiesUtilNew.getMessageMaxLength(conversationUser) ?: MESSAGE_MAX_LENGTH val lengthFilter = CapabilitiesUtilNew.getMessageMaxLength(conversationUser)
filters[0] = InputFilter.LengthFilter(lengthFilter) filters[0] = InputFilter.LengthFilter(lengthFilter)
binding.messageInputView.inputEditText?.filters = filters binding.messageInputView.inputEditText?.filters = filters
@ -692,7 +690,7 @@ class ChatController(args: Bundle) :
if (s.length >= lengthFilter) { if (s.length >= lengthFilter) {
binding.messageInputView.inputEditText?.error = String.format( binding.messageInputView.inputEditText?.error = String.format(
Objects.requireNonNull<Resources>(resources).getString(R.string.nc_limit_hit), Objects.requireNonNull<Resources>(resources).getString(R.string.nc_limit_hit),
Integer.toString(lengthFilter) lengthFilter.toString()
) )
} else { } else {
binding.messageInputView.inputEditText?.error = null binding.messageInputView.inputEditText?.error = null
@ -771,7 +769,7 @@ class ChatController(args: Bundle) :
requestRecordAudioPermissions() requestRecordAudioPermissions()
return true return true
} }
if (!UploadAndShareFilesWorker.isStoragePermissionGranted(context!!)) { if (!UploadAndShareFilesWorker.isStoragePermissionGranted(context)) {
UploadAndShareFilesWorker.requestStoragePermission(this@ChatController) UploadAndShareFilesWorker.requestStoragePermission(this@ChatController)
return true return true
} }
@ -803,10 +801,10 @@ class ChatController(args: Bundle) :
voiceRecordEndTime = System.currentTimeMillis() voiceRecordEndTime = System.currentTimeMillis()
val voiceRecordDuration = voiceRecordEndTime - voiceRecordStartTime val voiceRecordDuration = voiceRecordEndTime - voiceRecordStartTime
if (voiceRecordDuration < MINIMUM_VOICE_RECORD_DURATION) { if (voiceRecordDuration < MINIMUM_VOICE_RECORD_DURATION) {
Log.d(TAG, "voiceRecordDuration: " + voiceRecordDuration) Log.d(TAG, "voiceRecordDuration: $voiceRecordDuration")
Toast.makeText( Toast.makeText(
context, context,
context!!.getString(R.string.nc_voice_message_hold_to_record_info), context.getString(R.string.nc_voice_message_hold_to_record_info),
Toast.LENGTH_SHORT Toast.LENGTH_SHORT
).show() ).show()
stopAndDiscardAudioRecording() stopAndDiscardAudioRecording()
@ -993,7 +991,7 @@ class ChatController(args: Bundle) :
if (mediaPlayer == null) { if (mediaPlayer == null) {
val fileName = message.selectedIndividualHashMap!!["name"] val fileName = message.selectedIndividualHashMap!!["name"]
val absolutePath = context!!.cacheDir.absolutePath + "/" + fileName val absolutePath = context.cacheDir.absolutePath + "/" + fileName
mediaPlayer = MediaPlayer().apply { mediaPlayer = MediaPlayer().apply {
setDataSource(absolutePath) setDataSource(absolutePath)
prepare() prepare()
@ -1050,12 +1048,12 @@ class ChatController(args: Bundle) :
// check if download worker is already running // check if download worker is already running
val workers = WorkManager.getInstance( val workers = WorkManager.getInstance(
context!! context
).getWorkInfosByTag(fileId!!) ).getWorkInfosByTag(fileId!!)
try { try {
for (workInfo in workers.get()) { for (workInfo in workers.get()) {
if (workInfo.state == WorkInfo.State.RUNNING || workInfo.state == WorkInfo.State.ENQUEUED) { if (workInfo.state == WorkInfo.State.RUNNING || workInfo.state == WorkInfo.State.ENQUEUED) {
Log.d(TAG, "Download worker for " + fileId + " is already running or scheduled") Log.d(TAG, "Download worker for $fileId is already running or scheduled")
return return
} }
} }
@ -1081,7 +1079,7 @@ class ChatController(args: Bundle) :
WorkManager.getInstance().enqueue(downloadWorker) WorkManager.getInstance().enqueue(downloadWorker)
WorkManager.getInstance(context!!).getWorkInfoByIdLiveData(downloadWorker.id) WorkManager.getInstance(context).getWorkInfoByIdLiveData(downloadWorker.id)
.observeForever { workInfo: WorkInfo -> .observeForever { workInfo: WorkInfo ->
if (workInfo.state == WorkInfo.State.SUCCEEDED) { if (workInfo.state == WorkInfo.State.SUCCEEDED) {
startPlayback(message) startPlayback(message)
@ -1096,13 +1094,13 @@ class ChatController(args: Bundle) :
val date: String = simpleDateFormat.format(Date()) val date: String = simpleDateFormat.format(Date())
val fileNameWithoutSuffix = String.format( val fileNameWithoutSuffix = String.format(
context!!.resources.getString(R.string.nc_voice_message_filename), context.resources.getString(R.string.nc_voice_message_filename),
date, date,
currentConversation!!.displayName currentConversation!!.displayName
) )
val fileName = fileNameWithoutSuffix + VOICE_MESSAGE_FILE_SUFFIX val fileName = fileNameWithoutSuffix + VOICE_MESSAGE_FILE_SUFFIX
currentVoiceRecordFile = "${context!!.cacheDir.absolutePath}/$fileName" currentVoiceRecordFile = "${context.cacheDir.absolutePath}/$fileName"
} }
private fun showRecordAudioUi(show: Boolean) { private fun showRecordAudioUi(show: Boolean) {
@ -1124,14 +1122,14 @@ class ChatController(args: Bundle) :
binding.messageInputView.smileyButton.visibility = View.VISIBLE binding.messageInputView.smileyButton.visibility = View.VISIBLE
binding.messageInputView.messageInput.visibility = View.VISIBLE binding.messageInputView.messageInput.visibility = View.VISIBLE
binding.messageInputView.messageInput.hint = binding.messageInputView.messageInput.hint =
context?.resources?.getString(R.string.nc_hint_enter_a_message) context.resources?.getString(R.string.nc_hint_enter_a_message)
} }
} }
private fun isRecordAudioPermissionGranted(): Boolean { private fun isRecordAudioPermissionGranted(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
return PermissionChecker.checkSelfPermission( return PermissionChecker.checkSelfPermission(
context!!, context,
Manifest.permission.RECORD_AUDIO Manifest.permission.RECORD_AUDIO
) == PermissionChecker.PERMISSION_GRANTED ) == PermissionChecker.PERMISSION_GRANTED
} else { } else {
@ -1211,7 +1209,7 @@ class ChatController(args: Bundle) :
} }
fun vibrate() { fun vibrate() {
val vibrator = context?.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator val vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
if (Build.VERSION.SDK_INT >= O) { if (Build.VERSION.SDK_INT >= O) {
vibrator.vibrate(VibrationEffect.createOneShot(SHORT_VIBRATE, VibrationEffect.DEFAULT_AMPLITUDE)) vibrator.vibrate(VibrationEffect.createOneShot(SHORT_VIBRATE, VibrationEffect.DEFAULT_AMPLITUDE))
} else { } else {
@ -1403,25 +1401,25 @@ class ChatController(args: Bundle) :
} }
require(filesToUpload.isNotEmpty()) require(filesToUpload.isNotEmpty())
val filenamesWithLinebreaks = StringBuilder("\n") val filenamesWithLineBreaks = StringBuilder("\n")
for (file in filesToUpload) { for (file in filesToUpload) {
val filename = UriUtils.getFileName(Uri.parse(file), context) val filename = UriUtils.getFileName(Uri.parse(file), context)
filenamesWithLinebreaks.append(filename).append("\n") filenamesWithLineBreaks.append(filename).append("\n")
} }
val confirmationQuestion = when (filesToUpload.size) { val confirmationQuestion = when (filesToUpload.size) {
1 -> context?.resources?.getString(R.string.nc_upload_confirm_send_single)?.let { 1 -> context.resources?.getString(R.string.nc_upload_confirm_send_single)?.let {
String.format(it, title.trim()) String.format(it, title.trim())
} }
else -> context?.resources?.getString(R.string.nc_upload_confirm_send_multiple)?.let { else -> context.resources?.getString(R.string.nc_upload_confirm_send_multiple)?.let {
String.format(it, title.trim()) String.format(it, title.trim())
} }
} }
val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageInputView.context) val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageInputView.context)
.setTitle(confirmationQuestion) .setTitle(confirmationQuestion)
.setMessage(filenamesWithLinebreaks.toString()) .setMessage(filenamesWithLineBreaks.toString())
.setPositiveButton(R.string.nc_yes) { _, _ -> .setPositiveButton(R.string.nc_yes) { _, _ ->
if (UploadAndShareFilesWorker.isStoragePermissionGranted(context)) { if (UploadAndShareFilesWorker.isStoragePermissionGranted(context)) {
uploadFiles(filesToUpload, false) uploadFiles(filesToUpload, false)
@ -1445,11 +1443,11 @@ class ChatController(args: Bundle) :
dialog.getButton(AlertDialog.BUTTON_NEGATIVE) dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
) )
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG) Toast.makeText(context, context.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
.show() .show()
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e) Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG) Toast.makeText(context, context.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
.show() .show()
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e) Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
} }
@ -1460,8 +1458,8 @@ class ChatController(args: Bundle) :
if (cursor != null && cursor.moveToFirst()) { if (cursor != null && cursor.moveToFirst()) {
val id = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID)) val id = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.Contacts._ID))
val fileName = ContactUtils.getDisplayNameFromDeviceContact(context!!, id) + ".vcf" val fileName = ContactUtils.getDisplayNameFromDeviceContact(context, id) + ".vcf"
val file = File(context?.cacheDir, fileName) val file = File(context.cacheDir, fileName)
writeContactToVcfFile(cursor, file) writeContactToVcfFile(cursor, file)
val shareUri = FileProvider.getUriForFile( val shareUri = FileProvider.getUriForFile(
@ -1486,7 +1484,7 @@ class ChatController(args: Bundle) :
} }
require(filesToUpload.isNotEmpty()) require(filesToUpload.isNotEmpty())
if (UploadAndShareFilesWorker.isStoragePermissionGranted(context!!)) { if (UploadAndShareFilesWorker.isStoragePermissionGranted(context)) {
uploadFiles(filesToUpload, false) uploadFiles(filesToUpload, false)
} else { } else {
UploadAndShareFilesWorker.requestStoragePermission(this) UploadAndShareFilesWorker.requestStoragePermission(this)
@ -1494,7 +1492,7 @@ class ChatController(args: Bundle) :
} catch (e: IllegalStateException) { } catch (e: IllegalStateException) {
Toast.makeText( Toast.makeText(
context, context,
context?.resources?.getString(R.string.nc_upload_failed), context.resources?.getString(R.string.nc_upload_failed),
Toast.LENGTH_LONG Toast.LENGTH_LONG
) )
.show() .show()
@ -1502,7 +1500,7 @@ class ChatController(args: Bundle) :
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
Toast.makeText( Toast.makeText(
context, context,
context?.resources?.getString(R.string.nc_upload_failed), context.resources?.getString(R.string.nc_upload_failed),
Toast.LENGTH_LONG Toast.LENGTH_LONG
) )
.show() .show()
@ -1554,7 +1552,7 @@ class ChatController(args: Bundle) :
} }
} else { } else {
Toast Toast
.makeText(context, context?.getString(R.string.read_storage_no_permission), Toast.LENGTH_LONG) .makeText(context, context.getString(R.string.read_storage_no_permission), Toast.LENGTH_LONG)
.show() .show()
} }
} else if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) { } else if (requestCode == REQUEST_RECORD_AUDIO_PERMISSION) {
@ -1563,7 +1561,7 @@ class ChatController(args: Bundle) :
} else { } else {
Toast.makeText( Toast.makeText(
context, context,
context!!.getString(R.string.nc_voice_message_missing_audio_permission), context.getString(R.string.nc_voice_message_missing_audio_permission),
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()
} }
@ -1574,17 +1572,17 @@ class ChatController(args: Bundle) :
} else { } else {
Toast.makeText( Toast.makeText(
context, context,
context!!.getString(R.string.nc_share_contact_permission), context.getString(R.string.nc_share_contact_permission),
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()
} }
} else if (requestCode == REQUEST_CAMERA_PERMISSION) { } else if (requestCode == REQUEST_CAMERA_PERMISSION) {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "launch cam activity since permission for cam has been granted") Log.d(TAG, "launch cam activity since permission for cam has been granted")
startActivityForResult(TakePhotoActivity.createIntent(context!!), REQUEST_CODE_PICK_CAMERA) startActivityForResult(TakePhotoActivity.createIntent(context), REQUEST_CODE_PICK_CAMERA)
} else { } else {
Toast Toast
.makeText(context, context?.getString(R.string.take_photo_permission), Toast.LENGTH_LONG) .makeText(context, context.getString(R.string.take_photo_permission), Toast.LENGTH_LONG)
.show() .show()
} }
} }
@ -1621,12 +1619,12 @@ class ChatController(args: Bundle) :
if (!isVoiceMessage) { if (!isVoiceMessage) {
Toast.makeText( Toast.makeText(
context, context,
context?.getString(R.string.nc_upload_in_progess), context.getString(R.string.nc_upload_in_progess),
Toast.LENGTH_LONG Toast.LENGTH_LONG
).show() ).show()
} }
} catch (e: IllegalArgumentException) { } catch (e: IllegalArgumentException) {
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG).show() Toast.makeText(context, context.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG).show()
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e) Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
} }
} }
@ -1640,7 +1638,7 @@ class ChatController(args: Bundle) :
startActivityForResult( startActivityForResult(
Intent.createChooser( Intent.createChooser(
action, action,
context?.resources?.getString( context.resources?.getString(
R.string.nc_upload_choose_local_files R.string.nc_upload_choose_local_files
) )
), ),
@ -1724,7 +1722,7 @@ class ChatController(args: Bundle) :
eventBus.register(this) eventBus.register(this)
if (conversationUser?.userId != "?" && if (conversationUser?.userId != "?" &&
CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "mention-flag") ?: false && CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "mention-flag") &&
activity != null activity != null
) { ) {
activity?.findViewById<View>(R.id.toolbar)?.setOnClickListener { v -> showConversationInfoScreen() } activity?.findViewById<View>(R.id.toolbar)?.setOnClickListener { v -> showConversationInfoScreen() }
@ -1743,13 +1741,13 @@ class ChatController(args: Bundle) :
onEmojiPopupShownListener = { onEmojiPopupShownListener = {
if (resources != null) { if (resources != null) {
smileyButton?.setImageDrawable( smileyButton?.setImageDrawable(
ContextCompat.getDrawable(context!!, R.drawable.ic_baseline_keyboard_24) ContextCompat.getDrawable(context, R.drawable.ic_baseline_keyboard_24)
) )
} }
}, },
onEmojiPopupDismissListener = { onEmojiPopupDismissListener = {
smileyButton?.setImageDrawable( smileyButton?.setImageDrawable(
ContextCompat.getDrawable(context!!, R.drawable.ic_insert_emoticon_black_24dp) ContextCompat.getDrawable(context, R.drawable.ic_insert_emoticon_black_24dp)
) )
}, },
onEmojiClickListener = { onEmojiClickListener = {
@ -1777,7 +1775,7 @@ class ChatController(args: Bundle) :
cancelNotificationsForCurrentConversation() cancelNotificationsForCurrentConversation()
Log.d(TAG, "onAttach inConversation: " + inConversation.toString()) Log.d(TAG, "onAttach inConversation: $inConversation")
if (inConversation) { if (inConversation) {
Log.d(TAG, "execute joinRoomWithPassword in onAttach") Log.d(TAG, "execute joinRoomWithPassword in onAttach")
joinRoomWithPassword() joinRoomWithPassword()
@ -1881,11 +1879,11 @@ class ChatController(args: Bundle) :
var apiVersion = 1 var apiVersion = 1
// FIXME Fix API checking with guests? // FIXME Fix API checking with guests?
if (conversationUser != null) { if (conversationUser != null) {
apiVersion = ApiUtils.getConversationApiVersion(conversationUser!!, intArrayOf(ApiUtils.APIv4, 1)) apiVersion = ApiUtils.getConversationApiVersion(conversationUser, intArrayOf(ApiUtils.APIv4, 1))
} }
val startNanoTime = System.nanoTime() val startNanoTime = System.nanoTime()
Log.d(TAG, "joinRoomWithPassword - joinRoom - calling: " + startNanoTime) Log.d(TAG, "joinRoomWithPassword - joinRoom - calling: $startNanoTime")
ncApi.joinRoom( ncApi.joinRoom(
credentials, credentials,
ApiUtils.getUrlForParticipantsActive(apiVersion, conversationUser?.baseUrl, roomToken), ApiUtils.getUrlForParticipantsActive(apiVersion, conversationUser?.baseUrl, roomToken),
@ -1901,7 +1899,7 @@ class ChatController(args: Bundle) :
@Suppress("Detekt.TooGenericExceptionCaught") @Suppress("Detekt.TooGenericExceptionCaught")
override fun onNext(roomOverall: RoomOverall) { override fun onNext(roomOverall: RoomOverall) {
Log.d(TAG, "joinRoomWithPassword - joinRoom - got response: " + startNanoTime) Log.d(TAG, "joinRoomWithPassword - joinRoom - got response: $startNanoTime")
inConversation = true inConversation = true
currentConversation?.sessionId = roomOverall.ocs!!.data!!.sessionId currentConversation?.sessionId = roomOverall.ocs!!.data!!.sessionId
Log.d(TAG, "joinRoomWithPassword - sessionId: " + currentConversation?.sessionId) Log.d(TAG, "joinRoomWithPassword - sessionId: " + currentConversation?.sessionId)
@ -1915,7 +1913,7 @@ class ChatController(args: Bundle) :
checkLobbyState() checkLobbyState()
} catch (npe: NullPointerException) { } catch (npe: NullPointerException) {
// view binding can be null // view binding can be null
// since this is called asynchrously and UI might have been destroyed in the meantime // since this is called asynchronously and UI might have been destroyed in the meantime
Log.i(TAG, "UI destroyed - view binding already gone") Log.i(TAG, "UI destroyed - view binding already gone")
} }
@ -1971,7 +1969,7 @@ class ChatController(args: Bundle) :
} }
val startNanoTime = System.nanoTime() val startNanoTime = System.nanoTime()
Log.d(TAG, "leaveRoom - leaveRoom - calling: " + startNanoTime) Log.d(TAG, "leaveRoom - leaveRoom - calling: $startNanoTime")
ncApi.leaveRoom( ncApi.leaveRoom(
credentials, credentials,
ApiUtils.getUrlForParticipantsActive( ApiUtils.getUrlForParticipantsActive(
@ -1988,7 +1986,7 @@ class ChatController(args: Bundle) :
} }
override fun onNext(genericOverall: GenericOverall) { override fun onNext(genericOverall: GenericOverall) {
Log.d(TAG, "leaveRoom - leaveRoom - got response: " + startNanoTime) Log.d(TAG, "leaveRoom - leaveRoom - got response: $startNanoTime")
checkingLobbyStatus = false checkingLobbyStatus = false
if (lobbyTimerHandler != null) { if (lobbyTimerHandler != null) {
@ -2012,7 +2010,7 @@ class ChatController(args: Bundle) :
} }
override fun onComplete() { override fun onComplete() {
Log.d(TAG, "leaveRoom - leaveRoom - completed: " + startNanoTime) Log.d(TAG, "leaveRoom - leaveRoom - completed: $startNanoTime")
disposables.dispose() disposables.dispose()
} }
}) })
@ -2055,7 +2053,7 @@ class ChatController(args: Bundle) :
if (conversationUser != null) { if (conversationUser != null) {
val apiVersion = ApiUtils.getChatApiVersion(conversationUser, intArrayOf(1)) val apiVersion = ApiUtils.getChatApiVersion(conversationUser, intArrayOf(1))
ncApi!!.sendChatMessage( ncApi.sendChatMessage(
credentials, credentials,
ApiUtils.getUrlForChat(apiVersion, conversationUser.baseUrl, roomToken), ApiUtils.getUrlForChat(apiVersion, conversationUser.baseUrl, roomToken),
message, message,
@ -2075,14 +2073,14 @@ class ChatController(args: Bundle) :
myFirstMessage = message myFirstMessage = message
try { try {
if (binding.popupBubbleView.isShown == true) { if (binding.popupBubbleView.isShown) {
binding.popupBubbleView.hide() binding.popupBubbleView.hide()
} }
binding.messagesListView.smoothScrollToPosition(0) binding.messagesListView.smoothScrollToPosition(0)
} catch (npe: NullPointerException) { } catch (npe: NullPointerException) {
// view binding can be null // view binding can be null
// since this is called asynchrously and UI might have been destroyed in the meantime // since this is called asynchronously and UI might have been destroyed in the meantime
Log.i(TAG, "UI destroyed - view binding already gone") Log.i(TAG, "UI destroyed - view binding already gone")
} }
} }
@ -2090,10 +2088,10 @@ class ChatController(args: Bundle) :
override fun onError(e: Throwable) { override fun onError(e: Throwable) {
if (e is HttpException) { if (e is HttpException) {
val code = e.code() val code = e.code()
if (Integer.toString(code).startsWith("2")) { if (code.toString().startsWith("2")) {
myFirstMessage = message myFirstMessage = message
if (binding.popupBubbleView.isShown == true) { if (binding.popupBubbleView.isShown) {
binding.popupBubbleView.hide() binding.popupBubbleView.hide()
} }
@ -2112,12 +2110,12 @@ class ChatController(args: Bundle) :
private fun setupWebsocket() { private fun setupWebsocket() {
if (conversationUser != null) { if (conversationUser != null) {
if (WebSocketConnectionHelper.getMagicWebSocketInstanceForUserId(conversationUser.id!!) != null) {
magicWebSocketInstance = magicWebSocketInstance =
if (WebSocketConnectionHelper.getMagicWebSocketInstanceForUserId(conversationUser.id!!) != null) {
WebSocketConnectionHelper.getMagicWebSocketInstanceForUserId(conversationUser.id!!) WebSocketConnectionHelper.getMagicWebSocketInstanceForUserId(conversationUser.id!!)
} else { } else {
Log.d(TAG, "magicWebSocketInstance became null") Log.d(TAG, "magicWebSocketInstance became null")
magicWebSocketInstance = null null
} }
} }
} }
@ -2166,11 +2164,10 @@ class ChatController(args: Bundle) :
fieldMap["limit"] = MESSAGE_PULL_LIMIT fieldMap["limit"] = MESSAGE_PULL_LIMIT
fieldMap["setReadMarker"] = setReadMarker fieldMap["setReadMarker"] = setReadMarker
val lastKnown: Int val lastKnown = if (lookIntoFuture > 0) {
if (lookIntoFuture > 0) { globalLastKnownFutureMessageId
lastKnown = globalLastKnownFutureMessageId
} else { } else {
lastKnown = globalLastKnownPastMessageId globalLastKnownPastMessageId
} }
fieldMap["lastKnownMessageId"] = lastKnown fieldMap["lastKnownMessageId"] = lastKnown
@ -2185,7 +2182,6 @@ class ChatController(args: Bundle) :
} }
if (lookIntoFuture > 0) { if (lookIntoFuture > 0) {
val finalTimeout = timeout
Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture > 0] - calling") Log.d(TAG, "pullChatMessages - pullChatMessages[lookIntoFuture > 0] - calling")
ncApi.pullChatMessages( ncApi.pullChatMessages(
credentials, credentials,
@ -2210,11 +2206,11 @@ class ChatController(args: Bundle) :
} else if (response.code() == HTTP_CODE_PRECONDITION_FAILED) { } else if (response.code() == HTTP_CODE_PRECONDITION_FAILED) {
futurePreconditionFailed = true futurePreconditionFailed = true
} else { } else {
processMessages(response, true, finalTimeout) processMessagesResponse(response, true)
} }
} catch (npe: NullPointerException) { } catch (npe: NullPointerException) {
// view binding can be null // view binding can be null
// since this is called asynchrously and UI might have been destroyed in the meantime // since this is called asynchronously and UI might have been destroyed in the meantime
Log.i(TAG, "UI destroyed - view binding already gone") Log.i(TAG, "UI destroyed - view binding already gone")
} }
@ -2252,11 +2248,11 @@ class ChatController(args: Bundle) :
if (response.code() == HTTP_CODE_PRECONDITION_FAILED) { if (response.code() == HTTP_CODE_PRECONDITION_FAILED) {
pastPreconditionFailed = true pastPreconditionFailed = true
} else { } else {
processMessages(response, false, 0) processMessagesResponse(response, false)
} }
} catch (e: NullPointerException) { } catch (e: NullPointerException) {
// view binding can be null // view binding can be null
// since this is called asynchrously and UI might have been destroyed in the meantime // since this is called asynchronously and UI might have been destroyed in the meantime
Log.i(TAG, "UI destroyed - view binding already gone", e) Log.i(TAG, "UI destroyed - view binding already gone", e)
} }
@ -2297,29 +2293,40 @@ class ChatController(args: Bundle) :
} }
} }
private fun processMessages(response: Response<*>, isFromTheFuture: Boolean, timeout: Int) { private fun processMessagesResponse(response: Response<*>, isFromTheFuture: Boolean) {
val xChatLastGivenHeader: String? = response.headers().get("X-Chat-Last-Given")
val xChatLastCommonRead = response.headers().get("X-Chat-Last-Common-Read")?.let { val xChatLastCommonRead = response.headers()["X-Chat-Last-Common-Read"]?.let {
Integer.parseInt(it) Integer.parseInt(it)
} }
if (response.headers().size > 0 && !TextUtils.isEmpty(xChatLastGivenHeader)) {
val header = Integer.parseInt(xChatLastGivenHeader!!) processHeaderChatLastGiven(response, isFromTheFuture)
if (header > 0) {
if (isFromTheFuture) {
globalLastKnownFutureMessageId = header
} else {
if (globalLastKnownFutureMessageId == -1) {
globalLastKnownFutureMessageId = header
}
globalLastKnownPastMessageId = header
}
}
}
if (response.code() == HTTP_CODE_OK) { if (response.code() == HTTP_CODE_OK) {
val chatOverall = response.body() as ChatOverall? val chatOverall = response.body() as ChatOverall?
val chatMessageList = handleSystemMessages(chatOverall?.ocs!!.data!!) val chatMessageList = handleSystemMessages(chatOverall?.ocs!!.data!!)
processMessages(chatMessageList, isFromTheFuture, xChatLastCommonRead)
} else if (response.code() == HTTP_CODE_NOT_MODIFIED && !isFromTheFuture) {
if (isFirstMessagesProcessing) {
cancelNotificationsForCurrentConversation()
isFirstMessagesProcessing = false
binding.progressBar.visibility = View.GONE
}
historyRead = true
if (!lookingIntoFuture && inConversation) {
pullChatMessages(1)
}
}
}
private fun processMessages(
chatMessageList: List<ChatMessage>,
isFromTheFuture: Boolean,
xChatLastCommonRead: Int?
) {
if (chatMessageList.isNotEmpty() && if (chatMessageList.isNotEmpty() &&
ChatMessage.SystemMessageType.CLEARED_CHAT == chatMessageList[0].systemMessageType ChatMessage.SystemMessageType.CLEARED_CHAT == chatMessageList[0].systemMessageType
) { ) {
@ -2336,24 +2343,117 @@ class ChatController(args: Bundle) :
binding.messagesListView.visibility = View.VISIBLE binding.messagesListView.visibility = View.VISIBLE
} }
if (isFromTheFuture) {
processMessagesFromTheFuture(chatMessageList)
} else {
processMessagesNotFromTheFuture(chatMessageList)
}
updateReadStatusOfAllMessages(xChatLastCommonRead)
adapter?.notifyDataSetChanged()
if (inConversation) {
pullChatMessages(1, 1, xChatLastCommonRead)
}
}
private fun updateReadStatusOfAllMessages(xChatLastCommonRead: Int?) {
for (message in adapter!!.items) {
xChatLastCommonRead?.let {
updateReadStatusOfMessage(message, it)
}
}
}
private fun updateReadStatusOfMessage(
message: MessagesListAdapter<IMessage>.Wrapper<Any>,
xChatLastCommonRead: Int
) {
if (message.item is ChatMessage) {
val chatMessage = message.item as ChatMessage
if (chatMessage.jsonMessageId <= xChatLastCommonRead) {
chatMessage.readStatus = ReadStatus.READ
} else {
chatMessage.readStatus = ReadStatus.SENT
}
}
}
private fun processMessagesFromTheFuture(chatMessageList: List<ChatMessage>) {
val shouldAddNewMessagesNotice = (adapter?.itemCount ?: 0) > 0 && chatMessageList.isNotEmpty()
if (shouldAddNewMessagesNotice) {
val unreadChatMessage = ChatMessage()
unreadChatMessage.jsonMessageId = -1
unreadChatMessage.actorId = "-1"
unreadChatMessage.timestamp = chatMessageList[0].timestamp
unreadChatMessage.message = context.getString(R.string.nc_new_messages)
adapter?.addToStart(unreadChatMessage, false)
}
determinePreviousMessageIds(chatMessageList)
addMessagesToAdapter(shouldAddNewMessagesNotice, chatMessageList)
if (shouldAddNewMessagesNotice && adapter != null) {
layoutManager?.scrollToPositionWithOffset(
adapter!!.getMessagePositionByIdInReverse("-1"),
binding.messagesListView.height / 2
)
}
}
private fun addMessagesToAdapter(
shouldAddNewMessagesNotice: Boolean,
chatMessageList: List<ChatMessage>
) {
val isThereANewNotice =
shouldAddNewMessagesNotice || adapter?.getMessagePositionByIdInReverse("-1") != -1
for (chatMessage in chatMessageList) {
chatMessage.activeUser = conversationUser
val shouldScroll =
!isThereANewNotice &&
!shouldAddNewMessagesNotice &&
layoutManager?.findFirstVisibleItemPosition() == 0 ||
adapter != null &&
adapter?.itemCount == 0
modifyMessageCount(shouldAddNewMessagesNotice, shouldScroll)
adapter?.let {
chatMessage.isGrouped = (
it.isPreviousSameAuthor(
chatMessage.actorId,
-1
) && it.getSameAuthorLastMessagesCount(chatMessage.actorId) %
GROUPED_MESSAGES_SAME_AUTHOR_THRESHOLD > 0
)
chatMessage.isOneToOneConversation =
(currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
it.addToStart(chatMessage, shouldScroll)
}
}
}
private fun modifyMessageCount(shouldAddNewMessagesNotice: Boolean, shouldScroll: Boolean) {
if (!shouldAddNewMessagesNotice && !shouldScroll) {
if (!binding.popupBubbleView.isShown) {
newMessagesCount = 1
binding.popupBubbleView.show()
} else if (binding.popupBubbleView.isShown) {
newMessagesCount++
}
} else {
newMessagesCount = 0
}
}
private fun processMessagesNotFromTheFuture(chatMessageList: List<ChatMessage>) {
var countGroupedMessages = 0 var countGroupedMessages = 0
if (!isFromTheFuture) { determinePreviousMessageIds(chatMessageList)
var previousMessageId = NO_PREVIOUS_MESSAGE_ID
for (i in chatMessageList.indices.reversed()) {
val chatMessage = chatMessageList[i]
if (previousMessageId > NO_PREVIOUS_MESSAGE_ID) {
chatMessage.previousMessageId = previousMessageId
} else if (adapter?.isEmpty != true) {
if (adapter!!.items[0].item is ChatMessage) {
chatMessage.previousMessageId = (adapter!!.items[0].item as ChatMessage).jsonMessageId
} else if (adapter!!.items.size > 1 && adapter!!.items[1].item is ChatMessage) {
chatMessage.previousMessageId = (adapter!!.items[1].item as ChatMessage).jsonMessageId
}
}
previousMessageId = chatMessage.jsonMessageId
}
for (i in chatMessageList.indices) { for (i in chatMessageList.indices) {
if (chatMessageList.size > i + 1) { if (chatMessageList.size > i + 1) {
@ -2378,116 +2478,46 @@ class ChatController(args: Bundle) :
adapter?.addToEnd(chatMessageList, false) adapter?.addToEnd(chatMessageList, false)
} }
scrollToRequestedMessageIfNeeded() scrollToRequestedMessageIfNeeded()
} else {
var chatMessage: ChatMessage
val shouldAddNewMessagesNotice = (adapter?.itemCount ?: 0) > 0 && chatMessageList.isNotEmpty()
if (shouldAddNewMessagesNotice) {
val unreadChatMessage = ChatMessage()
unreadChatMessage.jsonMessageId = -1
unreadChatMessage.actorId = "-1"
unreadChatMessage.timestamp = chatMessageList[0].timestamp
unreadChatMessage.message = context?.getString(R.string.nc_new_messages)
adapter?.addToStart(unreadChatMessage, false)
} }
val isThereANewNotice = private fun determinePreviousMessageIds(chatMessageList: List<ChatMessage>) {
shouldAddNewMessagesNotice || adapter?.getMessagePositionByIdInReverse("-1") != -1
var previousMessageId = NO_PREVIOUS_MESSAGE_ID var previousMessageId = NO_PREVIOUS_MESSAGE_ID
for (i in chatMessageList.indices.reversed()) { for (i in chatMessageList.indices.reversed()) {
val chatMessageItem = chatMessageList[i] val chatMessage = chatMessageList[i]
if (previousMessageId > NO_PREVIOUS_MESSAGE_ID) { if (previousMessageId > NO_PREVIOUS_MESSAGE_ID) {
chatMessageItem.previousMessageId = previousMessageId chatMessage.previousMessageId = previousMessageId
} else if (adapter?.isEmpty != true) { } else if (adapter?.isEmpty != true) {
if (adapter!!.items[0].item is ChatMessage) { if (adapter!!.items[0].item is ChatMessage) {
chatMessageItem.previousMessageId = (adapter!!.items[0].item as ChatMessage).jsonMessageId chatMessage.previousMessageId = (adapter!!.items[0].item as ChatMessage).jsonMessageId
} else if (adapter!!.items.size > 1 && adapter!!.items[1].item is ChatMessage) { } else if (adapter!!.items.size > 1 && adapter!!.items[1].item is ChatMessage) {
chatMessageItem.previousMessageId = (adapter!!.items[1].item as ChatMessage).jsonMessageId chatMessage.previousMessageId = (adapter!!.items[1].item as ChatMessage).jsonMessageId
} }
} }
previousMessageId = chatMessageItem.jsonMessageId previousMessageId = chatMessage.jsonMessageId
}
} }
for (i in chatMessageList.indices) { private fun processHeaderChatLastGiven(response: Response<*>, isFromTheFuture: Boolean) {
chatMessage = chatMessageList[i] val xChatLastGivenHeader: String? = response.headers()["X-Chat-Last-Given"]
chatMessage.activeUser = conversationUser val header = if (response.headers().size > 0 &&
xChatLastGivenHeader?.isNotEmpty() == true
val shouldScroll = ) {
!isThereANewNotice && xChatLastGivenHeader.toInt()
!shouldAddNewMessagesNotice &&
layoutManager?.findFirstVisibleItemPosition() == 0 ||
adapter != null &&
adapter?.itemCount == 0
if (!shouldAddNewMessagesNotice && !shouldScroll) {
if (!binding.popupBubbleView.isShown) {
newMessagesCount = 1
binding.popupBubbleView.show()
} else if (binding.popupBubbleView.isShown == true) {
newMessagesCount++
}
} else { } else {
newMessagesCount = 0 return
} }
if (adapter != null) { if (header > 0) {
chatMessage.isGrouped = ( if (isFromTheFuture) {
adapter!!.isPreviousSameAuthor( globalLastKnownFutureMessageId = header
chatMessage.actorId,
-1
) && adapter!!.getSameAuthorLastMessagesCount(chatMessage.actorId) %
GROUPED_MESSAGES_SAME_AUTHOR_THRESHOLD > 0
)
chatMessage.isOneToOneConversation =
(currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
adapter?.addToStart(chatMessage, shouldScroll)
}
}
if (shouldAddNewMessagesNotice && adapter != null) {
layoutManager?.scrollToPositionWithOffset(
adapter!!.getMessagePositionByIdInReverse("-1"),
binding.messagesListView.height / 2
)
}
}
// update read status of all messages
for (message in adapter!!.items) {
xChatLastCommonRead?.let {
if (message.item is ChatMessage) {
val chatMessage = message.item as ChatMessage
if (chatMessage.jsonMessageId <= it) {
chatMessage.readStatus = ReadStatus.READ
} else { } else {
chatMessage.readStatus = ReadStatus.SENT if (globalLastKnownFutureMessageId == -1) {
globalLastKnownFutureMessageId = header
} }
} globalLastKnownPastMessageId = header
}
}
adapter?.notifyDataSetChanged()
if (inConversation) {
pullChatMessages(1, 1, xChatLastCommonRead)
}
} else if (response.code() == HTTP_CODE_NOT_MODIFIED && !isFromTheFuture) {
if (isFirstMessagesProcessing) {
cancelNotificationsForCurrentConversation()
isFirstMessagesProcessing = false
binding.progressBar.visibility = View.GONE
}
historyRead = true
if (!lookingIntoFuture && inConversation) {
pullChatMessages(1)
} }
} }
} }
@ -2760,7 +2790,7 @@ class ChatController(args: Bundle) :
currentConversation, currentConversation,
isShowMessageDeletionButton(message), isShowMessageDeletionButton(message),
hasChatPermission, hasChatPermission,
ncApi!! ncApi
).show() ).show()
} }
} }
@ -2838,7 +2868,7 @@ class ChatController(args: Bundle) :
message?.user?.id?.substring(INVITE_LENGTH), message?.user?.id?.substring(INVITE_LENGTH),
null null
) )
ncApi!!.createRoom( ncApi.createRoom(
credentials, credentials,
retrofitBucket.url, retrofitBucket.url,
retrofitBucket.queryMap retrofitBucket.queryMap
@ -2857,7 +2887,7 @@ class ChatController(args: Bundle) :
bundle.putString(KEY_ROOM_ID, roomOverall.ocs!!.data!!.roomId) bundle.putString(KEY_ROOM_ID, roomOverall.ocs!!.data!!.roomId)
// FIXME once APIv2+ is used only, the createRoom already returns all the data // FIXME once APIv2+ is used only, the createRoom already returns all the data
ncApi!!.getRoom( ncApi.getRoom(
credentials, credentials,
ApiUtils.getUrlForRoom( ApiUtils.getUrlForRoom(
apiVersion, apiVersion,
@ -2921,7 +2951,7 @@ class ChatController(args: Bundle) :
fun markAsUnread(message: IMessage?) { fun markAsUnread(message: IMessage?) {
val chatMessage = message as ChatMessage? val chatMessage = message as ChatMessage?
if (chatMessage!!.previousMessageId > NO_PREVIOUS_MESSAGE_ID) { if (chatMessage!!.previousMessageId > NO_PREVIOUS_MESSAGE_ID) {
ncApi!!.setChatReadMarker( ncApi.setChatReadMarker(
credentials, credentials,
ApiUtils.getUrlForSetChatReadMarker( ApiUtils.getUrlForSetChatReadMarker(
ApiUtils.getChatApiVersion(conversationUser, intArrayOf(ApiUtils.APIv1)), ApiUtils.getChatApiVersion(conversationUser, intArrayOf(ApiUtils.APIv1)),
@ -2966,7 +2996,7 @@ class ChatController(args: Bundle) :
return !message.isDeleted || // copy message return !message.isDeleted || // copy message
message.replyable || // reply to message.replyable || // reply to
message.replyable && // reply privately message.replyable && // reply privately
conversationUser?.userId?.isNotEmpty() == true && conversationUser?.userId != "?" && conversationUser?.userId?.isNotEmpty() == true && conversationUser.userId != "?" &&
message.user.id.startsWith("users/") && message.user.id.startsWith("users/") &&
message.user.id.substring(ACTOR_LENGTH) != currentConversation?.actorId && message.user.id.substring(ACTOR_LENGTH) != currentConversation?.actorId &&
currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL || currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL ||
@ -2993,7 +3023,7 @@ class ChatController(args: Bundle) :
quotedMessage?.ellipsize = TextUtils.TruncateAt.END quotedMessage?.ellipsize = TextUtils.TruncateAt.END
quotedMessage?.text = it.text quotedMessage?.text = it.text
binding.messageInputView.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text = binding.messageInputView.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text =
it.actorDisplayName ?: context!!.getText(R.string.nc_nick_guest) it.actorDisplayName ?: context.getText(R.string.nc_nick_guest)
conversationUser?.let { currentUser -> conversationUser?.let { currentUser ->
val quotedMessageImage = binding val quotedMessageImage = binding
@ -3091,7 +3121,7 @@ class ChatController(args: Bundle) :
val isOlderThanSixHours = message val isOlderThanSixHours = message
.createdAt .createdAt
?.before(Date(System.currentTimeMillis() - AGE_THREHOLD_FOR_DELETE_MESSAGE)) == true .before(Date(System.currentTimeMillis() - AGE_THRESHOLD_FOR_DELETE_MESSAGE))
return when { return when {
!isUserAllowedByPrivileges -> false !isUserAllowedByPrivileges -> false
@ -3219,7 +3249,7 @@ class ChatController(args: Bundle) :
if (!permissionUtil.isCameraPermissionGranted()) { if (!permissionUtil.isCameraPermissionGranted()) {
requestCameraPermissions() requestCameraPermissions()
} else { } else {
startActivityForResult(TakePhotoActivity.createIntent(context!!), REQUEST_CODE_PICK_CAMERA) startActivityForResult(TakePhotoActivity.createIntent(context), REQUEST_CODE_PICK_CAMERA)
} }
} }
@ -3244,8 +3274,7 @@ class ChatController(args: Bundle) :
private const val POP_CURRENT_CONTROLLER_DELAY: Long = 100 private const val POP_CURRENT_CONTROLLER_DELAY: Long = 100
private const val LOBBY_TIMER_DELAY: Long = 5000 private const val LOBBY_TIMER_DELAY: Long = 5000
private const val HTTP_CODE_OK: Int = 200 private const val HTTP_CODE_OK: Int = 200
private const val MESSAGE_MAX_LENGTH: Int = 1000 private const val AGE_THRESHOLD_FOR_DELETE_MESSAGE: Int = 21600000 // (6 hours in millis = 6 * 3600 * 1000)
private const val AGE_THREHOLD_FOR_DELETE_MESSAGE: Int = 21600000 // (6 hours in millis = 6 * 3600 * 1000)
private const val REQUEST_CODE_CHOOSE_FILE: Int = 555 private const val REQUEST_CODE_CHOOSE_FILE: Int = 555
private const val REQUEST_CODE_SELECT_CONTACT: Int = 666 private const val REQUEST_CODE_SELECT_CONTACT: Int = 666
private const val REQUEST_CODE_MESSAGE_SEARCH: Int = 777 private const val REQUEST_CODE_MESSAGE_SEARCH: Int = 777