Power level: use confirmation dialog
This commit is contained in:
parent
d2dba1826d
commit
a8ae4ddde8
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2020 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.riotx.core.dialogs
|
||||
|
||||
import android.app.Activity
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import im.vector.riotx.R
|
||||
import kotlinx.android.synthetic.main.dialog_confirmation_with_reason.view.*
|
||||
|
||||
object ConfirmationDialogBuilder {
|
||||
|
||||
fun show(activity: Activity,
|
||||
askForReason: Boolean,
|
||||
@StringRes titleRes: Int,
|
||||
@StringRes confirmationRes: Int,
|
||||
@StringRes positiveRes: Int,
|
||||
@StringRes reasonHintRes: Int,
|
||||
confirmation: (String?) -> Unit) {
|
||||
val layout = activity.layoutInflater.inflate(R.layout.dialog_confirmation_with_reason, null)
|
||||
layout.dialogConfirmationText.setText(confirmationRes)
|
||||
|
||||
layout.dialogReasonCheck.isVisible = askForReason
|
||||
layout.dialogReasonTextInputLayout.isVisible = askForReason
|
||||
|
||||
layout.dialogReasonCheck.setOnCheckedChangeListener { _, isChecked ->
|
||||
layout.dialogReasonTextInputLayout.isEnabled = isChecked
|
||||
}
|
||||
if (askForReason && reasonHintRes != 0) {
|
||||
layout.dialogReasonInput.setHint(reasonHintRes)
|
||||
}
|
||||
|
||||
AlertDialog.Builder(activity)
|
||||
.setTitle(titleRes)
|
||||
.setView(layout)
|
||||
.setPositiveButton(positiveRes) { _, _ ->
|
||||
val reason = layout.dialogReasonInput.text.toString()
|
||||
.takeIf { askForReason }
|
||||
?.takeIf { layout.dialogReasonCheck.isChecked }
|
||||
?.takeIf { it.isNotBlank() }
|
||||
confirmation(reason)
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
}
|
|
@ -18,18 +18,11 @@ package im.vector.riotx.core.ui.views
|
|||
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.text.SpannableString
|
||||
import android.text.TextPaint
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.text.style.ClickableSpan
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.RelativeLayout
|
||||
import androidx.core.content.ContextCompat
|
||||
import im.vector.matrix.android.api.failure.MatrixError
|
||||
import im.vector.matrix.android.api.session.events.model.Event
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.error.ResourceLimitErrorFormatter
|
||||
import im.vector.riotx.core.utils.DimensionConverter
|
||||
import im.vector.riotx.features.themes.ThemeUtils
|
||||
import kotlinx.android.synthetic.main.view_notification_area.view.*
|
||||
|
|
|
@ -56,10 +56,8 @@ import com.airbnb.mvrx.Success
|
|||
import com.airbnb.mvrx.args
|
||||
import com.airbnb.mvrx.fragmentViewModel
|
||||
import com.airbnb.mvrx.withState
|
||||
import com.google.android.material.checkbox.MaterialCheckBox
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.textfield.TextInputEditText
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.jakewharton.rxbinding3.widget.textChanges
|
||||
import im.vector.matrix.android.api.MatrixCallback
|
||||
import im.vector.matrix.android.api.permalinks.PermalinkFactory
|
||||
|
@ -88,6 +86,7 @@ import im.vector.matrix.android.api.util.MatrixItem
|
|||
import im.vector.matrix.android.api.util.toMatrixItem
|
||||
import im.vector.matrix.android.internal.crypto.attachments.toElementToDecrypt
|
||||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.dialogs.ConfirmationDialogBuilder
|
||||
import im.vector.riotx.core.dialogs.withColoredButton
|
||||
import im.vector.riotx.core.epoxy.LayoutManagerStateRestorer
|
||||
import im.vector.riotx.core.extensions.cleanup
|
||||
|
@ -862,28 +861,17 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun promptConfirmationToRedactEvent(action: EventSharedAction.Redact) {
|
||||
val layout = requireActivity().layoutInflater.inflate(R.layout.dialog_delete_event, null)
|
||||
val reasonCheckBox = layout.findViewById<MaterialCheckBox>(R.id.deleteEventReasonCheck)
|
||||
val reasonTextInputLayout = layout.findViewById<TextInputLayout>(R.id.deleteEventReasonTextInputLayout)
|
||||
val reasonInput = layout.findViewById<TextInputEditText>(R.id.deleteEventReasonInput)
|
||||
|
||||
reasonCheckBox.isVisible = action.askForReason
|
||||
reasonTextInputLayout.isVisible = action.askForReason
|
||||
|
||||
reasonCheckBox.setOnCheckedChangeListener { _, isChecked -> reasonTextInputLayout.isEnabled = isChecked }
|
||||
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(R.string.delete_event_dialog_title)
|
||||
.setView(layout)
|
||||
.setPositiveButton(R.string.remove) { _, _ ->
|
||||
val reason = reasonInput.text.toString()
|
||||
.takeIf { action.askForReason }
|
||||
?.takeIf { reasonCheckBox.isChecked }
|
||||
?.takeIf { it.isNotBlank() }
|
||||
ConfirmationDialogBuilder
|
||||
.show(
|
||||
activity = requireActivity(),
|
||||
askForReason = action.askForReason,
|
||||
confirmationRes = R.string.delete_event_dialog_content,
|
||||
positiveRes = R.string.remove,
|
||||
reasonHintRes = R.string.delete_event_dialog_reason_hint,
|
||||
titleRes = R.string.delete_event_dialog_title
|
||||
) { reason ->
|
||||
roomDetailViewModel.handle(RoomDetailAction.RedactAction(action.eventId, reason))
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun displayRoomDetailActionFailure(result: RoomDetailViewEvents.ActionFailure) {
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.os.Bundle
|
|||
import android.os.Parcelable
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.core.view.isVisible
|
||||
import com.airbnb.mvrx.Fail
|
||||
|
@ -35,6 +34,7 @@ import im.vector.matrix.android.api.util.MatrixItem
|
|||
import im.vector.riotx.R
|
||||
import im.vector.riotx.core.animations.AppBarStateChangeListener
|
||||
import im.vector.riotx.core.animations.MatrixItemAppBarStateChangeListener
|
||||
import im.vector.riotx.core.dialogs.ConfirmationDialogBuilder
|
||||
import im.vector.riotx.core.extensions.cleanup
|
||||
import im.vector.riotx.core.extensions.configureWith
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
|
@ -221,9 +221,32 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
|
||||
// RoomMemberProfileController.Callback
|
||||
|
||||
override fun onIgnoreClicked() {
|
||||
override fun onIgnoreClicked() = withState(viewModel) { state ->
|
||||
val isIgnored = state.isIgnored() ?: false
|
||||
val titleRes: Int
|
||||
val positiveButtonRes: Int
|
||||
val confirmationRes: Int
|
||||
if (isIgnored) {
|
||||
confirmationRes = R.string.room_participants_action_unignore_prompt_msg
|
||||
titleRes = R.string.room_participants_action_unignore_title
|
||||
positiveButtonRes = R.string.room_participants_action_unignore
|
||||
} else {
|
||||
confirmationRes = R.string.room_participants_action_ignore_prompt_msg
|
||||
titleRes = R.string.room_participants_action_ignore_title
|
||||
positiveButtonRes = R.string.room_participants_action_ignore
|
||||
}
|
||||
ConfirmationDialogBuilder
|
||||
.show(
|
||||
activity = requireActivity(),
|
||||
askForReason = false,
|
||||
confirmationRes = confirmationRes,
|
||||
positiveRes = positiveButtonRes,
|
||||
reasonHintRes = 0,
|
||||
titleRes = titleRes
|
||||
) {
|
||||
viewModel.handle(RoomMemberProfileAction.IgnoreUser)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTapVerify() {
|
||||
viewModel.handle(RoomMemberProfileAction.VerifyUser)
|
||||
|
@ -260,47 +283,57 @@ class RoomMemberProfileFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun onKickClicked() {
|
||||
val layout = layoutInflater.inflate(R.layout.dialog_base_edit_text, null)
|
||||
val input = layout.findViewById<TextView>(R.id.editText)
|
||||
input.setHint(R.string.reason_hint)
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(resources.getQuantityString(R.plurals.room_participants_kick_prompt_msg, 1))
|
||||
.setView(layout)
|
||||
.setPositiveButton(R.string.room_participants_action_kick) { _, _ ->
|
||||
viewModel.handle(RoomMemberProfileAction.KickUser(input.text.toString()))
|
||||
ConfirmationDialogBuilder
|
||||
.show(
|
||||
activity = requireActivity(),
|
||||
askForReason = true,
|
||||
confirmationRes = R.string.room_participants_kick_prompt_msg,
|
||||
positiveRes = R.string.room_participants_action_kick,
|
||||
reasonHintRes = R.string.room_participants_kick_reason,
|
||||
titleRes = R.string.room_participants_kick_title
|
||||
) { reason ->
|
||||
viewModel.handle(RoomMemberProfileAction.KickUser(reason))
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onBanClicked(isUserBanned: Boolean) {
|
||||
val layout = layoutInflater.inflate(R.layout.dialog_base_edit_text, null)
|
||||
val input = layout.findViewById<TextView>(R.id.editText)
|
||||
input.setHint(R.string.reason_hint)
|
||||
val (titleRes, positiveButtonRes) = if (isUserBanned) {
|
||||
input.isVisible = false
|
||||
Pair(R.string.room_participants_unban_prompt_msg, R.string.room_participants_action_unban)
|
||||
val titleRes: Int
|
||||
val positiveButtonRes: Int
|
||||
val confirmationRes: Int
|
||||
if (isUserBanned) {
|
||||
confirmationRes = R.string.room_participants_unban_prompt_msg
|
||||
titleRes = R.string.room_participants_unban_title
|
||||
positiveButtonRes = R.string.room_participants_action_unban
|
||||
} else {
|
||||
Pair(R.string.room_participants_ban_prompt_msg, R.string.room_participants_action_ban)
|
||||
confirmationRes = R.string.room_participants_ban_prompt_msg
|
||||
titleRes = R.string.room_participants_ban_title
|
||||
positiveButtonRes = R.string.room_participants_action_ban
|
||||
}
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(titleRes)
|
||||
.setView(layout)
|
||||
.setPositiveButton(positiveButtonRes) { _, _ ->
|
||||
viewModel.handle(RoomMemberProfileAction.BanUser(input.text.toString()))
|
||||
ConfirmationDialogBuilder
|
||||
.show(
|
||||
activity = requireActivity(),
|
||||
askForReason = !isUserBanned,
|
||||
confirmationRes = confirmationRes,
|
||||
positiveRes = positiveButtonRes,
|
||||
reasonHintRes = R.string.room_participants_ban_reason,
|
||||
titleRes = titleRes
|
||||
) { reason ->
|
||||
viewModel.handle(RoomMemberProfileAction.BanUser(reason))
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onCancelInviteClicked() {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(resources.getString(R.string.room_participants_action_cancel_invite_prompt_msg))
|
||||
.setPositiveButton(R.string.room_participants_action_cancel_invite) { _, _ ->
|
||||
ConfirmationDialogBuilder
|
||||
.show(
|
||||
activity = requireActivity(),
|
||||
askForReason = false,
|
||||
confirmationRes = R.string.room_participants_action_cancel_invite_prompt_msg,
|
||||
positiveRes = R.string.room_participants_action_cancel_invite,
|
||||
reasonHintRes = 0,
|
||||
titleRes = R.string.room_participants_action_cancel_invite_title
|
||||
) {
|
||||
viewModel.handle(RoomMemberProfileAction.KickUser(null))
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onInviteClicked() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/layout_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -12,36 +13,36 @@
|
|||
android:paddingBottom="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/deleteEventConfirmationText"
|
||||
android:id="@+id/dialogConfirmationText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/delete_event_dialog_content"
|
||||
tools:text="@string/delete_event_dialog_content"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/deleteEventReasonCheck"
|
||||
android:id="@+id/dialogReasonCheck"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:checked="true"
|
||||
android:text="@string/delete_event_dialog_reason_checkbox"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/deleteEventConfirmationText" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/dialogConfirmationText" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/deleteEventReasonTextInputLayout"
|
||||
android:id="@+id/dialogReasonTextInputLayout"
|
||||
style="@style/VectorTextInputLayout"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/delete_event_dialog_reason_hint"
|
||||
tools:hint="@string/delete_event_dialog_reason_hint"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="240"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/deleteEventReasonCheck">
|
||||
app:layout_constraintTop_toBottomOf="@+id/dialogReasonCheck">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/deleteEventReasonInput"
|
||||
android:id="@+id/dialogReasonInput"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
|
@ -474,22 +474,30 @@
|
|||
<string name="room_participants_action_set_default_power_level">Reset to normal user</string>
|
||||
<string name="room_participants_action_set_moderator">Make moderator</string>
|
||||
<string name="room_participants_action_set_admin">Make admin</string>
|
||||
<string name="room_participants_action_ignore">Hide all messages from this user</string>
|
||||
<string name="room_participants_action_unignore">Show all messages from this user</string>
|
||||
<string name="room_participants_action_unignore_prompt">Show all messages from this user?\n\nNote that this action will restart the app and it may take some time.</string>
|
||||
<string name="room_participants_invite_search_another_user">User ID, Name or email</string>
|
||||
<string name="room_participants_action_mention">Mention</string>
|
||||
<string name="room_participants_action_devices_list">Show Session List</string>
|
||||
<string name="room_participants_power_level_prompt">You will not be able to undo this change as you are promoting the user to have the same power level as yourself.\nAre you sure?</string>
|
||||
|
||||
<string name="room_participants_action_cancel_invite_prompt_msg">Are you sure you want to cancel the invite for this user?</string>
|
||||
|
||||
<plurals name="room_participants_kick_prompt_msg">
|
||||
<item quantity="one">Are you sure that you want to kick this user from this chat?</item>
|
||||
<item quantity="other">Are you sure that you want to kick these users from this chat?</item>
|
||||
</plurals>
|
||||
<string name="room_participants_ban_prompt_msg">Are you sure that you want to ban this user from this chat?</string>
|
||||
<string name="room_participants_unban_prompt_msg">Are you sure that you want to unban this user from this chat?</string>
|
||||
<string name="room_participants_action_ignore_title">Ignore user</string>
|
||||
<string name="room_participants_action_ignore_prompt_msg">Ignoring this user will remove their messages from rooms you share.\n\nYou can reverse this action at any time in the general settings.</string>
|
||||
<string name="room_participants_action_ignore">Ignore</string>
|
||||
|
||||
<string name="room_participants_action_unignore_title">Unignore user</string>
|
||||
<string name="room_participants_action_unignore_prompt_msg">Unignoring this user will show all messages from them again.</string>
|
||||
<string name="room_participants_action_unignore">Unignore</string>
|
||||
|
||||
<string name="room_participants_action_cancel_invite_title">Cancel invite</string>
|
||||
<string name="room_participants_action_cancel_invite_prompt_msg">Are you sure you want to cancel the invite for this user?</string>
|
||||
<string name="room_participants_kick_title">Kick user</string>
|
||||
<string name="room_participants_kick_reason">Reason to kick</string>
|
||||
<string name="room_participants_kick_prompt_msg">kicking user will remove them from this room.\n\nTo prevent them from joining again, you should ban them instead.</string>
|
||||
<string name="room_participants_ban_title">Ban user</string>
|
||||
<string name="room_participants_ban_reason">Reason to ban</string>
|
||||
<string name="room_participants_unban_title">Unban user</string>
|
||||
<string name="room_participants_ban_prompt_msg">Banning user will kick them from this room and prevent them from joining again.</string>
|
||||
<string name="room_participants_unban_prompt_msg">Unbanning user will allow them to join the room again.</string>
|
||||
|
||||
<string name="reason_hint">Reason</string>
|
||||
|
||||
|
@ -2433,6 +2441,6 @@ Not all features in Riot are implemented in RiotX yet. Main missing (and coming
|
|||
<string name="identity_server_set_alternative_notice">Alternatively, you can enter any other identity server URL</string>
|
||||
<string name="identity_server_set_alternative_notice_no_default">Enter the URL of an identity server</string>
|
||||
<string name="identity_server_set_alternative_submit">Submit</string>
|
||||
<string name="power_level_edit_title">Edit power level</string>
|
||||
<string name="power_level_edit_title">Set role</string>
|
||||
|
||||
</resources>
|
||||
|
|
Loading…
Reference in New Issue