From 3a8a8d5b78282ec5339f4e83ab840a4d378773d7 Mon Sep 17 00:00:00 2001 From: ganfra Date: Tue, 15 Jun 2021 16:03:52 +0200 Subject: [PATCH] Dial pad: clean some code, remove useless method and allow cursor --- .../call/dialpad/CallDialPadBottomSheet.kt | 5 +- .../features/call/dialpad/DialPadFragment.kt | 166 +++++++++++------- .../call/transfer/CallTransferActivity.kt | 27 +-- .../call/transfer/CallTransferPagerAdapter.kt | 30 +--- 4 files changed, 123 insertions(+), 105 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt b/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt index 06b4dbfe7b..02e170d20c 100644 --- a/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/call/dialpad/CallDialPadBottomSheet.kt @@ -61,6 +61,7 @@ class CallDialPadBottomSheet : VectorBaseBottomSheetDialogFragment(R.id.dialpad_view) as DialpadView dialpadView.findViewById(R.id.dialpad_key_voicemail).isVisible = false - digits = dialpadView.digits as? DigitsEditText - digits?.isCursorVisible = cursorVisible - digits?.setTextColor(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_primary)) - dialpadView.findViewById(R.id.zero).setOnClickListener { append('0') } - if (enablePlus) { - dialpadView.findViewById(R.id.zero).setOnLongClickListener { - append('+') - true - } - } - dialpadView.findViewById(R.id.one).setOnClickListener { append('1') } - dialpadView.findViewById(R.id.two).setOnClickListener { append('2') } - dialpadView.findViewById(R.id.three).setOnClickListener { append('3') } - dialpadView.findViewById(R.id.four).setOnClickListener { append('4') } - dialpadView.findViewById(R.id.four).setOnClickListener { append('4') } - dialpadView.findViewById(R.id.five).setOnClickListener { append('5') } - dialpadView.findViewById(R.id.six).setOnClickListener { append('6') } - dialpadView.findViewById(R.id.seven).setOnClickListener { append('7') } - dialpadView.findViewById(R.id.eight).setOnClickListener { append('8') } - dialpadView.findViewById(R.id.nine).setOnClickListener { append('9') } + digits = dialpadView.digits as DigitsEditText + digits.isCursorVisible = cursorVisible + digits.inputType = InputType.TYPE_CLASS_PHONE + digits.keyListener = DialerKeyListener.getInstance() + digits.setTextColor(ThemeUtils.getColor(requireContext(), R.attr.vctr_content_primary)) + digits.addTextChangedListener(PhoneNumberFormattingTextWatcher(if (formatAsYouType) regionCode else "")) + digits.addTextChangedListener(this) + dialpadView.findViewById(R.id.zero).setOnClickListener { keyPressed(KeyEvent.KEYCODE_0, "0") } + dialpadView.findViewById(R.id.one).setOnClickListener { keyPressed(KeyEvent.KEYCODE_1,"1") } + dialpadView.findViewById(R.id.two).setOnClickListener { keyPressed(KeyEvent.KEYCODE_2,"2") } + dialpadView.findViewById(R.id.three).setOnClickListener { keyPressed(KeyEvent.KEYCODE_3,"3") } + dialpadView.findViewById(R.id.four).setOnClickListener { keyPressed(KeyEvent.KEYCODE_4,"4") } + dialpadView.findViewById(R.id.five).setOnClickListener { keyPressed(KeyEvent.KEYCODE_5,"5") } + dialpadView.findViewById(R.id.six).setOnClickListener { keyPressed(KeyEvent.KEYCODE_6,"6") } + dialpadView.findViewById(R.id.seven).setOnClickListener { keyPressed(KeyEvent.KEYCODE_7,"7") } + dialpadView.findViewById(R.id.eight).setOnClickListener { keyPressed(KeyEvent.KEYCODE_8,"8") } + dialpadView.findViewById(R.id.nine).setOnClickListener { keyPressed(KeyEvent.KEYCODE_9,"9") } if (enableStar) { - dialpadView.findViewById(R.id.star).setOnClickListener { append('*') } + dialpadView.findViewById(R.id.star).setOnClickListener { keyPressed(KeyEvent.KEYCODE_STAR,"*") } } else { dialpadView.findViewById(R.id.star).isVisible = false } if (enablePound) { - dialpadView.findViewById(R.id.pound).setOnClickListener { append('#') } + dialpadView.findViewById(R.id.pound).setOnClickListener { keyPressed(KeyEvent.KEYCODE_POUND,"#") } } else { dialpadView.findViewById(R.id.pound).isVisible = false } + if (enablePlus) { + dialpadView.findViewById(R.id.zero).setOnLongClickListener { + keyPressed(KeyEvent.KEYCODE_PLUS, "+") + true + } + } if (enableDelete) { - dialpadView.deleteButton.setOnClickListener { poll() } + dialpadView.deleteButton.setOnClickListener { keyPressed(KeyEvent.KEYCODE_DEL, null) } dialpadView.deleteButton.setOnLongClickListener { clear() true } - val tintColor = ThemeUtils.getColor(requireContext(), im.vector.app.R.attr.vctr_content_secondary) + val tintColor = ThemeUtils.getColor(requireContext(), R.attr.vctr_content_secondary) ImageViewCompat.setImageTintList(dialpadView.deleteButton, ColorStateList.valueOf(tintColor)) } else { dialpadView.deleteButton.isVisible = false } - - // if region code is null, no formatting is performed - formatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(if (formatAsYouType) regionCode else "") - val fabOk = view.findViewById(R.id.fab_ok) if (enableFabOk) { - fabOk.setOnClickListener { - callback?.onOkClicked(digits?.text.toString(), input) - } + fabOk.setOnClickListener { onOkClicked() } } else { fabOk.isVisible = false } - - digits?.setOnTextContextMenuClickListener { - val string = digits?.text.toString() - clear() - for (element in string) { - append(element) - } - } return view } + private fun onOkClicked() { + val rawInput = getRawInput() + if (rawInput.isEmpty()) { + val clipboard = (requireContext().getSystemService(Context.CLIPBOARD_SERVICE)) as? ClipboardManager + val textToPaste = clipboard?.primaryClip?.getItemAt(0)?.text ?: return + val formatted = formatNumber(textToPaste.toString()) + digits.setText(formatted) + digits.setSelection(digits.text!!.length) + } else { + val formatted = digits.text.toString() + callback?.onOkClicked(formatted, rawInput) + } + } + + fun getRawInput(): String { + return PhoneNumberUtils.normalizeNumber(digits.text.toString()) + } + override fun onSaveInstanceState(outState: Bundle) { super.onSaveInstanceState(outState) outState.putString(EXTRA_REGION_CODE, regionCode) @@ -145,40 +158,40 @@ class DialPadFragment : Fragment() { } } - private fun poll() { - if (input.isNotEmpty()) { - input = input.substring(0, input.length - 1) - formatter = PhoneNumberUtil.getInstance().getAsYouTypeFormatter(regionCode) - if (formatAsYouType) { - digits?.setText("") - for (c in input.toCharArray()) { - digits?.setText(formatter?.inputDigit(c)) - } - } else { - digits?.setText(input) - } + private fun keyPressed(keyCode: Int, digitString: String?) { + val event = KeyEvent(KeyEvent.ACTION_DOWN, keyCode) + // Disable cursor and enable it again after onKeyDown otherwise DigitsEditText force replacing cursor at the end + digits.isCursorVisible = false + digits.onKeyDown(keyCode, event) + digits.isCursorVisible = cursorVisible + digitString?.also { + callback?.onDigitAppended(it) } } private fun clear() { - formatter?.clear() - digits?.setText("") - input = "" + digits.setText("") } - private fun append(c: Char) { - callback?.onDigitAppended(c.toString()) - input += c - if (formatAsYouType) { - digits?.setText(formatter?.inputDigit(c)) + private fun formatNumber(dialString: String): String { + var number = PhoneNumberUtils.extractNetworkPortion(dialString) + // Also retrieve the post dial portion of the provided data, so that the entire dial + // string can be reconstituted later. + val postDial = PhoneNumberUtils.extractPostDialPortion(dialString) + if (TextUtils.isEmpty(number)) { + return "" + } + number = PhoneNumberUtils.formatNumber(number, null, regionCode) ?: number + return if (TextUtils.isEmpty(postDial)) { + number } else { - digits?.setText(input) + number + postDial } } interface Callback { - fun onOkClicked(formatted: String?, raw: String?) = Unit fun onDigitAppended(digit: String) = Unit + fun onOkClicked(formatted: String?, raw: String?) = Unit } companion object { @@ -193,4 +206,21 @@ class DialPadFragment : Fragment() { private const val DEFAULT_REGION_CODE = "US" } + + // Text watcher + + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + //Noop + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + //Noop + } + + override fun afterTextChanged(s: Editable) { + if (s.isEmpty()) { + digits.clearFocus() + } + } + } diff --git a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt index 7f59a1c89b..c80b21334a 100644 --- a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferActivity.kt @@ -79,24 +79,20 @@ class CallTransferActivity : VectorBaseActivity(), waitingView = views.waitingView.waitingView callTransferViewModel.observeViewEvents { - when (it) { + when (it) { is CallTransferViewEvents.Dismiss -> finish() CallTransferViewEvents.Loading -> showWaitingView() is CallTransferViewEvents.FailToTransfer -> showSnackbar(getString(R.string.call_transfer_failure)) } } - sectionsPagerAdapter = CallTransferPagerAdapter(this).register() + sectionsPagerAdapter = CallTransferPagerAdapter(this) views.callTransferViewPager.adapter = sectionsPagerAdapter - sectionsPagerAdapter.onDialPadOkClicked = { phoneNumber -> - val action = CallTransferAction.ConnectWithPhoneNumber(views.callTransferConsultCheckBox.isChecked, phoneNumber) - callTransferViewModel.handle(action) - } TabLayoutMediator(views.callTransferTabLayout, views.callTransferViewPager) { tab, position -> when (position) { - 0 -> tab.text = getString(R.string.call_transfer_users_tab_title) - 1 -> tab.text = getString(R.string.call_dial_pad_title) + CallTransferPagerAdapter.USER_LIST_INDEX -> tab.text = getString(R.string.call_transfer_users_tab_title) + CallTransferPagerAdapter.DIAL_PAD_INDEX -> tab.text = getString(R.string.call_dial_pad_title) } }.attach() configureToolbar(views.callTransferToolbar) @@ -106,10 +102,17 @@ class CallTransferActivity : VectorBaseActivity(), private fun setupConnectAction() { views.callTransferConnectAction.debouncedClicks { - val selectedUser = sectionsPagerAdapter.userListFragment?.getCurrentState()?.getSelectedMatrixId()?.firstOrNull() - if (selectedUser != null) { - val action = CallTransferAction.ConnectWithUserId(views.callTransferConsultCheckBox.isChecked, selectedUser) - callTransferViewModel.handle(action) + when (views.callTransferTabLayout.selectedTabPosition) { + CallTransferPagerAdapter.USER_LIST_INDEX -> { + val selectedUser = sectionsPagerAdapter.userListFragment?.getCurrentState()?.getSelectedMatrixId()?.firstOrNull() ?: return@debouncedClicks + val action = CallTransferAction.ConnectWithUserId(views.callTransferConsultCheckBox.isChecked, selectedUser) + callTransferViewModel.handle(action) + } + CallTransferPagerAdapter.DIAL_PAD_INDEX -> { + val phoneNumber = sectionsPagerAdapter.dialPadFragment?.getRawInput() ?: return@debouncedClicks + val action = CallTransferAction.ConnectWithPhoneNumber(views.callTransferConsultCheckBox.isChecked, phoneNumber) + callTransferViewModel.handle(action) + } } } } diff --git a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt index 1f2d3070dd..4f921c485e 100644 --- a/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt +++ b/vector/src/main/java/im/vector/app/features/call/transfer/CallTransferPagerAdapter.kt @@ -29,14 +29,17 @@ import im.vector.app.features.userdirectory.UserListFragmentArgs class CallTransferPagerAdapter( private val fragmentActivity: FragmentActivity -) : FragmentStateAdapter(fragmentActivity), Restorable { +) : FragmentStateAdapter(fragmentActivity) { + + companion object { + const val USER_LIST_INDEX = 0 + const val DIAL_PAD_INDEX = 1 + } val userListFragment: UserListFragment? - get() = findFragmentAtPosition(0) as? UserListFragment + get() = findFragmentAtPosition(USER_LIST_INDEX) as? UserListFragment val dialPadFragment: DialPadFragment? - get() = findFragmentAtPosition(1) as? DialPadFragment - - var onDialPadOkClicked: ((String) -> Unit)? = null + get() = findFragmentAtPosition(DIAL_PAD_INDEX) as? DialPadFragment override fun getItemCount() = 2 @@ -57,10 +60,9 @@ class CallTransferPagerAdapter( (fragment as DialPadFragment).apply { arguments = Bundle().apply { putBoolean(DialPadFragment.EXTRA_ENABLE_DELETE, true) - putBoolean(DialPadFragment.EXTRA_ENABLE_OK, true) + putBoolean(DialPadFragment.EXTRA_ENABLE_OK, false) putString(DialPadFragment.EXTRA_REGION_CODE, VectorLocale.applicationLocale.country) } - applyCallback() } } return fragment @@ -70,19 +72,5 @@ class CallTransferPagerAdapter( return fragmentActivity.supportFragmentManager.findFragmentByTag("f$position") } - override fun onSaveInstanceState(outState: Bundle) = Unit - override fun onRestoreInstanceState(savedInstanceState: Bundle?) { - dialPadFragment?.applyCallback() - } - - private fun DialPadFragment.applyCallback(): DialPadFragment { - callback = object : DialPadFragment.Callback { - override fun onOkClicked(formatted: String?, raw: String?) { - if (raw.isNullOrEmpty()) return - onDialPadOkClicked?.invoke(raw) - } - } - return this - } }