Migrate to ViewBindings (#1072) - WIP
This commit is contained in:
parent
706736273c
commit
dba65dcd22
|
@ -172,3 +172,6 @@ getSystemService\(Context
|
|||
|
||||
### Use DefaultSharedPreferences.getInstance() instead for better performance
|
||||
PreferenceManager\.getDefaultSharedPreferences==2
|
||||
|
||||
### Use ViewBindings
|
||||
findViewById
|
||||
|
|
|
@ -24,26 +24,27 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
|||
import com.google.android.material.snackbar.Snackbar
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.utils.toast
|
||||
|
||||
import im.vector.app.databinding.ActivityTestMaterialThemeBinding
|
||||
|
||||
// Rendering is not the same with VectorBaseActivity
|
||||
abstract class DebugMaterialThemeActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_test_material_theme)
|
||||
val views = ActivityTestMaterialThemeBinding.inflate(layoutInflater)
|
||||
setContentView(views.root)
|
||||
|
||||
debugShowSnackbar.setOnClickListener {
|
||||
Snackbar.make(debugMaterialCoordinator, "Snackbar!", Snackbar.LENGTH_SHORT)
|
||||
views.debugShowSnackbar.setOnClickListener {
|
||||
Snackbar.make(views.debugMaterialCoordinator, "Snackbar!", Snackbar.LENGTH_SHORT)
|
||||
.setAction("Action") { }
|
||||
.show()
|
||||
}
|
||||
|
||||
debugShowToast.setOnClickListener {
|
||||
views.debugShowToast.setOnClickListener {
|
||||
toast("Toast")
|
||||
}
|
||||
|
||||
debugShowDialog.setOnClickListener {
|
||||
views.debugShowDialog.setOnClickListener {
|
||||
AlertDialog.Builder(this)
|
||||
.setMessage("Dialog content")
|
||||
.setIcon(R.drawable.ic_settings_x)
|
||||
|
@ -53,7 +54,7 @@ abstract class DebugMaterialThemeActivity : AppCompatActivity() {
|
|||
.show()
|
||||
}
|
||||
|
||||
debugShowBottomSheet.setOnClickListener {
|
||||
views.debugShowBottomSheet.setOnClickListener {
|
||||
BottomSheetDialogFragment().show(supportFragmentManager, "TAG")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,15 +22,16 @@ import android.view.ViewGroup
|
|||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import im.vector.app.R
|
||||
|
||||
import im.vector.app.databinding.ActivityTestLinkifyBinding
|
||||
import im.vector.app.databinding.ActivityTestMaterialThemeBinding
|
||||
|
||||
class TestLinkifyActivity : AppCompatActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_test_linkify)
|
||||
|
||||
test_linkify_content_view.removeAllViews()
|
||||
val views = ActivityTestLinkifyBinding.inflate(layoutInflater)
|
||||
setContentView(views.root)
|
||||
views.testLinkifyContentView.removeAllViews()
|
||||
|
||||
listOf(
|
||||
"https://www.html5rocks.com/en/tutorials/webrtc/basics/ |",
|
||||
|
@ -79,7 +80,7 @@ class TestLinkifyActivity : AppCompatActivity() {
|
|||
)
|
||||
.forEach { textContent ->
|
||||
val item = LayoutInflater.from(this)
|
||||
.inflate(R.layout.item_test_linkify, test_linkify_content_view, false)
|
||||
.inflate(R.layout.item_test_linkify, views.testLinkifyContentView, false)
|
||||
|
||||
item.findViewById<TextView>(R.id.test_linkify_auto_text)
|
||||
?.apply {
|
||||
|
@ -115,7 +116,7 @@ class TestLinkifyActivity : AppCompatActivity() {
|
|||
// TODO Call VectorLinkify.addLinks(text)
|
||||
}
|
||||
|
||||
test_linkify_content_view.addView(item, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
views.testLinkifyContentView.addView(item, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,14 +21,18 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.databinding.FragmentGenericRecyclerBinding
|
||||
import org.matrix.android.sdk.api.crypto.getAllVerificationEmojis
|
||||
|
||||
|
||||
class DebugSasEmojiActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var views: FragmentGenericRecyclerBinding
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.fragment_generic_recycler)
|
||||
views = FragmentGenericRecyclerBinding.inflate(layoutInflater)
|
||||
setContentView(views.root)
|
||||
val controller = SasEmojiController()
|
||||
views.genericRecyclerView.configureWith(controller)
|
||||
controller.setData(SasState(getAllVerificationEmojis()))
|
||||
|
|
|
@ -21,7 +21,7 @@ import androidx.annotation.StringRes
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.app.R
|
||||
|
||||
import im.vector.app.databinding.DialogConfirmationWithReasonBinding
|
||||
|
||||
object ConfirmationDialogBuilder {
|
||||
|
||||
|
@ -33,25 +33,26 @@ object ConfirmationDialogBuilder {
|
|||
@StringRes reasonHintRes: Int,
|
||||
confirmation: (String?) -> Unit) {
|
||||
val layout = activity.layoutInflater.inflate(R.layout.dialog_confirmation_with_reason, null)
|
||||
layout.dialogConfirmationText.setText(confirmationRes)
|
||||
val views = DialogConfirmationWithReasonBinding.bind(layout)
|
||||
views.dialogConfirmationText.setText(confirmationRes)
|
||||
|
||||
layout.dialogReasonCheck.isVisible = askForReason
|
||||
layout.dialogReasonTextInputLayout.isVisible = askForReason
|
||||
views.dialogReasonCheck.isVisible = askForReason
|
||||
views.dialogReasonTextInputLayout.isVisible = askForReason
|
||||
|
||||
layout.dialogReasonCheck.setOnCheckedChangeListener { _, isChecked ->
|
||||
layout.dialogReasonTextInputLayout.isEnabled = isChecked
|
||||
views.dialogReasonCheck.setOnCheckedChangeListener { _, isChecked ->
|
||||
views.dialogReasonTextInputLayout.isEnabled = isChecked
|
||||
}
|
||||
if (askForReason && reasonHintRes != 0) {
|
||||
layout.dialogReasonInput.setHint(reasonHintRes)
|
||||
views.dialogReasonInput.setHint(reasonHintRes)
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(titleRes)
|
||||
.setView(layout)
|
||||
.setPositiveButton(positiveRes) { _, _ ->
|
||||
val reason = layout.dialogReasonInput.text.toString()
|
||||
val reason = views.dialogReasonInput.text.toString()
|
||||
.takeIf { askForReason }
|
||||
?.takeIf { layout.dialogReasonCheck.isChecked }
|
||||
?.takeIf { views.dialogReasonCheck.isChecked }
|
||||
?.takeIf { it.isNotBlank() }
|
||||
confirmation(reason)
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.google.android.material.textfield.TextInputLayout
|
|||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.showPassword
|
||||
import im.vector.app.core.platform.SimpleTextWatcher
|
||||
import im.vector.app.databinding.DialogExportE2eKeysBinding
|
||||
|
||||
class ExportKeysDialog {
|
||||
|
||||
|
@ -33,48 +34,45 @@ class ExportKeysDialog {
|
|||
|
||||
fun show(activity: Activity, exportKeyDialogListener: ExportKeyDialogListener) {
|
||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_export_e2e_keys, null)
|
||||
val views = DialogExportE2eKeysBinding.bind(dialogLayout)
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.encryption_export_room_keys)
|
||||
.setView(dialogLayout)
|
||||
|
||||
val passPhrase1EditText = dialogLayout.findViewById<TextInputEditText>(R.id.exportDialogEt)
|
||||
val passPhrase2EditText = dialogLayout.findViewById<TextInputEditText>(R.id.exportDialogEtConfirm)
|
||||
val passPhrase2Til = dialogLayout.findViewById<TextInputLayout>(R.id.exportDialogTilConfirm)
|
||||
val exportButton = dialogLayout.findViewById<Button>(R.id.exportDialogSubmit)
|
||||
val textWatcher = object : SimpleTextWatcher() {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
when {
|
||||
passPhrase1EditText.text.isNullOrEmpty() -> {
|
||||
exportButton.isEnabled = false
|
||||
passPhrase2Til.error = null
|
||||
views.exportDialogEt.text.isNullOrEmpty() -> {
|
||||
views.exportDialogSubmit.isEnabled = false
|
||||
views.exportDialogTilConfirm.error = null
|
||||
}
|
||||
passPhrase1EditText.text.toString() == passPhrase2EditText.text.toString() -> {
|
||||
exportButton.isEnabled = true
|
||||
passPhrase2Til.error = null
|
||||
views.exportDialogEt.text.toString() == views.exportDialogEtConfirm.text.toString() -> {
|
||||
views.exportDialogSubmit.isEnabled = true
|
||||
views.exportDialogTilConfirm.error = null
|
||||
}
|
||||
else -> {
|
||||
exportButton.isEnabled = false
|
||||
passPhrase2Til.error = activity.getString(R.string.passphrase_passphrase_does_not_match)
|
||||
views.exportDialogSubmit.isEnabled = false
|
||||
views.exportDialogTilConfirm.error = activity.getString(R.string.passphrase_passphrase_does_not_match)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
passPhrase1EditText.addTextChangedListener(textWatcher)
|
||||
passPhrase2EditText.addTextChangedListener(textWatcher)
|
||||
views.exportDialogEt.addTextChangedListener(textWatcher)
|
||||
views.exportDialogEtConfirm.addTextChangedListener(textWatcher)
|
||||
|
||||
val showPassword = dialogLayout.findViewById<ImageView>(R.id.exportDialogShowPassword)
|
||||
showPassword.setOnClickListener {
|
||||
passwordVisible = !passwordVisible
|
||||
passPhrase1EditText.showPassword(passwordVisible)
|
||||
passPhrase2EditText.showPassword(passwordVisible)
|
||||
views.exportDialogEt.showPassword(passwordVisible)
|
||||
views.exportDialogEtConfirm.showPassword(passwordVisible)
|
||||
showPassword.setImageResource(if (passwordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
|
||||
val exportDialog = builder.show()
|
||||
|
||||
exportButton.setOnClickListener {
|
||||
exportKeyDialogListener.onPassphrase(passPhrase1EditText.text.toString())
|
||||
views.exportDialogSubmit.setOnClickListener {
|
||||
exportKeyDialogListener.onPassphrase(views.exportDialogEt.text.toString())
|
||||
|
||||
exportDialog.dismiss()
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
package im.vector.app.core.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.DialogDeviceVerifyBinding
|
||||
import org.matrix.android.sdk.api.extensions.getFingerprintHumanReadable
|
||||
import org.matrix.android.sdk.internal.crypto.model.CryptoDeviceInfo
|
||||
|
||||
|
@ -27,6 +27,7 @@ object ManuallyVerifyDialog {
|
|||
|
||||
fun show(activity: Activity, cryptoDeviceInfo: CryptoDeviceInfo, onVerified: (() -> Unit)) {
|
||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_device_verify, null)
|
||||
val views = DialogDeviceVerifyBinding.bind(dialogLayout)
|
||||
val builder = AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.cross_signing_verify_by_text)
|
||||
.setView(dialogLayout)
|
||||
|
@ -35,17 +36,9 @@ object ManuallyVerifyDialog {
|
|||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
|
||||
dialogLayout.findViewById<TextView>(R.id.encrypted_device_info_device_name)?.let {
|
||||
it.text = cryptoDeviceInfo.displayName()
|
||||
}
|
||||
|
||||
dialogLayout.findViewById<TextView>(R.id.encrypted_device_info_device_id)?.let {
|
||||
it.text = cryptoDeviceInfo.deviceId
|
||||
}
|
||||
|
||||
dialogLayout.findViewById<TextView>(R.id.encrypted_device_info_device_key)?.let {
|
||||
it.text = cryptoDeviceInfo.getFingerprintHumanReadable()
|
||||
}
|
||||
views.encryptedDeviceInfoDeviceName.text = cryptoDeviceInfo.displayName()
|
||||
views.encryptedDeviceInfoDeviceId.text = cryptoDeviceInfo.deviceId
|
||||
views.encryptedDeviceInfoDeviceKey.text = cryptoDeviceInfo.getFingerprintHumanReadable()
|
||||
|
||||
builder.show()
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import im.vector.app.R
|
|||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.core.extensions.showPassword
|
||||
import im.vector.app.core.platform.SimpleTextWatcher
|
||||
import im.vector.app.databinding.DialogPromptPasswordBinding
|
||||
|
||||
class PromptPasswordDialog {
|
||||
|
||||
|
@ -35,20 +36,18 @@ class PromptPasswordDialog {
|
|||
|
||||
fun show(activity: Activity, listener: (String) -> Unit) {
|
||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_prompt_password, null)
|
||||
|
||||
val passwordTil = dialogLayout.findViewById<TextInputLayout>(R.id.promptPasswordTil)
|
||||
val passwordEditText = dialogLayout.findViewById<TextInputEditText>(R.id.promptPassword)
|
||||
val views = DialogPromptPasswordBinding.bind(dialogLayout)
|
||||
val textWatcher = object : SimpleTextWatcher() {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
passwordTil.error = null
|
||||
views.promptPasswordTil.error = null
|
||||
}
|
||||
}
|
||||
passwordEditText.addTextChangedListener(textWatcher)
|
||||
views.promptPassword.addTextChangedListener(textWatcher)
|
||||
|
||||
val showPassword = dialogLayout.findViewById<ImageView>(R.id.promptPasswordPasswordReveal)
|
||||
showPassword.setOnClickListener {
|
||||
passwordVisible = !passwordVisible
|
||||
passwordEditText.showPassword(passwordVisible)
|
||||
views.promptPassword.showPassword(passwordVisible)
|
||||
showPassword.setImageResource(if (passwordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
|
||||
|
@ -73,10 +72,10 @@ class PromptPasswordDialog {
|
|||
setOnShowListener {
|
||||
getButton(AlertDialog.BUTTON_POSITIVE)
|
||||
.setOnClickListener {
|
||||
if (passwordEditText.text.toString().isEmpty()) {
|
||||
passwordTil.error = activity.getString(R.string.error_empty_field_your_password)
|
||||
if (views.promptPassword.text.toString().isEmpty()) {
|
||||
views.promptPasswordTil.error = activity.getString(R.string.error_empty_field_your_password)
|
||||
} else {
|
||||
listener.invoke(passwordEditText.text.toString())
|
||||
listener.invoke(views.promptPassword.text.toString())
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.widget.TextView
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.content.ContextCompat
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.DialogRecoveryKeySavedInfoBinding
|
||||
import me.gujun.android.span.image
|
||||
import me.gujun.android.span.span
|
||||
|
||||
|
@ -30,10 +31,9 @@ class KeepItSafeDialog {
|
|||
|
||||
fun show(activity: Activity) {
|
||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_recovery_key_saved_info, null)
|
||||
val views = DialogRecoveryKeySavedInfoBinding.bind(dialogLayout)
|
||||
|
||||
val descriptionText = dialogLayout.findViewById<TextView>(R.id.keepItSafeText)
|
||||
|
||||
descriptionText.text = span {
|
||||
views.keepItSafeText.text = span {
|
||||
span {
|
||||
image(ContextCompat.getDrawable(activity, R.drawable.ic_check_on)!!)
|
||||
+" "
|
||||
|
|
|
@ -35,6 +35,7 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
|
@ -113,6 +114,7 @@ import im.vector.app.core.utils.saveMedia
|
|||
import im.vector.app.core.utils.shareMedia
|
||||
import im.vector.app.core.utils.shareText
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.databinding.FragmentRoomDetailBinding
|
||||
import im.vector.app.features.attachments.AttachmentTypeSelectorView
|
||||
import im.vector.app.features.attachments.AttachmentsHelper
|
||||
import im.vector.app.features.attachments.ContactAttachment
|
||||
|
@ -232,7 +234,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
private val roomDetailPendingActionStore: RoomDetailPendingActionStore,
|
||||
private val pillsPostProcessorFactory: PillsPostProcessor.Factory
|
||||
) :
|
||||
VectorBaseFragment(),
|
||||
VectorBaseFragment<FragmentRoomDetailBinding>(),
|
||||
TimelineEventController.Callback,
|
||||
VectorInviteView.Callback,
|
||||
JumpToReadMarkerView.Callback,
|
||||
|
@ -278,7 +280,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
private lateinit var scrollOnNewMessageCallback: ScrollOnNewMessageCallback
|
||||
private lateinit var scrollOnHighlightedEventCallback: ScrollOnHighlightedEventCallback
|
||||
|
||||
override fun getLayoutResId() = R.layout.fragment_room_detail
|
||||
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentRoomDetailBinding {
|
||||
return FragmentRoomDetailBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun getMenuRes() = R.menu.menu_timeline
|
||||
|
||||
|
@ -303,7 +307,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
sharedCallActionViewModel = activityViewModelProvider.get(SharedActiveCallViewModel::class.java)
|
||||
attachmentsHelper = AttachmentsHelper(requireContext(), this).register()
|
||||
keyboardStateUtils = KeyboardStateUtils(requireActivity())
|
||||
setupToolbar(roomToolbar)
|
||||
setupToolbar(views.roomToolbar)
|
||||
setupRecyclerView()
|
||||
setupComposer()
|
||||
setupInviteView()
|
||||
|
@ -314,7 +318,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
setupConfBannerView()
|
||||
setupEmojiPopup()
|
||||
|
||||
roomToolbarContentView.debouncedClicks {
|
||||
views.roomToolbarContentView.debouncedClicks {
|
||||
navigator.openRoomProfile(requireActivity(), roomDetailArgs.roomId)
|
||||
}
|
||||
|
||||
|
@ -349,7 +353,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
roomDetailViewModel.selectSubscribe(RoomDetailViewState::syncState) { syncState ->
|
||||
syncStateView.render(syncState)
|
||||
views.syncStateView.render(syncState)
|
||||
}
|
||||
|
||||
roomDetailViewModel.observeViewEvents {
|
||||
|
@ -396,8 +400,8 @@ class RoomDetailFragment @Inject constructor(
|
|||
private fun handleChatEffect(chatEffect: ChatEffect) {
|
||||
when (chatEffect) {
|
||||
ChatEffect.CONFETTI -> {
|
||||
viewKonfetti.isVisible = true
|
||||
viewKonfetti.build()
|
||||
views.viewKonfetti.isVisible = true
|
||||
views.viewKonfetti.build()
|
||||
.addColors(Color.YELLOW, Color.GREEN, Color.MAGENTA)
|
||||
.setDirection(0.0, 359.0)
|
||||
.setSpeed(2f, 5f)
|
||||
|
@ -405,20 +409,20 @@ class RoomDetailFragment @Inject constructor(
|
|||
.setTimeToLive(2000L)
|
||||
.addShapes(Shape.Square, Shape.Circle)
|
||||
.addSizes(Size(12))
|
||||
.setPosition(-50f, viewKonfetti.width + 50f, -50f, -50f)
|
||||
.setPosition(-50f, views.viewKonfetti.width + 50f, -50f, -50f)
|
||||
.streamFor(150, 3000L)
|
||||
}
|
||||
ChatEffect.SNOW -> {
|
||||
viewSnowFall.isVisible = true
|
||||
viewSnowFall.restartFalling()
|
||||
views.viewSnowFall.isVisible = true
|
||||
views.viewSnowFall.restartFalling()
|
||||
}
|
||||
}
|
||||
}
|
||||
private fun handleStopChatEffects() {
|
||||
TransitionManager.beginDelayedTransition(rootConstraintLayout)
|
||||
viewSnowFall.isVisible = false
|
||||
TransitionManager.beginDelayedTransition(views.rootConstraintLayout)
|
||||
views.viewSnowFall.isVisible = false
|
||||
// when gone the effect is a bit buggy
|
||||
viewKonfetti.isInvisible = true
|
||||
views.viewKonfetti.isInvisible = true
|
||||
}
|
||||
|
||||
override fun onImageReady(uri: Uri?) {
|
||||
|
@ -486,7 +490,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setupConfBannerView() {
|
||||
activeConferenceView.callback = object : ActiveConferenceView.Callback {
|
||||
views.activeConferenceView.callback = object : ActiveConferenceView.Callback {
|
||||
override fun onTapJoinAudio(jitsiWidget: Widget) {
|
||||
// need to check if allowed first
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed(
|
||||
|
@ -513,13 +517,13 @@ class RoomDetailFragment @Inject constructor(
|
|||
private fun setupEmojiPopup() {
|
||||
val emojiPopup = EmojiPopup
|
||||
.Builder
|
||||
.fromRootView(rootConstraintLayout)
|
||||
.fromRootView(views.rootConstraintLayout)
|
||||
.setKeyboardAnimationStyle(R.style.emoji_fade_animation_style)
|
||||
.setOnEmojiPopupShownListener { composerLayout?.composerEmojiButton?.setImageResource(R.drawable.ic_keyboard) }
|
||||
.setOnEmojiPopupDismissListener { composerLayout?.composerEmojiButton?.setImageResource(R.drawable.ic_insert_emoji) }
|
||||
.build(composerLayout.composerEditText)
|
||||
.setOnEmojiPopupShownListener { views.composerLayout.views.composerEmojiButton.setImageResource(R.drawable.ic_keyboard) }
|
||||
.setOnEmojiPopupDismissListener { views.composerLayout.views.composerEmojiButton.setImageResource(R.drawable.ic_insert_emoji) }
|
||||
.build(views.composerLayout.views.composerEditText)
|
||||
|
||||
composerLayout.composerEmojiButton.debouncedClicks {
|
||||
views.composerLayout.views.composerEmojiButton.debouncedClicks {
|
||||
emojiPopup.toggle()
|
||||
}
|
||||
}
|
||||
|
@ -585,11 +589,11 @@ class RoomDetailFragment @Inject constructor(
|
|||
override fun onDestroyView() {
|
||||
timelineEventController.callback = null
|
||||
timelineEventController.removeModelBuildListener(modelBuildListener)
|
||||
activeCallView.callback = null
|
||||
views.activeCallView.callback = null
|
||||
modelBuildListener = null
|
||||
autoCompleter.clear()
|
||||
debouncer.cancelAll()
|
||||
timelineRecyclerView.cleanup()
|
||||
views.timelineRecyclerView.cleanup()
|
||||
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
@ -601,10 +605,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setupJumpToBottomView() {
|
||||
jumpToBottomView.visibility = View.INVISIBLE
|
||||
jumpToBottomView.debouncedClicks {
|
||||
views.jumpToBottomView.visibility = View.INVISIBLE
|
||||
views.jumpToBottomView.debouncedClicks {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ExitTrackingUnreadMessagesState)
|
||||
jumpToBottomView.visibility = View.INVISIBLE
|
||||
views.jumpToBottomView.visibility = View.INVISIBLE
|
||||
if (!roomDetailViewModel.timeline.isLive) {
|
||||
scrollOnNewMessageCallback.forceScrollOnNextUpdate()
|
||||
roomDetailViewModel.timeline.restartWithEventId(null)
|
||||
|
@ -614,22 +618,22 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
jumpToBottomViewVisibilityManager = JumpToBottomViewVisibilityManager(
|
||||
jumpToBottomView,
|
||||
views.jumpToBottomView,
|
||||
debouncer,
|
||||
timelineRecyclerView,
|
||||
views.timelineRecyclerView,
|
||||
layoutManager
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupJumpToReadMarkerView() {
|
||||
jumpToReadMarkerView.callback = this
|
||||
views.jumpToReadMarkerView.callback = this
|
||||
}
|
||||
|
||||
private fun setupActiveCallView() {
|
||||
activeCallViewHolder.bind(
|
||||
activeCallPiP,
|
||||
activeCallView,
|
||||
activeCallPiPWrap,
|
||||
views.activeCallPiP,
|
||||
views.activeCallView,
|
||||
views.activeCallPiPWrap,
|
||||
this
|
||||
)
|
||||
}
|
||||
|
@ -639,7 +643,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
if (scrollPosition == null) {
|
||||
scrollOnHighlightedEventCallback.scheduleScrollTo(action.eventId)
|
||||
} else {
|
||||
timelineRecyclerView.stopScroll()
|
||||
views.timelineRecyclerView.stopScroll()
|
||||
layoutManager.scrollToPosition(scrollPosition)
|
||||
}
|
||||
}
|
||||
|
@ -679,7 +683,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setupNotificationView() {
|
||||
notificationAreaView.delegate = object : NotificationAreaView.Delegate {
|
||||
views.notificationAreaView.delegate = object : NotificationAreaView.Delegate {
|
||||
override fun onTombstoneEventClicked(tombstoneEvent: Event) {
|
||||
roomDetailViewModel.handle(RoomDetailAction.HandleTombstoneEvent(tombstoneEvent))
|
||||
}
|
||||
|
@ -906,10 +910,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
private fun renderRegularMode(text: String) {
|
||||
autoCompleter.exitSpecialMode()
|
||||
composerLayout.collapse()
|
||||
views.composerLayout.collapse()
|
||||
|
||||
updateComposerText(text)
|
||||
composerLayout.sendButton.contentDescription = getString(R.string.send)
|
||||
views.composerLayout.views.sendButton.contentDescription = getString(R.string.send)
|
||||
}
|
||||
|
||||
private fun renderSpecialMode(event: TimelineEvent,
|
||||
|
@ -918,7 +922,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
defaultContent: String) {
|
||||
autoCompleter.enterSpecialMode()
|
||||
// switch to expanded bar
|
||||
composerLayout.composerRelatedMessageTitle.apply {
|
||||
views.composerLayout.views.composerRelatedMessageTitle.apply {
|
||||
text = event.senderInfo.disambiguatedDisplayName
|
||||
setTextColor(matrixItemColorProvider.getColor(MatrixItem.UserItem(event.root.senderId ?: "@")))
|
||||
}
|
||||
|
@ -931,16 +935,16 @@ class RoomDetailFragment @Inject constructor(
|
|||
val document = parser.parse(messageContent.formattedBody ?: messageContent.body)
|
||||
formattedBody = eventHtmlRenderer.render(document, pillsPostProcessor)
|
||||
}
|
||||
composerLayout.composerRelatedMessageContent.text = (formattedBody ?: nonFormattedBody)
|
||||
views.composerLayout.views.composerRelatedMessageContent.text = (formattedBody ?: nonFormattedBody)
|
||||
|
||||
updateComposerText(defaultContent)
|
||||
|
||||
composerLayout.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), iconRes))
|
||||
composerLayout.sendButton.contentDescription = getString(descriptionRes)
|
||||
views.composerLayout.views.composerRelatedMessageActionIcon.setImageDrawable(ContextCompat.getDrawable(requireContext(), iconRes))
|
||||
views.composerLayout.views.sendButton.contentDescription = getString(descriptionRes)
|
||||
|
||||
avatarRenderer.render(event.senderInfo.toMatrixItem(), composerLayout.composerRelatedMessageAvatar)
|
||||
avatarRenderer.render(event.senderInfo.toMatrixItem(), views.composerLayout.views.composerRelatedMessageAvatar)
|
||||
|
||||
composerLayout.expand {
|
||||
views.composerLayout.expand {
|
||||
if (isAdded) {
|
||||
// need to do it here also when not using quick reply
|
||||
focusComposerAndShowKeyboard()
|
||||
|
@ -951,11 +955,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
private fun updateComposerText(text: String) {
|
||||
// Do not update if this is the same text to avoid the cursor to move
|
||||
if (text != composerLayout.composerEditText.text.toString()) {
|
||||
if (text != views.composerLayout.text.toString()) {
|
||||
// Ignore update to avoid saving a draft
|
||||
composerLayout.composerEditText.setText(text)
|
||||
composerLayout.composerEditText.setSelection(composerLayout.composerEditText.text?.length
|
||||
?: 0)
|
||||
views.composerLayout.views.composerEditText.setText(text)
|
||||
views.composerLayout.views.composerEditText.setSelection(views.composerLayout.text?.length ?: 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -982,7 +985,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
notificationDrawerManager.setCurrentRoom(null)
|
||||
|
||||
roomDetailViewModel.handle(RoomDetailAction.SaveDraft(composerLayout.composerEditText.text.toString()))
|
||||
roomDetailViewModel.handle(RoomDetailAction.SaveDraft(views.composerLayout.text.toString()))
|
||||
}
|
||||
|
||||
private val attachmentFileActivityResultLauncher = registerStartForActivityResult {
|
||||
|
@ -1050,14 +1053,14 @@ class RoomDetailFragment @Inject constructor(
|
|||
timelineEventController.callback = this
|
||||
timelineEventController.timeline = roomDetailViewModel.timeline
|
||||
|
||||
timelineRecyclerView.trackItemsVisibilityChange()
|
||||
views.timelineRecyclerView.trackItemsVisibilityChange()
|
||||
layoutManager = LinearLayoutManager(context, RecyclerView.VERTICAL, true)
|
||||
val stateRestorer = LayoutManagerStateRestorer(layoutManager).register()
|
||||
scrollOnNewMessageCallback = ScrollOnNewMessageCallback(layoutManager, timelineEventController)
|
||||
scrollOnHighlightedEventCallback = ScrollOnHighlightedEventCallback(timelineRecyclerView, layoutManager, timelineEventController)
|
||||
timelineRecyclerView.layoutManager = layoutManager
|
||||
timelineRecyclerView.itemAnimator = null
|
||||
timelineRecyclerView.setHasFixedSize(true)
|
||||
scrollOnHighlightedEventCallback = ScrollOnHighlightedEventCallback(views.timelineRecyclerView, layoutManager, timelineEventController)
|
||||
views.timelineRecyclerView.layoutManager = layoutManager
|
||||
views.timelineRecyclerView.itemAnimator = null
|
||||
views.timelineRecyclerView.setHasFixedSize(true)
|
||||
modelBuildListener = OnModelBuildFinishedListener {
|
||||
it.dispatchTo(stateRestorer)
|
||||
it.dispatchTo(scrollOnNewMessageCallback)
|
||||
|
@ -1066,14 +1069,14 @@ class RoomDetailFragment @Inject constructor(
|
|||
jumpToBottomViewVisibilityManager.maybeShowJumpToBottomViewVisibilityWithDelay()
|
||||
}
|
||||
timelineEventController.addModelBuildListener(modelBuildListener)
|
||||
timelineRecyclerView.adapter = timelineEventController.adapter
|
||||
views.timelineRecyclerView.adapter = timelineEventController.adapter
|
||||
|
||||
if (vectorPreferences.swipeToReplyIsEnabled()) {
|
||||
val quickReplyHandler = object : RoomMessageTouchHelperCallback.QuickReplayHandler {
|
||||
override fun performQuickReplyOnHolder(model: EpoxyModel<*>) {
|
||||
(model as? AbsMessageItem)?.attributes?.informationData?.let {
|
||||
val eventId = it.eventId
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterReplyMode(eventId, composerLayout.composerEditText.text.toString()))
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterReplyMode(eventId, views.composerLayout.text.toString()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1096,9 +1099,9 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
val swipeCallback = RoomMessageTouchHelperCallback(requireContext(), R.drawable.ic_reply, quickReplyHandler)
|
||||
val touchHelper = ItemTouchHelper(swipeCallback)
|
||||
touchHelper.attachToRecyclerView(timelineRecyclerView)
|
||||
touchHelper.attachToRecyclerView(views.timelineRecyclerView)
|
||||
}
|
||||
timelineRecyclerView.addGlidePreloader(
|
||||
views.timelineRecyclerView.addGlidePreloader(
|
||||
epoxyController = timelineEventController,
|
||||
requestManager = GlideApp.with(this),
|
||||
preloader = glidePreloader { requestManager, epoxyModel: MessageImageVideoItem, _ ->
|
||||
|
@ -1111,7 +1114,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun updateJumpToReadMarkerViewVisibility() {
|
||||
jumpToReadMarkerView?.post {
|
||||
views.jumpToReadMarkerView?.post {
|
||||
withState(roomDetailViewModel) {
|
||||
val showJumpToUnreadBanner = when (it.unreadState) {
|
||||
UnreadState.Unknown,
|
||||
|
@ -1131,13 +1134,13 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
}
|
||||
jumpToReadMarkerView?.isVisible = showJumpToUnreadBanner
|
||||
views.jumpToReadMarkerView?.isVisible = showJumpToUnreadBanner
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupComposer() {
|
||||
val composerEditText = composerLayout.composerEditText
|
||||
val composerEditText = views.composerLayout.views.composerEditText
|
||||
autoCompleter.setup(composerEditText)
|
||||
|
||||
observerUserTyping()
|
||||
|
@ -1164,12 +1167,12 @@ class RoomDetailFragment @Inject constructor(
|
|||
} else false
|
||||
}
|
||||
|
||||
composerLayout.callback = object : TextComposerView.Callback {
|
||||
views.composerLayout.callback = object : TextComposerView.Callback {
|
||||
override fun onAddAttachment() {
|
||||
if (!::attachmentTypeSelector.isInitialized) {
|
||||
attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this@RoomDetailFragment)
|
||||
}
|
||||
attachmentTypeSelector.show(composerLayout.attachmentButton, keyboardStateUtils.isKeyboardShowing)
|
||||
attachmentTypeSelector.show(views.composerLayout.views.attachmentButton, keyboardStateUtils.isKeyboardShowing)
|
||||
}
|
||||
|
||||
override fun onSendMessage(text: CharSequence) {
|
||||
|
@ -1177,7 +1180,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onCloseRelatedMessage() {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterRegularMode(composerLayout.text.toString(), false))
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterRegularMode(views.composerLayout.text.toString(), false))
|
||||
}
|
||||
|
||||
override fun onRichContentSelected(contentUri: Uri): Boolean {
|
||||
|
@ -1193,14 +1196,14 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
if (text.isNotBlank()) {
|
||||
// We collapse ASAP, if not there will be a slight anoying delay
|
||||
composerLayout.collapse(true)
|
||||
views.composerLayout.collapse(true)
|
||||
lockSendButton = true
|
||||
roomDetailViewModel.handle(RoomDetailAction.SendMessage(text, vectorPreferences.isMarkdownEnabled()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun observerUserTyping() {
|
||||
composerLayout.composerEditText.textChanges()
|
||||
views.composerLayout.views.composerEditText.textChanges()
|
||||
.skipInitialValue()
|
||||
.debounce(300, TimeUnit.MILLISECONDS)
|
||||
.map { it.isNotEmpty() }
|
||||
|
@ -1221,39 +1224,39 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setupInviteView() {
|
||||
inviteView.callback = this
|
||||
views.inviteView.callback = this
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(roomDetailViewModel) { state ->
|
||||
invalidateOptionsMenu()
|
||||
val summary = state.asyncRoomSummary()
|
||||
renderToolbar(summary, state.typingMessage)
|
||||
activeConferenceView.render(state)
|
||||
views.activeConferenceView.render(state)
|
||||
val inviter = state.asyncInviter()
|
||||
if (summary?.membership == Membership.JOIN) {
|
||||
jumpToBottomView.count = summary.notificationCount
|
||||
jumpToBottomView.drawBadge = summary.hasUnreadMessages
|
||||
views.jumpToBottomView.count = summary.notificationCount
|
||||
views.jumpToBottomView.drawBadge = summary.hasUnreadMessages
|
||||
scrollOnHighlightedEventCallback.timeline = roomDetailViewModel.timeline
|
||||
timelineEventController.update(state)
|
||||
inviteView.visibility = View.GONE
|
||||
views.inviteView.visibility = View.GONE
|
||||
if (state.tombstoneEvent == null) {
|
||||
if (state.canSendMessage) {
|
||||
composerLayout.visibility = View.VISIBLE
|
||||
composerLayout.setRoomEncrypted(summary.isEncrypted, summary.roomEncryptionTrustLevel)
|
||||
notificationAreaView.render(NotificationAreaView.State.Hidden)
|
||||
views.composerLayout.visibility = View.VISIBLE
|
||||
views.composerLayout.setRoomEncrypted(summary.isEncrypted, summary.roomEncryptionTrustLevel)
|
||||
views.notificationAreaView.render(NotificationAreaView.State.Hidden)
|
||||
} else {
|
||||
composerLayout.visibility = View.GONE
|
||||
notificationAreaView.render(NotificationAreaView.State.NoPermissionToPost)
|
||||
views.composerLayout.visibility = View.GONE
|
||||
views.notificationAreaView.render(NotificationAreaView.State.NoPermissionToPost)
|
||||
}
|
||||
} else {
|
||||
composerLayout.visibility = View.GONE
|
||||
notificationAreaView.render(NotificationAreaView.State.Tombstone(state.tombstoneEvent))
|
||||
views.composerLayout.visibility = View.GONE
|
||||
views.notificationAreaView.render(NotificationAreaView.State.Tombstone(state.tombstoneEvent))
|
||||
}
|
||||
} else if (summary?.membership == Membership.INVITE && inviter != null) {
|
||||
inviteView.visibility = View.VISIBLE
|
||||
inviteView.render(inviter, VectorInviteView.Mode.LARGE, state.changeMembershipState)
|
||||
views.inviteView.visibility = View.VISIBLE
|
||||
views.inviteView.render(inviter, VectorInviteView.Mode.LARGE, state.changeMembershipState)
|
||||
// Intercept click event
|
||||
inviteView.setOnClickListener { }
|
||||
views.inviteView.setOnClickListener { }
|
||||
} else if (state.asyncInviter.complete) {
|
||||
vectorBaseActivity.finish()
|
||||
}
|
||||
|
@ -1261,14 +1264,14 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
private fun renderToolbar(roomSummary: RoomSummary?, typingMessage: String?) {
|
||||
if (roomSummary == null) {
|
||||
roomToolbarContentView.isClickable = false
|
||||
views.roomToolbarContentView.isClickable = false
|
||||
} else {
|
||||
roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN
|
||||
roomToolbarTitleView.text = roomSummary.displayName
|
||||
avatarRenderer.render(roomSummary.toMatrixItem(), roomToolbarAvatarImageView)
|
||||
views.roomToolbarContentView.isClickable = roomSummary.membership == Membership.JOIN
|
||||
views.roomToolbarTitleView.text = roomSummary.displayName
|
||||
avatarRenderer.render(roomSummary.toMatrixItem(), views.roomToolbarAvatarImageView)
|
||||
|
||||
renderSubTitle(typingMessage, roomSummary.topic)
|
||||
roomToolbarDecorationImageView.let {
|
||||
views.roomToolbarDecorationImageView.let {
|
||||
it.setImageResource(roomSummary.roomEncryptionTrustLevel.toImageRes())
|
||||
it.isVisible = roomSummary.roomEncryptionTrustLevel != null
|
||||
}
|
||||
|
@ -1278,7 +1281,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
private fun renderSubTitle(typingMessage: String?, topic: String) {
|
||||
// TODO Temporary place to put typing data
|
||||
val subtitle = typingMessage?.takeIf { it.isNotBlank() } ?: topic
|
||||
roomToolbarSubtitleView.apply {
|
||||
views.roomToolbarSubtitleView.apply {
|
||||
setTextOrHide(subtitle)
|
||||
if (typingMessage.isNullOrBlank()) {
|
||||
setTextColor(ThemeUtils.getColor(requireContext(), R.attr.vctr_toolbar_secondary_text_color))
|
||||
|
@ -1294,9 +1297,11 @@ class RoomDetailFragment @Inject constructor(
|
|||
when (async) {
|
||||
is Loading -> {
|
||||
// TODO Better handling progress
|
||||
/* TODO BMA Yes, improve that
|
||||
vectorBaseActivity.showWaitingView()
|
||||
vectorBaseActivity.waitingStatusText.visibility = View.VISIBLE
|
||||
vectorBaseActivity.waitingStatusText.text = getString(R.string.joining_room)
|
||||
*/
|
||||
}
|
||||
is Success -> {
|
||||
navigator.openRoom(vectorBaseActivity, async())
|
||||
|
@ -1544,8 +1549,8 @@ class RoomDetailFragment @Inject constructor(
|
|||
mediaData = mediaData,
|
||||
view = view
|
||||
) { pairs ->
|
||||
pairs.add(Pair(roomToolbar, ViewCompat.getTransitionName(roomToolbar) ?: ""))
|
||||
pairs.add(Pair(composerLayout, ViewCompat.getTransitionName(composerLayout) ?: ""))
|
||||
pairs.add(Pair(views.roomToolbar, ViewCompat.getTransitionName(views.roomToolbar) ?: ""))
|
||||
pairs.add(Pair(views.composerLayout, ViewCompat.getTransitionName(views.composerLayout) ?: ""))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1556,8 +1561,8 @@ class RoomDetailFragment @Inject constructor(
|
|||
mediaData = mediaData,
|
||||
view = view
|
||||
) { pairs ->
|
||||
pairs.add(Pair(roomToolbar, ViewCompat.getTransitionName(roomToolbar) ?: ""))
|
||||
pairs.add(Pair(composerLayout, ViewCompat.getTransitionName(composerLayout) ?: ""))
|
||||
pairs.add(Pair(views.roomToolbar, ViewCompat.getTransitionName(views.roomToolbar) ?: ""))
|
||||
pairs.add(Pair(views.composerLayout, ViewCompat.getTransitionName(views.composerLayout) ?: ""))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1785,13 +1790,13 @@ class RoomDetailFragment @Inject constructor(
|
|||
roomDetailViewModel.handle(RoomDetailAction.UpdateQuickReactAction(action.eventId, action.clickedOn, action.add))
|
||||
}
|
||||
is EventSharedAction.Edit -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterEditMode(action.eventId, composerLayout.text.toString()))
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterEditMode(action.eventId, views.composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.Quote -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterQuoteMode(action.eventId, composerLayout.text.toString()))
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterQuoteMode(action.eventId, views.composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.Reply -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterReplyMode(action.eventId, composerLayout.text.toString()))
|
||||
roomDetailViewModel.handle(RoomDetailAction.EnterReplyMode(action.eventId, views.composerLayout.text.toString()))
|
||||
}
|
||||
is EventSharedAction.CopyPermalink -> {
|
||||
val permalink = session.permalinkService().createPermalink(roomDetailArgs.roomId, action.eventId)
|
||||
|
@ -1857,13 +1862,13 @@ class RoomDetailFragment @Inject constructor(
|
|||
*/
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun insertUserDisplayNameInTextEditor(userId: String) {
|
||||
val startToCompose = composerLayout.composerEditText.text.isNullOrBlank()
|
||||
val startToCompose = views.composerLayout.text.isNullOrBlank()
|
||||
|
||||
if (startToCompose
|
||||
&& userId == session.myUserId) {
|
||||
// Empty composer, current user: start an emote
|
||||
composerLayout.composerEditText.setText(Command.EMOTE.command + " ")
|
||||
composerLayout.composerEditText.setSelection(Command.EMOTE.length)
|
||||
views.composerLayout.views.composerEditText.setText(Command.EMOTE.command + " ")
|
||||
views.composerLayout.views.composerEditText.setSelection(Command.EMOTE.length)
|
||||
} else {
|
||||
val roomMember = roomDetailViewModel.getMember(userId)
|
||||
// TODO move logic outside of fragment
|
||||
|
@ -1879,7 +1884,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
requireContext(),
|
||||
MatrixItem.UserItem(userId, displayName, roomMember?.avatarUrl)
|
||||
)
|
||||
.also { it.bind(composerLayout.composerEditText) },
|
||||
.also { it.bind(views.composerLayout.views.composerEditText) },
|
||||
0,
|
||||
displayName.length,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
|
@ -1889,11 +1894,11 @@ class RoomDetailFragment @Inject constructor(
|
|||
if (startToCompose) {
|
||||
if (displayName.startsWith("/")) {
|
||||
// Ensure displayName will not be interpreted as a Slash command
|
||||
composerLayout.composerEditText.append("\\")
|
||||
views.composerLayout.views.composerEditText.append("\\")
|
||||
}
|
||||
composerLayout.composerEditText.append(pill)
|
||||
views.composerLayout.views.composerEditText.append(pill)
|
||||
} else {
|
||||
composerLayout.composerEditText.text?.insert(composerLayout.composerEditText.selectionStart, pill)
|
||||
views.composerLayout.views.composerEditText.text?.insert(views.composerLayout.views.composerEditText.selectionStart, pill)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1902,8 +1907,8 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun focusComposerAndShowKeyboard() {
|
||||
if (composerLayout.isVisible) {
|
||||
composerLayout.composerEditText.showKeyboard(andRequestFocus = true)
|
||||
if (views.composerLayout.isVisible) {
|
||||
views.composerLayout.views.composerEditText.showKeyboard(andRequestFocus = true)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1933,7 +1938,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
// JumpToReadMarkerView.Callback
|
||||
|
||||
override fun onJumpToReadMarkerClicked() = withState(roomDetailViewModel) {
|
||||
jumpToReadMarkerView.isVisible = false
|
||||
views.jumpToReadMarkerView.isVisible = false
|
||||
if (it.unreadState is UnreadState.HasUnread) {
|
||||
roomDetailViewModel.handle(RoomDetailAction.NavigateToEvent(it.unreadState.firstUnreadEventId, false))
|
||||
}
|
||||
|
|
|
@ -20,7 +20,12 @@ import android.content.Context
|
|||
import android.net.Uri
|
||||
import android.text.Editable
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.text.toSpannable
|
||||
|
@ -31,6 +36,7 @@ import androidx.transition.Transition
|
|||
import androidx.transition.TransitionManager
|
||||
import androidx.transition.TransitionSet
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.ComposerLayoutBinding
|
||||
|
||||
import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
|
||||
|
||||
|
@ -38,7 +44,9 @@ import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel
|
|||
* Encapsulate the timeline composer UX.
|
||||
*
|
||||
*/
|
||||
class TextComposerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null,
|
||||
class TextComposerView @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
interface Callback : ComposerEditText.Callback {
|
||||
|
@ -47,6 +55,8 @@ class TextComposerView @JvmOverloads constructor(context: Context, attrs: Attrib
|
|||
fun onAddAttachment()
|
||||
}
|
||||
|
||||
val views: ComposerLayoutBinding
|
||||
|
||||
var callback: Callback? = null
|
||||
|
||||
private var currentConstraintSetId: Int = -1
|
||||
|
@ -54,27 +64,30 @@ class TextComposerView @JvmOverloads constructor(context: Context, attrs: Attrib
|
|||
private val animationDuration = 100L
|
||||
|
||||
val text: Editable?
|
||||
get() = composerEditText.text
|
||||
get() = views.composerEditText.text
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.composer_layout, this)
|
||||
views = ComposerLayoutBinding.bind(this)
|
||||
|
||||
collapse(false)
|
||||
composerEditText.callback = object : ComposerEditText.Callback {
|
||||
|
||||
views.composerEditText.callback = object : ComposerEditText.Callback {
|
||||
override fun onRichContentSelected(contentUri: Uri): Boolean {
|
||||
return callback?.onRichContentSelected(contentUri) ?: false
|
||||
}
|
||||
}
|
||||
composerRelatedMessageCloseButton.setOnClickListener {
|
||||
views.composerRelatedMessageCloseButton.setOnClickListener {
|
||||
collapse()
|
||||
callback?.onCloseRelatedMessage()
|
||||
}
|
||||
|
||||
sendButton.setOnClickListener {
|
||||
views.sendButton.setOnClickListener {
|
||||
val textMessage = text?.toSpannable() ?: ""
|
||||
callback?.onSendMessage(textMessage)
|
||||
}
|
||||
|
||||
attachmentButton.setOnClickListener {
|
||||
views.attachmentButton.setOnClickListener {
|
||||
callback?.onAddAttachment()
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +117,7 @@ class TextComposerView @JvmOverloads constructor(context: Context, attrs: Attrib
|
|||
ConstraintSet().also {
|
||||
it.clone(context, currentConstraintSetId)
|
||||
// in case shield is hidden, we will have glitch without this
|
||||
it.getConstraint(R.id.composerShieldImageView).propertySet.visibility = composerShieldImageView.visibility
|
||||
it.getConstraint(R.id.composerShieldImageView).propertySet.visibility = views.composerShieldImageView.visibility
|
||||
it.applyTo(this)
|
||||
}
|
||||
}
|
||||
|
@ -134,17 +147,17 @@ class TextComposerView @JvmOverloads constructor(context: Context, attrs: Attrib
|
|||
|
||||
fun setRoomEncrypted(isEncrypted: Boolean, roomEncryptionTrustLevel: RoomEncryptionTrustLevel?) {
|
||||
if (isEncrypted) {
|
||||
composerEditText.setHint(R.string.room_message_placeholder)
|
||||
composerShieldImageView.isVisible = true
|
||||
views.composerEditText.setHint(R.string.room_message_placeholder)
|
||||
views.composerShieldImageView.isVisible = true
|
||||
val shieldRes = when (roomEncryptionTrustLevel) {
|
||||
RoomEncryptionTrustLevel.Trusted -> R.drawable.ic_shield_trusted
|
||||
RoomEncryptionTrustLevel.Warning -> R.drawable.ic_shield_warning
|
||||
else -> R.drawable.ic_shield_black
|
||||
}
|
||||
composerShieldImageView.setImageResource(shieldRes)
|
||||
views.composerShieldImageView.setImageResource(shieldRes)
|
||||
} else {
|
||||
composerEditText.setHint(R.string.room_message_placeholder)
|
||||
composerShieldImageView.isVisible = false
|
||||
views.composerEditText.setHint(R.string.room_message_placeholder)
|
||||
views.composerShieldImageView.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ import android.view.LayoutInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.Fail
|
||||
|
@ -43,6 +45,7 @@ import im.vector.app.core.extensions.setTextOrHide
|
|||
import im.vector.app.core.platform.StateView
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||
import im.vector.app.databinding.DialogShareQrCodeBinding
|
||||
import im.vector.app.databinding.FragmentGenericRecyclerBinding
|
||||
import im.vector.app.databinding.FragmentMatrixProfileBinding
|
||||
import im.vector.app.features.crypto.verification.VerificationBottomSheet
|
||||
|
@ -72,6 +75,14 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
) : VectorBaseFragment<FragmentMatrixProfileBinding>(),
|
||||
RoomMemberProfileController.Callback {
|
||||
|
||||
private lateinit var memberProfileStateView: StateView
|
||||
private lateinit var memberProfileInfoContainer: View
|
||||
private lateinit var memberProfileDecorationImageView: ImageView
|
||||
private lateinit var memberProfileAvatarView: ImageView
|
||||
private lateinit var memberProfileNameView: TextView
|
||||
private lateinit var memberProfileIdView: TextView
|
||||
private lateinit var memberProfilePowerLevelView: TextView
|
||||
|
||||
private val fragmentArgs: RoomMemberProfileArgs by args()
|
||||
private val viewModel: RoomMemberProfileViewModel by fragmentViewModel()
|
||||
|
||||
|
@ -85,27 +96,28 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setupToolbar(matrixProfileToolbar)
|
||||
val headerView = matrixProfileHeaderView.let {
|
||||
setupToolbar(views.matrixProfileToolbar)
|
||||
val headerView = views.matrixProfileHeaderView.let {
|
||||
it.layoutResource = R.layout.view_stub_room_member_profile_header
|
||||
it.inflate()
|
||||
}
|
||||
findHeaderSubViews(headerView)
|
||||
memberProfileStateView.eventCallback = object : StateView.EventCallback {
|
||||
override fun onRetryClicked() {
|
||||
viewModel.handle(RoomMemberProfileAction.RetryFetchingInfo)
|
||||
}
|
||||
}
|
||||
memberProfileStateView.contentView = memberProfileInfoContainer
|
||||
matrixProfileRecyclerView.configureWith(roomMemberProfileController, hasFixedSize = true, disableItemAnimation = true)
|
||||
views.matrixProfileRecyclerView.configureWith(roomMemberProfileController, hasFixedSize = true, disableItemAnimation = true)
|
||||
roomMemberProfileController.callback = this
|
||||
appBarStateChangeListener = MatrixItemAppBarStateChangeListener(headerView,
|
||||
listOf(
|
||||
matrixProfileToolbarAvatarImageView,
|
||||
matrixProfileToolbarTitleView,
|
||||
matrixProfileDecorationToolbarAvatarImageView
|
||||
views.matrixProfileToolbarAvatarImageView,
|
||||
views.matrixProfileToolbarTitleView,
|
||||
views.matrixProfileDecorationToolbarAvatarImageView
|
||||
)
|
||||
)
|
||||
matrixProfileAppBarLayout.addOnOffsetChangedListener(appBarStateChangeListener)
|
||||
views.matrixProfileAppBarLayout.addOnOffsetChangedListener(appBarStateChangeListener)
|
||||
viewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomMemberProfileViewEvents.Loading -> showLoading(it.message)
|
||||
|
@ -124,6 +136,16 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
setupLongClicks()
|
||||
}
|
||||
|
||||
private fun findHeaderSubViews(headerView: View) {
|
||||
memberProfileStateView = headerView.findViewById(R.id.memberProfileStateView)
|
||||
memberProfileInfoContainer = headerView.findViewById(R.id.memberProfileInfoContainer)
|
||||
memberProfileNameView = headerView.findViewById(R.id.roomProfileNameView)
|
||||
memberProfileIdView = headerView.findViewById(R.id.memberProfileIdView)
|
||||
memberProfileAvatarView = headerView.findViewById(R.id.roomProfileAvatarView)
|
||||
memberProfilePowerLevelView = headerView.findViewById(R.id.memberProfilePowerLevelView)
|
||||
memberProfileDecorationImageView = headerView.findViewById(R.id.roomProfileDecorationImageView)
|
||||
}
|
||||
|
||||
private fun setupLongClicks() {
|
||||
memberProfileNameView.copyOnLongClick()
|
||||
memberProfileIdView.copyOnLongClick()
|
||||
|
@ -171,23 +193,23 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
matrixProfileAppBarLayout.removeOnOffsetChangedListener(appBarStateChangeListener)
|
||||
views.matrixProfileAppBarLayout.removeOnOffsetChangedListener(appBarStateChangeListener)
|
||||
roomMemberProfileController.callback = null
|
||||
appBarStateChangeListener = null
|
||||
matrixProfileRecyclerView.cleanup()
|
||||
views.matrixProfileRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
when (val asyncUserMatrixItem = state.userMatrixItem) {
|
||||
is Incomplete -> {
|
||||
matrixProfileToolbarTitleView.text = state.userId
|
||||
avatarRenderer.render(MatrixItem.UserItem(state.userId, null, null), matrixProfileToolbarAvatarImageView)
|
||||
views.matrixProfileToolbarTitleView.text = state.userId
|
||||
avatarRenderer.render(MatrixItem.UserItem(state.userId, null, null), views.matrixProfileToolbarAvatarImageView)
|
||||
memberProfileStateView.state = StateView.State.Loading
|
||||
}
|
||||
is Fail -> {
|
||||
avatarRenderer.render(MatrixItem.UserItem(state.userId, null, null), matrixProfileToolbarAvatarImageView)
|
||||
matrixProfileToolbarTitleView.text = state.userId
|
||||
avatarRenderer.render(MatrixItem.UserItem(state.userId, null, null), views.matrixProfileToolbarAvatarImageView)
|
||||
views.matrixProfileToolbarTitleView.text = state.userId
|
||||
val failureMessage = errorFormatter.toHumanReadable(asyncUserMatrixItem.error)
|
||||
memberProfileStateView.state = StateView.State.Error(failureMessage)
|
||||
}
|
||||
|
@ -197,9 +219,9 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
memberProfileIdView.text = userMatrixItem.id
|
||||
val bestName = userMatrixItem.getBestName()
|
||||
memberProfileNameView.text = bestName
|
||||
matrixProfileToolbarTitleView.text = bestName
|
||||
views.matrixProfileToolbarTitleView.text = bestName
|
||||
avatarRenderer.render(userMatrixItem, memberProfileAvatarView)
|
||||
avatarRenderer.render(userMatrixItem, matrixProfileToolbarAvatarImageView)
|
||||
avatarRenderer.render(userMatrixItem, views.matrixProfileToolbarAvatarImageView)
|
||||
|
||||
if (state.isRoomEncrypted) {
|
||||
memberProfileDecorationImageView.isVisible = true
|
||||
|
@ -217,15 +239,15 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
}
|
||||
|
||||
memberProfileDecorationImageView.setImageResource(icon)
|
||||
matrixProfileDecorationToolbarAvatarImageView.setImageResource(icon)
|
||||
views.matrixProfileDecorationToolbarAvatarImageView.setImageResource(icon)
|
||||
} else {
|
||||
// Legacy
|
||||
if (state.allDevicesAreTrusted) {
|
||||
memberProfileDecorationImageView.setImageResource(R.drawable.ic_shield_trusted)
|
||||
matrixProfileDecorationToolbarAvatarImageView.setImageResource(R.drawable.ic_shield_trusted)
|
||||
views.matrixProfileDecorationToolbarAvatarImageView.setImageResource(R.drawable.ic_shield_trusted)
|
||||
} else {
|
||||
memberProfileDecorationImageView.setImageResource(R.drawable.ic_shield_warning)
|
||||
matrixProfileDecorationToolbarAvatarImageView.setImageResource(R.drawable.ic_shield_warning)
|
||||
views.matrixProfileDecorationToolbarAvatarImageView.setImageResource(R.drawable.ic_shield_warning)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -235,7 +257,7 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
memberProfileAvatarView.setOnClickListener { view ->
|
||||
onAvatarClicked(view, userMatrixItem)
|
||||
}
|
||||
matrixProfileToolbarAvatarImageView.setOnClickListener { view ->
|
||||
views.matrixProfileToolbarAvatarImageView.setOnClickListener { view ->
|
||||
onAvatarClicked(view, userMatrixItem)
|
||||
}
|
||||
}
|
||||
|
@ -302,8 +324,8 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
|
||||
private fun handleShareRoomMemberProfile(permalink: String) {
|
||||
val view = layoutInflater.inflate(R.layout.dialog_share_qr_code, null)
|
||||
val qrCode = view.findViewById<im.vector.app.core.ui.views.QrCodeImageView>(R.id.itemShareQrCodeImage)
|
||||
qrCode.setData(permalink)
|
||||
val views = DialogShareQrCodeBinding.bind(view)
|
||||
views.itemShareQrCodeImage.setData(permalink)
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setView(view)
|
||||
.setNeutralButton(R.string.ok, null)
|
||||
|
|
|
@ -23,6 +23,7 @@ import androidx.appcompat.app.AlertDialog
|
|||
import androidx.core.view.isVisible
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.hideKeyboard
|
||||
import im.vector.app.databinding.DialogEditPowerLevelBinding
|
||||
|
||||
import org.matrix.android.sdk.api.session.room.powerlevels.Role
|
||||
|
||||
|
@ -30,28 +31,29 @@ object EditPowerLevelDialogs {
|
|||
|
||||
fun showChoice(activity: Activity, currentRole: Role, listener: (Int) -> Unit) {
|
||||
val dialogLayout = activity.layoutInflater.inflate(R.layout.dialog_edit_power_level, null)
|
||||
dialogLayout.powerLevelRadioGroup.setOnCheckedChangeListener { _, checkedId ->
|
||||
dialogLayout.powerLevelCustomEditLayout.isVisible = checkedId == R.id.powerLevelCustomRadio
|
||||
val views = DialogEditPowerLevelBinding.bind(dialogLayout)
|
||||
views.powerLevelRadioGroup.setOnCheckedChangeListener { _, checkedId ->
|
||||
views.powerLevelCustomEditLayout.isVisible = checkedId == R.id.powerLevelCustomRadio
|
||||
}
|
||||
dialogLayout.powerLevelCustomEdit.setText(currentRole.value.toString())
|
||||
views.powerLevelCustomEdit.setText(currentRole.value.toString())
|
||||
|
||||
when (currentRole) {
|
||||
Role.Admin -> dialogLayout.powerLevelAdminRadio.isChecked = true
|
||||
Role.Moderator -> dialogLayout.powerLevelModeratorRadio.isChecked = true
|
||||
Role.Default -> dialogLayout.powerLevelDefaultRadio.isChecked = true
|
||||
else -> dialogLayout.powerLevelCustomRadio.isChecked = true
|
||||
Role.Admin -> views.powerLevelAdminRadio.isChecked = true
|
||||
Role.Moderator -> views.powerLevelModeratorRadio.isChecked = true
|
||||
Role.Default -> views.powerLevelDefaultRadio.isChecked = true
|
||||
else -> views.powerLevelCustomRadio.isChecked = true
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.power_level_edit_title)
|
||||
.setView(dialogLayout)
|
||||
.setPositiveButton(R.string.edit) { _, _ ->
|
||||
val newValue = when (dialogLayout.powerLevelRadioGroup.checkedRadioButtonId) {
|
||||
val newValue = when (views.powerLevelRadioGroup.checkedRadioButtonId) {
|
||||
R.id.powerLevelAdminRadio -> Role.Admin.value
|
||||
R.id.powerLevelModeratorRadio -> Role.Moderator.value
|
||||
R.id.powerLevelDefaultRadio -> Role.Default.value
|
||||
else -> {
|
||||
dialogLayout.powerLevelCustomEdit.text?.toString()?.toInt() ?: currentRole.value
|
||||
views.powerLevelCustomEdit.text?.toString()?.toInt() ?: currentRole.value
|
||||
}
|
||||
}
|
||||
listener(newValue)
|
||||
|
|
|
@ -29,6 +29,7 @@ import im.vector.app.core.extensions.addFragment
|
|||
import im.vector.app.core.extensions.addFragmentToBackstack
|
||||
import im.vector.app.core.platform.ToolbarConfigurable
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.databinding.ActivitySimpleBinding
|
||||
import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewEvents
|
||||
import im.vector.app.features.room.RequireActiveMembershipViewModel
|
||||
|
@ -41,7 +42,7 @@ import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
|
|||
import javax.inject.Inject
|
||||
|
||||
class RoomProfileActivity :
|
||||
VectorBaseActivity(),
|
||||
VectorBaseActivity<ActivitySimpleBinding>(),
|
||||
ToolbarConfigurable,
|
||||
RequireActiveMembershipViewModel.Factory {
|
||||
|
||||
|
@ -81,7 +82,9 @@ class RoomProfileActivity :
|
|||
injector.inject(this)
|
||||
}
|
||||
|
||||
override fun getLayoutRes() = R.layout.activity_simple
|
||||
override fun getBinding(): ActivitySimpleBinding {
|
||||
return ActivitySimpleBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
override fun initUiAndData() {
|
||||
sharedActionViewModel = viewModelProvider.get(RoomProfileSharedActionViewModel::class.java)
|
||||
|
|
|
@ -23,6 +23,8 @@ import android.view.LayoutInflater
|
|||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.app.ActivityOptionsCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
|
@ -42,7 +44,6 @@ import im.vector.app.core.extensions.setTextOrHide
|
|||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.copyToClipboard
|
||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||
import im.vector.app.databinding.FragmentGenericRecyclerBinding
|
||||
import im.vector.app.databinding.FragmentMatrixProfileBinding
|
||||
import im.vector.app.features.crypto.util.toImageRes
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
|
@ -70,9 +71,15 @@ class RoomProfileFragment @Inject constructor(
|
|||
private val roomProfileController: RoomProfileController,
|
||||
private val avatarRenderer: AvatarRenderer,
|
||||
val roomProfileViewModelFactory: RoomProfileViewModel.Factory
|
||||
) : VectorBaseFragment<FragmentMatrixProfileBinding>(),
|
||||
) :
|
||||
VectorBaseFragment<FragmentMatrixProfileBinding>(),
|
||||
RoomProfileController.Callback {
|
||||
|
||||
private lateinit var roomProfileDecorationImageView: ImageView
|
||||
private lateinit var roomProfileAvatarView: ImageView
|
||||
private lateinit var roomProfileAliasView: TextView
|
||||
private lateinit var roomProfileNameView: TextView
|
||||
|
||||
private val roomProfileArgs: RoomProfileArgs by args()
|
||||
private lateinit var roomListQuickActionsSharedActionViewModel: RoomListQuickActionsSharedActionViewModel
|
||||
private lateinit var roomProfileSharedActionViewModel: RoomProfileSharedActionViewModel
|
||||
|
@ -90,20 +97,21 @@ class RoomProfileFragment @Inject constructor(
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
roomListQuickActionsSharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java)
|
||||
roomProfileSharedActionViewModel = activityViewModelProvider.get(RoomProfileSharedActionViewModel::class.java)
|
||||
val headerView = matrixProfileHeaderView.let {
|
||||
val headerView = views.matrixProfileHeaderView.let {
|
||||
it.layoutResource = R.layout.view_stub_room_profile_header
|
||||
it.inflate()
|
||||
}
|
||||
findHeaderSubViews(headerView)
|
||||
setupWaitingView()
|
||||
setupToolbar(matrixProfileToolbar)
|
||||
setupToolbar(views.matrixProfileToolbar)
|
||||
setupRecyclerView()
|
||||
appBarStateChangeListener = MatrixItemAppBarStateChangeListener(
|
||||
headerView,
|
||||
listOf(matrixProfileToolbarAvatarImageView,
|
||||
matrixProfileToolbarTitleView,
|
||||
matrixProfileDecorationToolbarAvatarImageView)
|
||||
listOf(views.matrixProfileToolbarAvatarImageView,
|
||||
views. matrixProfileToolbarTitleView,
|
||||
views. matrixProfileDecorationToolbarAvatarImageView)
|
||||
)
|
||||
matrixProfileAppBarLayout.addOnOffsetChangedListener(appBarStateChangeListener)
|
||||
views.matrixProfileAppBarLayout.addOnOffsetChangedListener(appBarStateChangeListener)
|
||||
roomProfileViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is RoomProfileViewEvents.Loading -> showLoading(it.message)
|
||||
|
@ -119,9 +127,16 @@ class RoomProfileFragment @Inject constructor(
|
|||
setupLongClicks()
|
||||
}
|
||||
|
||||
private fun findHeaderSubViews(headerView: View) {
|
||||
roomProfileNameView = headerView.findViewById(R.id.roomProfileNameView)
|
||||
roomProfileAliasView = headerView.findViewById(R.id.roomProfileAliasView)
|
||||
roomProfileAvatarView = headerView.findViewById(R.id.roomProfileAvatarView)
|
||||
roomProfileDecorationImageView = headerView.findViewById(R.id.roomProfileDecorationImageView)
|
||||
}
|
||||
|
||||
private fun setupWaitingView() {
|
||||
waitingStatusText.setText(R.string.please_wait)
|
||||
waitingStatusText.isVisible = true
|
||||
views.waitingView.waitingStatusText.setText(R.string.please_wait)
|
||||
views.waitingView.waitingStatusText.isVisible = true
|
||||
}
|
||||
|
||||
private fun setupLongClicks() {
|
||||
|
@ -157,18 +172,18 @@ class RoomProfileFragment @Inject constructor(
|
|||
|
||||
private fun setupRecyclerView() {
|
||||
roomProfileController.callback = this
|
||||
matrixProfileRecyclerView.configureWith(roomProfileController, hasFixedSize = true, disableItemAnimation = true)
|
||||
views.matrixProfileRecyclerView.configureWith(roomProfileController, hasFixedSize = true, disableItemAnimation = true)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
matrixProfileAppBarLayout.removeOnOffsetChangedListener(appBarStateChangeListener)
|
||||
matrixProfileRecyclerView.cleanup()
|
||||
views.matrixProfileAppBarLayout.removeOnOffsetChangedListener(appBarStateChangeListener)
|
||||
views.matrixProfileRecyclerView.cleanup()
|
||||
appBarStateChangeListener = null
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(roomProfileViewModel) { state ->
|
||||
waiting_view.isVisible = state.isLoading
|
||||
views.waitingView.root.isVisible = state.isLoading
|
||||
|
||||
state.roomSummary()?.also {
|
||||
if (it.membership.isLeft()) {
|
||||
|
@ -176,19 +191,19 @@ class RoomProfileFragment @Inject constructor(
|
|||
activity?.finish()
|
||||
} else {
|
||||
roomProfileNameView.text = it.displayName
|
||||
matrixProfileToolbarTitleView.text = it.displayName
|
||||
views.matrixProfileToolbarTitleView.text = it.displayName
|
||||
roomProfileAliasView.setTextOrHide(it.canonicalAlias)
|
||||
val matrixItem = it.toMatrixItem()
|
||||
avatarRenderer.render(matrixItem, roomProfileAvatarView)
|
||||
avatarRenderer.render(matrixItem, matrixProfileToolbarAvatarImageView)
|
||||
avatarRenderer.render(matrixItem, views.matrixProfileToolbarAvatarImageView)
|
||||
roomProfileDecorationImageView.isVisible = it.roomEncryptionTrustLevel != null
|
||||
roomProfileDecorationImageView.setImageResource(it.roomEncryptionTrustLevel.toImageRes())
|
||||
matrixProfileDecorationToolbarAvatarImageView.setImageResource(it.roomEncryptionTrustLevel.toImageRes())
|
||||
views.matrixProfileDecorationToolbarAvatarImageView.setImageResource(it.roomEncryptionTrustLevel.toImageRes())
|
||||
|
||||
roomProfileAvatarView.setOnClickListener { view ->
|
||||
onAvatarClicked(view, matrixItem)
|
||||
}
|
||||
matrixProfileToolbarAvatarImageView.setOnClickListener { view ->
|
||||
views.matrixProfileToolbarAvatarImageView.setOnClickListener { view ->
|
||||
onAvatarClicked(view, matrixItem)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,29 +61,29 @@ class RoomMemberListFragment @Inject constructor(
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
roomMemberListController.callback = this
|
||||
setupToolbar(roomSettingsToolbar)
|
||||
setupToolbar(views.roomSettingGeneric.roomSettingsToolbar)
|
||||
setupSearchView()
|
||||
setupInviteUsersButton()
|
||||
views.roomSettingsRecyclerView.configureWith(roomMemberListController, hasFixedSize = true)
|
||||
views.roomSettingGeneric.roomSettingsRecyclerView.configureWith(roomMemberListController, hasFixedSize = true)
|
||||
}
|
||||
|
||||
private fun setupInviteUsersButton() {
|
||||
inviteUsersButton.debouncedClicks {
|
||||
views.inviteUsersButton.debouncedClicks {
|
||||
navigator.openInviteUsersToRoom(requireContext(), roomProfileArgs.roomId)
|
||||
}
|
||||
// Hide FAB when list is scrolling
|
||||
views.roomSettingsRecyclerView.addOnScrollListener(
|
||||
views.roomSettingGeneric.roomSettingsRecyclerView.addOnScrollListener(
|
||||
object : RecyclerView.OnScrollListener() {
|
||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||
when (newState) {
|
||||
RecyclerView.SCROLL_STATE_IDLE -> {
|
||||
if (withState(viewModel) { it.actionsPermissions.canInvite }) {
|
||||
inviteUsersButton.show()
|
||||
views.inviteUsersButton.show()
|
||||
}
|
||||
}
|
||||
RecyclerView.SCROLL_STATE_DRAGGING,
|
||||
RecyclerView.SCROLL_STATE_SETTLING -> {
|
||||
inviteUsersButton.hide()
|
||||
views.inviteUsersButton.hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +92,8 @@ class RoomMemberListFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setupSearchView() {
|
||||
searchView.queryHint = getString(R.string.search_members_hint)
|
||||
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
views.roomSettingGeneric.searchView.queryHint = getString(R.string.search_members_hint)
|
||||
views.roomSettingGeneric.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
return true
|
||||
}
|
||||
|
@ -106,16 +106,16 @@ class RoomMemberListFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
views.roomSettingsRecyclerView.cleanup()
|
||||
views.roomSettingGeneric.roomSettingsRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { viewState ->
|
||||
roomMemberListController.setData(viewState)
|
||||
renderRoomSummary(viewState)
|
||||
inviteUsersButton.isVisible = viewState.actionsPermissions.canInvite
|
||||
views.inviteUsersButton.isVisible = viewState.actionsPermissions.canInvite
|
||||
// Display filter only if there are more than 2 members in this room
|
||||
searchViewAppBarLayout.isVisible = viewState.roomSummary()?.otherMemberIds.orEmpty().size > 1
|
||||
views.roomSettingGeneric.searchViewAppBarLayout.isVisible = viewState.roomSummary()?.otherMemberIds.orEmpty().size > 1
|
||||
}
|
||||
|
||||
override fun onRoomMemberClicked(roomMember: RoomMemberSummary) {
|
||||
|
@ -140,8 +140,8 @@ class RoomMemberListFragment @Inject constructor(
|
|||
|
||||
private fun renderRoomSummary(state: RoomMemberListViewState) {
|
||||
state.roomSummary()?.let {
|
||||
roomSettingsToolbarTitleView.text = it.displayName
|
||||
avatarRenderer.render(it.toMatrixItem(), roomSettingsToolbarAvatarImageView)
|
||||
views.roomSettingGeneric.roomSettingsToolbarTitleView.text = it.displayName
|
||||
avatarRenderer.render(it.toMatrixItem(), views.roomSettingGeneric.roomSettingsToolbarAvatarImageView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.view.View
|
|||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import im.vector.app.R
|
||||
import im.vector.app.databinding.DialogBackgroundSyncModeBinding
|
||||
|
||||
class BackgroundSyncModeChooserDialog : DialogFragment() {
|
||||
|
||||
|
@ -31,25 +32,26 @@ class BackgroundSyncModeChooserDialog : DialogFragment() {
|
|||
val initialMode = BackgroundSyncMode.fromString(arguments?.getString(ARG_INITIAL_MODE))
|
||||
|
||||
val view = requireActivity().layoutInflater.inflate(R.layout.dialog_background_sync_mode, null)
|
||||
val views = DialogBackgroundSyncModeBinding.bind(view)
|
||||
val dialog = AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.settings_background_fdroid_sync_mode)
|
||||
.setView(view)
|
||||
.setPositiveButton(R.string.cancel, null)
|
||||
.create()
|
||||
|
||||
view.findViewById<View>(R.id.backgroundSyncModeBattery).setOnClickListener {
|
||||
views.backgroundSyncModeBattery.setOnClickListener {
|
||||
interactionListener
|
||||
?.takeIf { initialMode != BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY }
|
||||
?.onOptionSelected(BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_BATTERY)
|
||||
dialog.dismiss()
|
||||
}
|
||||
view.findViewById<View>(R.id.backgroundSyncModeReal).setOnClickListener {
|
||||
views.backgroundSyncModeReal.setOnClickListener {
|
||||
interactionListener
|
||||
?.takeIf { initialMode != BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME }
|
||||
?.onOptionSelected(BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_FOR_REALTIME)
|
||||
dialog.dismiss()
|
||||
}
|
||||
view.findViewById<View>(R.id.backgroundSyncModeOff).setOnClickListener {
|
||||
views.backgroundSyncModeOff.setOnClickListener {
|
||||
interactionListener
|
||||
?.takeIf { initialMode != BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED }
|
||||
?.onOptionSelected(BackgroundSyncMode.FDROID_BACKGROUND_SYNC_MODE_DISABLED)
|
||||
|
|
|
@ -49,6 +49,7 @@ import im.vector.app.core.resources.ColorProvider
|
|||
import im.vector.app.core.utils.TextUtils
|
||||
import im.vector.app.core.utils.getSizeOfFiles
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.databinding.DialogChangePasswordBinding
|
||||
import im.vector.app.features.MainActivity
|
||||
import im.vector.app.features.MainActivityArgs
|
||||
import im.vector.app.features.workers.signout.SignOutUiWorker
|
||||
|
@ -352,25 +353,18 @@ class VectorSettingsGeneralFragment @Inject constructor(
|
|||
private fun onPasswordUpdateClick() {
|
||||
activity?.let { activity ->
|
||||
val view: ViewGroup = activity.layoutInflater.inflate(R.layout.dialog_change_password, null) as ViewGroup
|
||||
|
||||
val showPassword: ImageView = view.findViewById(R.id.change_password_show_passwords)
|
||||
val oldPasswordTil: TextInputLayout = view.findViewById(R.id.change_password_old_pwd_til)
|
||||
val oldPasswordText: TextInputEditText = view.findViewById(R.id.change_password_old_pwd_text)
|
||||
val newPasswordText: TextInputEditText = view.findViewById(R.id.change_password_new_pwd_text)
|
||||
val confirmNewPasswordTil: TextInputLayout = view.findViewById(R.id.change_password_confirm_new_pwd_til)
|
||||
val confirmNewPasswordText: TextInputEditText = view.findViewById(R.id.change_password_confirm_new_pwd_text)
|
||||
val changePasswordLoader: View = view.findViewById(R.id.change_password_loader)
|
||||
val views = DialogChangePasswordBinding.bind(view)
|
||||
|
||||
var passwordShown = false
|
||||
|
||||
showPassword.setOnClickListener {
|
||||
views.changePasswordShowPasswords.setOnClickListener {
|
||||
passwordShown = !passwordShown
|
||||
|
||||
oldPasswordText.showPassword(passwordShown)
|
||||
newPasswordText.showPassword(passwordShown)
|
||||
confirmNewPasswordText.showPassword(passwordShown)
|
||||
views.changePasswordOldPwdText.showPassword(passwordShown)
|
||||
views.changePasswordNewPwdText.showPassword(passwordShown)
|
||||
views.changePasswordConfirmNewPwdText.showPassword(passwordShown)
|
||||
|
||||
showPassword.setImageResource(if (passwordShown) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
views.changePasswordShowPasswords.setImageResource(if (passwordShown) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
|
||||
val dialog = AlertDialog.Builder(activity)
|
||||
|
@ -389,53 +383,53 @@ class VectorSettingsGeneralFragment @Inject constructor(
|
|||
updateButton.isEnabled = false
|
||||
|
||||
fun updateUi() {
|
||||
val oldPwd = oldPasswordText.text.toString()
|
||||
val newPwd = newPasswordText.text.toString()
|
||||
val newConfirmPwd = confirmNewPasswordText.text.toString()
|
||||
val oldPwd = views.changePasswordOldPwdText.text.toString()
|
||||
val newPwd = views.changePasswordNewPwdText.text.toString()
|
||||
val newConfirmPwd = views.changePasswordConfirmNewPwdText.text.toString()
|
||||
|
||||
updateButton.isEnabled = oldPwd.isNotEmpty() && newPwd.isNotEmpty() && newPwd == newConfirmPwd
|
||||
|
||||
if (newPwd.isNotEmpty() && newConfirmPwd.isNotEmpty() && newPwd != newConfirmPwd) {
|
||||
confirmNewPasswordTil.error = getString(R.string.passwords_do_not_match)
|
||||
views.changePasswordConfirmNewPwdTil.error = getString(R.string.passwords_do_not_match)
|
||||
}
|
||||
}
|
||||
|
||||
oldPasswordText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
views.changePasswordOldPwdText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
oldPasswordTil.error = null
|
||||
views.changePasswordOldPwdTil.error = null
|
||||
updateUi()
|
||||
}
|
||||
})
|
||||
|
||||
newPasswordText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
views.changePasswordNewPwdText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
confirmNewPasswordTil.error = null
|
||||
views.changePasswordConfirmNewPwdTil.error = null
|
||||
updateUi()
|
||||
}
|
||||
})
|
||||
|
||||
confirmNewPasswordText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
views.changePasswordConfirmNewPwdText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
confirmNewPasswordTil.error = null
|
||||
views.changePasswordConfirmNewPwdTil.error = null
|
||||
updateUi()
|
||||
}
|
||||
})
|
||||
|
||||
fun showPasswordLoadingView(toShow: Boolean) {
|
||||
if (toShow) {
|
||||
showPassword.isEnabled = false
|
||||
oldPasswordText.isEnabled = false
|
||||
newPasswordText.isEnabled = false
|
||||
confirmNewPasswordText.isEnabled = false
|
||||
changePasswordLoader.isVisible = true
|
||||
views.changePasswordShowPasswords.isEnabled = false
|
||||
views.changePasswordOldPwdText.isEnabled = false
|
||||
views.changePasswordNewPwdText.isEnabled = false
|
||||
views.changePasswordConfirmNewPwdText.isEnabled = false
|
||||
views.changePasswordLoader.isVisible = true
|
||||
updateButton.isEnabled = false
|
||||
cancelButton.isEnabled = false
|
||||
} else {
|
||||
showPassword.isEnabled = true
|
||||
oldPasswordText.isEnabled = true
|
||||
newPasswordText.isEnabled = true
|
||||
confirmNewPasswordText.isEnabled = true
|
||||
changePasswordLoader.isVisible = false
|
||||
views.changePasswordShowPasswords.isEnabled = true
|
||||
views.changePasswordOldPwdText.isEnabled = true
|
||||
views.changePasswordNewPwdText.isEnabled = true
|
||||
views.changePasswordConfirmNewPwdText.isEnabled = true
|
||||
views.changePasswordLoader.isVisible = false
|
||||
updateButton.isEnabled = true
|
||||
cancelButton.isEnabled = true
|
||||
}
|
||||
|
@ -444,13 +438,13 @@ class VectorSettingsGeneralFragment @Inject constructor(
|
|||
updateButton.setOnClickListener {
|
||||
if (passwordShown) {
|
||||
// Hide passwords during processing
|
||||
showPassword.performClick()
|
||||
views.changePasswordShowPasswords.performClick()
|
||||
}
|
||||
|
||||
view.hideKeyboard()
|
||||
|
||||
val oldPwd = oldPasswordText.text.toString()
|
||||
val newPwd = newPasswordText.text.toString()
|
||||
val oldPwd = views.changePasswordOldPwdText.text.toString()
|
||||
val newPwd = views.changePasswordNewPwdText.text.toString()
|
||||
|
||||
showPasswordLoadingView(true)
|
||||
lifecycleScope.launch {
|
||||
|
@ -466,9 +460,9 @@ class VectorSettingsGeneralFragment @Inject constructor(
|
|||
activity.toast(R.string.settings_password_updated)
|
||||
}, { failure ->
|
||||
if (failure.isInvalidPassword()) {
|
||||
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password)
|
||||
views.changePasswordOldPwdTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password)
|
||||
} else {
|
||||
oldPasswordTil.error = getString(R.string.settings_fail_to_update_password)
|
||||
views.changePasswordOldPwdTil.error = getString(R.string.settings_fail_to_update_password)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -63,71 +64,70 @@ class VectorSettingsNotificationsTroubleshootFragment @Inject constructor(
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
val layoutManager = LinearLayoutManager(context)
|
||||
troubleshoot_test_recycler_view.layoutManager = layoutManager
|
||||
views.troubleshootTestRecyclerView.layoutManager = layoutManager
|
||||
|
||||
val dividerItemDecoration = DividerItemDecoration(troubleshoot_test_recycler_view.context,
|
||||
layoutManager.orientation)
|
||||
troubleshoot_test_recycler_view.addItemDecoration(dividerItemDecoration)
|
||||
val dividerItemDecoration = DividerItemDecoration(view.context, layoutManager.orientation)
|
||||
views.troubleshootTestRecyclerView.addItemDecoration(dividerItemDecoration)
|
||||
|
||||
troubleshoot_summ_button.debouncedClicks {
|
||||
views.troubleshootSummButton.debouncedClicks {
|
||||
bugReporter.openBugReportScreen(requireActivity())
|
||||
}
|
||||
|
||||
troubleshoot_run_button.debouncedClicks {
|
||||
views.troubleshootRunButton.debouncedClicks {
|
||||
testManager?.retry(testStartForActivityResult)
|
||||
}
|
||||
startUI()
|
||||
}
|
||||
|
||||
private fun startUI() {
|
||||
toubleshoot_summ_description.text = getString(R.string.settings_troubleshoot_diagnostic_running_status, 0, 0)
|
||||
views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_running_status, 0, 0)
|
||||
testManager = testManagerFactory.create(this)
|
||||
testManager?.statusListener = { troubleshootTestManager ->
|
||||
if (isAdded) {
|
||||
TransitionManager.beginDelayedTransition(troubleshoot_bottom_view)
|
||||
TransitionManager.beginDelayedTransition(views.troubleshootBottomView)
|
||||
when (troubleshootTestManager.diagStatus) {
|
||||
TroubleshootTest.TestStatus.NOT_STARTED -> {
|
||||
toubleshoot_summ_description.text = ""
|
||||
troubleshoot_summ_button.visibility = View.GONE
|
||||
troubleshoot_run_button.visibility = View.VISIBLE
|
||||
views.toubleshootSummDescription.text = ""
|
||||
views.troubleshootSummButton.visibility = View.GONE
|
||||
views.troubleshootRunButton.visibility = View.VISIBLE
|
||||
}
|
||||
TroubleshootTest.TestStatus.RUNNING,
|
||||
TroubleshootTest.TestStatus.WAITING_FOR_USER -> {
|
||||
val size = troubleshootTestManager.testListSize
|
||||
val currentTestIndex = troubleshootTestManager.currentTestIndex
|
||||
toubleshoot_summ_description.text = getString(
|
||||
views.toubleshootSummDescription.text = getString(
|
||||
R.string.settings_troubleshoot_diagnostic_running_status,
|
||||
currentTestIndex,
|
||||
size
|
||||
)
|
||||
troubleshoot_summ_button.visibility = View.GONE
|
||||
troubleshoot_run_button.visibility = View.GONE
|
||||
views.troubleshootSummButton.visibility = View.GONE
|
||||
views.troubleshootRunButton.visibility = View.GONE
|
||||
}
|
||||
TroubleshootTest.TestStatus.FAILED -> {
|
||||
// check if there are quick fixes
|
||||
val hasQuickFix = testManager?.hasQuickFix().orFalse()
|
||||
if (hasQuickFix) {
|
||||
toubleshoot_summ_description.text = getString(R.string.settings_troubleshoot_diagnostic_failure_status_with_quickfix)
|
||||
views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_failure_status_with_quickfix)
|
||||
} else {
|
||||
toubleshoot_summ_description.text = getString(R.string.settings_troubleshoot_diagnostic_failure_status_no_quickfix)
|
||||
views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_failure_status_no_quickfix)
|
||||
}
|
||||
troubleshoot_summ_button.visibility = View.VISIBLE
|
||||
troubleshoot_run_button.visibility = View.VISIBLE
|
||||
views.troubleshootSummButton.visibility = View.VISIBLE
|
||||
views.troubleshootRunButton.visibility = View.VISIBLE
|
||||
}
|
||||
TroubleshootTest.TestStatus.SUCCESS -> {
|
||||
toubleshoot_summ_description.text = getString(R.string.settings_troubleshoot_diagnostic_success_status)
|
||||
troubleshoot_summ_button.visibility = View.VISIBLE
|
||||
troubleshoot_run_button.visibility = View.VISIBLE
|
||||
views.toubleshootSummDescription.text = getString(R.string.settings_troubleshoot_diagnostic_success_status)
|
||||
views.troubleshootSummButton.visibility = View.VISIBLE
|
||||
views.troubleshootRunButton.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
troubleshoot_test_recycler_view.adapter = testManager?.adapter
|
||||
views.troubleshootTestRecyclerView.adapter = testManager?.adapter
|
||||
testManager?.runDiagnostic(testStartForActivityResult)
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
troubleshoot_test_recycler_view.cleanup()
|
||||
views.troubleshootTestRecyclerView.cleanup()
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ import im.vector.app.core.preference.VectorPreferenceCategory
|
|||
import im.vector.app.core.utils.copyToClipboard
|
||||
import im.vector.app.core.utils.openFileSelection
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.databinding.DialogImportE2eKeysBinding
|
||||
import im.vector.app.features.crypto.keys.KeysExporter
|
||||
import im.vector.app.features.crypto.keys.KeysImporter
|
||||
import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivity
|
||||
|
@ -447,42 +448,37 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
|
|||
val filename = getFilenameFromUri(appContext, uri)
|
||||
|
||||
val dialogLayout = thisActivity.layoutInflater.inflate(R.layout.dialog_import_e2e_keys, null)
|
||||
|
||||
val textView = dialogLayout.findViewById<TextView>(R.id.dialog_e2e_keys_passphrase_filename)
|
||||
val views = DialogImportE2eKeysBinding.bind(dialogLayout)
|
||||
|
||||
if (filename.isNullOrBlank()) {
|
||||
textView.isVisible = false
|
||||
views.dialogE2eKeysPassphraseFilename.isVisible = false
|
||||
} else {
|
||||
textView.isVisible = true
|
||||
textView.text = getString(R.string.import_e2e_keys_from_file, filename)
|
||||
views.dialogE2eKeysPassphraseFilename.isVisible = true
|
||||
views.dialogE2eKeysPassphraseFilename.text = getString(R.string.import_e2e_keys_from_file, filename)
|
||||
}
|
||||
|
||||
val builder = AlertDialog.Builder(thisActivity)
|
||||
.setTitle(R.string.encryption_import_room_keys)
|
||||
.setView(dialogLayout)
|
||||
|
||||
val passPhraseEditText = dialogLayout.findViewById<TextInputEditText>(R.id.dialog_e2e_keys_passphrase_edit_text)
|
||||
val importButton = dialogLayout.findViewById<Button>(R.id.dialog_e2e_keys_import_button)
|
||||
|
||||
val showPassword = dialogLayout.findViewById<ImageView>(R.id.importDialogShowPassword)
|
||||
var passwordVisible = false
|
||||
|
||||
showPassword.setOnClickListener {
|
||||
views.importDialogShowPassword.setOnClickListener {
|
||||
passwordVisible = !passwordVisible
|
||||
passPhraseEditText.showPassword(passwordVisible)
|
||||
showPassword.setImageResource(if (passwordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
views.dialogE2eKeysPassphraseEditText.showPassword(passwordVisible)
|
||||
views.importDialogShowPassword.setImageResource(if (passwordVisible) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
|
||||
passPhraseEditText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
views.dialogE2eKeysPassphraseEditText.addTextChangedListener(object : SimpleTextWatcher() {
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
|
||||
importButton.isEnabled = !passPhraseEditText.text.isNullOrEmpty()
|
||||
views.dialogE2eKeysImportButton.isEnabled = !views.dialogE2eKeysPassphraseEditText.text.isNullOrEmpty()
|
||||
}
|
||||
})
|
||||
|
||||
val importDialog = builder.show()
|
||||
|
||||
importButton.setOnClickListener {
|
||||
val password = passPhraseEditText.text.toString()
|
||||
views.dialogE2eKeysImportButton.setOnClickListener {
|
||||
val password = views.dialogE2eKeysPassphraseEditText.text.toString()
|
||||
|
||||
displayLoadingView()
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
|
@ -73,23 +74,23 @@ class DeactivateAccountFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setupUi() {
|
||||
deactivateAccountPassword.textChanges()
|
||||
views.deactivateAccountPassword.textChanges()
|
||||
.subscribe {
|
||||
deactivateAccountPasswordTil.error = null
|
||||
deactivateAccountSubmit.isEnabled = it.isNotEmpty()
|
||||
views.deactivateAccountPasswordTil.error = null
|
||||
views.deactivateAccountSubmit.isEnabled = it.isNotEmpty()
|
||||
}
|
||||
.disposeOnDestroyView()
|
||||
}
|
||||
|
||||
private fun setupViewListeners() {
|
||||
deactivateAccountPasswordReveal.setOnClickListener {
|
||||
views.deactivateAccountPasswordReveal.setOnClickListener {
|
||||
viewModel.handle(DeactivateAccountAction.TogglePassword)
|
||||
}
|
||||
|
||||
deactivateAccountSubmit.debouncedClicks {
|
||||
views.deactivateAccountSubmit.debouncedClicks {
|
||||
viewModel.handle(DeactivateAccountAction.DeactivateAccount(
|
||||
deactivateAccountPassword.text.toString(),
|
||||
deactivateAccountEraseCheckbox.isChecked))
|
||||
views.deactivateAccountPassword.text.toString(),
|
||||
views.deactivateAccountEraseCheckbox.isChecked))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,11 +103,11 @@ class DeactivateAccountFragment @Inject constructor(
|
|||
}
|
||||
DeactivateAccountViewEvents.EmptyPassword -> {
|
||||
settingsActivity?.ignoreInvalidTokenError = false
|
||||
deactivateAccountPasswordTil.error = getString(R.string.error_empty_field_your_password)
|
||||
views.deactivateAccountPasswordTil.error = getString(R.string.error_empty_field_your_password)
|
||||
}
|
||||
DeactivateAccountViewEvents.InvalidPassword -> {
|
||||
settingsActivity?.ignoreInvalidTokenError = false
|
||||
deactivateAccountPasswordTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password)
|
||||
views.deactivateAccountPasswordTil.error = getString(R.string.settings_fail_to_update_password_invalid_current_password)
|
||||
}
|
||||
is DeactivateAccountViewEvents.OtherFailure -> {
|
||||
settingsActivity?.ignoreInvalidTokenError = false
|
||||
|
@ -119,7 +120,7 @@ class DeactivateAccountFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun invalidate() = withState(viewModel) { state ->
|
||||
deactivateAccountPassword.showPassword(state.passwordShown)
|
||||
deactivateAccountPasswordReveal.setImageResource(if (state.passwordShown) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
views.deactivateAccountPassword.showPassword(state.passwordShown)
|
||||
views.deactivateAccountPasswordReveal.setImageResource(if (state.passwordShown) R.drawable.ic_eye_closed else R.drawable.ic_eye)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,10 @@ package im.vector.app.features.settings.troubleshoot
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.ImageView
|
||||
import android.widget.ProgressBar
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import im.vector.app.R
|
||||
|
@ -43,68 +47,73 @@ class NotificationTroubleshootRecyclerViewAdapter(val tests: ArrayList<Troublesh
|
|||
override fun getItemCount(): Int = tests.size
|
||||
|
||||
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val troubleshootProgressBar = itemView.findViewById<ProgressBar>(R.id.troubleshootProgressBar)
|
||||
private val troubleshootTestTitle = itemView.findViewById<TextView>(R.id.troubleshootTestTitle)
|
||||
private val troubleshootTestDescription = itemView.findViewById<TextView>(R.id.troubleshootTestDescription)
|
||||
private val troubleshootStatusIcon = itemView.findViewById<ImageView>(R.id.troubleshootStatusIcon)
|
||||
private val troubleshootTestButton = itemView.findViewById<Button>(R.id.troubleshootTestButton)
|
||||
|
||||
fun bind(test: TroubleshootTest) {
|
||||
val context = itemView.context
|
||||
itemView.troubleshootTestTitle.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_primary))
|
||||
itemView.troubleshootTestDescription.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary))
|
||||
troubleshootTestTitle.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_primary))
|
||||
troubleshootTestDescription.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary))
|
||||
|
||||
when (test.status) {
|
||||
TroubleshootTest.TestStatus.NOT_STARTED -> {
|
||||
itemView.troubleshootTestTitle.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary))
|
||||
troubleshootTestTitle.setTextColor(ThemeUtils.getColor(context, R.attr.riotx_text_secondary))
|
||||
|
||||
itemView.troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
itemView.troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
itemView.troubleshootStatusIcon.setImageResource(R.drawable.unit_test)
|
||||
troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
troubleshootStatusIcon.setImageResource(R.drawable.unit_test)
|
||||
}
|
||||
TroubleshootTest.TestStatus.WAITING_FOR_USER -> {
|
||||
itemView.troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
itemView.troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
val infoColor = ContextCompat.getColor(context, R.color.vector_info_color)
|
||||
val drawable = ContextCompat.getDrawable(itemView.context, R.drawable.ic_notification_privacy_warning)?.apply {
|
||||
ThemeUtils.tintDrawableWithColor(this, infoColor)
|
||||
}
|
||||
itemView.troubleshootStatusIcon.setImageDrawable(drawable)
|
||||
itemView.troubleshootTestDescription.setTextColor(infoColor)
|
||||
troubleshootStatusIcon.setImageDrawable(drawable)
|
||||
troubleshootTestDescription.setTextColor(infoColor)
|
||||
}
|
||||
TroubleshootTest.TestStatus.RUNNING -> {
|
||||
itemView.troubleshootProgressBar.visibility = View.VISIBLE
|
||||
itemView.troubleshootStatusIcon.visibility = View.INVISIBLE
|
||||
troubleshootProgressBar.visibility = View.VISIBLE
|
||||
troubleshootStatusIcon.visibility = View.INVISIBLE
|
||||
}
|
||||
TroubleshootTest.TestStatus.FAILED -> {
|
||||
itemView.troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
itemView.troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
itemView.troubleshootStatusIcon.setImageResource(R.drawable.unit_test_ko)
|
||||
troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
troubleshootStatusIcon.setImageResource(R.drawable.unit_test_ko)
|
||||
|
||||
itemView.troubleshootStatusIcon.imageTintList = null
|
||||
troubleshootStatusIcon.imageTintList = null
|
||||
|
||||
itemView.troubleshootTestDescription.setTextColor(ContextCompat.getColor(context, R.color.riotx_notice))
|
||||
troubleshootTestDescription.setTextColor(ContextCompat.getColor(context, R.color.riotx_notice))
|
||||
}
|
||||
TroubleshootTest.TestStatus.SUCCESS -> {
|
||||
itemView.troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
itemView.troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
itemView.troubleshootStatusIcon.setImageResource(R.drawable.unit_test_ok)
|
||||
troubleshootProgressBar.visibility = View.INVISIBLE
|
||||
troubleshootStatusIcon.visibility = View.VISIBLE
|
||||
troubleshootStatusIcon.setImageResource(R.drawable.unit_test_ok)
|
||||
}
|
||||
}
|
||||
|
||||
val quickFix = test.quickFix
|
||||
if (quickFix != null) {
|
||||
itemView.troubleshootTestButton.setText(test.quickFix!!.title)
|
||||
itemView.troubleshootTestButton.setOnClickListener { _ ->
|
||||
troubleshootTestButton.setText(test.quickFix!!.title)
|
||||
troubleshootTestButton.setOnClickListener { _ ->
|
||||
test.quickFix!!.doFix()
|
||||
}
|
||||
itemView.troubleshootTestButton.visibility = View.VISIBLE
|
||||
troubleshootTestButton.visibility = View.VISIBLE
|
||||
} else {
|
||||
itemView.troubleshootTestButton.visibility = View.GONE
|
||||
troubleshootTestButton.visibility = View.GONE
|
||||
}
|
||||
|
||||
itemView.troubleshootTestTitle.setText(test.titleResId)
|
||||
troubleshootTestTitle.setText(test.titleResId)
|
||||
val description = test.description
|
||||
if (description == null) {
|
||||
itemView.troubleshootTestDescription.visibility = View.GONE
|
||||
troubleshootTestDescription.visibility = View.GONE
|
||||
} else {
|
||||
itemView.troubleshootTestDescription.visibility = View.VISIBLE
|
||||
itemView.troubleshootTestDescription.text = description
|
||||
troubleshootTestDescription.visibility = View.VISIBLE
|
||||
troubleshootTestDescription.text = description
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.Loading
|
||||
import com.airbnb.mvrx.Success
|
||||
|
@ -58,10 +59,10 @@ class ReviewTermsFragment @Inject constructor(
|
|||
}
|
||||
|
||||
termsController.listener = this
|
||||
reviewTermsRecyclerView.configureWith(termsController)
|
||||
views.reviewTermsRecyclerView.configureWith(termsController)
|
||||
|
||||
reviewTermsAccept.onClick { reviewTermsViewModel.handle(ReviewTermsAction.Accept) }
|
||||
reviewTermsDecline.onClick { activity?.finish() }
|
||||
views.reviewTermsAccept.onClick { reviewTermsViewModel.handle(ReviewTermsAction.Accept) }
|
||||
views.reviewTermsDecline.onClick { activity?.finish() }
|
||||
|
||||
reviewTermsViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
|
@ -79,7 +80,7 @@ class ReviewTermsFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
reviewTermsRecyclerView.cleanup()
|
||||
views.reviewTermsRecyclerView.cleanup()
|
||||
termsController.listener = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
@ -94,11 +95,11 @@ class ReviewTermsFragment @Inject constructor(
|
|||
|
||||
when (state.termsList) {
|
||||
is Loading -> {
|
||||
reviewTermsBottomBar.isVisible = false
|
||||
views.reviewTermsBottomBar.isVisible = false
|
||||
}
|
||||
is Success -> {
|
||||
reviewTermsBottomBar.isVisible = true
|
||||
reviewTermsAccept.isEnabled = state.termsList.invoke().all { it.accepted }
|
||||
views.reviewTermsBottomBar.isVisible = true
|
||||
views.reviewTermsAccept.isEnabled = state.termsList.invoke().all { it.accepted }
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
|
|
@ -57,11 +57,11 @@ class ScanUserCodeFragment @Inject constructor()
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
userCodeMyCodeButton.debouncedClicks {
|
||||
views.userCodeMyCodeButton.debouncedClicks {
|
||||
sharedViewModel.handle(UserCodeActions.SwitchMode(UserCodeState.Mode.SHOW))
|
||||
}
|
||||
|
||||
userCodeOpenGalleryButton.debouncedClicks {
|
||||
views.userCodeOpenGalleryButton.debouncedClicks {
|
||||
MultiPicker.get(MultiPicker.IMAGE).single().startWith(pickImageActivityResultLauncher)
|
||||
}
|
||||
}
|
||||
|
@ -94,11 +94,11 @@ class ScanUserCodeFragment @Inject constructor()
|
|||
}
|
||||
|
||||
private fun startCamera() {
|
||||
userCodeScannerView.startCamera()
|
||||
userCodeScannerView.setAutoFocus(autoFocus)
|
||||
userCodeScannerView.debouncedClicks {
|
||||
views.userCodeScannerView.startCamera()
|
||||
views.userCodeScannerView.setAutoFocus(autoFocus)
|
||||
views.userCodeScannerView.debouncedClicks {
|
||||
this.autoFocus = !autoFocus
|
||||
userCodeScannerView.setAutoFocus(autoFocus)
|
||||
views.userCodeScannerView.setAutoFocus(autoFocus)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,7 +112,7 @@ class ScanUserCodeFragment @Inject constructor()
|
|||
override fun onResume() {
|
||||
super.onResume()
|
||||
// Register ourselves as a handler for scan results.
|
||||
userCodeScannerView.setResultHandler(this)
|
||||
views.userCodeScannerView.setResultHandler(this)
|
||||
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA)) {
|
||||
startCamera()
|
||||
}
|
||||
|
@ -120,9 +120,9 @@ class ScanUserCodeFragment @Inject constructor()
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
userCodeScannerView.setResultHandler(null)
|
||||
views.userCodeScannerView.setResultHandler(null)
|
||||
// Stop camera on pause
|
||||
userCodeScannerView.stopCamera()
|
||||
views.userCodeScannerView.stopCamera()
|
||||
}
|
||||
|
||||
override fun handleResult(result: Result?) {
|
||||
|
|
|
@ -78,9 +78,9 @@ class WidgetFragment @Inject constructor() :
|
|||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
setHasOptionsMenu(true)
|
||||
widgetWebView.setupForWidget(this)
|
||||
views.widgetWebView.setupForWidget(this)
|
||||
if (fragmentArgs.kind.isAdmin()) {
|
||||
viewModel.getPostAPIMediator().setWebView(widgetWebView)
|
||||
viewModel.getPostAPIMediator().setWebView(views.widgetWebView)
|
||||
}
|
||||
viewModel.observeViewEvents {
|
||||
Timber.v("Observed view events: $it")
|
||||
|
@ -114,12 +114,12 @@ class WidgetFragment @Inject constructor() :
|
|||
if (fragmentArgs.kind.isAdmin()) {
|
||||
viewModel.getPostAPIMediator().clearWebView()
|
||||
}
|
||||
widgetWebView.clearAfterWidget()
|
||||
views.widgetWebView.clearAfterWidget()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
widgetWebView?.let {
|
||||
views.widgetWebView?.let {
|
||||
it.resumeTimers()
|
||||
it.onResume()
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ class WidgetFragment @Inject constructor() :
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
widgetWebView?.let {
|
||||
views.widgetWebView?.let {
|
||||
it.pauseTimers()
|
||||
it.onPause()
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ class WidgetFragment @Inject constructor() :
|
|||
return@withState true
|
||||
}
|
||||
R.id.action_refresh -> if (state.formattedURL.complete) {
|
||||
widgetWebView.reload()
|
||||
views.widgetWebView.reload()
|
||||
return@withState true
|
||||
}
|
||||
R.id.action_widget_open_ext -> if (state.formattedURL.complete) {
|
||||
|
@ -183,8 +183,8 @@ class WidgetFragment @Inject constructor() :
|
|||
|
||||
override fun onBackPressed(toolbarButton: Boolean): Boolean = withState(viewModel) { state ->
|
||||
if (state.formattedURL.complete) {
|
||||
if (widgetWebView.canGoBack()) {
|
||||
widgetWebView.goBack()
|
||||
if (views.widgetWebView.canGoBack()) {
|
||||
views.widgetWebView.goBack()
|
||||
return@withState true
|
||||
}
|
||||
}
|
||||
|
@ -196,37 +196,37 @@ class WidgetFragment @Inject constructor() :
|
|||
when (state.formattedURL) {
|
||||
is Incomplete -> {
|
||||
setStateError(null)
|
||||
widgetWebView.isInvisible = true
|
||||
widgetProgressBar.isIndeterminate = true
|
||||
widgetProgressBar.isVisible = true
|
||||
views.widgetWebView.isInvisible = true
|
||||
views.widgetProgressBar.isIndeterminate = true
|
||||
views.widgetProgressBar.isVisible = true
|
||||
}
|
||||
is Success -> {
|
||||
setStateError(null)
|
||||
when (state.webviewLoadedUrl) {
|
||||
Uninitialized -> {
|
||||
widgetWebView.isInvisible = true
|
||||
views.widgetWebView.isInvisible = true
|
||||
}
|
||||
is Loading -> {
|
||||
setStateError(null)
|
||||
widgetWebView.isInvisible = false
|
||||
widgetProgressBar.isIndeterminate = true
|
||||
widgetProgressBar.isVisible = true
|
||||
views.widgetWebView.isInvisible = false
|
||||
views.widgetProgressBar.isIndeterminate = true
|
||||
views.widgetProgressBar.isVisible = true
|
||||
}
|
||||
is Success -> {
|
||||
widgetWebView.isInvisible = false
|
||||
widgetProgressBar.isVisible = false
|
||||
views.widgetWebView.isInvisible = false
|
||||
views.widgetProgressBar.isVisible = false
|
||||
setStateError(null)
|
||||
}
|
||||
is Fail -> {
|
||||
widgetProgressBar.isInvisible = true
|
||||
views.widgetProgressBar.isInvisible = true
|
||||
setStateError(state.webviewLoadedUrl.error.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
is Fail -> {
|
||||
// we need to show Error
|
||||
widgetWebView.isInvisible = true
|
||||
widgetProgressBar.isVisible = false
|
||||
views.widgetWebView.isInvisible = true
|
||||
views.widgetProgressBar.isVisible = false
|
||||
setStateError(state.formattedURL.error.message)
|
||||
}
|
||||
}
|
||||
|
@ -282,19 +282,19 @@ class WidgetFragment @Inject constructor() :
|
|||
}
|
||||
|
||||
private fun loadFormattedUrl(event: WidgetViewEvents.OnURLFormatted) {
|
||||
widgetWebView.clearHistory()
|
||||
widgetWebView.loadUrl(event.formattedURL)
|
||||
views.widgetWebView.clearHistory()
|
||||
views.widgetWebView.loadUrl(event.formattedURL)
|
||||
}
|
||||
|
||||
private fun setStateError(message: String?) {
|
||||
if (message == null) {
|
||||
widgetErrorLayout.isVisible = false
|
||||
widgetErrorText.text = null
|
||||
views.widgetErrorLayout.isVisible = false
|
||||
views.widgetErrorText.text = null
|
||||
} else {
|
||||
widgetProgressBar.isVisible = false
|
||||
widgetErrorLayout.isVisible = true
|
||||
widgetWebView.isInvisible = true
|
||||
widgetErrorText.text = getString(R.string.room_widget_failed_to_load, message)
|
||||
views.widgetProgressBar.isVisible = false
|
||||
views.widgetErrorLayout.isVisible = true
|
||||
views.widgetWebView.isInvisible = true
|
||||
views.widgetErrorText.text = getString(R.string.room_widget_failed_to_load, message)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,9 @@ import android.content.Context
|
|||
import android.content.res.ColorStateList
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.util.AttributeSet
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
|
@ -31,6 +33,9 @@ class SignOutBottomSheetActionButton @JvmOverloads constructor(
|
|||
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
|
||||
) : LinearLayout(context, attrs, defStyleAttr) {
|
||||
|
||||
private val actionIconImageView: ImageView
|
||||
private val actionTitleText: TextView
|
||||
|
||||
var action: (() -> Unit)? = null
|
||||
|
||||
var title: String? = null
|
||||
|
@ -72,9 +77,12 @@ class SignOutBottomSheetActionButton @JvmOverloads constructor(
|
|||
tint = typedArray.getColor(R.styleable.SignOutBottomSheetActionButton_iconTint, ThemeUtils.getColor(context, android.R.attr.textColor))
|
||||
textColor = typedArray.getColor(R.styleable.SignOutBottomSheetActionButton_textColor, ThemeUtils.getColor(context, android.R.attr.textColor))
|
||||
|
||||
actionIconImageView = findViewById(R.id.actionIconImageView)
|
||||
actionTitleText = findViewById(R.id.actionTitleText)
|
||||
|
||||
typedArray.recycle()
|
||||
|
||||
signedOutActionClickable.setOnClickListener {
|
||||
setOnClickListener {
|
||||
action?.invoke()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<include layout="@layout/fragment_room_setting_generic" />
|
||||
<include
|
||||
android:id="@+id/room_setting_generic"
|
||||
layout="@layout/fragment_room_setting_generic" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/inviteUsersButton"
|
||||
|
|
Loading…
Reference in New Issue