From 33e4da7abbdbfa683500b38955e7fa273bc7ed53 Mon Sep 17 00:00:00 2001 From: Konrad Pozniak Date: Mon, 2 Jan 2023 14:09:40 +0100 Subject: [PATCH] Improve muted users list (#3127) * migrate MutesAdapter to viewbinding * migrate item_muted_user to ConstraintLayout * add switch instead of button * change unmute button position * delete unused string --- .../tusky/adapter/MutesAdapter.kt | 148 +++++++----------- .../tusky/fragment/AccountListFragment.kt | 2 +- app/src/main/res/layout/item_muted_user.xml | 115 +++++++------- app/src/main/res/values/strings.xml | 3 +- 4 files changed, 115 insertions(+), 153 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.kt index 979141d4..42e19c65 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.kt @@ -1,16 +1,12 @@ package com.keylesspalace.tusky.adapter import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.widget.ImageButton -import android.widget.ImageView -import android.widget.TextView import androidx.core.view.ViewCompat -import androidx.recyclerview.widget.RecyclerView import com.keylesspalace.tusky.R -import com.keylesspalace.tusky.entity.TimelineAccount +import com.keylesspalace.tusky.databinding.ItemMutedUserBinding import com.keylesspalace.tusky.interfaces.AccountActionListener +import com.keylesspalace.tusky.util.BindingHolder import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.loadAvatar @@ -23,7 +19,7 @@ class MutesAdapter( animateAvatar: Boolean, animateEmojis: Boolean, showBotOverlay: Boolean -) : AccountAdapter( +) : AccountAdapter>( accountActionListener, animateAvatar, animateEmojis, @@ -31,21 +27,58 @@ class MutesAdapter( ) { private val mutingNotificationsMap = HashMap() - override fun createAccountViewHolder(parent: ViewGroup): MutedUserViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_muted_user, parent, false) - return MutedUserViewHolder(view) + override fun createAccountViewHolder(parent: ViewGroup): BindingHolder { + val binding = ItemMutedUserBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return BindingHolder(binding) } - override fun onBindAccountViewHolder(viewHolder: MutedUserViewHolder, position: Int) { + override fun onBindAccountViewHolder(viewHolder: BindingHolder, position: Int) { val account = accountList[position] - viewHolder.setupWithAccount( - account, - mutingNotificationsMap[account.id], - animateAvatar, - animateEmojis - ) - viewHolder.setupActionListener(accountActionListener) + val binding = viewHolder.binding + val context = binding.root.context + + val mutingNotifications = mutingNotificationsMap[account.id] + + val emojifiedName = account.name.emojify(account.emojis, binding.mutedUserDisplayName, animateEmojis) + binding.mutedUserDisplayName.text = emojifiedName + + val formattedUsername = context.getString(R.string.post_username_format, account.username) + binding.mutedUserUsername.text = formattedUsername + + val avatarRadius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp) + loadAvatar(account.avatar, binding.mutedUserAvatar, avatarRadius, animateAvatar) + + val unmuteString = context.getString(R.string.action_unmute_desc, formattedUsername) + binding.mutedUserUnmute.contentDescription = unmuteString + ViewCompat.setTooltipText(binding.mutedUserUnmute, unmuteString) + + binding.mutedUserMuteNotifications.setOnCheckedChangeListener(null) + + binding.mutedUserMuteNotifications.isChecked = if (mutingNotifications == null) { + binding.mutedUserMuteNotifications.isEnabled = false + true + } else { + binding.mutedUserMuteNotifications.isEnabled = true + mutingNotifications + } + + binding.mutedUserUnmute.setOnClickListener { + accountActionListener.onMute( + false, + account.id, + viewHolder.bindingAdapterPosition, + false + ) + } + binding.mutedUserMuteNotifications.setOnCheckedChangeListener { _, isChecked -> + accountActionListener.onMute( + true, + account.id, + viewHolder.bindingAdapterPosition, + isChecked + ) + } + binding.root.setOnClickListener { accountActionListener.onViewAccount(account.id) } } fun updateMutingNotifications(id: String, mutingNotifications: Boolean, position: Int) { @@ -53,81 +86,8 @@ class MutesAdapter( notifyItemChanged(position) } - fun updateMutingNotificationsMap(newMutingNotificationsMap: HashMap?) { - mutingNotificationsMap.putAll(newMutingNotificationsMap!!) + fun updateMutingNotificationsMap(newMutingNotificationsMap: HashMap) { + mutingNotificationsMap.putAll(newMutingNotificationsMap) notifyDataSetChanged() } - - class MutedUserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - private val avatar: ImageView = itemView.findViewById(R.id.muted_user_avatar) - private val username: TextView = itemView.findViewById(R.id.muted_user_username) - private val displayName: TextView = itemView.findViewById(R.id.muted_user_display_name) - private val unmute: ImageButton = itemView.findViewById(R.id.muted_user_unmute) - private val muteNotifications: ImageButton = - itemView.findViewById(R.id.muted_user_mute_notifications) - - private var id: String? = null - private var notifications = false - - fun setupWithAccount( - account: TimelineAccount, - mutingNotifications: Boolean?, - animateAvatar: Boolean, - animateEmojis: Boolean - ) { - id = account.id - val emojifiedName = account.name.emojify(account.emojis, displayName, animateEmojis) - displayName.text = emojifiedName - val format = username.context.getString(R.string.post_username_format) - val formattedUsername = String.format(format, account.username) - username.text = formattedUsername - val avatarRadius = avatar.context.resources - .getDimensionPixelSize(R.dimen.avatar_radius_48dp) - loadAvatar(account.avatar, avatar, avatarRadius, animateAvatar) - val unmuteString = - unmute.context.getString(R.string.action_unmute_desc, formattedUsername) - unmute.contentDescription = unmuteString - ViewCompat.setTooltipText(unmute, unmuteString) - if (mutingNotifications == null) { - muteNotifications.isEnabled = false - notifications = true - } else { - muteNotifications.isEnabled = true - notifications = mutingNotifications - } - if (notifications) { - muteNotifications.setImageResource(R.drawable.ic_notifications_24dp) - val unmuteNotificationsString = muteNotifications.context - .getString(R.string.action_unmute_notifications_desc, formattedUsername) - muteNotifications.contentDescription = unmuteNotificationsString - ViewCompat.setTooltipText(muteNotifications, unmuteNotificationsString) - } else { - muteNotifications.setImageResource(R.drawable.ic_notifications_off_24dp) - val muteNotificationsString = muteNotifications.context - .getString(R.string.action_mute_notifications_desc, formattedUsername) - muteNotifications.contentDescription = muteNotificationsString - ViewCompat.setTooltipText(muteNotifications, muteNotificationsString) - } - } - - fun setupActionListener(listener: AccountActionListener) { - unmute.setOnClickListener { - listener.onMute( - false, - id, - bindingAdapterPosition, - false - ) - } - muteNotifications.setOnClickListener { - listener.onMute( - true, - id, - bindingAdapterPosition, - !notifications - ) - } - itemView.setOnClickListener { listener.onViewAccount(id) } - } - } } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt index 96301c08..62535baa 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt @@ -394,7 +394,7 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct fun newInstance(type: Type, id: String? = null, accountLocked: Boolean = false): AccountListFragment { return AccountListFragment().apply { - arguments = Bundle(2).apply { + arguments = Bundle(3).apply { putSerializable(ARG_TYPE, type) putString(ARG_ID, id) putBoolean(ARG_ACCOUNT_LOCKED, accountLocked) diff --git a/app/src/main/res/layout/item_muted_user.xml b/app/src/main/res/layout/item_muted_user.xml index 404bbb74..ef8c83dc 100644 --- a/app/src/main/res/layout/item_muted_user.xml +++ b/app/src/main/res/layout/item_muted_user.xml @@ -1,77 +1,80 @@ - + android:layout_height="wrap_content" + android:paddingStart="16dp" + android:paddingEnd="16dp"> + android:layout_marginTop="10dp" + android:layout_marginBottom="10dp" + android:contentDescription="@string/action_view_profile" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:src="@drawable/avatar_default" /> + + + + + app:layout_constraintBottom_toBottomOf="@id/muted_user_avatar" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_clear_24dp" + tools:ignore="ContentDescription" /> - - - + android:layout_height="wrap_content" + android:layout_marginBottom="4dp" + android:textColor="?android:textColorTertiary" + android:layout_marginTop="4dp" + app:layout_constraintBottom_toBottomOf="parent" + app:switchPadding="4dp" + app:layout_constraintStart_toStartOf="@id/muted_user_display_name" + app:layout_constraintTop_toBottomOf="@id/muted_user_username" /> - - - - - - - \ No newline at end of file + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db103117..147bf27a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -134,8 +134,6 @@ Mute Unmute Unmute %s - Unmute notifications from %s - Mute notifications from %s Mute %s Unmute %s Mute conversation @@ -712,6 +710,7 @@ Other Unfollow #%s? + Mute notifications %1$s edited %2$s