From 4124a65c7a09a420b8760e6dc6e8a234e1faa553 Mon Sep 17 00:00:00 2001 From: Marcel Hibbe Date: Mon, 16 Jan 2023 14:58:31 +0100 Subject: [PATCH] make ControllerViewBindingDelegate nullable check nullable bindings in all controllers Signed-off-by: Marcel Hibbe --- .../AccountVerificationController.kt | 50 +-- .../talk/controllers/ChatController.kt | 323 ++++++++--------- .../talk/controllers/ContactsController.kt | 66 ++-- .../controllers/ConversationInfoController.kt | 242 +++++++------ .../ConversationsListController.kt | 327 +++++++++--------- .../talk/controllers/GeocodingController.kt | 8 +- .../controllers/LocationPickerController.kt | 56 +-- .../talk/controllers/LockedController.kt | 4 +- .../talk/controllers/ProfileController.kt | 78 +++-- .../RingtoneSelectionController.kt | 10 +- .../controllers/ServerSelectionController.kt | 75 ++-- .../talk/controllers/SettingsController.kt | 292 ++++++++-------- .../controllers/SwitchAccountController.kt | 12 +- .../controllers/WebViewLoginController.kt | 42 +-- .../bottomsheet/EntryMenuController.kt | 140 ++++---- .../bottomsheet/OperationsMenuController.kt | 34 +- .../util/ControllerViewBindingDelegate.kt | 10 +- 17 files changed, 900 insertions(+), 869 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt index 984d6131f..5118eb7cc 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/AccountVerificationController.kt @@ -80,7 +80,8 @@ class AccountVerificationController(args: Bundle? = null) : R.layout.controller_account_verification, args ) { - private val binding: ControllerAccountVerificationBinding by viewBinding(ControllerAccountVerificationBinding::bind) + private val binding: ControllerAccountVerificationBinding? by + viewBinding(ControllerAccountVerificationBinding::bind) @Inject lateinit var ncApi: NcApi @@ -212,7 +213,7 @@ class AccountVerificationController(args: Bundle? = null) : } else { if (activity != null && resources != null) { activity!!.runOnUiThread { - binding.progressText.setText( + binding?.progressText?.setText( String.format( resources!!.getString(R.string.nc_nextcloud_talk_app_not_installed), resources!!.getString(R.string.nc_app_product_name) @@ -230,17 +231,14 @@ class AccountVerificationController(args: Bundle? = null) : override fun onError(e: Throwable) { if (activity != null && resources != null) { activity!!.runOnUiThread { - binding.progressText.setText( - String.format( - resources!!.getString(R.string.nc_nextcloud_talk_app_not_installed), - resources!!.getString(R.string.nc_app_product_name) - ) + binding?.progressText?.text = String.format( + resources!!.getString(R.string.nc_nextcloud_talk_app_not_installed), + resources!!.getString(R.string.nc_app_product_name) ) } } - ApplicationWideMessageHolder.getInstance().setMessageType( + ApplicationWideMessageHolder.getInstance().messageType = ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK - ) abortVerification() } @@ -279,8 +277,8 @@ class AccountVerificationController(args: Bundle? = null) : registerForPush() } else { activity!!.runOnUiThread { - binding.progressText.text = - """ ${binding.progressText.text} + binding?.progressText?.text = + """ ${binding?.progressText?.text} ${resources!!.getString(R.string.nc_push_disabled)} """.trimIndent() } @@ -290,8 +288,8 @@ class AccountVerificationController(args: Bundle? = null) : @SuppressLint("SetTextI18n") override fun onError(e: Throwable) { - binding.progressText.text = - """ ${binding.progressText.text} + binding?.progressText?.text = + """ ${binding?.progressText?.text} """ .trimIndent() + resources!!.getString(R.string.nc_display_name_not_stored) abortVerification() @@ -331,9 +329,9 @@ class AccountVerificationController(args: Bundle? = null) : } else { if (activity != null) { activity!!.runOnUiThread { - binding.progressText.text = + binding?.progressText?.text = """ - ${binding.progressText.text} + ${binding?.progressText?.text} ${resources!!.getString(R.string.nc_display_name_not_fetched)} """.trimIndent() } @@ -346,9 +344,9 @@ class AccountVerificationController(args: Bundle? = null) : override fun onError(e: Throwable) { if (activity != null) { activity!!.runOnUiThread { - binding.progressText.text = + binding?.progressText?.text = """ - ${binding.progressText.text} + ${binding?.progressText?.text} ${resources!!.getString(R.string.nc_display_name_not_fetched)} """.trimIndent() } @@ -380,11 +378,17 @@ class AccountVerificationController(args: Bundle? = null) : if (eventStatus.eventType == EventStatus.EventType.PUSH_REGISTRATION) { if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood && activity != null) { activity!!.runOnUiThread { - binding.progressText.text = + // try { + binding?.progressText?.text = """ - ${binding.progressText.text} + ${binding?.progressText?.text} ${resources!!.getString(R.string.nc_push_disabled)} """.trimIndent() + // } catch (npe: NullPointerException) { + // // view binding can be null + // // since this is called asynchronously and UI might have been destroyed in the meantime + // Log.i(TAG, "UI destroyed - view binding already gone") + // } } } fetchAndStoreCapabilities() @@ -392,9 +396,9 @@ class AccountVerificationController(args: Bundle? = null) : if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood) { if (activity != null) { activity!!.runOnUiThread { - binding.progressText.text = + binding?.progressText?.text = """ - ${binding.progressText.text} + ${binding?.progressText?.text} ${resources!!.getString(R.string.nc_capabilities_failed)} """.trimIndent() } @@ -407,9 +411,9 @@ class AccountVerificationController(args: Bundle? = null) : if (internalAccountId == eventStatus.userId && !eventStatus.isAllGood) { if (activity != null) { activity!!.runOnUiThread { - binding.progressText.text = + binding?.progressText?.text = """ - ${binding.progressText.text} + ${binding?.progressText?.text} ${resources!!.getString(R.string.nc_external_server_failed)} """.trimIndent() } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt index 7f870d1cf..73a97fb90 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt @@ -213,23 +213,7 @@ import java.util.Locale import java.util.Objects import java.util.concurrent.ExecutionException import javax.inject.Inject -import kotlin.collections.ArrayList -import kotlin.collections.HashMap -import kotlin.collections.LinkedHashMap -import kotlin.collections.List -import kotlin.collections.MutableList -import kotlin.collections.MutableMap -import kotlin.collections.chunked -import kotlin.collections.indexOfFirst -import kotlin.collections.indices -import kotlin.collections.isNotEmpty -import kotlin.collections.iterator -import kotlin.collections.map import kotlin.collections.set -import kotlin.collections.toList -import kotlin.collections.toMap -import kotlin.collections.toMutableMap -import kotlin.collections.toTypedArray import kotlin.math.roundToInt @AutoInjector(NextcloudTalkApplication::class) @@ -246,7 +230,7 @@ class ChatController(args: Bundle) : CommonMessageInterface, PreviewMessageInterface { - private val binding: ControllerChatBinding by viewBinding(ControllerChatBinding::bind) + private val binding: ControllerChatBinding? by viewBinding(ControllerChatBinding::bind) @Inject lateinit var ncApi: NcApi @@ -437,7 +421,7 @@ class ChatController(args: Bundle) : withNullableControllerViewBinding { val itemTouchHelper = ItemTouchHelper(messageSwipeController) - itemTouchHelper.attachToRecyclerView(binding.messagesListView) + itemTouchHelper.attachToRecyclerView(binding?.messagesListView) } } } @@ -541,7 +525,7 @@ class ChatController(args: Bundle) : var adapterWasNull = false if (adapter == null) { - binding.progressBar.visibility = View.VISIBLE + binding?.progressBar?.visibility = View.VISIBLE adapterWasNull = true @@ -651,10 +635,10 @@ class ChatController(args: Bundle) : this ) } else { - binding.messagesListView.visibility = View.VISIBLE + binding?.messagesListView?.visibility = View.VISIBLE } - binding.messagesListView.setAdapter(adapter) + binding?.messagesListView?.setAdapter(adapter) adapter?.setLoadMoreListener(this) adapter?.setDateHeadersFormatter { format(it) } adapter?.setOnMessageViewLongClickListener { view, message -> onMessageViewLongClick(view, message) } @@ -677,11 +661,11 @@ class ChatController(args: Bundle) : setupSwipeToReply() - layoutManager = binding.messagesListView.layoutManager as LinearLayoutManager? + layoutManager = binding?.messagesListView?.layoutManager as LinearLayoutManager? - binding.popupBubbleView.setRecyclerView(binding.messagesListView) + binding?.popupBubbleView?.setRecyclerView(binding?.messagesListView) - binding.popupBubbleView.setPopupBubbleListener { context -> + binding?.popupBubbleView?.setPopupBubbleListener { context -> if (newMessagesCount != 0) { val scrollPosition = if (newMessagesCount - 1 < 0) { 0 @@ -690,18 +674,18 @@ class ChatController(args: Bundle) : } Handler().postDelayed( { - binding.messagesListView.smoothScrollToPosition(scrollPosition) + binding?.messagesListView?.smoothScrollToPosition(scrollPosition) }, NEW_MESSAGES_POPUP_BUBBLE_DELAY ) } } - viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.popupBubbleView) + binding?.let { viewThemeUtils.material.colorMaterialButtonPrimaryFilled(it.popupBubbleView) } - binding.messageInputView.setPadding(0, 0, 0, 0) + binding?.messageInputView?.setPadding(0, 0, 0, 0) - binding.messagesListView.addOnScrollListener(object : RecyclerView.OnScrollListener() { + binding?.messagesListView?.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { super.onScrollStateChanged(recyclerView, newState) @@ -710,8 +694,8 @@ class ChatController(args: Bundle) : if (layoutManager!!.findFirstCompletelyVisibleItemPosition() < newMessagesCount) { newMessagesCount = 0 - if (binding.popupBubbleView.isShown) { - binding.popupBubbleView.hide() + if (binding?.popupBubbleView?.isShown == true) { + binding?.popupBubbleView?.hide() } } } @@ -723,9 +707,9 @@ class ChatController(args: Bundle) : val lengthFilter = CapabilitiesUtilNew.getMessageMaxLength(conversationUser) filters[0] = InputFilter.LengthFilter(lengthFilter) - binding.messageInputView.inputEditText?.filters = filters + binding?.messageInputView?.inputEditText?.filters = filters - binding.messageInputView.inputEditText?.addTextChangedListener(object : TextWatcher { + binding?.messageInputView?.inputEditText?.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { // unused atm } @@ -734,19 +718,19 @@ class ChatController(args: Bundle) : override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { try { if (s.length >= lengthFilter) { - binding.messageInputView.inputEditText?.error = String.format( + binding?.messageInputView?.inputEditText?.error = String.format( Objects.requireNonNull(resources).getString(R.string.nc_limit_hit), lengthFilter.toString() ) } else { - binding.messageInputView.inputEditText?.error = null + binding?.messageInputView?.inputEditText?.error = null } - val editable = binding.messageInputView.inputEditText?.editableText - if (editable != null && binding.messageInputView.inputEditText != null) { + val editable = binding?.messageInputView?.inputEditText?.editableText + if (editable != null && binding?.messageInputView?.inputEditText != null) { val mentionSpans = editable.getSpans( 0, - binding.messageInputView.inputEditText!!.length(), + binding?.messageInputView?.inputEditText!!.length(), Spans.MentionChipSpan::class.java ) var mentionSpan: Spans.MentionChipSpan @@ -779,15 +763,15 @@ class ChatController(args: Bundle) : // Image keyboard support // See: https://developer.android.com/guide/topics/text/image-keyboard - (binding.messageInputView.inputEditText as ImageEmojiEditText).onCommitContentListener = { + (binding?.messageInputView?.inputEditText as ImageEmojiEditText).onCommitContentListener = { uploadFile(it.toString(), false) } showMicrophoneButton(true) - binding.messageInputView.messageInput.doAfterTextChanged { + binding?.messageInputView?.messageInput?.doAfterTextChanged { try { - if (binding.messageInputView.messageInput.text.isEmpty()) { + if (binding?.messageInputView?.messageInput?.text?.isEmpty() == true) { showMicrophoneButton(true) } else { showMicrophoneButton(false) @@ -806,7 +790,7 @@ class ChatController(args: Bundle) : var voiceRecordStartTime = 0L var voiceRecordEndTime = 0L - binding.messageInputView.recordAudioButton.setOnTouchListener(object : View.OnTouchListener { + binding?.messageInputView?.recordAudioButton?.setOnTouchListener(object : View.OnTouchListener { override fun onTouch(v: View?, event: MotionEvent?): Boolean { view.performClick() when (event?.action) { @@ -835,7 +819,7 @@ class ChatController(args: Bundle) : stopAndDiscardAudioRecording() showRecordAudioUi(false) - binding.messageInputView.slideToCancelDescription.x = sliderInitX + binding?.messageInputView?.slideToCancelDescription?.x = sliderInitX } MotionEvent.ACTION_UP -> { Log.d(TAG, "ACTION_UP. stop recording??") @@ -861,7 +845,7 @@ class ChatController(args: Bundle) : stopAndSendAudioRecording() } - binding.messageInputView.slideToCancelDescription.x = sliderInitX + binding?.messageInputView?.slideToCancelDescription?.x = sliderInitX } MotionEvent.ACTION_MOVE -> { Log.d(TAG, "ACTION_MOVE.") @@ -873,26 +857,26 @@ class ChatController(args: Bundle) : showRecordAudioUi(true) if (sliderInitX == 0.0F) { - sliderInitX = binding.messageInputView.slideToCancelDescription.x + sliderInitX = binding?.messageInputView?.slideToCancelDescription?.x!! } val movedX: Float = event.x deltaX = movedX - downX // only allow slide to left - if (binding.messageInputView.slideToCancelDescription.x > sliderInitX) { - binding.messageInputView.slideToCancelDescription.x = sliderInitX + if (binding?.messageInputView?.slideToCancelDescription?.x!! > sliderInitX) { + binding?.messageInputView?.slideToCancelDescription?.x = sliderInitX } - if (binding.messageInputView.slideToCancelDescription.x < VOICE_RECORD_CANCEL_SLIDER_X) { + if (binding?.messageInputView?.slideToCancelDescription?.x!! < VOICE_RECORD_CANCEL_SLIDER_X) { Log.d(TAG, "stopping recording because slider was moved to left") stopAndDiscardAudioRecording() showRecordAudioUi(false) - binding.messageInputView.slideToCancelDescription.x = sliderInitX + binding?.messageInputView?.slideToCancelDescription?.x = sliderInitX return true } else { - binding.messageInputView.slideToCancelDescription.x = binding.messageInputView - .slideToCancelDescription.x + deltaX + binding?.messageInputView?.slideToCancelDescription?.x = + binding?.messageInputView?.slideToCancelDescription?.x!! + deltaX downX = movedX } } @@ -902,26 +886,24 @@ class ChatController(args: Bundle) : } }) - binding.messageInputView.inputEditText?.setText(sharedText) - binding.messageInputView.setAttachmentsListener { + binding?.messageInputView?.inputEditText?.setText(sharedText) + binding?.messageInputView?.setAttachmentsListener { activity?.let { AttachmentDialog(it, this).show() } } - binding.messageInputView.button.setOnClickListener { submitMessage(false) } + binding?.messageInputView?.button?.setOnClickListener { submitMessage(false) } if (CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "silent-send")) { - binding.messageInputView.button.setOnLongClickListener { + binding?.messageInputView?.button?.setOnLongClickListener { showSendButtonMenu() true } } - binding.messageInputView.button.contentDescription = resources?.getString( - R.string - .nc_description_send_message_button - ) + binding?.messageInputView?.button?.contentDescription = + resources?.getString(R.string.nc_description_send_message_button) - viewThemeUtils.platform.colorImageView(binding.messageInputView.button) + binding?.messageInputView?.button?.let { viewThemeUtils.platform.colorImageView(it) } if (currentConversation != null && currentConversation?.roomId != null) { loadAvatarForStatusBar() @@ -942,7 +924,7 @@ class ChatController(args: Bundle) : private fun showSendButtonMenu() { val popupMenu = PopupMenu( ContextThemeWrapper(view?.context, R.style.ChatSendButtonMenu), - binding.messageInputView.button, + binding?.messageInputView?.button, Gravity.END ) popupMenu.inflate(R.menu.chat_send_menu) @@ -1150,23 +1132,23 @@ class ChatController(args: Bundle) : private fun showRecordAudioUi(show: Boolean) { if (show) { - binding.messageInputView.microphoneEnabledInfo.visibility = View.VISIBLE - binding.messageInputView.microphoneEnabledInfoBackground.visibility = View.VISIBLE - binding.messageInputView.audioRecordDuration.visibility = View.VISIBLE - binding.messageInputView.slideToCancelDescription.visibility = View.VISIBLE - binding.messageInputView.attachmentButton.visibility = View.GONE - binding.messageInputView.smileyButton.visibility = View.GONE - binding.messageInputView.messageInput.visibility = View.GONE - binding.messageInputView.messageInput.hint = "" + binding?.messageInputView?.microphoneEnabledInfo?.visibility = View.VISIBLE + binding?.messageInputView?.microphoneEnabledInfoBackground?.visibility = View.VISIBLE + binding?.messageInputView?.audioRecordDuration?.visibility = View.VISIBLE + binding?.messageInputView?.slideToCancelDescription?.visibility = View.VISIBLE + binding?.messageInputView?.attachmentButton?.visibility = View.GONE + binding?.messageInputView?.smileyButton?.visibility = View.GONE + binding?.messageInputView?.messageInput?.visibility = View.GONE + binding?.messageInputView?.messageInput?.hint = "" } else { - binding.messageInputView.microphoneEnabledInfo.visibility = View.GONE - binding.messageInputView.microphoneEnabledInfoBackground.visibility = View.GONE - binding.messageInputView.audioRecordDuration.visibility = View.GONE - binding.messageInputView.slideToCancelDescription.visibility = View.GONE - binding.messageInputView.attachmentButton.visibility = View.VISIBLE - binding.messageInputView.smileyButton.visibility = View.VISIBLE - binding.messageInputView.messageInput.visibility = View.VISIBLE - binding.messageInputView.messageInput.hint = + binding?.messageInputView?.microphoneEnabledInfo?.visibility = View.GONE + binding?.messageInputView?.microphoneEnabledInfoBackground?.visibility = View.GONE + binding?.messageInputView?.audioRecordDuration?.visibility = View.GONE + binding?.messageInputView?.slideToCancelDescription?.visibility = View.GONE + binding?.messageInputView?.attachmentButton?.visibility = View.VISIBLE + binding?.messageInputView?.smileyButton?.visibility = View.VISIBLE + binding?.messageInputView?.messageInput?.visibility = View.VISIBLE + binding?.messageInputView?.messageInput?.hint = context.resources?.getString(R.string.nc_hint_enter_a_message) } } @@ -1179,15 +1161,15 @@ class ChatController(args: Bundle) : } private fun startAudioRecording(file: String) { - binding.messageInputView.audioRecordDuration.base = SystemClock.elapsedRealtime() - binding.messageInputView.audioRecordDuration.start() + binding?.messageInputView?.audioRecordDuration?.base = SystemClock.elapsedRealtime() + binding?.messageInputView?.audioRecordDuration?.start() val animation: Animation = AlphaAnimation(1.0f, 0.0f) animation.duration = ANIMATION_DURATION animation.interpolator = LinearInterpolator() animation.repeatCount = Animation.INFINITE animation.repeatMode = Animation.REVERSE - binding.messageInputView.microphoneEnabledInfo.startAnimation(animation) + binding?.messageInputView?.microphoneEnabledInfo?.startAnimation(animation) recorder = MediaRecorder().apply { setAudioSource(MediaRecorder.AudioSource.MIC) @@ -1227,8 +1209,8 @@ class ChatController(args: Bundle) : @Suppress("Detekt.TooGenericExceptionCaught") private fun stopAudioRecording() { - binding.messageInputView.audioRecordDuration.stop() - binding.messageInputView.microphoneEnabledInfo.clearAnimation() + binding?.messageInputView?.audioRecordDuration?.stop() + binding?.messageInputView?.microphoneEnabledInfo?.clearAnimation() if (isVoiceRecordingInProgress) { recorder?.apply { @@ -1301,9 +1283,9 @@ class ChatController(args: Bundle) : shouldShowLobby() || !participantPermissions.hasChatPermission() ) { - binding.messageInputView.visibility = View.GONE + binding?.messageInputView?.visibility = View.GONE } else { - binding.messageInputView.visibility = View.VISIBLE + binding?.messageInputView?.visibility = View.VISIBLE } } } @@ -1359,10 +1341,10 @@ class ChatController(args: Bundle) : } if (shouldShowLobby()) { - binding.lobby.lobbyView.visibility = View.VISIBLE - binding.messagesListView.visibility = View.GONE - binding.messageInputView.visibility = View.GONE - binding.progressBar.visibility = View.GONE + binding?.lobby?.lobbyView?.visibility = View.VISIBLE + binding?.messagesListView?.visibility = View.GONE + binding?.messageInputView?.visibility = View.GONE + binding?.progressBar?.visibility = View.GONE val sb = StringBuilder() sb.append(resources!!.getText(R.string.nc_lobby_waiting)) @@ -1383,11 +1365,11 @@ class ChatController(args: Bundle) : } sb.append(currentConversation!!.description) - binding.lobby.lobbyTextView.text = sb.toString() + binding?.lobby?.lobbyTextView?.text = sb.toString() } else { - binding.lobby.lobbyView.visibility = View.GONE - binding.messagesListView.visibility = View.VISIBLE - binding.messageInputView.inputEditText?.visibility = View.VISIBLE + binding?.lobby?.lobbyView?.visibility = View.GONE + binding?.messagesListView?.visibility = View.VISIBLE + binding?.messageInputView?.inputEditText?.visibility = View.VISIBLE if (isFirstMessagesProcessing && pastPreconditionFailed) { pastPreconditionFailed = false pullChatMessages(0) @@ -1397,9 +1379,9 @@ class ChatController(args: Bundle) : } } } else { - binding.lobby.lobbyView.visibility = View.GONE - binding.messagesListView.visibility = View.VISIBLE - binding.messageInputView.inputEditText?.visibility = View.VISIBLE + binding?.lobby?.lobbyView?.visibility = View.GONE + binding?.messagesListView?.visibility = View.VISIBLE + binding?.messageInputView?.inputEditText?.visibility = View.VISIBLE } } @@ -1461,31 +1443,30 @@ class ChatController(args: Bundle) : } } - val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageInputView.context) - .setTitle(confirmationQuestion) - .setMessage(filenamesWithLineBreaks.toString()) - .setPositiveButton(R.string.nc_yes) { _, _ -> - if (UploadAndShareFilesWorker.isStoragePermissionGranted(context)) { - uploadFiles(filesToUpload) - } else { - UploadAndShareFilesWorker.requestStoragePermission(this) + binding?.messageInputView?.context?.let { + val materialAlertDialogBuilder = MaterialAlertDialogBuilder(it) + .setTitle(confirmationQuestion) + .setMessage(filenamesWithLineBreaks.toString()) + .setPositiveButton(R.string.nc_yes) { _, _ -> + if (UploadAndShareFilesWorker.isStoragePermissionGranted(context)) { + uploadFiles(filesToUpload) + } else { + UploadAndShareFilesWorker.requestStoragePermission(this) + } + } + .setNegativeButton(R.string.nc_no) { _, _ -> + // unused atm } - } - .setNegativeButton(R.string.nc_no) { _, _ -> - // unused atm - } - viewThemeUtils.dialog.colorMaterialAlertDialogBackground( - binding.messageInputView.context, - materialAlertDialogBuilder - ) + viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it, materialAlertDialogBuilder) - val dialog = materialAlertDialogBuilder.show() + val dialog = materialAlertDialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) + } } catch (e: IllegalStateException) { Toast.makeText(context, context.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG) .show() @@ -1572,7 +1553,7 @@ class ChatController(args: Bundle) : it.item is ChatMessage && (it.item as ChatMessage).id == messageId } if (position != null && position >= 0) { - binding.messagesListView.smoothScrollToPosition(position) + binding?.messagesListView?.smoothScrollToPosition(position) } else { // TODO show error that we don't have that message? } @@ -1732,12 +1713,12 @@ class ChatController(args: Bundle) : val callback = MentionAutocompleteCallback( activity, conversationUser!!, - binding.messageInputView.inputEditText, + binding?.messageInputView?.inputEditText, viewThemeUtils ) - if (mentionAutocomplete == null && binding.messageInputView.inputEditText != null) { - mentionAutocomplete = Autocomplete.on(binding.messageInputView.inputEditText) + if (mentionAutocomplete == null && binding?.messageInputView?.inputEditText != null) { + mentionAutocomplete = Autocomplete.on(binding?.messageInputView?.inputEditText) .with(elevation) .with(backgroundDrawable) .with(MagicCharPolicy('@')) @@ -1773,9 +1754,9 @@ class ChatController(args: Bundle) : ApplicationWideCurrentRoomHolder.getInstance().currentRoomToken = roomToken ApplicationWideCurrentRoomHolder.getInstance().userInRoom = conversationUser - val smileyButton = binding.messageInputView.findViewById(R.id.smileyButton) + val smileyButton = binding?.messageInputView?.findViewById(R.id.smileyButton) - emojiPopup = binding.messageInputView.inputEditText?.let { + emojiPopup = binding?.messageInputView?.inputEditText?.let { EmojiPopup( rootView = view, editText = it, @@ -1793,7 +1774,7 @@ class ChatController(args: Bundle) : }, onEmojiClickListener = { try { - binding.messageInputView.inputEditText?.editableText?.append(" ") + binding?.messageInputView?.inputEditText?.editableText?.append(" ") } catch (npe: NullPointerException) { // view binding can be null // since this is called asynchronously and UI might have been destroyed in the meantime @@ -1807,12 +1788,14 @@ class ChatController(args: Bundle) : emojiPopup?.toggle() } - binding.messageInputView.findViewById(R.id.cancelReplyButton)?.setOnClickListener { + binding?.messageInputView?.findViewById(R.id.cancelReplyButton)?.setOnClickListener { cancelReply() } - viewThemeUtils.platform - .themeImageButton(binding.messageInputView.findViewById(R.id.cancelReplyButton)) + binding?.messageInputView?.findViewById(R.id.cancelReplyButton)?.let { + viewThemeUtils.platform + .themeImageButton(it) + } cancelNotificationsForCurrentConversation() @@ -1824,8 +1807,8 @@ class ChatController(args: Bundle) : } private fun cancelReply() { - binding.messageInputView.findViewById(R.id.quotedChatMessageView)?.visibility = View.GONE - binding.messageInputView.findViewById(R.id.attachmentButton)?.visibility = View.VISIBLE + binding?.messageInputView?.findViewById(R.id.quotedChatMessageView)?.visibility = View.GONE + binding?.messageInputView?.findViewById(R.id.attachmentButton)?.visibility = View.VISIBLE } @Suppress("Detekt.TooGenericExceptionCaught") @@ -2087,8 +2070,8 @@ class ChatController(args: Bundle) : } private fun submitMessage(sendWithoutNotification: Boolean) { - if (binding.messageInputView.inputEditText != null) { - val editable = binding.messageInputView.inputEditText!!.editableText + if (binding?.messageInputView?.inputEditText != null) { + val editable = binding?.messageInputView?.inputEditText!!.editableText val mentionSpans = editable.getSpans( 0, editable.length, @@ -2104,7 +2087,7 @@ class ChatController(args: Bundle) : editable.replace(editable.getSpanStart(mentionSpan), editable.getSpanEnd(mentionSpan), "@$mentionId") } - binding.messageInputView.inputEditText?.setText("") + binding?.messageInputView?.inputEditText?.setText("") val replyMessageId: Int? = view?.findViewById(R.id.quotedChatMessageView)?.tag as Int? sendMessage( editable, @@ -2143,11 +2126,11 @@ class ChatController(args: Bundle) : myFirstMessage = message try { - if (binding.popupBubbleView.isShown) { - binding.popupBubbleView.hide() + if (binding?.popupBubbleView?.isShown == true) { + binding?.popupBubbleView?.hide() } - binding.messagesListView.smoothScrollToPosition(0) + binding?.messagesListView?.smoothScrollToPosition(0) } catch (npe: NullPointerException) { // view binding can be null // since this is called asynchronously and UI might have been destroyed in the meantime @@ -2161,11 +2144,11 @@ class ChatController(args: Bundle) : if (code.toString().startsWith("2")) { myFirstMessage = message - if (binding.popupBubbleView.isShown) { - binding.popupBubbleView.hide() + if (binding?.popupBubbleView?.isShown == true) { + binding?.popupBubbleView?.hide() } - binding.messagesListView.smoothScrollToPosition(0) + binding?.messagesListView?.smoothScrollToPosition(0) } } } @@ -2379,7 +2362,7 @@ class ChatController(args: Bundle) : cancelNotificationsForCurrentConversation() isFirstMessagesProcessing = false - binding.progressBar.visibility = View.GONE + binding?.progressBar?.visibility = View.GONE } historyRead = true @@ -2406,9 +2389,9 @@ class ChatController(args: Bundle) : cancelNotificationsForCurrentConversation() isFirstMessagesProcessing = false - binding.progressBar.visibility = View.GONE + binding?.progressBar?.visibility = View.GONE - binding.messagesListView.visibility = View.VISIBLE + binding?.messagesListView?.visibility = View.VISIBLE } if (isFromTheFuture) { @@ -2468,7 +2451,7 @@ class ChatController(args: Bundle) : if (shouldAddNewMessagesNotice && adapter != null) { layoutManager?.scrollToPositionWithOffset( adapter!!.getMessagePositionByIdInReverse("-1"), - binding.messagesListView.height / 2 + binding?.messagesListView?.height!! / 2 ) } } @@ -2508,10 +2491,10 @@ class ChatController(args: Bundle) : private fun modifyMessageCount(shouldAddNewMessagesNotice: Boolean, shouldScroll: Boolean) { if (!shouldAddNewMessagesNotice && !shouldScroll) { - if (!binding.popupBubbleView.isShown) { + if (!binding?.popupBubbleView?.isShown!!) { newMessagesCount = 1 - binding.popupBubbleView.show() - } else if (binding.popupBubbleView.isShown) { + binding?.popupBubbleView?.show() + } else if (binding?.popupBubbleView?.isShown!!) { newMessagesCount++ } } else { @@ -2622,15 +2605,15 @@ class ChatController(args: Bundle) : super.onCreateOptionsMenu(menu, inflater) inflater.inflate(R.menu.menu_conversation, menu) - viewThemeUtils.platform.colorToolbarMenuIcon( - binding.messageInputView.context, - menu.findItem(R.id.conversation_voice_call) - ) + binding?.messageInputView?.context?.let { + viewThemeUtils.platform.colorToolbarMenuIcon( + it, menu.findItem(R.id.conversation_voice_call) + ) - viewThemeUtils.platform.colorToolbarMenuIcon( - binding.messageInputView.context, - menu.findItem(R.id.conversation_video_call) - ) + viewThemeUtils.platform.colorToolbarMenuIcon( + it, menu.findItem(R.id.conversation_video_call) + ) + } if (conversationUser?.userId == "?") { menu.removeItem(R.id.conversation_info) @@ -3148,25 +3131,21 @@ class ChatController(args: Bundle) : fun replyToMessage(message: IMessage?) { val chatMessage = message as ChatMessage? chatMessage?.let { - binding.messageInputView.findViewById(R.id.attachmentButton)?.visibility = + binding?.messageInputView?.findViewById(R.id.attachmentButton)?.visibility = View.GONE - binding.messageInputView.findViewById(R.id.cancelReplyButton)?.visibility = + binding?.messageInputView?.findViewById(R.id.cancelReplyButton)?.visibility = View.VISIBLE - val quotedMessage = binding - .messageInputView - .findViewById(R.id.quotedMessage) + val quotedMessage = binding?.messageInputView?.findViewById(R.id.quotedMessage) quotedMessage?.maxLines = 2 quotedMessage?.ellipsize = TextUtils.TruncateAt.END quotedMessage?.text = it.text - binding.messageInputView.findViewById(R.id.quotedMessageAuthor)?.text = + binding?.messageInputView?.findViewById(R.id.quotedMessageAuthor)?.text = it.actorDisplayName ?: context.getText(R.string.nc_nick_guest) - conversationUser?.let { currentUser -> - val quotedMessageImage = binding - .messageInputView - .findViewById(R.id.quotedMessageImage) + conversationUser?.let { + val quotedMessageImage = binding?.messageInputView?.findViewById(R.id.quotedMessageImage) chatMessage.imageUrl?.let { previewImageUrl -> quotedMessageImage?.visibility = View.VISIBLE @@ -3184,16 +3163,12 @@ class ChatController(args: Bundle) : addHeader("Authorization", credentials!!) } } ?: run { - binding - .messageInputView - .findViewById(R.id.quotedMessageImage) - ?.visibility = View.GONE + binding?.messageInputView?.findViewById(R.id.quotedMessageImage)?.visibility = View.GONE } } - val quotedChatMessageView = binding - .messageInputView - .findViewById(R.id.quotedChatMessageView) + val quotedChatMessageView = + binding?.messageInputView?.findViewById(R.id.quotedChatMessageView) quotedChatMessageView?.tag = message?.jsonMessageId quotedChatMessageView?.visibility = View.VISIBLE } @@ -3201,11 +3176,11 @@ class ChatController(args: Bundle) : private fun showMicrophoneButton(show: Boolean) { if (show && CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "voice-message-sharing")) { - binding.messageInputView.messageSendButton.visibility = View.GONE - binding.messageInputView.recordAudioButton.visibility = View.VISIBLE + binding?.messageInputView?.messageSendButton?.visibility = View.GONE + binding?.messageInputView?.recordAudioButton?.visibility = View.VISIBLE } else { - binding.messageInputView.messageSendButton.visibility = View.VISIBLE - binding.messageInputView.recordAudioButton.visibility = View.GONE + binding?.messageInputView?.messageSendButton?.visibility = View.VISIBLE + binding?.messageInputView?.recordAudioButton?.visibility = View.GONE } } @@ -3236,7 +3211,7 @@ class ChatController(args: Bundle) : } if (message.reactionsSelf == null) { - message.reactionsSelf = ArrayList() + message.reactionsSelf = ArrayList() } var amount = message.reactions!![emoji] @@ -3254,7 +3229,7 @@ class ChatController(args: Bundle) : } if (message.reactionsSelf == null) { - message.reactionsSelf = ArrayList() + message.reactionsSelf = ArrayList() } var amount = message.reactions!![emoji] diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt index cbe6c7242..b1bcc05c2 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt @@ -92,7 +92,7 @@ class ContactsController(args: Bundle) : BaseController(R.layout.controller_contacts_rv), SearchView.OnQueryTextListener, FlexibleAdapter.OnItemClickListener { - private val binding: ControllerContactsRvBinding by viewBinding(ControllerContactsRvBinding::bind) + private val binding: ControllerContactsRvBinding? by viewBinding(ControllerContactsRvBinding::bind) @Inject lateinit var userManager: UserManager @@ -153,13 +153,13 @@ class ContactsController(args: Bundle) : toggleConversationPrivacyLayout(!isPublicCall) } if (isAddingParticipantsView) { - binding.joinConversationViaLink.joinConversationViaLinkRelativeLayout.visibility = View.GONE - binding.conversationPrivacyToggle.callHeaderLayout.visibility = View.GONE + binding?.joinConversationViaLink?.joinConversationViaLinkRelativeLayout?.visibility = View.GONE + binding?.conversationPrivacyToggle?.callHeaderLayout?.visibility = View.GONE } else { - binding.joinConversationViaLink.joinConversationViaLinkRelativeLayout.setOnClickListener { + binding?.joinConversationViaLink?.joinConversationViaLinkRelativeLayout?.setOnClickListener { joinConversationViaLink() } - binding.conversationPrivacyToggle.callHeaderLayout.setOnClickListener { + binding?.conversationPrivacyToggle?.callHeaderLayout?.setOnClickListener { toggleCallHeader() } } @@ -382,10 +382,12 @@ class ContactsController(args: Bundle) : super.onPrepareOptionsMenu(menu) if (searchItem != null) { - viewThemeUtils.platform.colorToolbarMenuIcon( - binding.titleTextView.context, - searchItem!! - ) + binding?.titleTextView?.let { + viewThemeUtils.platform.colorToolbarMenuIcon( + it.context, + searchItem!! + ) + } } checkAndHandleDoneMenuItem() @@ -451,20 +453,20 @@ class ContactsController(args: Bundle) : } withNullableControllerViewBinding { - binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false + binding?.controllerGenericRv?.swipeRefreshLayout?.isRefreshing = false } } override fun onError(e: Throwable) { withNullableControllerViewBinding { - binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false + binding?.controllerGenericRv?.swipeRefreshLayout?.isRefreshing = false } dispose(contactsQueryDisposable) } override fun onComplete() { withNullableControllerViewBinding { - binding.controllerGenericRv.swipeRefreshLayout.isRefreshing = false + binding?.controllerGenericRv?.swipeRefreshLayout?.isRefreshing = false } dispose(contactsQueryDisposable) alreadyFetching = false @@ -627,31 +629,31 @@ class ContactsController(args: Bundle) : private fun prepareViews() { layoutManager = SmoothScrollLinearLayoutManager(activity) - binding.controllerGenericRv.recyclerView.layoutManager = layoutManager - binding.controllerGenericRv.recyclerView.setHasFixedSize(true) - binding.controllerGenericRv.recyclerView.adapter = adapter - binding.controllerGenericRv.swipeRefreshLayout.setOnRefreshListener { fetchData() } + binding?.controllerGenericRv?.recyclerView?.layoutManager = layoutManager + binding?.controllerGenericRv?.recyclerView?.setHasFixedSize(true) + binding?.controllerGenericRv?.recyclerView?.adapter = adapter + binding?.controllerGenericRv?.swipeRefreshLayout?.setOnRefreshListener { fetchData() } - viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.controllerGenericRv.swipeRefreshLayout) + binding?.controllerGenericRv?.let { viewThemeUtils.androidx.themeSwipeRefreshLayout(it.swipeRefreshLayout) } - binding.joinConversationViaLink.joinConversationViaLinkImageView - .background - .setColorFilter( + binding?.joinConversationViaLink?.joinConversationViaLinkImageView + ?.background + ?.setColorFilter( ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null), PorterDuff.Mode.SRC_IN ) - viewThemeUtils.platform.colorImageViewButton(binding.conversationPrivacyToggle.publicCallLink) + binding?.conversationPrivacyToggle?.let { viewThemeUtils.platform.colorImageViewButton(it.publicCallLink) } disengageProgressBar() } private fun disengageProgressBar() { if (!alreadyFetching) { - binding.loadingContent.visibility = View.GONE - binding.controllerGenericRv.root.visibility = View.VISIBLE + binding?.loadingContent?.visibility = View.GONE + binding?.controllerGenericRv?.root?.visibility = View.VISIBLE if (isNewConversationView) { - binding.conversationPrivacyToggle.callHeaderLayout.visibility = View.VISIBLE - binding.joinConversationViaLink.joinConversationViaLinkRelativeLayout.visibility = View.VISIBLE + binding?.conversationPrivacyToggle?.callHeaderLayout?.visibility = View.VISIBLE + binding?.joinConversationViaLink?.joinConversationViaLinkRelativeLayout?.visibility = View.VISIBLE } } } @@ -698,7 +700,7 @@ class ContactsController(args: Bundle) : } withNullableControllerViewBinding { - binding.controllerGenericRv.swipeRefreshLayout.isEnabled = !adapter!!.hasFilter() + binding?.controllerGenericRv?.swipeRefreshLayout?.isEnabled = !adapter!!.hasFilter() } return true @@ -929,11 +931,11 @@ class ContactsController(args: Bundle) : private fun toggleConversationPrivacyLayout(showInitialLayout: Boolean) { withNullableControllerViewBinding { if (showInitialLayout) { - binding.conversationPrivacyToggle.initialRelativeLayout.visibility = View.VISIBLE - binding.conversationPrivacyToggle.secondaryRelativeLayout.visibility = View.GONE + binding?.conversationPrivacyToggle?.initialRelativeLayout?.visibility = View.VISIBLE + binding?.conversationPrivacyToggle?.secondaryRelativeLayout?.visibility = View.GONE } else { - binding.conversationPrivacyToggle.initialRelativeLayout.visibility = View.GONE - binding.conversationPrivacyToggle.secondaryRelativeLayout.visibility = View.VISIBLE + binding?.conversationPrivacyToggle?.initialRelativeLayout?.visibility = View.GONE + binding?.conversationPrivacyToggle?.secondaryRelativeLayout?.visibility = View.VISIBLE } } } @@ -941,10 +943,10 @@ class ContactsController(args: Bundle) : private fun toggleConversationViaLinkVisibility(isPublicCall: Boolean) { withNullableControllerViewBinding { if (isPublicCall) { - binding.joinConversationViaLink.joinConversationViaLinkRelativeLayout.visibility = View.GONE + binding?.joinConversationViaLink?.joinConversationViaLinkRelativeLayout?.visibility = View.GONE updateGroupParticipantSelection() } else { - binding.joinConversationViaLink.joinConversationViaLinkRelativeLayout.visibility = View.VISIBLE + binding?.joinConversationViaLink?.joinConversationViaLinkRelativeLayout?.visibility = View.VISIBLE } } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt index 82833debb..650ae3aa3 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt @@ -63,9 +63,9 @@ import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.ControllerConversationInfoBinding import com.nextcloud.talk.events.EventStatus import com.nextcloud.talk.extensions.loadAvatar -import com.nextcloud.talk.extensions.loadSystemAvatar import com.nextcloud.talk.extensions.loadGroupCallAvatar import com.nextcloud.talk.extensions.loadPublicCallAvatar +import com.nextcloud.talk.extensions.loadSystemAvatar import com.nextcloud.talk.jobs.DeleteConversationWorker import com.nextcloud.talk.jobs.LeaveConversationWorker import com.nextcloud.talk.models.json.conversations.Conversation @@ -107,7 +107,7 @@ class ConversationInfoController(args: Bundle) : ), FlexibleAdapter.OnItemClickListener { - private val binding: ControllerConversationInfoBinding by viewBinding(ControllerConversationInfoBinding::bind) + private val binding: ControllerConversationInfoBinding? by viewBinding(ControllerConversationInfoBinding::bind) @Inject lateinit var ncApi: NcApi @@ -173,19 +173,19 @@ class ConversationInfoController(args: Bundle) : databaseStorageModule = DatabaseStorageModule(conversationUser!!, conversationToken) } - binding.notificationSettingsView.notificationSettings.setStorageModule(databaseStorageModule) - binding.webinarInfoView.webinarSettings.setStorageModule(databaseStorageModule) - binding.guestAccessView.guestAccessSettings.setStorageModule(databaseStorageModule) + binding?.notificationSettingsView?.notificationSettings?.setStorageModule(databaseStorageModule) + binding?.webinarInfoView?.webinarSettings?.setStorageModule(databaseStorageModule) + binding?.guestAccessView?.guestAccessSettings?.setStorageModule(databaseStorageModule) - binding.deleteConversationAction.setOnClickListener { showDeleteConversationDialog() } - binding.leaveConversationAction.setOnClickListener { leaveConversation() } - binding.clearConversationHistory.setOnClickListener { showClearHistoryDialog() } - binding.addParticipantsAction.setOnClickListener { addParticipants() } + binding?.deleteConversationAction?.setOnClickListener { showDeleteConversationDialog() } + binding?.leaveConversationAction?.setOnClickListener { leaveConversation() } + binding?.clearConversationHistory?.setOnClickListener { showClearHistoryDialog() } + binding?.addParticipantsAction?.setOnClickListener { addParticipants() } if (CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "rich-object-list-media")) { - binding.showSharedItemsAction.setOnClickListener { showSharedItems() } + binding?.showSharedItemsAction?.setOnClickListener { showSharedItems() } } else { - binding.categorySharedItems.visibility = GONE + binding?.categorySharedItems?.visibility = GONE } fetchRoomInfo() @@ -195,19 +195,19 @@ class ConversationInfoController(args: Bundle) : } private fun themeSwitchPreferences() { - binding.run { + binding?.run { listOf( - binding.webinarInfoView.conversationInfoLobby, - binding.notificationSettingsView.callNotifications, - binding.notificationSettingsView.conversationInfoPriorityConversation, - binding.guestAccessView.guestAccessAllowSwitch, - binding.guestAccessView.guestAccessPasswordSwitch + binding?.webinarInfoView?.conversationInfoLobby!!, + binding?.notificationSettingsView?.callNotifications!!, + binding?.notificationSettingsView?.conversationInfoPriorityConversation!!, + binding?.guestAccessView?.guestAccessAllowSwitch!!, + binding?.guestAccessView?.guestAccessPasswordSwitch!! ).forEach(viewThemeUtils.talk::colorSwitchPreference) } } private fun themeCategories() { - binding.run { + binding?.run { listOf( conversationInfoName, conversationDescription, @@ -216,9 +216,9 @@ class ConversationInfoController(args: Bundle) : ownOptions, categorySharedItems, categoryConversationSettings, - binding.guestAccessView.guestAccessCategory, - binding.webinarInfoView.conversationInfoWebinar, - binding.notificationSettingsView.notificationSettingsCategory + binding?.guestAccessView?.guestAccessCategory!!, + binding?.webinarInfoView?.conversationInfoWebinar!!, + binding?.notificationSettingsView?.notificationSettingsCategory!! ).forEach(viewThemeUtils.talk::colorPreferenceCategory) } } @@ -237,9 +237,9 @@ class ConversationInfoController(args: Bundle) : override fun onViewBound(view: View) { super.onViewBound(view) - binding.addParticipantsAction.visibility = GONE + binding?.addParticipantsAction?.visibility = GONE - viewThemeUtils.platform.colorCircularProgressBar(binding.progressBar) + binding?.progressBar?.let { viewThemeUtils.platform.colorCircularProgressBar(it) } } private fun setupWebinaryView() { @@ -247,16 +247,16 @@ class ConversationInfoController(args: Bundle) : webinaryRoomType(conversation!!) && conversation!!.canModerate(conversationUser!!) ) { - binding.webinarInfoView.webinarSettings.visibility = VISIBLE + binding?.webinarInfoView?.webinarSettings?.visibility = VISIBLE val isLobbyOpenToModeratorsOnly = conversation!!.lobbyState == Conversation.LobbyState.LOBBY_STATE_MODERATORS_ONLY - (binding.webinarInfoView.conversationInfoLobby.findViewById(R.id.mp_checkable) as SwitchCompat) + (binding?.webinarInfoView?.conversationInfoLobby?.findViewById(R.id.mp_checkable) as SwitchCompat) .isChecked = isLobbyOpenToModeratorsOnly reconfigureLobbyTimerView() - binding.webinarInfoView.startTimePreferences.setOnClickListener { + binding?.webinarInfoView?.startTimePreferences?.setOnClickListener { MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show { val currentTimeCalendar = Calendar.getInstance() if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != 0L) { @@ -277,13 +277,13 @@ class ConversationInfoController(args: Bundle) : } } - (binding.webinarInfoView.conversationInfoLobby.findViewById(R.id.mp_checkable) as SwitchCompat) + (binding?.webinarInfoView?.conversationInfoLobby?.findViewById(R.id.mp_checkable) as SwitchCompat) .setOnCheckedChangeListener { _, _ -> reconfigureLobbyTimerView() submitLobbyChanges() } } else { - binding.webinarInfoView.webinarSettings.visibility = GONE + binding?.webinarInfoView?.webinarSettings?.visibility = GONE } } @@ -294,7 +294,7 @@ class ConversationInfoController(args: Bundle) : private fun reconfigureLobbyTimerView(dateTime: Calendar? = null) { val isChecked = - (binding.webinarInfoView.conversationInfoLobby.findViewById(R.id.mp_checkable) as SwitchCompat) + (binding?.webinarInfoView?.conversationInfoLobby?.findViewById(R.id.mp_checkable) as SwitchCompat) .isChecked if (dateTime != null && isChecked) { @@ -313,25 +313,25 @@ class ConversationInfoController(args: Bundle) : conversation!!.lobbyTimer != java.lang.Long.MIN_VALUE && conversation!!.lobbyTimer != 0L ) { - binding.webinarInfoView.startTimePreferences.setSummary( + binding?.webinarInfoView?.startTimePreferences?.setSummary( dateUtils.getLocalDateTimeStringFromTimestamp( conversation!!.lobbyTimer!! * DateConstants.SECOND_DIVIDER, ) ) } else { - binding.webinarInfoView.startTimePreferences.setSummary(R.string.nc_manual) + binding?.webinarInfoView?.startTimePreferences?.setSummary(R.string.nc_manual) } if (isChecked) { - binding.webinarInfoView.startTimePreferences.visibility = VISIBLE + binding?.webinarInfoView?.startTimePreferences?.visibility = VISIBLE } else { - binding.webinarInfoView.startTimePreferences.visibility = GONE + binding?.webinarInfoView?.startTimePreferences?.visibility = GONE } } fun submitLobbyChanges() { val state = if ( - (binding.webinarInfoView.conversationInfoLobby.findViewById(R.id.mp_checkable) as SwitchCompat) + (binding?.webinarInfoView?.conversationInfoLobby?.findViewById(R.id.mp_checkable) as SwitchCompat) .isChecked ) 1 else 0 @@ -376,23 +376,30 @@ class ConversationInfoController(args: Bundle) : private fun showDeleteConversationDialog() { if (activity != null) { - val dialogBuilder = MaterialAlertDialogBuilder(binding.conversationInfoName.context) - .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp)) - .setTitle(R.string.nc_delete_call) - .setMessage(R.string.nc_delete_conversation_more) - .setPositiveButton(R.string.nc_delete) { _, _ -> - deleteConversation() - } - .setNegativeButton(R.string.nc_cancel) { _, _ -> - // unused atm - } - viewThemeUtils.dialog - .colorMaterialAlertDialogBackground(binding.conversationInfoName.context, dialogBuilder) - val dialog = dialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) + binding?.conversationInfoName?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it.context) + .setIcon( + viewThemeUtils.dialog.colorMaterialAlertDialogIcon( + context, R.drawable.ic_delete_black_24dp + ) + ) + .setTitle(R.string.nc_delete_call) + .setMessage(R.string.nc_delete_conversation_more) + .setPositiveButton(R.string.nc_delete) { _, _ -> + deleteConversation() + } + .setNegativeButton(R.string.nc_cancel) { _, _ -> + // unused atm + } + + viewThemeUtils.dialog + .colorMaterialAlertDialogBackground(it.context, dialogBuilder) + val dialog = dialogBuilder.show() + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) + } } } @@ -403,9 +410,9 @@ class ConversationInfoController(args: Bundle) : } val layoutManager = SmoothScrollLinearLayoutManager(activity) - binding.recyclerView.layoutManager = layoutManager - binding.recyclerView.setHasFixedSize(true) - binding.recyclerView.adapter = adapter + binding?.recyclerView?.layoutManager = layoutManager + binding?.recyclerView?.setHasFixedSize(true) + binding?.recyclerView?.adapter = adapter adapter!!.addListener(this) } @@ -446,7 +453,7 @@ class ConversationInfoController(args: Bundle) : setupAdapter() - binding.participantsListCategory.visibility = VISIBLE + binding?.participantsListCategory?.visibility = VISIBLE adapter!!.updateDataSet(userItems) } @@ -548,23 +555,30 @@ class ConversationInfoController(args: Bundle) : private fun showClearHistoryDialog() { if (activity != null) { - val dialogBuilder = MaterialAlertDialogBuilder(binding.conversationInfoName.context) - .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp)) - .setTitle(R.string.nc_clear_history) - .setMessage(R.string.nc_clear_history_warning) - .setPositiveButton(R.string.nc_delete_all) { _, _ -> - clearHistory() - } - .setNegativeButton(R.string.nc_cancel) { _, _ -> - // unused atm - } - viewThemeUtils.dialog - .colorMaterialAlertDialogBackground(binding.conversationInfoName.context, dialogBuilder) - val dialog = dialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) + binding?.conversationInfoName?.context?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it) + .setIcon( + viewThemeUtils.dialog.colorMaterialAlertDialogIcon( + context, R.drawable.ic_delete_black_24dp + ) + ) + .setTitle(R.string.nc_clear_history) + .setMessage(R.string.nc_clear_history_warning) + .setPositiveButton(R.string.nc_delete_all) { _, _ -> + clearHistory() + } + .setNegativeButton(R.string.nc_cancel) { _, _ -> + // unused atm + } + + viewThemeUtils.dialog + .colorMaterialAlertDialogBackground(it, dialogBuilder) + val dialog = dialogBuilder.show() + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) + } } } @@ -638,70 +652,72 @@ class ConversationInfoController(args: Bundle) : val conversationCopy = conversation if (conversationCopy!!.canModerate(conversationUser)) { - binding.addParticipantsAction.visibility = VISIBLE + binding?.addParticipantsAction?.visibility = VISIBLE if (CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "clear-history")) { - binding.clearConversationHistory.visibility = VISIBLE + binding?.clearConversationHistory?.visibility = VISIBLE } else { - binding.clearConversationHistory.visibility = GONE + binding?.clearConversationHistory?.visibility = GONE } } else { - binding.addParticipantsAction.visibility = GONE - binding.clearConversationHistory.visibility = GONE + binding?.addParticipantsAction?.visibility = GONE + binding?.clearConversationHistory?.visibility = GONE } if (isAttached && (!isBeingDestroyed || !isDestroyed)) { - binding.ownOptions.visibility = VISIBLE + binding?.ownOptions?.visibility = VISIBLE setupWebinaryView() if (!conversation!!.canLeave()) { - binding.leaveConversationAction.visibility = GONE + binding?.leaveConversationAction?.visibility = GONE } else { - binding.leaveConversationAction.visibility = VISIBLE + binding?.leaveConversationAction?.visibility = VISIBLE } if (!conversation!!.canDelete(conversationUser)) { - binding.deleteConversationAction.visibility = GONE + binding?.deleteConversationAction?.visibility = GONE } else { - binding.deleteConversationAction.visibility = VISIBLE + binding?.deleteConversationAction?.visibility = VISIBLE } if (Conversation.ConversationType.ROOM_SYSTEM == conversation!!.type) { - binding.notificationSettingsView.callNotifications.visibility = GONE + binding?.notificationSettingsView?.callNotifications?.visibility = GONE } if (conversation!!.notificationCalls === null) { - binding.notificationSettingsView.callNotifications.visibility = GONE + binding?.notificationSettingsView?.callNotifications?.visibility = GONE } else { - binding.notificationSettingsView.callNotifications.value = + binding?.notificationSettingsView?.callNotifications?.value = conversationCopy.notificationCalls == 1 } getListOfParticipants() - binding.progressBar.visibility = GONE + binding?.progressBar?.visibility = GONE - binding.conversationInfoName.visibility = VISIBLE + binding?.conversationInfoName?.visibility = VISIBLE - binding.displayNameText.text = conversation!!.displayName + binding?.displayNameText?.text = conversation!!.displayName if (conversation!!.description != null && !conversation!!.description!!.isEmpty()) { - binding.descriptionText.text = conversation!!.description - binding.conversationDescription.visibility = VISIBLE + binding?.descriptionText?.text = conversation!!.description + binding?.conversationDescription?.visibility = VISIBLE } loadConversationAvatar() adjustNotificationLevelUI() initExpiringMessageOption() - GuestAccessHelper( - this@ConversationInfoController, - binding, - conversation!!, - conversationUser - ).setupGuestAccess() + binding?.let { + GuestAccessHelper( + this@ConversationInfoController, + it, + conversation!!, + conversationUser + ).setupGuestAccess() + } - binding.notificationSettingsView.notificationSettings.visibility = VISIBLE + binding?.notificationSettingsView?.notificationSettings?.visibility = VISIBLE } } catch (npe: NullPointerException) { // view binding can be null @@ -725,11 +741,11 @@ class ConversationInfoController(args: Bundle) : CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "message-expiration") ) { databaseStorageModule?.setMessageExpiration(conversation!!.messageExpiration) - binding.conversationInfoExpireMessages.setStorageModule(databaseStorageModule) - binding.conversationInfoExpireMessages.visibility = View.VISIBLE - binding.conversationInfoExpireMessagesExplanation.visibility = View.VISIBLE + binding?.conversationInfoExpireMessages?.setStorageModule(databaseStorageModule) + binding?.conversationInfoExpireMessages?.visibility = VISIBLE + binding?.conversationInfoExpireMessagesExplanation?.visibility = VISIBLE } else { - binding.categoryConversationSettings.visibility = View.GONE + binding?.categoryConversationSettings?.visibility = GONE } } @@ -739,8 +755,8 @@ class ConversationInfoController(args: Bundle) : conversationUser != null && CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "notification-levels") ) { - binding.notificationSettingsView.conversationInfoMessageNotifications.isEnabled = true - binding.notificationSettingsView.conversationInfoMessageNotifications.alpha = 1.0f + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.isEnabled = true + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.alpha = 1.0f if (conversation!!.notificationLevel != Conversation.NotificationLevel.DEFAULT) { val stringValue: String = @@ -751,13 +767,13 @@ class ConversationInfoController(args: Bundle) : else -> "mention" } - binding.notificationSettingsView.conversationInfoMessageNotifications.value = stringValue + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.value = stringValue } else { setProperNotificationValue(conversation) } } else { - binding.notificationSettingsView.conversationInfoMessageNotifications.isEnabled = false - binding.notificationSettingsView.conversationInfoMessageNotifications.alpha = LOW_EMPHASIS_OPACITY + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.isEnabled = false + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.alpha = LOW_EMPHASIS_OPACITY setProperNotificationValue(conversation) } } @@ -767,28 +783,28 @@ class ConversationInfoController(args: Bundle) : if (conversation!!.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) { // hack to see if we get mentioned always or just on mention if (CapabilitiesUtilNew.hasSpreedFeatureCapability(conversationUser, "mention-flag")) { - binding.notificationSettingsView.conversationInfoMessageNotifications.value = "always" + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.value = "always" } else { - binding.notificationSettingsView.conversationInfoMessageNotifications.value = "mention" + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.value = "mention" } } else { - binding.notificationSettingsView.conversationInfoMessageNotifications.value = "mention" + binding?.notificationSettingsView?.conversationInfoMessageNotifications?.value = "mention" } } private fun loadConversationAvatar() { when (conversation!!.type) { Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(conversation!!.name)) { - conversation!!.name?.let { binding.avatarImage.loadAvatar(conversationUser!!, it) } + conversation!!.name?.let { binding?.avatarImage?.loadAvatar(conversationUser!!, it) } } Conversation.ConversationType.ROOM_GROUP_CALL -> { - binding.avatarImage.loadGroupCallAvatar(viewThemeUtils) + binding?.avatarImage?.loadGroupCallAvatar(viewThemeUtils) } Conversation.ConversationType.ROOM_PUBLIC_CALL -> { - binding.avatarImage.loadPublicCallAvatar(viewThemeUtils) + binding?.avatarImage?.loadPublicCallAvatar(viewThemeUtils) } Conversation.ConversationType.ROOM_SYSTEM -> { - binding.avatarImage.loadSystemAvatar() + binding?.avatarImage?.loadSystemAvatar() } else -> { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt index 3674200d9..fa3f132ba 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt @@ -157,7 +157,7 @@ class ConversationsListController(bundle: Bundle) : @Inject lateinit var unifiedSearchRepository: UnifiedSearchRepository - private val binding: ControllerConversationsRvBinding by viewBinding(ControllerConversationsRvBinding::bind) + private val binding: ControllerConversationsRvBinding? by viewBinding(ControllerConversationsRvBinding::bind) override val title: String get() = resources!!.getString(R.string.nc_app_product_name) @@ -200,7 +200,7 @@ class ConversationsListController(bundle: Bundle) : if (adapter == null) { adapter = FlexibleAdapter(conversationItems, activity, true) } else { - binding.loadingContent.visibility = View.GONE + binding?.loadingContent?.visibility = View.GONE } adapter!!.addListener(this) prepareViews() @@ -410,7 +410,7 @@ class ConversationsListController(bundle: Bundle) : adapter!!.updateDataSet(searchableConversationItems, false) adapter!!.showAllHeaders() withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isEnabled = false + binding?.swipeRefreshLayoutView?.isEnabled = false } return true } @@ -422,10 +422,10 @@ class ConversationsListController(bundle: Bundle) : if (searchHelper != null) { // cancel any pending searches searchHelper!!.cancelSearch() - binding.swipeRefreshLayoutView.isRefreshing = false + binding?.swipeRefreshLayoutView?.isRefreshing = false } withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isEnabled = true + binding?.swipeRefreshLayoutView?.isEnabled = true } searchView!!.onActionViewCollapsed() val mainActivity = getActivity() as MainActivity? @@ -441,7 +441,7 @@ class ConversationsListController(bundle: Bundle) : .resetStatusBar(mainActivity) } } - val layoutManager = binding.recyclerView.layoutManager as SmoothScrollLinearLayoutManager? + val layoutManager = binding?.recyclerView?.layoutManager as SmoothScrollLinearLayoutManager? layoutManager?.scrollToPositionWithOffset(0, 0) return true } @@ -503,7 +503,7 @@ class ConversationsListController(bundle: Bundle) : } if (adapterWasNull) { adapterWasNull = false - binding.loadingContent.visibility = View.GONE + binding?.loadingContent?.visibility = View.GONE } initOverallLayout(ocs!!.data!!.isNotEmpty()) for (conversation in ocs.data!!) { @@ -515,19 +515,19 @@ class ConversationsListController(bundle: Bundle) : Handler().postDelayed({ checkToShowUnreadBubble() }, UNREAD_BUBBLE_DELAY.toLong()) fetchOpenConversations(apiVersion) withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isRefreshing = false + binding?.swipeRefreshLayoutView?.isRefreshing = false } }, { throwable: Throwable -> handleHttpExceptions(throwable) withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isRefreshing = false + binding?.swipeRefreshLayoutView?.isRefreshing = false showErrorDialog() } dispose(roomsQueryDisposable) }) { dispose(roomsQueryDisposable) withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isRefreshing = false + binding?.swipeRefreshLayoutView?.isRefreshing = false } isRefreshing = false } @@ -535,18 +535,18 @@ class ConversationsListController(bundle: Bundle) : private fun initOverallLayout(isConversationListNotEmpty: Boolean) { if (isConversationListNotEmpty) { - if (binding.emptyLayout.visibility != View.GONE) { - binding.emptyLayout.visibility = View.GONE + if (binding?.emptyLayout?.visibility != View.GONE) { + binding?.emptyLayout?.visibility = View.GONE } - if (binding.swipeRefreshLayoutView.visibility != View.VISIBLE) { - binding.swipeRefreshLayoutView.visibility = View.VISIBLE + if (binding?.swipeRefreshLayoutView?.visibility != View.VISIBLE) { + binding?.swipeRefreshLayoutView?.visibility = View.VISIBLE } } else { - if (binding.emptyLayout.visibility != View.VISIBLE) { - binding.emptyLayout.visibility = View.VISIBLE + if (binding?.emptyLayout?.visibility != View.VISIBLE) { + binding?.emptyLayout?.visibility = View.VISIBLE } - if (binding.swipeRefreshLayoutView.visibility != View.GONE) { - binding.swipeRefreshLayoutView.visibility = View.GONE + if (binding?.swipeRefreshLayoutView?.visibility != View.GONE) { + binding?.swipeRefreshLayoutView?.visibility = View.GONE } } } @@ -584,21 +584,24 @@ class ConversationsListController(bundle: Bundle) : } private fun showErrorDialog() { - val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context) - .setIcon( - viewThemeUtils.dialog.colorMaterialAlertDialogIcon( - context, - R.drawable.ic_baseline_error_outline_24dp, + binding?.floatingActionButton?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it.context) + .setIcon( + viewThemeUtils.dialog.colorMaterialAlertDialogIcon( + context, + R.drawable.ic_baseline_error_outline_24dp, + ) ) + .setTitle(R.string.error_loading_chats) + .setCancelable(false) + .setNegativeButton(R.string.close, null) + + viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder) + val dialog = dialogBuilder.show() + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) ) - .setTitle(R.string.error_loading_chats) - .setCancelable(false) - .setNegativeButton(R.string.close, null) - viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder) - val dialog = dialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) + } } private fun sortConversations(conversationItems: MutableList>) { @@ -678,10 +681,10 @@ class ConversationsListController(bundle: Bundle) : @SuppressLint("ClickableViewAccessibility") private fun prepareViews() { layoutManager = SmoothScrollLinearLayoutManager(Objects.requireNonNull(activity)) - binding.recyclerView.layoutManager = layoutManager - binding.recyclerView.setHasFixedSize(true) - binding.recyclerView.adapter = adapter - binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { + binding?.recyclerView?.layoutManager = layoutManager + binding?.recyclerView?.setHasFixedSize(true) + binding?.recyclerView?.adapter = adapter + binding?.recyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { super.onScrollStateChanged(recyclerView, newState) if (newState == RecyclerView.SCROLL_STATE_IDLE) { @@ -689,21 +692,21 @@ class ConversationsListController(bundle: Bundle) : } } }) - binding.recyclerView.setOnTouchListener { v: View, _: MotionEvent? -> + binding?.recyclerView?.setOnTouchListener { v: View, _: MotionEvent? -> if (isAttached && (!isBeingDestroyed || !isDestroyed)) { val imm = activity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager imm.hideSoftInputFromWindow(v.windowToken, 0) } false } - binding.swipeRefreshLayoutView.setOnRefreshListener { fetchRooms() } - viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeRefreshLayoutView) - binding.emptyLayout.setOnClickListener { showNewConversationsScreen() } - binding.floatingActionButton.setOnClickListener { + binding?.swipeRefreshLayoutView?.setOnRefreshListener { fetchRooms() } + binding?.swipeRefreshLayoutView?.let { viewThemeUtils.androidx.themeSwipeRefreshLayout(it) } + binding?.emptyLayout?.setOnClickListener { showNewConversationsScreen() } + binding?.floatingActionButton?.setOnClickListener { run(context) showNewConversationsScreen() } - viewThemeUtils.material.themeFAB(binding.floatingActionButton) + binding?.floatingActionButton?.let { viewThemeUtils.material.themeFAB(it) } if (activity != null && activity is MainActivity) { val activity = activity as MainActivity? activity!!.binding.switchAccountButton.setOnClickListener { @@ -722,13 +725,13 @@ class ConversationsListController(bundle: Bundle) : } } } - binding.newMentionPopupBubble.hide() - binding.newMentionPopupBubble.setPopupBubbleListener { - binding.recyclerView.smoothScrollToPosition( + binding?.newMentionPopupBubble?.hide() + binding?.newMentionPopupBubble?.setPopupBubbleListener { + binding?.recyclerView?.smoothScrollToPosition( nextUnreadConversationScrollPosition ) } - viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.newMentionPopupBubble) + binding?.newMentionPopupBubble?.let { viewThemeUtils.material.colorMaterialButtonPrimaryFilled(it) } } @Suppress("Detekt.TooGenericExceptionCaught") @@ -740,14 +743,14 @@ class ConversationsListController(bundle: Bundle) : val position = adapter!!.getGlobalPositionOf(flexItem) if (hasUnreadItems(conversation) && position > lastVisibleItem) { nextUnreadConversationScrollPosition = position - if (!binding.newMentionPopupBubble.isShown) { - binding.newMentionPopupBubble.show() + if (!binding?.newMentionPopupBubble?.isShown!!) { + binding?.newMentionPopupBubble?.show() } return } } nextUnreadConversationScrollPosition = 0 - binding.newMentionPopupBubble.hide() + binding?.newMentionPopupBubble?.hide() } catch (e: NullPointerException) { Log.d( TAG, @@ -852,7 +855,7 @@ class ConversationsListController(bundle: Bundle) : @SuppressLint("CheckResult") // handled by helper private fun startMessageSearch(search: String?) { withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isRefreshing = true + binding?.swipeRefreshLayoutView?.isRefreshing = true } searchHelper?.startMessageSearch(search!!) ?.subscribeOn(Schedulers.io()) @@ -866,7 +869,7 @@ class ConversationsListController(bundle: Bundle) : @SuppressLint("CheckResult") // handled by helper private fun loadMoreMessages() { - binding.swipeRefreshLayoutView.isRefreshing = true + binding?.swipeRefreshLayoutView?.isRefreshing = true val observable = searchHelper!!.loadMore() observable?.observeOn(AndroidSchedulers.mainThread()) ?.subscribe({ results: MessageSearchResults -> onMessageSearchResult(results) }) { throwable: Throwable -> @@ -977,24 +980,27 @@ class ConversationsListController(bundle: Bundle) : selectedConversation!!.displayName ) } - val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context) - .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.upload)) - .setTitle(confirmationQuestion) - .setMessage(fileNamesWithLineBreaks.toString()) - .setPositiveButton(R.string.nc_yes) { _, _ -> - upload() - openConversation() - } - .setNegativeButton(R.string.nc_no) { _, _ -> - Log.d(TAG, "sharing files aborted, going back to share-to screen") - } - viewThemeUtils.dialog - .colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder) - val dialog = dialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) + binding?.floatingActionButton?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it.context) + .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.upload)) + .setTitle(confirmationQuestion) + .setMessage(fileNamesWithLineBreaks.toString()) + .setPositiveButton(R.string.nc_yes) { _, _ -> + upload() + openConversation() + } + .setNegativeButton(R.string.nc_no) { _, _ -> + Log.d(TAG, "sharing files aborted, going back to share-to screen") + } + + viewThemeUtils.dialog + .colorMaterialAlertDialogBackground(it.context, dialogBuilder) + val dialog = dialogBuilder.show() + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) + } } else { requestStoragePermission(this@ConversationsListController) } @@ -1161,33 +1167,36 @@ class ConversationsListController(bundle: Bundle) : ) { val conversation = Parcels.unwrap(conversationMenuBundle!!.getParcelable(KEY_ROOM)) if (conversation != null) { - val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context) - .setIcon( - viewThemeUtils.dialog - .colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp) - ) - .setTitle(R.string.nc_delete_call) - .setMessage(R.string.nc_delete_conversation_more) - .setPositiveButton(R.string.nc_delete) { _, _ -> - val data = Data.Builder() - data.putLong( - KEY_INTERNAL_USER_ID, - conversationMenuBundle!!.getLong(KEY_INTERNAL_USER_ID) + binding?.floatingActionButton?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it.context) + .setIcon( + viewThemeUtils.dialog + .colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp) ) - data.putString(KEY_ROOM_TOKEN, conversation.token) - conversationMenuBundle = null - deleteConversation(data.build()) - } - .setNegativeButton(R.string.nc_cancel) { _, _ -> - conversationMenuBundle = null - } - viewThemeUtils.dialog - .colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder) - val dialog = dialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) + .setTitle(R.string.nc_delete_call) + .setMessage(R.string.nc_delete_conversation_more) + .setPositiveButton(R.string.nc_delete) { _, _ -> + val data = Data.Builder() + data.putLong( + KEY_INTERNAL_USER_ID, + conversationMenuBundle!!.getLong(KEY_INTERNAL_USER_ID) + ) + data.putString(KEY_ROOM_TOKEN, conversation.token) + conversationMenuBundle = null + deleteConversation(data.build()) + } + .setNegativeButton(R.string.nc_cancel) { _, _ -> + conversationMenuBundle = null + } + + viewThemeUtils.dialog + .colorMaterialAlertDialogBackground(it.context, dialogBuilder) + val dialog = dialogBuilder.show() + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) + } } } } @@ -1198,12 +1207,62 @@ class ConversationsListController(bundle: Bundle) : private fun showUnauthorizedDialog() { if (activity != null) { - val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context) - .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp)) - .setTitle(R.string.nc_dialog_invalid_password) - .setMessage(R.string.nc_dialog_reauth_or_delete) + binding?.floatingActionButton?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it.context) + .setIcon( + viewThemeUtils.dialog.colorMaterialAlertDialogIcon( + context, R.drawable.ic_delete_black_24dp + ) + ) + .setTitle(R.string.nc_dialog_invalid_password) + .setMessage(R.string.nc_dialog_reauth_or_delete) + .setCancelable(false) + .setPositiveButton(R.string.nc_delete) { _, _ -> + val otherUserExists = userManager + .scheduleUserForDeletionWithId(currentUser!!.id!!) + .blockingGet() + val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build() + WorkManager.getInstance().enqueue(accountRemovalWork) + if (otherUserExists && view != null) { + onViewBound(view!!) + onAttach(view!!) + } else if (!otherUserExists) { + router.setRoot( + RouterTransaction.with(ServerSelectionController()) + .pushChangeHandler(VerticalChangeHandler()) + .popChangeHandler(VerticalChangeHandler()) + ) + } + } + .setNegativeButton(R.string.nc_settings_reauthorize) { _, _ -> + router.pushController( + RouterTransaction.with( + WebViewLoginController(currentUser!!.baseUrl, true) + ) + .pushChangeHandler(VerticalChangeHandler()) + .popChangeHandler(VerticalChangeHandler()) + ) + } + + viewThemeUtils.dialog + .colorMaterialAlertDialogBackground(it.context, dialogBuilder) + val dialog = dialogBuilder.show() + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) + } + } + } + + private fun showServerEOLDialog() { + binding?.floatingActionButton?.let { + val dialogBuilder = MaterialAlertDialogBuilder(it.context) + .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_warning_white)) + .setTitle(R.string.nc_settings_server_eol_title) + .setMessage(R.string.nc_settings_server_eol) .setCancelable(false) - .setPositiveButton(R.string.nc_delete) { _, _ -> + .setPositiveButton(R.string.nc_settings_remove_account) { _, _ -> val otherUserExists = userManager .scheduleUserForDeletionWithId(currentUser!!.id!!) .blockingGet() @@ -1214,23 +1273,24 @@ class ConversationsListController(bundle: Bundle) : onAttach(view!!) } else if (!otherUserExists) { router.setRoot( - RouterTransaction.with(ServerSelectionController()) + RouterTransaction.with( + ServerSelectionController() + ) .pushChangeHandler(VerticalChangeHandler()) .popChangeHandler(VerticalChangeHandler()) ) } } - .setNegativeButton(R.string.nc_settings_reauthorize) { _, _ -> - router.pushController( - RouterTransaction.with( - WebViewLoginController(currentUser!!.baseUrl, true) - ) - .pushChangeHandler(VerticalChangeHandler()) - .popChangeHandler(VerticalChangeHandler()) - ) + .setNegativeButton(R.string.nc_cancel) { _, _ -> + if (userManager.users.blockingGet().isNotEmpty()) { + router.pushController(RouterTransaction.with(SwitchAccountController())) + } else { + activity!!.finishAffinity() + activity!!.finish() + } } - viewThemeUtils.dialog - .colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder) + + viewThemeUtils.dialog.colorMaterialAlertDialogBackground(it.context, dialogBuilder) val dialog = dialogBuilder.show() viewThemeUtils.platform.colorTextButtons( dialog.getButton(AlertDialog.BUTTON_POSITIVE), @@ -1239,47 +1299,6 @@ class ConversationsListController(bundle: Bundle) : } } - private fun showServerEOLDialog() { - val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context) - .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_warning_white)) - .setTitle(R.string.nc_settings_server_eol_title) - .setMessage(R.string.nc_settings_server_eol) - .setCancelable(false) - .setPositiveButton(R.string.nc_settings_remove_account) { _, _ -> - val otherUserExists = userManager - .scheduleUserForDeletionWithId(currentUser!!.id!!) - .blockingGet() - val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build() - WorkManager.getInstance().enqueue(accountRemovalWork) - if (otherUserExists && view != null) { - onViewBound(view!!) - onAttach(view!!) - } else if (!otherUserExists) { - router.setRoot( - RouterTransaction.with( - ServerSelectionController() - ) - .pushChangeHandler(VerticalChangeHandler()) - .popChangeHandler(VerticalChangeHandler()) - ) - } - } - .setNegativeButton(R.string.nc_cancel) { _, _ -> - if (userManager.users.blockingGet().isNotEmpty()) { - router.pushController(RouterTransaction.with(SwitchAccountController())) - } else { - activity!!.finishAffinity() - activity!!.finish() - } - } - viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder) - val dialog = dialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) - } - private fun deleteConversation(data: Data) { val deleteConversationWorker = OneTimeWorkRequest.Builder(DeleteConversationWorker::class.java).setInputData(data).build() @@ -1309,18 +1328,18 @@ class ConversationsListController(bundle: Bundle) : } // add unified search result at the end of the list adapter!!.addItems(adapter!!.mainItemCount + adapter!!.scrollableHeaders.size, adapterItems) - binding.recyclerView.scrollToPosition(0) + binding?.recyclerView?.scrollToPosition(0) } } withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isRefreshing = false + binding?.swipeRefreshLayoutView?.isRefreshing = false } } private fun onMessageSearchError(throwable: Throwable) { handleHttpExceptions(throwable) withNullableControllerViewBinding { - binding.swipeRefreshLayoutView.isRefreshing = false + binding?.swipeRefreshLayoutView?.isRefreshing = false showErrorDialog() } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/GeocodingController.kt b/app/src/main/java/com/nextcloud/talk/controllers/GeocodingController.kt index 592b729e0..9b09095f5 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/GeocodingController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/GeocodingController.kt @@ -63,7 +63,7 @@ class GeocodingController(args: Bundle) : args ), SearchView.OnQueryTextListener { - private val binding: ControllerGeocodingBinding by viewBinding(ControllerGeocodingBinding::bind) + private val binding: ControllerGeocodingBinding? by viewBinding(ControllerGeocodingBinding::bind) @Inject lateinit var ncApi: NcApi @@ -94,8 +94,8 @@ class GeocodingController(args: Bundle) : } private fun initAdapter(addresses: List
) { - adapter = GeocodingAdapter(binding.geocodingResults.context!!, addresses) - binding.geocodingResults.adapter = adapter + adapter = GeocodingAdapter(binding?.geocodingResults?.context!!, addresses) + binding?.geocodingResults?.adapter = adapter } override fun onAttach(view: View) { @@ -110,7 +110,7 @@ class GeocodingController(args: Bundle) : Log.e(TAG, "search string that was passed to GeocodingController was null or empty") } - binding.geocodingResults.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> + binding?.geocodingResults?.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id -> val address: Address = adapter.getItem(position) as Address val listener: GeocodingResultListener? = targetController as GeocodingResultListener? listener?.receiveChosenGeocodingResult(address.latitude, address.longitude, address.displayName) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/LocationPickerController.kt b/app/src/main/java/com/nextcloud/talk/controllers/LocationPickerController.kt index 708cd4d80..ccf34a9a8 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/LocationPickerController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/LocationPickerController.kt @@ -90,7 +90,7 @@ class LocationPickerController(args: Bundle) : SearchView.OnQueryTextListener, LocationListener, GeocodingController.GeocodingResultListener { - private val binding: ControllerLocationBinding by viewBinding(ControllerLocationBinding::bind) + private val binding: ControllerLocationBinding? by viewBinding(ControllerLocationBinding::bind) @Inject lateinit var ncApi: NcApi @@ -164,13 +164,13 @@ class LocationPickerController(args: Bundle) : override fun onViewBound(view: View) { setLocationDescription(false, receivedChosenGeocodingResult) - binding.shareLocation.isClickable = false - binding.shareLocation.setOnClickListener { + binding?.shareLocation?.isClickable = false + binding?.shareLocation?.setOnClickListener { if (readyToShareLocation) { shareLocation( - binding.map.mapCenter?.latitude, - binding.map.mapCenter?.longitude, - binding.placeName.text.toString() + binding?.map?.mapCenter?.latitude, + binding?.map?.mapCenter?.longitude, + binding?.placeName?.text.toString() ) } else { Log.w(TAG, "readyToShareLocation was false while user tried to share location.") @@ -217,8 +217,8 @@ class LocationPickerController(args: Bundle) : @Suppress("Detekt.TooGenericExceptionCaught", "Detekt.ComplexMethod") private fun initMap() { - binding.map.setTileSource(TileSourceFactory.MAPNIK) - binding.map.onResume() + binding?.map?.setTileSource(TileSourceFactory.MAPNIK) + binding?.map?.onResume() locationManager = activity!!.getSystemService(Context.LOCATION_SERVICE) as LocationManager @@ -229,12 +229,12 @@ class LocationPickerController(args: Bundle) : } val copyrightOverlay = CopyrightOverlay(context) - binding.map.overlays?.add(copyrightOverlay) + binding?.map?.overlays?.add(copyrightOverlay) - binding.map.setMultiTouchControls(true) - binding.map.isTilesScaledToDpi = true + binding?.map?.setMultiTouchControls(true) + binding?.map?.isTilesScaledToDpi = true - locationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(context), binding.map) + locationOverlay = MyLocationNewOverlay(GpsMyLocationProvider(context), binding?.map) locationOverlay.enableMyLocation() locationOverlay.setPersonHotspot(PERSON_HOT_SPOT_X, PERSON_HOT_SPOT_Y) locationOverlay.setPersonIcon( @@ -242,9 +242,9 @@ class LocationPickerController(args: Bundle) : ResourcesCompat.getDrawable(resources!!, R.drawable.current_location_circle, null) ) ) - binding.map.overlays?.add(locationOverlay) + binding?.map?.overlays?.add(locationOverlay) - val mapController = binding.map.controller + val mapController = binding?.map?.controller if (receivedChosenGeocodingResult) { mapController?.setZoom(ZOOM_LEVEL_RECEIVED_RESULT) @@ -273,16 +273,16 @@ class LocationPickerController(args: Bundle) : mapController?.setCenter(GeoPoint(geocodedLat, geocodedLon)) } - binding.centerMapButton.setOnClickListener { + binding?.centerMapButton?.setOnClickListener { if (myLocation.latitude == COORDINATE_ZERO && myLocation.longitude == COORDINATE_ZERO) { - Toast.makeText(context, context?.getString(R.string.nc_location_unknown), Toast.LENGTH_LONG).show() + Toast.makeText(context, context.getString(R.string.nc_location_unknown), Toast.LENGTH_LONG).show() } else { mapController?.animateTo(myLocation) moveToCurrentLocationWasClicked = true } } - binding.map.addMapListener( + binding?.map?.addMapListener( delayedMapListener() ) } @@ -298,12 +298,12 @@ class LocationPickerController(args: Bundle) : moveToCurrentLocationWasClicked = false } receivedChosenGeocodingResult -> { - binding.shareLocation.isClickable = true + binding?.shareLocation?.isClickable = true setLocationDescription(isGpsLocation = false, isGeocodedResult = true) receivedChosenGeocodingResult = false } else -> { - binding.shareLocation.isClickable = true + binding?.shareLocation?.isClickable = true setLocationDescription(isGpsLocation = false, isGeocodedResult = false) } } @@ -364,19 +364,19 @@ class LocationPickerController(args: Bundle) : private fun setLocationDescription(isGpsLocation: Boolean, isGeocodedResult: Boolean) { when { isGpsLocation -> { - binding.shareLocationDescription.text = context!!.getText(R.string.nc_share_current_location) - binding.placeName.visibility = View.GONE - binding.placeName.text = "" + binding?.shareLocationDescription?.text = context!!.getText(R.string.nc_share_current_location) + binding?.placeName?.visibility = View.GONE + binding?.placeName?.text = "" } isGeocodedResult -> { - binding.shareLocationDescription.text = context!!.getText(R.string.nc_share_this_location) - binding.placeName.visibility = View.VISIBLE - binding.placeName.text = geocodedName + binding?.shareLocationDescription?.text = context!!.getText(R.string.nc_share_this_location) + binding?.placeName?.visibility = View.VISIBLE + binding?.placeName?.text = geocodedName } else -> { - binding.shareLocationDescription.text = context!!.getText(R.string.nc_share_this_location) - binding.placeName.visibility = View.GONE - binding.placeName.text = "" + binding?.shareLocationDescription?.text = context!!.getText(R.string.nc_share_this_location) + binding?.placeName?.visibility = View.GONE + binding?.placeName?.text = "" } } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/LockedController.kt b/app/src/main/java/com/nextcloud/talk/controllers/LockedController.kt index 43f39435f..2fde68332 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/LockedController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/LockedController.kt @@ -47,7 +47,7 @@ import java.util.concurrent.Executors @AutoInjector(NextcloudTalkApplication::class) class LockedController : BaseController(R.layout.controller_locked) { - private val binding: ControllerLockedBinding by viewBinding(ControllerLockedBinding::bind) + private val binding: ControllerLockedBinding? by viewBinding(ControllerLockedBinding::bind) override val appBarLayoutType: AppBarLayoutType get() = AppBarLayoutType.EMPTY @@ -60,7 +60,7 @@ class LockedController : BaseController(R.layout.controller_locked) { override fun onViewBound(view: View) { super.onViewBound(view) sharedApplication!!.componentApplication.inject(this) - binding.unlockContainer.setOnClickListener { + binding?.unlockContainer?.setOnClickListener { unlock() } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt index a2c5254b3..6a6e87b30 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt @@ -96,7 +96,7 @@ import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) @Suppress("Detekt.TooManyFunctions") class ProfileController : BaseController(R.layout.controller_profile) { - private val binding: ControllerProfileBinding by viewBinding(ControllerProfileBinding::bind) + private val binding: ControllerProfileBinding? by viewBinding(ControllerProfileBinding::bind) @Inject lateinit var ncApi: NcApi @@ -146,11 +146,11 @@ class ProfileController : BaseController(R.layout.controller_profile) { edit = !edit if (edit) { item.setTitle(R.string.save) - binding.emptyList.root.visibility = View.GONE - binding.userinfoList.visibility = View.VISIBLE + binding?.emptyList?.root?.visibility = View.GONE + binding?.userinfoList?.visibility = View.VISIBLE if (CapabilitiesUtilNew.isAvatarEndpointAvailable(currentUser!!)) { // TODO later avatar can also be checked via user fields, for now it is in Talk capability - binding.avatarButtons.visibility = View.VISIBLE + binding?.avatarButtons?.visibility = View.VISIBLE } ncApi.getEditableUserProfileFields( ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token), @@ -179,10 +179,10 @@ class ProfileController : BaseController(R.layout.controller_profile) { }) } else { item.setTitle(R.string.edit) - binding.avatarButtons.visibility = View.INVISIBLE + binding?.avatarButtons?.visibility = View.INVISIBLE if (adapter!!.filteredDisplayList.isEmpty()) { - binding.emptyList.root.visibility = View.VISIBLE - binding.userinfoList.visibility = View.GONE + binding?.emptyList?.root?.visibility = View.VISIBLE + binding?.userinfoList?.visibility = View.GONE } } adapter!!.notifyDataSetChanged() @@ -194,14 +194,14 @@ class ProfileController : BaseController(R.layout.controller_profile) { override fun onAttach(view: View) { super.onAttach(view) adapter = UserInfoAdapter(null, viewThemeUtils, this) - binding.userinfoList.adapter = adapter - binding.userinfoList.setItemViewCacheSize(DEFAULT_CACHE_SIZE) + binding?.userinfoList?.adapter = adapter + binding?.userinfoList?.setItemViewCacheSize(DEFAULT_CACHE_SIZE) currentUser = userManager.currentUser.blockingGet() val credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token) - binding.avatarUpload.setOnClickListener { sendSelectLocalFileIntent() } - binding.avatarChoose.setOnClickListener { showBrowserScreen() } - binding.avatarCamera.setOnClickListener { checkPermissionAndTakePicture() } - binding.avatarDelete.setOnClickListener { + binding?.avatarUpload?.setOnClickListener { sendSelectLocalFileIntent() } + binding?.avatarChoose?.setOnClickListener { showBrowserScreen() } + binding?.avatarCamera?.setOnClickListener { checkPermissionAndTakePicture() } + binding?.avatarDelete?.setOnClickListener { ncApi.deleteAvatar( credentials, ApiUtils.getUrlForTempAvatar(currentUser!!.baseUrl) @@ -216,7 +216,7 @@ class ProfileController : BaseController(R.layout.controller_profile) { override fun onNext(genericOverall: GenericOverall) { DisplayUtils.loadAvatarImage( currentUser, - binding.avatarImage, + binding?.avatarImage, true ) } @@ -230,7 +230,7 @@ class ProfileController : BaseController(R.layout.controller_profile) { } }) } - ViewCompat.setTransitionName(binding.avatarImage, "userAvatar.transitionTag") + binding?.avatarImage?.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") } ncApi.getUserProfile(credentials, ApiUtils.getUrlForUserProfile(currentUser!!.baseUrl)) .retry(DEFAULT_RETRIES) .subscribeOn(Schedulers.io()) @@ -262,10 +262,12 @@ class ProfileController : BaseController(R.layout.controller_profile) { } private fun colorIcons() { - viewThemeUtils.material.themeFAB(binding.avatarChoose) - viewThemeUtils.material.themeFAB(binding.avatarCamera) - viewThemeUtils.material.themeFAB(binding.avatarUpload) - viewThemeUtils.material.themeFAB(binding.avatarDelete) + binding?.let { + viewThemeUtils.material.themeFAB(it.avatarChoose) + viewThemeUtils.material.themeFAB(it.avatarCamera) + viewThemeUtils.material.themeFAB(it.avatarUpload) + viewThemeUtils.material.themeFAB(it.avatarDelete) + } } private fun isAllEmpty(items: Array): Boolean { @@ -283,13 +285,13 @@ class ProfileController : BaseController(R.layout.controller_profile) { return } if (currentUser!!.baseUrl != null) { - binding.userinfoBaseurl.text = Uri.parse(currentUser!!.baseUrl).host + binding?.userinfoBaseurl?.text = Uri.parse(currentUser!!.baseUrl).host } - DisplayUtils.loadAvatarImage(currentUser, binding.avatarImage, false) + DisplayUtils.loadAvatarImage(currentUser, binding?.avatarImage, false) if (!TextUtils.isEmpty(userInfo?.displayName)) { - binding.userinfoFullName.text = userInfo?.displayName + binding?.userinfoFullName?.text = userInfo?.displayName } - binding.loadingContent.visibility = View.VISIBLE + binding?.loadingContent?.visibility = View.VISIBLE adapter!!.setData(createUserInfoDetails(userInfo)) if (isAllEmpty( arrayOf( @@ -302,18 +304,18 @@ class ProfileController : BaseController(R.layout.controller_profile) { ) ) ) { - binding.userinfoList.visibility = View.GONE - binding.loadingContent.visibility = View.GONE - binding.emptyList.root.visibility = View.VISIBLE + binding?.userinfoList?.visibility = View.GONE + binding?.loadingContent?.visibility = View.GONE + binding?.emptyList?.root?.visibility = View.VISIBLE setErrorMessageForMultiList( activity!!.getString(R.string.userinfo_no_info_headline), activity!!.getString(R.string.userinfo_no_info_text), R.drawable.ic_user ) } else { - binding.emptyList.root.visibility = View.GONE - binding.loadingContent.visibility = View.GONE - binding.userinfoList.visibility = View.VISIBLE + binding?.emptyList?.root?.visibility = View.GONE + binding?.loadingContent?.visibility = View.GONE + binding?.userinfoList?.visibility = View.VISIBLE } // show edit button @@ -354,13 +356,13 @@ class ProfileController : BaseController(R.layout.controller_profile) { } try { - binding.emptyList.emptyListViewHeadline.text = headline - binding.emptyList.emptyListViewText.text = message - binding.emptyList.emptyListIcon.setImageResource(errorResource) - binding.emptyList.emptyListIcon.visibility = View.VISIBLE - binding.emptyList.emptyListViewText.visibility = View.VISIBLE - binding.userinfoList.visibility = View.GONE - binding.loadingContent.visibility = View.GONE + binding?.emptyList?.emptyListViewHeadline?.text = headline + binding?.emptyList?.emptyListViewText?.text = message + binding?.emptyList?.emptyListIcon?.setImageResource(errorResource) + binding?.emptyList?.emptyListIcon?.visibility = View.VISIBLE + binding?.emptyList?.emptyListViewText?.visibility = View.VISIBLE + binding?.userinfoList?.visibility = View.GONE + binding?.loadingContent?.visibility = View.GONE } catch (npe: NullPointerException) { // view binding can be null // since this is called asynchronously and UI might have been destroyed in the meantime @@ -453,7 +455,7 @@ class ProfileController : BaseController(R.layout.controller_profile) { override fun onNext(userProfileOverall: GenericOverall) { Log.d(TAG, "Successfully saved: " + item.text + " as " + item.field) if (item.field == Field.DISPLAYNAME) { - binding.userinfoFullName.text = item.text + binding?.userinfoFullName?.text = item.text } } @@ -646,7 +648,7 @@ class ProfileController : BaseController(R.layout.controller_profile) { } override fun onNext(genericOverall: GenericOverall) { - DisplayUtils.loadAvatarImage(currentUser, binding.avatarImage, true) + DisplayUtils.loadAvatarImage(currentUser, binding?.avatarImage, true) } override fun onError(e: Throwable) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.kt b/app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.kt index a41834f27..2c5e81193 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/RingtoneSelectionController.kt @@ -57,7 +57,7 @@ class RingtoneSelectionController(args: Bundle) : args ), FlexibleAdapter.OnItemClickListener { - private val binding: ControllerGenericRvBinding by viewBinding(ControllerGenericRvBinding::bind) + private val binding: ControllerGenericRvBinding? by viewBinding(ControllerGenericRvBinding::bind) private var adapter: FlexibleAdapter<*>? = null private var adapterDataObserver: RecyclerView.AdapterDataObserver? = null @@ -89,9 +89,9 @@ class RingtoneSelectionController(args: Bundle) : private fun prepareViews() { val layoutManager: RecyclerView.LayoutManager = SmoothScrollLinearLayoutManager(activity) - binding.recyclerView.layoutManager = layoutManager - binding.recyclerView.setHasFixedSize(true) - binding.recyclerView.adapter = adapter + binding?.recyclerView?.layoutManager = layoutManager + binding?.recyclerView?.setHasFixedSize(true) + binding?.recyclerView?.adapter = adapter adapterDataObserver = object : RecyclerView.AdapterDataObserver() { override fun onChanged() { super.onChanged() @@ -99,7 +99,7 @@ class RingtoneSelectionController(args: Bundle) : } } adapter!!.registerAdapterDataObserver(adapterDataObserver!!) - binding.swipeRefreshLayout.isEnabled = false + binding?.swipeRefreshLayout?.isEnabled = false } @SuppressLint("LongLogTag") diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt index 1f12dd4f7..3ca396525 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ServerSelectionController.kt @@ -63,7 +63,7 @@ import javax.inject.Inject class ServerSelectionController : BaseController(R.layout.controller_server_selection) { - private val binding: ControllerServerSelectionBinding by viewBinding(ControllerServerSelectionBinding::bind) + private val binding: ControllerServerSelectionBinding? by viewBinding(ControllerServerSelectionBinding::bind) @Inject lateinit var ncApi: NcApi @@ -99,14 +99,14 @@ class ServerSelectionController : actionBar?.hide() - binding.hostUrlInputHelperText.text = String.format( + binding?.hostUrlInputHelperText?.text = String.format( resources!!.getString(R.string.nc_server_helper_text), resources!!.getString(R.string.nc_server_product_name) ) - binding.serverEntryTextInputLayout.setEndIconOnClickListener { checkServerAndProceed() } + binding?.serverEntryTextInputLayout?.setEndIconOnClickListener { checkServerAndProceed() } if (resources!!.getBoolean(R.bool.hide_auth_cert)) { - binding.certTextView.visibility = View.GONE + binding?.certTextView?.visibility = View.GONE } val loggedInUsers = userManager.users.blockingGet() @@ -117,21 +117,21 @@ class ServerSelectionController : } else if (isAbleToShowProviderLink() && loggedInUsers.isEmpty()) { showVisitProvidersInfo() } else { - binding.importOrChooseProviderText.visibility = View.INVISIBLE + binding?.importOrChooseProviderText?.visibility = View.INVISIBLE } - binding.serverEntryTextInputEditText.requestFocus() + binding?.serverEntryTextInputEditText?.requestFocus() if (!TextUtils.isEmpty(resources!!.getString(R.string.weblogin_url))) { - binding.serverEntryTextInputEditText.setText(resources!!.getString(R.string.weblogin_url)) + binding?.serverEntryTextInputEditText?.setText(resources!!.getString(R.string.weblogin_url)) checkServerAndProceed() } - binding.serverEntryTextInputEditText.setOnEditorActionListener { _: TextView?, i: Int, _: KeyEvent? -> + binding?.serverEntryTextInputEditText?.setOnEditorActionListener { _: TextView?, i: Int, _: KeyEvent? -> if (i == EditorInfo.IME_ACTION_DONE) { checkServerAndProceed() } false } - binding.certTextView.setOnClickListener { onCertClick() } + binding?.certTextView?.setOnClickListener { onCertClick() } } private fun isAbleToShowProviderLink(): Boolean { @@ -145,25 +145,26 @@ class ServerSelectionController : ) ) { if (availableAccounts.size > 1) { - binding.importOrChooseProviderText.text = String.format( + binding?.importOrChooseProviderText?.text = String.format( resources!!.getString(R.string.nc_server_import_accounts), AccountUtils.getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from)) ) } else { - binding.importOrChooseProviderText.text = String.format( + binding?.importOrChooseProviderText?.text = String.format( resources!!.getString(R.string.nc_server_import_account), AccountUtils.getAppNameBasedOnPackage(resources!!.getString(R.string.nc_import_accounts_from)) ) } } else { if (availableAccounts.size > 1) { - binding.importOrChooseProviderText.text = + binding?.importOrChooseProviderText?.text = resources!!.getString(R.string.nc_server_import_accounts_plain) } else { - binding.importOrChooseProviderText.text = resources!!.getString(R.string.nc_server_import_account_plain) + binding?.importOrChooseProviderText?.text = + resources!!.getString(R.string.nc_server_import_account_plain) } } - binding.importOrChooseProviderText.setOnClickListener { + binding?.importOrChooseProviderText?.setOnClickListener { val bundle = Bundle() bundle.putBoolean(KEY_IS_ACCOUNT_IMPORT, true) router.pushController( @@ -177,8 +178,8 @@ class ServerSelectionController : } private fun showVisitProvidersInfo() { - binding.importOrChooseProviderText.setText(R.string.nc_get_from_provider) - binding.importOrChooseProviderText.setOnClickListener { + binding?.importOrChooseProviderText?.setText(R.string.nc_get_from_provider) + binding?.importOrChooseProviderText?.setOnClickListener { val browserIntent = Intent( Intent.ACTION_VIEW, Uri.parse( @@ -199,12 +200,12 @@ class ServerSelectionController : private fun checkServerAndProceed() { dispose() try { - var url: String = binding.serverEntryTextInputEditText.text.toString().trim { it <= ' ' } - binding.serverEntryTextInputEditText.isEnabled = false + var url: String = binding?.serverEntryTextInputEditText?.text.toString().trim { it <= ' ' } + binding?.serverEntryTextInputEditText?.isEnabled = false showserverEntryProgressBar() - if (binding.importOrChooseProviderText.visibility != View.INVISIBLE) { - binding.importOrChooseProviderText.visibility = View.INVISIBLE - binding.certTextView.visibility = View.INVISIBLE + if (binding?.importOrChooseProviderText?.visibility != View.INVISIBLE) { + binding?.importOrChooseProviderText?.visibility = View.INVISIBLE + binding?.certTextView?.visibility = View.INVISIBLE } if (url.endsWith("/")) { url = url.substring(0, url.length - 1) @@ -282,19 +283,19 @@ class ServerSelectionController : hideserverEntryProgressBar() } - binding.serverEntryTextInputEditText.isEnabled = true + binding?.serverEntryTextInputEditText?.isEnabled = true - if (binding.importOrChooseProviderText.visibility != View.INVISIBLE) { - binding.importOrChooseProviderText.visibility = View.VISIBLE - binding.certTextView.visibility = View.VISIBLE + if (binding?.importOrChooseProviderText?.visibility != View.INVISIBLE) { + binding?.importOrChooseProviderText?.visibility = View.VISIBLE + binding?.certTextView?.visibility = View.VISIBLE } dispose() } }) { hideserverEntryProgressBar() - if (binding.importOrChooseProviderText.visibility != View.INVISIBLE) { - binding.importOrChooseProviderText.visibility = View.VISIBLE - binding.certTextView.visibility = View.VISIBLE + if (binding?.importOrChooseProviderText?.visibility != View.INVISIBLE) { + binding?.importOrChooseProviderText?.visibility = View.VISIBLE + binding?.certTextView?.visibility = View.VISIBLE } dispose() } @@ -305,19 +306,19 @@ class ServerSelectionController : } private fun setErrorText(text: String) { - binding.errorText.text = text - binding.errorText.visibility = View.VISIBLE - binding.serverEntryProgressBar.visibility = View.GONE + binding?.errorText?.text = text + binding?.errorText?.visibility = View.VISIBLE + binding?.serverEntryProgressBar?.visibility = View.GONE } private fun showserverEntryProgressBar() { - binding.errorText.visibility = View.GONE - binding.serverEntryProgressBar.visibility = View.VISIBLE + binding?.errorText?.visibility = View.GONE + binding?.serverEntryProgressBar?.visibility = View.VISIBLE } private fun hideserverEntryProgressBar() { - binding.errorText.visibility = View.GONE - binding.serverEntryProgressBar.visibility = View.INVISIBLE + binding?.errorText?.visibility = View.GONE + binding?.serverEntryProgressBar?.visibility = View.INVISIBLE } override fun onAttach(view: View) { @@ -358,9 +359,9 @@ class ServerSelectionController : activity!!.runOnUiThread { try { if (!TextUtils.isEmpty(appPreferences!!.temporaryClientCertAlias)) { - binding.certTextView.setText(R.string.nc_change_cert_auth) + binding?.certTextView?.setText(R.string.nc_change_cert_auth) } else { - binding.certTextView.setText(R.string.nc_configure_cert_auth) + binding?.certTextView?.setText(R.string.nc_configure_cert_auth) } hideserverEntryProgressBar() } catch (npe: java.lang.NullPointerException) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt index 95adb858f..bfd31d227 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt @@ -106,7 +106,7 @@ import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) class SettingsController : BaseController(R.layout.controller_settings) { - private val binding: ControllerSettingsBinding by viewBinding(ControllerSettingsBinding::bind) + private val binding: ControllerSettingsBinding? by viewBinding(ControllerSettingsBinding::bind) @Inject lateinit var ncApi: NcApi @@ -144,7 +144,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { setHasOptionsMenu(true) sharedApplication!!.componentApplication.inject(this) - ViewCompat.setTransitionName((binding.avatarImage), "userAvatar.transitionTag") + binding?.avatarImage?.let { ViewCompat.setTransitionName(it, "userAvatar.transitionTag") } getCurrentUser() @@ -154,10 +154,10 @@ class SettingsController : BaseController(R.layout.controller_settings) { setupLicenceSetting() if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) { - binding.settingsIncognitoKeyboard.visibility = View.GONE + binding?.settingsIncognitoKeyboard?.visibility = View.GONE } - binding.settingsScreenLock.setSummary( + binding?.settingsScreenLock?.setSummary( String.format( Locale.getDefault(), resources!!.getString(R.string.nc_settings_screen_lock_desc), @@ -167,7 +167,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { setupPrivacyUrl() setupSourceCodeUrl() - binding.settingsVersion.setSummary("v" + BuildConfig.VERSION_NAME) + binding?.settingsVersion?.setSummary("v" + BuildConfig.VERSION_NAME) setupSoundSettings() @@ -178,15 +178,15 @@ class SettingsController : BaseController(R.layout.controller_settings) { private fun setupPhoneBookIntegration() { if (CapabilitiesUtilNew.isPhoneBookIntegrationAvailable(currentUser!!)) { - binding.settingsPhoneBookIntegration.visibility = View.VISIBLE + binding?.settingsPhoneBookIntegration?.visibility = View.VISIBLE } else { - binding.settingsPhoneBookIntegration.visibility = View.GONE + binding?.settingsPhoneBookIntegration?.visibility = View.GONE } } private fun setupSoundSettings() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - binding.settingsCallSound.setOnClickListener { + binding?.settingsCallSound?.setOnClickListener { val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID) intent.putExtra( @@ -196,7 +196,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { startActivity(intent) } - binding.settingsMessageSound.setOnClickListener { + binding?.settingsMessageSound?.setOnClickListener { val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) intent.putExtra(Settings.EXTRA_APP_PACKAGE, BuildConfig.APPLICATION_ID) intent.putExtra( @@ -206,7 +206,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { startActivity(intent) } } else { - binding.settingsCallSound.setOnClickListener { + binding?.settingsCallSound?.setOnClickListener { val bundle = Bundle() bundle.putBoolean(KEY_ARE_CALL_SOUNDS, true) @@ -216,7 +216,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { .popChangeHandler(HorizontalChangeHandler()) ) } - binding.settingsMessageSound.setOnClickListener { + binding?.settingsMessageSound?.setOnClickListener { val bundle = Bundle() bundle.putBoolean(KEY_ARE_CALL_SOUNDS, false) @@ -231,7 +231,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { private fun setupSourceCodeUrl() { if (!TextUtils.isEmpty(resources!!.getString(R.string.nc_source_code_url))) { - binding.settingsSourceCode.addPreferenceClickListener { + binding?.settingsSourceCode?.addPreferenceClickListener { startActivity( Intent( Intent.ACTION_VIEW, @@ -240,13 +240,13 @@ class SettingsController : BaseController(R.layout.controller_settings) { ) } } else { - binding.settingsSourceCode.visibility = View.GONE + binding?.settingsSourceCode?.visibility = View.GONE } } private fun setupPrivacyUrl() { if (!TextUtils.isEmpty(resources!!.getString(R.string.nc_privacy_url))) { - binding.settingsPrivacy.addPreferenceClickListener { + binding?.settingsPrivacy?.addPreferenceClickListener { startActivity( Intent( Intent.ACTION_VIEW, @@ -255,13 +255,13 @@ class SettingsController : BaseController(R.layout.controller_settings) { ) } } else { - binding.settingsPrivacy.visibility = View.GONE + binding?.settingsPrivacy?.visibility = View.GONE } } private fun setupLicenceSetting() { if (!TextUtils.isEmpty(resources!!.getString(R.string.nc_gpl3_url))) { - binding.settingsLicence.addPreferenceClickListener { + binding?.settingsLicence?.addPreferenceClickListener { startActivity( Intent( Intent.ACTION_VIEW, @@ -270,15 +270,15 @@ class SettingsController : BaseController(R.layout.controller_settings) { ) } } else { - binding.settingsLicence.visibility = View.GONE + binding?.settingsLicence?.visibility = View.GONE } } private fun setupSettingsScreen() { val listWithIntFields: MutableList = ArrayList() listWithIntFields.add("proxy_port") - binding.settingsScreen.setUserInputModule(MagicUserInputModule(activity, listWithIntFields)) - binding.settingsScreen.setVisibilityController( + binding?.settingsScreen?.setUserInputModule(MagicUserInputModule(activity, listWithIntFields)) + binding?.settingsScreen?.setVisibilityController( R.id.settings_proxy_use_credentials, Arrays.asList(R.id.settings_proxy_username_edit, R.id.settings_proxy_password_edit), true @@ -297,7 +297,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { Log.e(TAG, "Failed to create uri") } - binding.settingsClientCert.addPreferenceClickListener { + binding?.settingsClientCert?.addPreferenceClickListener { KeyChain.choosePrivateKeyAlias( activity!!, { alias: String? -> @@ -305,9 +305,9 @@ class SettingsController : BaseController(R.layout.controller_settings) { activity!!.runOnUiThread { if (finalAlias != null) { - binding.settingsClientCert.setTitle(R.string.nc_client_cert_change) + binding?.settingsClientCert?.setTitle(R.string.nc_client_cert_change) } else { - binding.settingsClientCert.setTitle(R.string.nc_client_cert_setup) + binding?.settingsClientCert?.setTitle(R.string.nc_client_cert_setup) } } @@ -370,27 +370,29 @@ class SettingsController : BaseController(R.layout.controller_settings) { private fun showRemoveAccountWarning() { if (activity != null) { - val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageText.context) - .setTitle(R.string.nc_settings_remove_account) - .setMessage(R.string.nc_settings_remove_confirmation) - .setPositiveButton(R.string.nc_settings_remove) { _, _ -> - removeCurrentAccount() - } - .setNegativeButton(R.string.nc_cancel) { _, _ -> - // unused atm - } + binding?.messageText?.context?.let { + val materialAlertDialogBuilder = MaterialAlertDialogBuilder(it) + .setTitle(R.string.nc_settings_remove_account) + .setMessage(R.string.nc_settings_remove_confirmation) + .setPositiveButton(R.string.nc_settings_remove) { _, _ -> + removeCurrentAccount() + } + .setNegativeButton(R.string.nc_cancel) { _, _ -> + // unused atm + } - viewThemeUtils.dialog.colorMaterialAlertDialogBackground( - binding.messageText.context, - materialAlertDialogBuilder - ) + viewThemeUtils.dialog.colorMaterialAlertDialogBackground( + it, + materialAlertDialogBuilder + ) - val dialog = materialAlertDialogBuilder.show() + val dialog = materialAlertDialogBuilder.show() - viewThemeUtils.platform.colorTextButtons( - dialog.getButton(AlertDialog.BUTTON_POSITIVE), - dialog.getButton(AlertDialog.BUTTON_NEGATIVE) - ) + viewThemeUtils.platform.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) + } } } @@ -428,38 +430,38 @@ class SettingsController : BaseController(R.layout.controller_settings) { actionBar?.show() dispose(null) - binding.settingsVersion.setOnClickListener { + binding?.settingsVersion?.setOnClickListener { sendLogs() } if (!TextUtils.isEmpty(currentUser!!.clientCertificate)) { - binding.settingsClientCert.setTitle(R.string.nc_client_cert_change) + binding?.settingsClientCert?.setTitle(R.string.nc_client_cert_change) } else { - binding.settingsClientCert.setTitle(R.string.nc_client_cert_setup) + binding?.settingsClientCert?.setTitle(R.string.nc_client_cert_setup) } setupCheckables() setupScreenLockSetting() if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - binding.settingsNotificationsCategory.setTitle( + binding?.settingsNotificationsCategory?.setTitle( resources!!.getString(R.string.nc_settings_notification_sounds_post_oreo) ) } val callRingtoneUri = getCallRingtoneUri(view.context, (appPreferences)!!) - binding.settingsCallSound.setSummary(getRingtoneName(view.context, callRingtoneUri)) + binding?.settingsCallSound?.setSummary(getRingtoneName(view.context, callRingtoneUri)) val messageRingtoneUri = getMessageRingtoneUri(view.context, (appPreferences)!!) - binding.settingsMessageSound.setSummary(getRingtoneName(view.context, messageRingtoneUri)) + binding?.settingsMessageSound?.setSummary(getRingtoneName(view.context, messageRingtoneUri)) setupProxyTypeSettings() setupProxyCredentialSettings() if (currentUser != null) { - binding.baseUrlText.text = Uri.parse(currentUser!!.baseUrl).host + binding?.baseUrlText?.text = Uri.parse(currentUser!!.baseUrl).host setupServerAgeWarning() - binding.settingsReauthorize.addPreferenceClickListener { + binding?.settingsReauthorize?.addPreferenceClickListener { router.pushController( RouterTransaction.with(WebViewLoginController(currentUser!!.baseUrl, true)) .pushChangeHandler(VerticalChangeHandler()) @@ -468,19 +470,19 @@ class SettingsController : BaseController(R.layout.controller_settings) { } if (currentUser!!.displayName != null) { - binding.displayNameText.text = currentUser!!.displayName + binding?.displayNameText?.text = currentUser!!.displayName } - DisplayUtils.loadAvatarImage(currentUser, binding.avatarImage, false) + DisplayUtils.loadAvatarImage(currentUser, binding?.avatarImage, false) setupProfileQueryDisposable() - binding.settingsRemoveAccount.addPreferenceClickListener { + binding?.settingsRemoveAccount?.addPreferenceClickListener { showRemoveAccountWarning() } } setupMessageView() - binding.avatarContainer.setOnClickListener { + binding?.avatarContainer?.setOnClickListener { router .pushController( RouterTransaction.with(ProfileController()) @@ -495,7 +497,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { } private fun themeSwitchPreferences() { - binding.run { + binding?.run { listOf( settingsScreenLock, settingsScreenSecurity, @@ -508,7 +510,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { } private fun themeCategories() { - binding.run { + binding?.run { listOf( settingsNotificationsCategory, settingsAboutCategory, @@ -539,54 +541,62 @@ class SettingsController : BaseController(R.layout.controller_settings) { if (ApplicationWideMessageHolder.getInstance().messageType != null) { when (ApplicationWideMessageHolder.getInstance().messageType) { ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED -> { - binding.messageText.setTextColor( - viewThemeUtils.getScheme(binding.messageText.context).primary - ) - binding.messageText.text = resources!!.getString(R.string.nc_settings_account_updated) - binding.messageView.visibility = View.VISIBLE + binding?.messageText?.let { + it.setTextColor( + viewThemeUtils.getScheme(it.context).primary + ) + it.text = resources!!.getString(R.string.nc_settings_account_updated) + binding?.messageView?.visibility = View.VISIBLE + } } ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK -> { - binding.messageText.setTextColor(resources!!.getColor(R.color.nc_darkRed)) - binding.messageText.text = resources!!.getString(R.string.nc_settings_wrong_account) - binding.messageView.visibility = View.VISIBLE - binding.messageText.setTextColor( - viewThemeUtils.getScheme(binding.messageText.context).primary - ) - binding.messageText.text = resources!!.getString(R.string.nc_Server_account_imported) - binding.messageView.visibility = View.VISIBLE + binding?.messageText?.let { + it.setTextColor(resources!!.getColor(R.color.nc_darkRed)) + it.text = resources!!.getString(R.string.nc_settings_wrong_account) + binding?.messageView?.visibility = View.VISIBLE + it.setTextColor( + viewThemeUtils.getScheme(it.context).primary + ) + it.text = resources!!.getString(R.string.nc_Server_account_imported) + binding?.messageView?.visibility = View.VISIBLE + } } ApplicationWideMessageHolder.MessageType.ACCOUNT_WAS_IMPORTED -> { - binding.messageText.setTextColor( - viewThemeUtils.getScheme(binding.messageText.context).primary - ) - binding.messageText.text = resources!!.getString(R.string.nc_Server_account_imported) - binding.messageView.visibility = View.VISIBLE + binding?.messageText?.let { + it.setTextColor( + viewThemeUtils.getScheme(it.context).primary + ) + it.text = resources!!.getString(R.string.nc_Server_account_imported) + binding?.messageView?.visibility = View.VISIBLE + } } ApplicationWideMessageHolder.MessageType.FAILED_TO_IMPORT_ACCOUNT -> { - binding.messageText.setTextColor(resources!!.getColor(R.color.nc_darkRed)) - binding.messageText.text = resources!!.getString(R.string.nc_server_failed_to_import_account) - binding.messageView.visibility = View.VISIBLE + binding?.messageText?.let { + it.setTextColor(resources!!.getColor(R.color.nc_darkRed)) + it.text = resources!!.getString(R.string.nc_server_failed_to_import_account) + binding?.messageView?.visibility = View.VISIBLE + } } - else -> binding.messageView.visibility = View.GONE + else -> binding?.messageView?.visibility = View.GONE } - ApplicationWideMessageHolder.getInstance().setMessageType(null) - binding.messageView.animate() - .translationY(0f) - .alpha(0.0f) - .setDuration(DURATION) - .setStartDelay(START_DELAY) - .setListener(object : AnimatorListenerAdapter() { + ApplicationWideMessageHolder.getInstance().messageType = null + binding?.messageView?.animate() + ?.translationY(0f) + ?.alpha(0.0f) + ?.setDuration(DURATION) + ?.setStartDelay(START_DELAY) + ?.setListener(object : AnimatorListenerAdapter() { override fun onAnimationEnd(animation: Animator) { super.onAnimationEnd(animation) - binding.messageView.visibility = View.GONE + binding?.messageView?.visibility = View.GONE } }) } else { - binding.messageView.visibility = View.GONE + binding?.messageView?.visibility = View.GONE } } @@ -614,7 +624,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { if ((!TextUtils.isEmpty(displayName) && !(displayName == currentUser!!.displayName))) { currentUser!!.displayName = displayName userManager.updateOrCreateUser(currentUser!!) - binding.displayNameText.text = currentUser!!.displayName + binding?.displayNameText?.text = currentUser!!.displayName } }, { dispose(profileQueryDisposable) }, @@ -625,74 +635,74 @@ class SettingsController : BaseController(R.layout.controller_settings) { private fun setupServerAgeWarning() { when { CapabilitiesUtilNew.isServerEOL(currentUser!!) -> { - binding.serverAgeWarningText.setTextColor(ContextCompat.getColor((context)!!, R.color.nc_darkRed)) - binding.serverAgeWarningText.setText(R.string.nc_settings_server_eol) - binding.serverAgeWarningIcon.setColorFilter( - ContextCompat.getColor((context)!!, R.color.nc_darkRed), + binding?.serverAgeWarningText?.setTextColor(ContextCompat.getColor((context)!!, R.color.nc_darkRed)) + binding?.serverAgeWarningText?.setText(R.string.nc_settings_server_eol) + binding?.serverAgeWarningIcon?.setColorFilter( + ContextCompat.getColor((context), R.color.nc_darkRed), PorterDuff.Mode.SRC_IN ) } CapabilitiesUtilNew.isServerAlmostEOL(currentUser!!) -> { - binding.serverAgeWarningText.setTextColor( - ContextCompat.getColor((context)!!, R.color.nc_darkYellow) + binding?.serverAgeWarningText?.setTextColor( + ContextCompat.getColor((context), R.color.nc_darkYellow) ) - binding.serverAgeWarningText.setText(R.string.nc_settings_server_almost_eol) - binding.serverAgeWarningIcon.setColorFilter( - ContextCompat.getColor((context)!!, R.color.nc_darkYellow), + binding?.serverAgeWarningText?.setText(R.string.nc_settings_server_almost_eol) + binding?.serverAgeWarningIcon?.setColorFilter( + ContextCompat.getColor((context), R.color.nc_darkYellow), PorterDuff.Mode.SRC_IN ) } else -> { - binding.serverAgeWarningTextCard.visibility = View.GONE + binding?.serverAgeWarningTextCard?.visibility = View.GONE } } } private fun setupCheckables() { - (binding.settingsScreenSecurity.findViewById(R.id.mp_checkable) as Checkable).isChecked = + (binding?.settingsScreenSecurity?.findViewById(R.id.mp_checkable) as Checkable).isChecked = appPreferences.isScreenSecured if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - (binding.settingsIncognitoKeyboard.findViewById(R.id.mp_checkable) as Checkable).isChecked = + (binding?.settingsIncognitoKeyboard?.findViewById(R.id.mp_checkable) as Checkable).isChecked = appPreferences.isKeyboardIncognito } - (binding.settingsIncognitoKeyboard.findViewById(R.id.mp_checkable) as Checkable).isChecked = + (binding?.settingsIncognitoKeyboard?.findViewById(R.id.mp_checkable) as Checkable).isChecked = appPreferences.isKeyboardIncognito if (CapabilitiesUtilNew.isReadStatusAvailable(userManager.currentUser.blockingGet())) { - (binding.settingsReadPrivacy.findViewById(R.id.mp_checkable) as Checkable).isChecked = + (binding?.settingsReadPrivacy?.findViewById(R.id.mp_checkable) as Checkable).isChecked = !CapabilitiesUtilNew.isReadStatusPrivate(currentUser!!) } else { - binding.settingsReadPrivacy.visibility = View.GONE + binding?.settingsReadPrivacy?.visibility = View.GONE } - (binding.settingsPhoneBookIntegration.findViewById(R.id.mp_checkable) as Checkable).isChecked = + (binding?.settingsPhoneBookIntegration?.findViewById(R.id.mp_checkable) as Checkable).isChecked = appPreferences.isPhoneBookIntegrationEnabled } private fun setupScreenLockSetting() { val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager if (keyguardManager.isKeyguardSecure) { - binding.settingsScreenLock.isEnabled = true - binding.settingsScreenLockTimeout.isEnabled = true - (binding.settingsScreenLock.findViewById(R.id.mp_checkable) as Checkable).isChecked = + binding?.settingsScreenLock?.isEnabled = true + binding?.settingsScreenLockTimeout?.isEnabled = true + (binding?.settingsScreenLock?.findViewById(R.id.mp_checkable) as Checkable).isChecked = appPreferences.isScreenLocked - binding.settingsScreenLockTimeout.isEnabled = appPreferences.isScreenLocked + binding?.settingsScreenLockTimeout?.isEnabled = appPreferences.isScreenLocked if (appPreferences.isScreenLocked) { - binding.settingsScreenLockTimeout.alpha = ENABLED_ALPHA + binding?.settingsScreenLockTimeout?.alpha = ENABLED_ALPHA } else { - binding.settingsScreenLockTimeout.alpha = DISABLED_ALPHA + binding?.settingsScreenLockTimeout?.alpha = DISABLED_ALPHA } - binding.settingsScreenLock.alpha = ENABLED_ALPHA + binding?.settingsScreenLock?.alpha = ENABLED_ALPHA } else { - binding.settingsScreenLock.isEnabled = false - binding.settingsScreenLockTimeout.isEnabled = false + binding?.settingsScreenLock?.isEnabled = false + binding?.settingsScreenLockTimeout?.isEnabled = false appPreferences.removeScreenLock() appPreferences.removeScreenLockTimeout() - (binding.settingsScreenLock.findViewById(R.id.mp_checkable) as Checkable).isChecked = false - binding.settingsScreenLock.alpha = DISABLED_ALPHA - binding.settingsScreenLockTimeout.alpha = DISABLED_ALPHA + (binding?.settingsScreenLock?.findViewById(R.id.mp_checkable) as Checkable).isChecked = false + binding?.settingsScreenLock?.alpha = DISABLED_ALPHA + binding?.settingsScreenLockTimeout?.alpha = DISABLED_ALPHA } } @@ -710,40 +720,40 @@ class SettingsController : BaseController(R.layout.controller_settings) { } private fun hideProxySettings() { - appPreferences?.removeProxyHost() - appPreferences?.removeProxyPort() - appPreferences?.removeProxyCredentials() - appPreferences?.removeProxyUsername() - appPreferences?.removeProxyPassword() - binding.settingsScreen.findViewById(R.id.settings_proxy_host_edit).visibility = View.GONE - binding.settingsScreen.findViewById(R.id.settings_proxy_port_edit).visibility = View.GONE - binding.settingsScreen.findViewById(R.id.settings_proxy_use_credentials).visibility = + appPreferences.removeProxyHost() + appPreferences.removeProxyPort() + appPreferences.removeProxyCredentials() + appPreferences.removeProxyUsername() + appPreferences.removeProxyPassword() + binding?.settingsScreen?.findViewById(R.id.settings_proxy_host_edit)?.visibility = View.GONE + binding?.settingsScreen?.findViewById(R.id.settings_proxy_port_edit)?.visibility = View.GONE + binding?.settingsScreen?.findViewById(R.id.settings_proxy_use_credentials)?.visibility = View.GONE - binding.settingsScreen.findViewById(R.id.settings_proxy_username_edit).visibility = View.GONE - binding.settingsScreen.findViewById(R.id.settings_proxy_password_edit).visibility = View.GONE + binding?.settingsScreen?.findViewById(R.id.settings_proxy_username_edit)?.visibility = View.GONE + binding?.settingsScreen?.findViewById(R.id.settings_proxy_password_edit)?.visibility = View.GONE } private fun showProxySettings() { - binding.settingsScreen.findViewById(R.id.settings_proxy_host_edit).visibility = + binding?.settingsScreen?.findViewById(R.id.settings_proxy_host_edit)?.visibility = View.VISIBLE - binding.settingsScreen.findViewById(R.id.settings_proxy_port_edit).visibility = + binding?.settingsScreen?.findViewById(R.id.settings_proxy_port_edit)?.visibility = View.VISIBLE - binding.settingsScreen.findViewById(R.id.settings_proxy_use_credentials).visibility = + binding?.settingsScreen?.findViewById(R.id.settings_proxy_use_credentials)?.visibility = View.VISIBLE } private fun showProxyCredentials() { - binding.settingsScreen.findViewById(R.id.settings_proxy_username_edit).visibility = + binding?.settingsScreen?.findViewById(R.id.settings_proxy_username_edit)?.visibility = View.VISIBLE - binding.settingsScreen.findViewById(R.id.settings_proxy_password_edit).visibility = + binding?.settingsScreen?.findViewById(R.id.settings_proxy_password_edit)?.visibility = View.VISIBLE } private fun hideProxyCredentials() { - appPreferences?.removeProxyUsername() - appPreferences?.removeProxyPassword() - binding.settingsScreen.findViewById(R.id.settings_proxy_username_edit).visibility = View.GONE - binding.settingsScreen.findViewById(R.id.settings_proxy_password_edit).visibility = View.GONE + appPreferences.removeProxyUsername() + appPreferences.removeProxyPassword() + binding?.settingsScreen?.findViewById(R.id.settings_proxy_username_edit)?.visibility = View.GONE + binding?.settingsScreen?.findViewById(R.id.settings_proxy_password_edit)?.visibility = View.GONE } private fun dispose(disposable: Disposable?) { @@ -784,7 +794,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { checkForPhoneNumber() } else { appPreferences.setPhoneBookIntegration(false) - (binding.settingsPhoneBookIntegration.findViewById(R.id.mp_checkable) as Checkable).isChecked = + (binding?.settingsPhoneBookIntegration?.findViewById(R.id.mp_checkable) as Checkable).isChecked = appPreferences.isPhoneBookIntegrationEnabled Toast.makeText( context, @@ -802,11 +812,11 @@ class SettingsController : BaseController(R.layout.controller_settings) { private inner class ScreenLockListener : OnPreferenceValueChangedListener { override fun onChanged(newValue: Boolean) { - binding.settingsScreenLockTimeout.isEnabled = newValue + binding?.settingsScreenLockTimeout?.isEnabled = newValue if (newValue) { - binding.settingsScreenLockTimeout.alpha = ENABLED_ALPHA + binding?.settingsScreenLockTimeout?.alpha = ENABLED_ALPHA } else { - binding.settingsScreenLockTimeout.alpha = DISABLED_ALPHA + binding?.settingsScreenLockTimeout?.alpha = DISABLED_ALPHA } } } @@ -844,11 +854,11 @@ class SettingsController : BaseController(R.layout.controller_settings) { } else { when (newValue) { "HTTP" -> - binding.settingsProxyPortEdit.value = "3128" + binding?.settingsProxyPortEdit?.value = "3128" "DIRECT" -> - binding.settingsProxyPortEdit.value = "8080" + binding?.settingsProxyPortEdit?.value = "8080" "SOCKS" -> - binding.settingsProxyPortEdit.value = "1080" + binding?.settingsProxyPortEdit?.value = "1080" else -> { } } @@ -1031,7 +1041,7 @@ class SettingsController : BaseController(R.layout.controller_settings) { override fun onError(e: Throwable) { appPreferences.setReadPrivacy(!newValue) - (binding.settingsReadPrivacy.findViewById(R.id.mp_checkable) as Checkable).isChecked = + (binding?.settingsReadPrivacy?.findViewById(R.id.mp_checkable) as Checkable).isChecked = !newValue } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt index 8bb1c5cc4..36bf20a06 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt @@ -63,7 +63,7 @@ class SwitchAccountController(args: Bundle? = null) : R.layout.controller_generic_rv, args ) { - private val binding: ControllerGenericRvBinding by viewBinding(ControllerGenericRvBinding::bind) + private val binding: ControllerGenericRvBinding? by viewBinding(ControllerGenericRvBinding::bind) @Inject lateinit var userManager: UserManager @@ -118,7 +118,7 @@ class SwitchAccountController(args: Bundle? = null) : override fun onViewBound(view: View) { super.onViewBound(view) - binding.swipeRefreshLayout.isEnabled = false + binding?.swipeRefreshLayout?.isEnabled = false actionBar?.show() @@ -167,10 +167,10 @@ class SwitchAccountController(args: Bundle? = null) : private fun prepareViews() { val layoutManager: LinearLayoutManager = SmoothScrollLinearLayoutManager(activity) - binding.recyclerView.layoutManager = layoutManager - binding.recyclerView.setHasFixedSize(true) - binding.recyclerView.adapter = adapter - binding.swipeRefreshLayout.isEnabled = false + binding?.recyclerView?.layoutManager = layoutManager + binding?.recyclerView?.setHasFixedSize(true) + binding?.recyclerView?.adapter = adapter + binding?.swipeRefreshLayout?.isEnabled = false } private fun reauthorizeFromImport(account: Account?) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt index 1f7ce3b65..25e2d09c2 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/WebViewLoginController.kt @@ -82,7 +82,7 @@ class WebViewLoginController(args: Bundle? = null) : BaseController( R.layout.controller_web_view_login, args ) { - private val binding: ControllerWebViewLoginBinding by viewBinding(ControllerWebViewLoginBinding::bind) + private val binding: ControllerWebViewLoginBinding? by viewBinding(ControllerWebViewLoginBinding::bind) @Inject lateinit var userManager: UserManager @@ -137,25 +137,25 @@ class WebViewLoginController(args: Bundle? = null) : BaseController( actionBar?.hide() assembledPrefix = resources!!.getString(R.string.nc_talk_login_scheme) + PROTOCOL_SUFFIX + "login/" - binding.webview.settings.allowFileAccess = false - binding.webview.settings.allowFileAccessFromFileURLs = false - binding.webview.settings.javaScriptEnabled = true - binding.webview.settings.javaScriptCanOpenWindowsAutomatically = false - binding.webview.settings.domStorageEnabled = true - binding.webview.settings.setUserAgentString(webLoginUserAgent) - binding.webview.settings.saveFormData = false - binding.webview.settings.savePassword = false - binding.webview.settings.setRenderPriority(WebSettings.RenderPriority.HIGH) - binding.webview.clearCache(true) - binding.webview.clearFormData() - binding.webview.clearHistory() + binding?.webview?.settings?.allowFileAccess = false + binding?.webview?.settings?.allowFileAccessFromFileURLs = false + binding?.webview?.settings?.javaScriptEnabled = true + binding?.webview?.settings?.javaScriptCanOpenWindowsAutomatically = false + binding?.webview?.settings?.domStorageEnabled = true + binding?.webview?.settings?.setUserAgentString(webLoginUserAgent) + binding?.webview?.settings?.saveFormData = false + binding?.webview?.settings?.savePassword = false + binding?.webview?.settings?.setRenderPriority(WebSettings.RenderPriority.HIGH) + binding?.webview?.clearCache(true) + binding?.webview?.clearFormData() + binding?.webview?.clearHistory() WebView.clearClientCertPreferences(null) - webViewFidoBridge = WebViewFidoBridge.createInstanceForWebView(activity as AppCompatActivity?, binding.webview) + webViewFidoBridge = WebViewFidoBridge.createInstanceForWebView(activity as AppCompatActivity?, binding?.webview) CookieSyncManager.createInstance(activity) android.webkit.CookieManager.getInstance().removeAllCookies(null) val headers: MutableMap = HashMap() headers.put("OCS-APIRequest", "true") - binding.webview.webViewClient = object : WebViewClient() { + binding?.webview?.webViewClient = object : WebViewClient() { private var basePageLoaded = false override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? { webViewFidoBridge?.delegateShouldInterceptRequest(view, request) @@ -181,24 +181,24 @@ class WebViewLoginController(args: Bundle? = null) : BaseController( try { loginStep++ if (!basePageLoaded) { - binding.progressBar.visibility = View.GONE - binding.webview.visibility = View.VISIBLE + binding?.progressBar?.visibility = View.GONE + binding?.webview?.visibility = View.VISIBLE basePageLoaded = true } if (!TextUtils.isEmpty(username)) { if (loginStep == 1) { - binding.webview.loadUrl( + binding?.webview?.loadUrl( "javascript: {document.getElementsByClassName('login')[0].click(); };" ) } else if (!automatedLoginAttempted) { automatedLoginAttempted = true if (TextUtils.isEmpty(password)) { - binding.webview.loadUrl( + binding?.webview?.loadUrl( "javascript:var justStore = document.getElementById('user').value = '$username';" ) } else { - binding.webview.loadUrl( + binding?.webview?.loadUrl( "javascript: {" + "document.getElementById('user').value = '" + username + "';" + "document.getElementById('password').value = '" + password + "';" + @@ -308,7 +308,7 @@ class WebViewLoginController(args: Bundle? = null) : BaseController( super.onReceivedError(view, errorCode, description, failingUrl) } } - binding.webview.loadUrl("$baseUrl/index.php/login/flow", headers) + binding?.webview?.loadUrl("$baseUrl/index.php/login/flow", headers) } private fun dispose() { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt index 5d5565281..6ad338fdb 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt @@ -62,7 +62,7 @@ class EntryMenuController(args: Bundle) : R.layout.controller_entry_menu, args ) { - private val binding: ControllerEntryMenuBinding by viewBinding(ControllerEntryMenuBinding::bind) + private val binding: ControllerEntryMenuBinding? by viewBinding(ControllerEntryMenuBinding::bind) @Inject lateinit var eventBus: EventBus @@ -87,11 +87,11 @@ class EntryMenuController(args: Bundle) : if (ApplicationWideMessageHolder.MessageType.CALL_PASSWORD_WRONG == ApplicationWideMessageHolder.getInstance().messageType ) { - binding.textInputLayout.error = resources?.getString(R.string.nc_wrong_password) - ApplicationWideMessageHolder.getInstance().setMessageType(null) - if (binding.okButton.isEnabled) { - binding.okButton.isEnabled = false - binding.okButton.alpha = OPACITY_BUTTON_DISABLED + binding?.textInputLayout?.error = resources?.getString(R.string.nc_wrong_password) + ApplicationWideMessageHolder.getInstance().messageType = null + if (binding?.okButton?.isEnabled == true) { + binding?.okButton?.isEnabled = false + binding?.okButton?.alpha = OPACITY_BUTTON_DISABLED } } } @@ -100,13 +100,13 @@ class EntryMenuController(args: Bundle) : super.onViewBound(view) if (conversation != null && operation === ConversationOperationEnum.OPS_CODE_RENAME_ROOM) { - binding.textEdit.setText(conversation!!.name) + binding?.textEdit?.setText(conversation!!.name) } - binding.textEdit.setOnEditorActionListener { v, actionId, event -> + binding?.textEdit?.setOnEditorActionListener { v, actionId, event -> @Suppress("IMPLICIT_BOXING_IN_IDENTITY_EQUALS") - if (actionId === EditorInfo.IME_ACTION_DONE && binding.okButton.isEnabled) { - binding.okButton.callOnClick() + if (actionId === EditorInfo.IME_ACTION_DONE && binding?.okButton?.isEnabled == true) { + binding?.okButton?.callOnClick() return@setOnEditorActionListener true } false @@ -118,57 +118,59 @@ class EntryMenuController(args: Bundle) : when (operation) { ConversationOperationEnum.OPS_CODE_INVITE_USERS, ConversationOperationEnum.OPS_CODE_RENAME_ROOM -> { labelText = resources!!.getString(R.string.nc_call_name) - binding.textEdit.inputType = InputType.TYPE_CLASS_TEXT - binding.smileyButton.visibility = View.VISIBLE - emojiPopup = EmojiPopup( - rootView = view, - editText = binding.textEdit, - onEmojiPopupShownListener = { - viewThemeUtils.platform.colorImageView(binding.smileyButton) - }, - onEmojiPopupDismissListener = { - binding.smileyButton.imageTintList = ColorStateList.valueOf( - ResourcesCompat.getColor(resources!!, R.color.medium_emphasis_text, context.theme) - ) - }, - onEmojiClickListener = { - binding.textEdit.editableText.append(" ") - } - ) + binding?.textEdit?.inputType = InputType.TYPE_CLASS_TEXT + binding?.smileyButton?.visibility = View.VISIBLE + emojiPopup = binding?.let { + EmojiPopup( + rootView = view, + editText = it.textEdit, + onEmojiPopupShownListener = { + viewThemeUtils.platform.colorImageView(it.smileyButton) + }, + onEmojiPopupDismissListener = { + it.smileyButton.imageTintList = ColorStateList.valueOf( + ResourcesCompat.getColor(resources!!, R.color.medium_emphasis_text, context.theme) + ) + }, + onEmojiClickListener = { + binding?.textEdit?.editableText?.append(" ") + } + ) + } } ConversationOperationEnum.OPS_CODE_JOIN_ROOM -> { // 99 is joining a conversation via password labelText = resources!!.getString(R.string.nc_password) - binding.textEdit.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD + binding?.textEdit?.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_PASSWORD } ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM -> { labelText = resources!!.getString(R.string.nc_conversation_link) - binding.textEdit.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI + binding?.textEdit?.inputType = InputType.TYPE_CLASS_TEXT or InputType.TYPE_TEXT_VARIATION_URI } else -> { } } if (PASSWORD_ENTRY_OPERATIONS.contains(operation)) { - binding.textInputLayout.endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE + binding?.textInputLayout?.endIconMode = TextInputLayout.END_ICON_PASSWORD_TOGGLE } else { - binding.textInputLayout.endIconMode = TextInputLayout.END_ICON_NONE + binding?.textInputLayout?.endIconMode = TextInputLayout.END_ICON_NONE } - viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout) - viewThemeUtils.material.colorMaterialButtonText(binding.okButton) + binding?.textInputLayout?.let { viewThemeUtils.material.colorTextInputLayout(it) } + binding?.okButton?.let { viewThemeUtils.material.colorMaterialButtonText(it) } - binding.textInputLayout.hint = labelText - binding.textInputLayout.requestFocus() + binding?.textInputLayout?.hint = labelText + binding?.textInputLayout?.requestFocus() - binding.smileyButton.setOnClickListener { onSmileyClick() } - binding.okButton.setOnClickListener { onOkButtonClick() } + binding?.smileyButton?.setOnClickListener { onSmileyClick() } + binding?.okButton?.setOnClickListener { onOkButtonClick() } } private fun textEditAddChangedListener() { - binding.textEdit.addTextChangedListener(object : TextWatcher { + binding?.textEdit?.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { // unused atm } @@ -181,46 +183,46 @@ class EntryMenuController(args: Bundle) : if (!TextUtils.isEmpty(s)) { if (operation === ConversationOperationEnum.OPS_CODE_RENAME_ROOM) { if (conversation!!.name == null || !conversation!!.name.equals(s.toString())) { - if (!binding.okButton.isEnabled) { - binding.okButton.isEnabled = true - binding.okButton.alpha = OPACITY_ENABLED + if (!binding?.okButton?.isEnabled!!) { + binding?.okButton?.isEnabled = true + binding?.okButton?.alpha = OPACITY_ENABLED } - binding.textInputLayout.isErrorEnabled = false + binding?.textInputLayout?.isErrorEnabled = false } else { - if (binding.okButton.isEnabled) { - binding.okButton.isEnabled = false - binding.okButton.alpha = OPACITY_DISABLED + if (binding?.okButton?.isEnabled == true) { + binding?.okButton?.isEnabled = false + binding?.okButton?.alpha = OPACITY_DISABLED } - binding.textInputLayout.error = resources?.getString(R.string.nc_call_name_is_same) + binding?.textInputLayout?.error = resources?.getString(R.string.nc_call_name_is_same) } } else if (operation !== ConversationOperationEnum.OPS_CODE_GET_AND_JOIN_ROOM) { - if (!binding.okButton.isEnabled) { - binding.okButton.isEnabled = true - binding.okButton.alpha = OPACITY_ENABLED + if (!binding?.okButton?.isEnabled!!) { + binding?.okButton?.isEnabled = true + binding?.okButton?.alpha = OPACITY_ENABLED } - binding.textInputLayout.isErrorEnabled = false + binding?.textInputLayout?.isErrorEnabled = false } else if ( - UriUtils.hasHttpProtocollPrefixed(binding.textEdit.text.toString()) && - binding.textEdit.text.toString().contains("/call/") + UriUtils.hasHttpProtocollPrefixed(binding?.textEdit?.text.toString()) && + binding?.textEdit?.text.toString().contains("/call/") ) { - if (!binding.okButton.isEnabled) { - binding.okButton.isEnabled = true - binding.okButton.alpha = OPACITY_ENABLED + if (!binding?.okButton?.isEnabled!!) { + binding?.okButton?.isEnabled = true + binding?.okButton?.alpha = OPACITY_ENABLED } - binding.textInputLayout.isErrorEnabled = false + binding?.textInputLayout?.isErrorEnabled = false } else { - if (binding.okButton.isEnabled) { - binding.okButton.isEnabled = false - binding.okButton.alpha = OPACITY_DISABLED + if (binding?.okButton?.isEnabled == true) { + binding?.okButton?.isEnabled = false + binding?.okButton?.alpha = OPACITY_DISABLED } - binding.textInputLayout.error = resources?.getString(R.string.nc_wrong_link) + binding?.textInputLayout?.error = resources?.getString(R.string.nc_wrong_link) } } else { - if (binding.okButton.isEnabled) { - binding.okButton.isEnabled = false - binding.okButton.alpha = OPACITY_DISABLED + if (binding?.okButton?.isEnabled == true) { + binding?.okButton?.isEnabled = false + binding?.okButton?.alpha = OPACITY_DISABLED } - binding.textInputLayout.isErrorEnabled = false + binding?.textInputLayout?.isErrorEnabled = false } } }) @@ -238,7 +240,7 @@ class EntryMenuController(args: Bundle) : operation !== ConversationOperationEnum.OPS_CODE_INVITE_USERS ) { val bundle = Bundle() - conversation!!.name = binding.textEdit.text.toString() + conversation!!.name = binding?.textEdit?.text.toString() bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation)) bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, operation) router.pushController( @@ -249,14 +251,14 @@ class EntryMenuController(args: Bundle) : } else if (operation !== ConversationOperationEnum.OPS_CODE_INVITE_USERS) { val bundle = Bundle() bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, operation) - bundle.putString(BundleKeys.KEY_CALL_URL, binding.textEdit.text.toString()) + bundle.putString(BundleKeys.KEY_CALL_URL, binding?.textEdit?.text.toString()) router.pushController( RouterTransaction.with(OperationsMenuController(bundle)) .pushChangeHandler(HorizontalChangeHandler()) .popChangeHandler(HorizontalChangeHandler()) ) } else if (operation === ConversationOperationEnum.OPS_CODE_INVITE_USERS) { - originalBundle.putString(BundleKeys.KEY_CONVERSATION_NAME, binding.textEdit.text.toString()) + originalBundle.putString(BundleKeys.KEY_CONVERSATION_NAME, binding?.textEdit?.text.toString()) router.pushController( RouterTransaction.with( OperationsMenuController( @@ -273,12 +275,12 @@ class EntryMenuController(args: Bundle) : val bundle = Bundle() bundle.putParcelable(BundleKeys.KEY_ROOM, Parcels.wrap(conversation)) bundle.putString(BundleKeys.KEY_CALL_URL, callUrl) - bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, binding.textEdit.text.toString()) + bundle.putString(BundleKeys.KEY_CONVERSATION_PASSWORD, binding?.textEdit?.text.toString()) bundle.putSerializable(BundleKeys.KEY_OPERATION_CODE, operation) if (originalBundle.containsKey(BundleKeys.KEY_SERVER_CAPABILITIES)) { bundle.putParcelable( BundleKeys.KEY_SERVER_CAPABILITIES, - originalBundle.getParcelable(BundleKeys.KEY_SERVER_CAPABILITIES) + originalBundle.getParcelable(BundleKeys.KEY_SERVER_CAPABILITIES) ) } router.pushController( diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt index 98a983f41..1fde700a1 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt @@ -83,7 +83,7 @@ class OperationsMenuController(args: Bundle) : BaseController( R.layout.controller_operations_menu, args ) { - private val binding: ControllerOperationsMenuBinding by viewBinding(ControllerOperationsMenuBinding::bind) + private val binding: ControllerOperationsMenuBinding? by viewBinding(ControllerOperationsMenuBinding::bind) @Inject lateinit var ncApi: NcApi @@ -117,7 +117,7 @@ class OperationsMenuController(args: Bundle) : BaseController( sharedApplication!!.componentApplication.inject(this) currentUser = userManager.currentUser.blockingGet() - viewThemeUtils.platform.colorCircularProgressBar(binding.progressBar) + binding?.progressBar?.let { viewThemeUtils.platform.colorCircularProgressBar(it) } if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) { conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1) @@ -476,10 +476,10 @@ class OperationsMenuController(args: Bundle) : BaseController( @Suppress("Detekt.TooGenericExceptionCaught") private fun showResultImage(everythingOK: Boolean, isGuestSupportError: Boolean) { try { - binding.progressBar.visibility = View.GONE + binding?.progressBar?.visibility = View.GONE if (resources != null) { if (everythingOK) { - binding.resultImageView.setImageDrawable( + binding?.resultImageView?.setImageDrawable( DisplayUtils.getTintedDrawable( resources, R.drawable.ic_check_circle_black_24dp, @@ -487,7 +487,7 @@ class OperationsMenuController(args: Bundle) : BaseController( ) ) } else { - binding.resultImageView.setImageDrawable( + binding?.resultImageView?.setImageDrawable( DisplayUtils.getTintedDrawable( resources, R.drawable.ic_cancel_black_24dp, @@ -496,35 +496,35 @@ class OperationsMenuController(args: Bundle) : BaseController( ) } } - binding.resultImageView.visibility = View.VISIBLE + binding?.resultImageView?.visibility = View.VISIBLE if (everythingOK) { - binding.resultTextView.setText(R.string.nc_all_ok_operation) + binding?.resultTextView?.setText(R.string.nc_all_ok_operation) } else { - binding.resultTextView.setTextColor(resources!!.getColor(R.color.nc_darkRed)) + binding?.resultTextView?.setTextColor(resources!!.getColor(R.color.nc_darkRed)) if (!isGuestSupportError) { - binding.resultTextView.setText(R.string.nc_failed_to_perform_operation) + binding?.resultTextView?.setText(R.string.nc_failed_to_perform_operation) } else { - binding.resultTextView.setText(R.string.nc_failed_signaling_settings) - binding.webButton.setOnClickListener { + binding?.resultTextView?.setText(R.string.nc_failed_signaling_settings) + binding?.webButton?.setOnClickListener { val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(callUrl)) startActivity(browserIntent) } - binding.webButton.visibility = View.VISIBLE + binding?.webButton?.visibility = View.VISIBLE } } - binding.resultTextView.visibility = View.VISIBLE + binding?.resultTextView?.visibility = View.VISIBLE if (everythingOK) { - eventBus!!.post(ConversationsListFetchDataEvent()) + eventBus.post(ConversationsListFetchDataEvent()) } else { - binding.resultImageView.setImageDrawable( + binding?.resultImageView?.setImageDrawable( DisplayUtils.getTintedDrawable( resources, R.drawable.ic_cancel_black_24dp, R.color.nc_darkRed ) ) - binding.okButton.setOnClickListener { v: View? -> eventBus!!.post(ConversationsListFetchDataEvent()) } - binding.okButton.visibility = View.VISIBLE + binding?.okButton?.setOnClickListener { v: View? -> eventBus.post(ConversationsListFetchDataEvent()) } + binding?.okButton?.visibility = View.VISIBLE } } catch (npe: NullPointerException) { Log.i(TAG, "Controller already closed", npe) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/util/ControllerViewBindingDelegate.kt b/app/src/main/java/com/nextcloud/talk/controllers/util/ControllerViewBindingDelegate.kt index 67b6244ab..bb70b037d 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/util/ControllerViewBindingDelegate.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/util/ControllerViewBindingDelegate.kt @@ -25,13 +25,13 @@ import com.bluelinelabs.conductor.Controller import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty -fun Controller.viewBinding(bindingFactory: (View) -> T) = +fun Controller.viewBinding(bindingFactory: (View) -> T?) = ControllerViewBindingDelegate(this, bindingFactory) class ControllerViewBindingDelegate( controller: Controller, - private val viewBinder: (View) -> T -) : ReadOnlyProperty, LifecycleObserver { + private val viewBinder: (View) -> T? +) : ReadOnlyProperty, LifecycleObserver { private var binding: T? = null @@ -43,7 +43,7 @@ class ControllerViewBindingDelegate( }) } - override fun getValue(thisRef: Controller, property: KProperty<*>): T { - return binding ?: viewBinder(thisRef.view!!).also { binding = it } + override fun getValue(thisRef: Controller, property: KProperty <*>): T? { + return binding ?: thisRef.view?.let { viewBinder(it).also { binding = it } } } }