diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e9546172..420b2352 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -122,7 +122,7 @@ - + . */ -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.recyclerview.widget.RecyclerView -import com.keylesspalace.tusky.R -import com.keylesspalace.tusky.entity.TimelineAccount -import com.keylesspalace.tusky.interfaces.AccountActionListener -import com.keylesspalace.tusky.util.emojify -import com.keylesspalace.tusky.util.loadAvatar - -/** Displays a list of blocked accounts. */ -class BlocksAdapter( - accountActionListener: AccountActionListener, - animateAvatar: Boolean, - animateEmojis: Boolean, - showBotOverlay: Boolean, -) : AccountAdapter( - accountActionListener, - animateAvatar, - animateEmojis, - showBotOverlay -) { - override fun createAccountViewHolder(parent: ViewGroup): BlockedUserViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_blocked_user, parent, false) - return BlockedUserViewHolder(view) - } - - override fun onBindAccountViewHolder(viewHolder: BlockedUserViewHolder, position: Int) { - viewHolder.setupWithAccount(accountList[position], animateAvatar, animateEmojis) - viewHolder.setupActionListener(accountActionListener) - } - - class BlockedUserViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { - private val avatar: ImageView = itemView.findViewById(R.id.blocked_user_avatar) - private val username: TextView = itemView.findViewById(R.id.blocked_user_username) - private val displayName: TextView = itemView.findViewById(R.id.blocked_user_display_name) - private val unblock: ImageButton = itemView.findViewById(R.id.blocked_user_unblock) - private var id: String? = null - - fun setupWithAccount(account: TimelineAccount, 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) - } - - fun setupActionListener(listener: AccountActionListener) { - unblock.setOnClickListener { - val position = bindingAdapterPosition - if (position != RecyclerView.NO_POSITION) { - listener.onBlock(false, id, position) - } - } - itemView.setOnClickListener { listener.onViewAccount(id) } - } - } -} diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt index 60770dda..7e675de3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestViewHolder.kt @@ -50,11 +50,11 @@ class FollowRequestViewHolder( }.emojify(account.emojis, itemView, animateEmojis) } binding.notificationTextView.visible(showHeader) - val format = itemView.context.getString(R.string.post_username_format) - val formattedUsername = String.format(format, account.username) + val formattedUsername = itemView.context.getString(R.string.post_username_format, account.username) binding.usernameTextView.text = formattedUsername val avatarRadius = binding.avatar.context.resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp) loadAvatar(account.avatar, binding.avatar, avatarRadius, animateAvatar) + binding.avatarBadge.visible(showBotOverlay && account.bot) } fun setupActionListener(listener: AccountActionListener, accountId: String) { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/LoadingFooterViewHolder.kt b/app/src/main/java/com/keylesspalace/tusky/adapter/LoadingFooterViewHolder.kt deleted file mode 100644 index 6d5ddbd8..00000000 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/LoadingFooterViewHolder.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* Copyright 2018 Conny Duck - * - * This file is a part of Tusky. - * - * This program is free software; you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation; either version 3 of the - * License, or (at your option) any later version. - * - * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even - * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. - * - * You should have received a copy of the GNU General Public License along with Tusky; if not, - * see . */ - -package com.keylesspalace.tusky.adapter - -import android.view.View -import androidx.recyclerview.widget.RecyclerView - -class LoadingFooterViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt index 1320bc91..dd732971 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/account/AccountActivity.kt @@ -50,13 +50,13 @@ import com.google.android.material.shape.ShapeAppearanceModel import com.google.android.material.snackbar.Snackbar import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayoutMediator -import com.keylesspalace.tusky.AccountListActivity import com.keylesspalace.tusky.BottomSheetActivity import com.keylesspalace.tusky.EditProfileActivity import com.keylesspalace.tusky.R import com.keylesspalace.tusky.StatusListActivity import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.components.account.list.ListsForAccountFragment +import com.keylesspalace.tusky.components.accountlist.AccountListActivity import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.report.ReportActivity import com.keylesspalace.tusky.databinding.ActivityAccountBinding diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListActivity.kt similarity index 90% rename from app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt rename to app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListActivity.kt index ca23f791..f379b95a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountListActivity.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListActivity.kt @@ -13,13 +13,15 @@ * You should have received a copy of the GNU General Public License along with Tusky; if not, * see . */ -package com.keylesspalace.tusky +package com.keylesspalace.tusky.components.accountlist import android.content.Context import android.content.Intent import android.os.Bundle +import androidx.fragment.app.commit +import com.keylesspalace.tusky.BaseActivity +import com.keylesspalace.tusky.R import com.keylesspalace.tusky.databinding.ActivityAccountListBinding -import com.keylesspalace.tusky.fragment.AccountListFragment import dagger.android.DispatchingAndroidInjector import dagger.android.HasAndroidInjector import javax.inject.Inject @@ -63,10 +65,9 @@ class AccountListActivity : BaseActivity(), HasAndroidInjector { setDisplayShowHomeEnabled(true) } - supportFragmentManager - .beginTransaction() - .replace(R.id.fragment_container, AccountListFragment.newInstance(type, id, accountLocked)) - .commit() + supportFragmentManager.commit { + replace(R.id.fragment_container, AccountListFragment.newInstance(type, id, accountLocked)) + } } override fun androidInjector() = dispatchingAndroidInjector @@ -76,8 +77,6 @@ class AccountListActivity : BaseActivity(), HasAndroidInjector { private const val EXTRA_ID = "id" private const val EXTRA_ACCOUNT_LOCKED = "acc_locked" - @JvmStatic - @JvmOverloads fun newIntent(context: Context, type: Type, id: String? = null, accountLocked: Boolean = false): Intent { return Intent(context, AccountListActivity::class.java).apply { putExtra(EXTRA_TYPE, type) diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListFragment.kt similarity index 93% rename from app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt rename to app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListFragment.kt index 9fa321d3..2649cbfe 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountListFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/AccountListFragment.kt @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License along with Tusky; if not, * see . */ -package com.keylesspalace.tusky.fragment +package com.keylesspalace.tusky.components.accountlist import android.os.Bundle import android.util.Log @@ -30,16 +30,16 @@ import androidx.recyclerview.widget.SimpleItemAnimator import autodispose2.androidx.lifecycle.AndroidLifecycleScopeProvider.from import autodispose2.autoDispose import com.google.android.material.snackbar.Snackbar -import com.keylesspalace.tusky.AccountListActivity.Type import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.R -import com.keylesspalace.tusky.adapter.AccountAdapter -import com.keylesspalace.tusky.adapter.BlocksAdapter -import com.keylesspalace.tusky.adapter.FollowAdapter -import com.keylesspalace.tusky.adapter.FollowRequestsAdapter -import com.keylesspalace.tusky.adapter.FollowRequestsHeaderAdapter -import com.keylesspalace.tusky.adapter.MutesAdapter import com.keylesspalace.tusky.components.account.AccountActivity +import com.keylesspalace.tusky.components.accountlist.AccountListActivity.Type +import com.keylesspalace.tusky.components.accountlist.adapter.AccountAdapter +import com.keylesspalace.tusky.components.accountlist.adapter.BlocksAdapter +import com.keylesspalace.tusky.components.accountlist.adapter.FollowAdapter +import com.keylesspalace.tusky.components.accountlist.adapter.FollowRequestsAdapter +import com.keylesspalace.tusky.components.accountlist.adapter.FollowRequestsHeaderAdapter +import com.keylesspalace.tusky.components.accountlist.adapter.MutesAdapter import com.keylesspalace.tusky.databinding.FragmentAccountListBinding import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.di.Injectable @@ -83,7 +83,6 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) binding.recyclerView.setHasFixedSize(true) val layoutManager = LinearLayoutManager(view.context) @@ -101,7 +100,10 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct Type.BLOCKS -> BlocksAdapter(this, animateAvatar, animateEmojis, showBotOverlay) Type.MUTES -> MutesAdapter(this, animateAvatar, animateEmojis, showBotOverlay) Type.FOLLOW_REQUESTS -> { - val headerAdapter = FollowRequestsHeaderAdapter(accountManager.activeAccount!!.domain, arguments?.getBoolean(ARG_ACCOUNT_LOCKED) == true) + val headerAdapter = FollowRequestsHeaderAdapter( + instanceName = accountManager.activeAccount!!.domain, + accountLocked = arguments?.getBoolean(ARG_ACCOUNT_LOCKED) == true + ) val followRequestsAdapter = FollowRequestsAdapter(this, animateAvatar, animateEmojis, showBotOverlay) binding.recyclerView.adapter = ConcatAdapter(headerAdapter, followRequestsAdapter) followRequestsAdapter @@ -350,8 +352,8 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct api.relationships(ids) .observeOn(AndroidSchedulers.mainThread()) .autoDispose(from(this)) - .subscribe(::onFetchRelationshipsSuccess) { - onFetchRelationshipsFailure(ids) + .subscribe(::onFetchRelationshipsSuccess) { throwable -> + Log.e(TAG, "Fetch failure for relationships of accounts: $ids", throwable) } } @@ -362,10 +364,6 @@ class AccountListFragment : Fragment(R.layout.fragment_account_list), AccountAct mutesAdapter.updateMutingNotificationsMap(mutingNotificationsMap) } - private fun onFetchRelationshipsFailure(ids: List) { - Log.e(TAG, "Fetch failure for relationships of accounts: $ids") - } - private fun onFetchAccountsFailure(throwable: Throwable) { fetching = false Log.e(TAG, "Fetch failure", throwable) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/AccountAdapter.kt similarity index 89% rename from app/src/main/java/com/keylesspalace/tusky/adapter/AccountAdapter.kt rename to app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/AccountAdapter.kt index bbd83df3..55a37cfb 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/AccountAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/AccountAdapter.kt @@ -12,24 +12,26 @@ * * You should have received a copy of the GNU General Public License along with Tusky; if not, * see . */ -package com.keylesspalace.tusky.adapter +package com.keylesspalace.tusky.components.accountlist.adapter import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import com.keylesspalace.tusky.R +import com.keylesspalace.tusky.databinding.ItemFooterBinding import com.keylesspalace.tusky.entity.TimelineAccount import com.keylesspalace.tusky.interfaces.AccountActionListener +import com.keylesspalace.tusky.util.BindingHolder import com.keylesspalace.tusky.util.removeDuplicates /** Generic adapter with bottom loading indicator. */ abstract class AccountAdapter internal constructor( - var accountActionListener: AccountActionListener, + protected val accountActionListener: AccountActionListener, protected val animateAvatar: Boolean, protected val animateEmojis: Boolean, protected val showBotOverlay: Boolean ) : RecyclerView.Adapter() { - var accountList = mutableListOf() + + protected var accountList: MutableList = mutableListOf() private var bottomLoading: Boolean = false override fun getItemCount(): Int { @@ -61,9 +63,8 @@ abstract class AccountAdapter internal constructo private fun createFooterViewHolder( parent: ViewGroup, ): RecyclerView.ViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_footer, parent, false) - return LoadingFooterViewHolder(view) + val binding = ItemFooterBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return BindingHolder(binding) } override fun getItemViewType(position: Int): Int { diff --git a/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/BlocksAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/BlocksAdapter.kt new file mode 100644 index 00000000..f769af34 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/BlocksAdapter.kt @@ -0,0 +1,68 @@ +/* Copyright 2017 Andrew Dawson + * + * This file is a part of Tusky. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tusky; if not, + * see . */ + +package com.keylesspalace.tusky.components.accountlist.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import com.keylesspalace.tusky.R +import com.keylesspalace.tusky.databinding.ItemBlockedUserBinding +import com.keylesspalace.tusky.interfaces.AccountActionListener +import com.keylesspalace.tusky.util.BindingHolder +import com.keylesspalace.tusky.util.emojify +import com.keylesspalace.tusky.util.loadAvatar +import com.keylesspalace.tusky.util.visible + +/** Displays a list of blocked accounts. */ +class BlocksAdapter( + accountActionListener: AccountActionListener, + animateAvatar: Boolean, + animateEmojis: Boolean, + showBotOverlay: Boolean, +) : AccountAdapter>( + accountActionListener = accountActionListener, + animateAvatar = animateAvatar, + animateEmojis = animateEmojis, + showBotOverlay = showBotOverlay +) { + + override fun createAccountViewHolder(parent: ViewGroup): BindingHolder { + val binding = ItemBlockedUserBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return BindingHolder(binding) + } + + override fun onBindAccountViewHolder(viewHolder: BindingHolder, position: Int) { + val account = accountList[position] + val binding = viewHolder.binding + val context = binding.root.context + + val emojifiedName = account.name.emojify(account.emojis, binding.blockedUserDisplayName, animateEmojis) + binding.blockedUserDisplayName.text = emojifiedName + val formattedUsername = context.getString(R.string.post_username_format, account.username) + binding.blockedUserUsername.text = formattedUsername + + val avatarRadius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp) + loadAvatar(account.avatar, binding.blockedUserAvatar, avatarRadius, animateAvatar) + + binding.blockedUserBotBadge.visible(showBotOverlay && account.bot) + + binding.blockedUserUnblock.setOnClickListener { + accountActionListener.onBlock(false, account.id, position) + } + binding.root.setOnClickListener { + accountActionListener.onViewAccount(account.id) + } + } +} diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowAdapter.kt similarity index 80% rename from app/src/main/java/com/keylesspalace/tusky/adapter/FollowAdapter.kt rename to app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowAdapter.kt index 5c546305..87b62486 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowAdapter.kt @@ -12,10 +12,12 @@ * * You should have received a copy of the GNU General Public License along with Tusky; if not, * see . */ -package com.keylesspalace.tusky.adapter + +package com.keylesspalace.tusky.components.accountlist.adapter import android.view.LayoutInflater import android.view.ViewGroup +import com.keylesspalace.tusky.adapter.AccountViewHolder import com.keylesspalace.tusky.databinding.ItemAccountBinding import com.keylesspalace.tusky.interfaces.AccountActionListener @@ -26,17 +28,14 @@ class FollowAdapter( animateEmojis: Boolean, showBotOverlay: Boolean ) : AccountAdapter( - accountActionListener, - animateAvatar, - animateEmojis, - showBotOverlay + accountActionListener = accountActionListener, + animateAvatar = animateAvatar, + animateEmojis = animateEmojis, + showBotOverlay = showBotOverlay ) { + override fun createAccountViewHolder(parent: ViewGroup): AccountViewHolder { - val binding = ItemAccountBinding.inflate( - LayoutInflater.from(parent.context), - parent, - false - ) + val binding = ItemAccountBinding.inflate(LayoutInflater.from(parent.context), parent, false) return AccountViewHolder(binding) } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowRequestsAdapter.kt similarity index 69% rename from app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.kt rename to app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowRequestsAdapter.kt index 95d944bd..35a59a8e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowRequestsAdapter.kt @@ -12,10 +12,12 @@ * * You should have received a copy of the GNU General Public License along with Tusky; if not, * see . */ -package com.keylesspalace.tusky.adapter + +package com.keylesspalace.tusky.components.accountlist.adapter import android.view.LayoutInflater import android.view.ViewGroup +import com.keylesspalace.tusky.adapter.FollowRequestViewHolder import com.keylesspalace.tusky.databinding.ItemFollowRequestBinding import com.keylesspalace.tusky.interfaces.AccountActionListener @@ -25,16 +27,25 @@ class FollowRequestsAdapter( animateAvatar: Boolean, animateEmojis: Boolean, showBotOverlay: Boolean -) : AccountAdapter(accountActionListener, animateAvatar, animateEmojis, showBotOverlay) { +) : AccountAdapter( + accountActionListener = accountActionListener, + animateAvatar = animateAvatar, + animateEmojis = animateEmojis, + showBotOverlay = showBotOverlay +) { + override fun createAccountViewHolder(parent: ViewGroup): FollowRequestViewHolder { - val binding = ItemFollowRequestBinding.inflate( - LayoutInflater.from(parent.context), parent, false - ) + val binding = ItemFollowRequestBinding.inflate(LayoutInflater.from(parent.context), parent, false) return FollowRequestViewHolder(binding, false) } override fun onBindAccountViewHolder(viewHolder: FollowRequestViewHolder, position: Int) { - viewHolder.setupWithAccount(accountList[position], animateAvatar, animateEmojis, showBotOverlay) + viewHolder.setupWithAccount( + account = accountList[position], + animateAvatar = animateAvatar, + animateEmojis = animateEmojis, + showBotOverlay = showBotOverlay + ) viewHolder.setupActionListener(accountActionListener, accountList[position].id) } } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsHeaderAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowRequestsHeaderAdapter.kt similarity index 54% rename from app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsHeaderAdapter.kt rename to app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowRequestsHeaderAdapter.kt index 2480086e..85cf4e20 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/FollowRequestsHeaderAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/FollowRequestsHeaderAdapter.kt @@ -13,27 +13,28 @@ * You should have received a copy of the GNU General Public License along with Tusky; if not, * see . */ -package com.keylesspalace.tusky.adapter +package com.keylesspalace.tusky.components.accountlist.adapter import android.view.LayoutInflater import android.view.ViewGroup -import android.widget.TextView import androidx.recyclerview.widget.RecyclerView import com.keylesspalace.tusky.R +import com.keylesspalace.tusky.databinding.ItemFollowRequestsHeaderBinding +import com.keylesspalace.tusky.util.BindingHolder -class FollowRequestsHeaderAdapter(private val instanceName: String, private val accountLocked: Boolean) : RecyclerView.Adapter() { +class FollowRequestsHeaderAdapter( + private val instanceName: String, + private val accountLocked: Boolean +) : RecyclerView.Adapter>() { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HeaderViewHolder { - val view = LayoutInflater.from(parent.context) - .inflate(R.layout.item_follow_requests_header, parent, false) as TextView - return HeaderViewHolder(view) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder { + val binding = ItemFollowRequestsHeaderBinding.inflate(LayoutInflater.from(parent.context), parent, false) + return BindingHolder(binding) } - override fun onBindViewHolder(viewHolder: HeaderViewHolder, position: Int) { - viewHolder.textView.text = viewHolder.textView.context.getString(R.string.follow_requests_info, instanceName) + override fun onBindViewHolder(viewHolder: BindingHolder, position: Int) { + viewHolder.binding.root.text = viewHolder.binding.root.context.getString(R.string.follow_requests_info, instanceName) } override fun getItemCount() = if (accountLocked) 0 else 1 } - -class HeaderViewHolder(var textView: TextView) : RecyclerView.ViewHolder(textView) diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.kt b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/MutesAdapter.kt similarity index 74% rename from app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.kt rename to app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/MutesAdapter.kt index 42e19c65..288d1339 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/MutesAdapter.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/accountlist/adapter/MutesAdapter.kt @@ -1,4 +1,19 @@ -package com.keylesspalace.tusky.adapter +/* Copyright 2023 Tusky Contributors + * + * This file is a part of Tusky. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Tusky; if not, + * see . */ + +package com.keylesspalace.tusky.components.accountlist.adapter import android.view.LayoutInflater import android.view.ViewGroup @@ -9,22 +24,21 @@ import com.keylesspalace.tusky.interfaces.AccountActionListener import com.keylesspalace.tusky.util.BindingHolder import com.keylesspalace.tusky.util.emojify import com.keylesspalace.tusky.util.loadAvatar +import com.keylesspalace.tusky.util.visible -/** - * Displays a list of muted accounts with mute/unmute account and mute/unmute notifications - * buttons. - * */ +/** Displays a list of muted accounts with mute/unmute account button and mute/unmute notifications switch */ class MutesAdapter( accountActionListener: AccountActionListener, animateAvatar: Boolean, animateEmojis: Boolean, showBotOverlay: Boolean ) : AccountAdapter>( - accountActionListener, - animateAvatar, - animateEmojis, - showBotOverlay + accountActionListener = accountActionListener, + animateAvatar = animateAvatar, + animateEmojis = animateEmojis, + showBotOverlay = showBotOverlay ) { + private val mutingNotificationsMap = HashMap() override fun createAccountViewHolder(parent: ViewGroup): BindingHolder { @@ -48,6 +62,8 @@ class MutesAdapter( val avatarRadius = context.resources.getDimensionPixelSize(R.dimen.avatar_radius_48dp) loadAvatar(account.avatar, binding.mutedUserAvatar, avatarRadius, animateAvatar) + binding.mutedUserBotBadge.visible(showBotOverlay && account.bot) + val unmuteString = context.getString(R.string.action_unmute_desc, formattedUsername) binding.mutedUserUnmute.contentDescription = unmuteString ViewCompat.setTooltipText(binding.mutedUserUnmute, unmuteString) diff --git a/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt index 3c919327..a883f73c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/preference/AccountPreferencesFragment.kt @@ -24,7 +24,6 @@ import androidx.annotation.DrawableRes import androidx.preference.PreferenceFragmentCompat import com.google.android.material.color.MaterialColors import com.google.android.material.snackbar.Snackbar -import com.keylesspalace.tusky.AccountListActivity import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.BuildConfig import com.keylesspalace.tusky.FiltersActivity @@ -32,6 +31,7 @@ import com.keylesspalace.tusky.R import com.keylesspalace.tusky.TabPreferenceActivity import com.keylesspalace.tusky.appstore.EventHub import com.keylesspalace.tusky.appstore.PreferenceChangedEvent +import com.keylesspalace.tusky.components.accountlist.AccountListActivity import com.keylesspalace.tusky.components.followedtags.FollowedTagsActivity import com.keylesspalace.tusky.components.instancemute.InstanceListActivity import com.keylesspalace.tusky.components.login.LoginActivity diff --git a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt index f8395c56..6d0ff7ae 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/timeline/TimelineFragment.kt @@ -34,14 +34,14 @@ import androidx.recyclerview.widget.SimpleItemAnimator import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener import at.connyduck.sparkbutton.helpers.Utils import autodispose2.androidx.lifecycle.autoDispose -import com.keylesspalace.tusky.AccountListActivity -import com.keylesspalace.tusky.AccountListActivity.Companion.newIntent import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.R import com.keylesspalace.tusky.adapter.StatusBaseViewHolder import com.keylesspalace.tusky.appstore.EventHub import com.keylesspalace.tusky.appstore.PreferenceChangedEvent import com.keylesspalace.tusky.appstore.StatusComposedEvent +import com.keylesspalace.tusky.components.accountlist.AccountListActivity +import com.keylesspalace.tusky.components.accountlist.AccountListActivity.Companion.newIntent import com.keylesspalace.tusky.components.preference.PreferencesFragment.ReadingOrder import com.keylesspalace.tusky.components.timeline.viewmodel.CachedTimelineViewModel import com.keylesspalace.tusky.components.timeline.viewmodel.NetworkTimelineViewModel diff --git a/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt b/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt index cb361f5d..487caae3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/components/viewthread/ViewThreadFragment.kt @@ -32,10 +32,10 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.SimpleItemAnimator import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener import com.google.android.material.snackbar.Snackbar -import com.keylesspalace.tusky.AccountListActivity -import com.keylesspalace.tusky.AccountListActivity.Companion.newIntent import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.R +import com.keylesspalace.tusky.components.accountlist.AccountListActivity +import com.keylesspalace.tusky.components.accountlist.AccountListActivity.Companion.newIntent import com.keylesspalace.tusky.components.viewthread.edits.ViewEditsFragment import com.keylesspalace.tusky.databinding.FragmentViewThreadBinding import com.keylesspalace.tusky.di.Injectable diff --git a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt index fbd12d77..2704ee70 100644 --- a/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt +++ b/app/src/main/java/com/keylesspalace/tusky/di/ActivitiesModule.kt @@ -16,7 +16,6 @@ package com.keylesspalace.tusky.di import com.keylesspalace.tusky.AboutActivity -import com.keylesspalace.tusky.AccountListActivity import com.keylesspalace.tusky.BaseActivity import com.keylesspalace.tusky.EditProfileActivity import com.keylesspalace.tusky.FiltersActivity @@ -28,6 +27,7 @@ import com.keylesspalace.tusky.StatusListActivity import com.keylesspalace.tusky.TabPreferenceActivity import com.keylesspalace.tusky.ViewMediaActivity import com.keylesspalace.tusky.components.account.AccountActivity +import com.keylesspalace.tusky.components.accountlist.AccountListActivity import com.keylesspalace.tusky.components.announcements.AnnouncementsActivity import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.drafts.DraftsActivity diff --git a/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt b/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt index bc202f14..4a5e9738 100644 --- a/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt +++ b/app/src/main/java/com/keylesspalace/tusky/di/FragmentBuildersModule.kt @@ -18,6 +18,7 @@ package com.keylesspalace.tusky.di import com.keylesspalace.tusky.AccountsInListFragment import com.keylesspalace.tusky.components.account.list.ListsForAccountFragment import com.keylesspalace.tusky.components.account.media.AccountMediaFragment +import com.keylesspalace.tusky.components.accountlist.AccountListFragment import com.keylesspalace.tusky.components.conversation.ConversationsFragment import com.keylesspalace.tusky.components.instancemute.fragment.InstanceListFragment import com.keylesspalace.tusky.components.preference.AccountPreferencesFragment @@ -32,7 +33,6 @@ import com.keylesspalace.tusky.components.search.fragments.SearchStatusesFragmen import com.keylesspalace.tusky.components.timeline.TimelineFragment import com.keylesspalace.tusky.components.viewthread.ViewThreadFragment import com.keylesspalace.tusky.components.viewthread.edits.ViewEditsFragment -import com.keylesspalace.tusky.fragment.AccountListFragment import com.keylesspalace.tusky.fragment.NotificationsFragment import dagger.Module import dagger.android.ContributesAndroidInjector diff --git a/app/src/main/res/layout/activity_account_list.xml b/app/src/main/res/layout/activity_account_list.xml index c72ba66a..f61ff830 100644 --- a/app/src/main/res/layout/activity_account_list.xml +++ b/app/src/main/res/layout/activity_account_list.xml @@ -4,7 +4,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context="com.keylesspalace.tusky.AccountListActivity"> + tools:context="com.keylesspalace.tusky.components.accountlist.AccountListActivity"> @@ -14,6 +14,7 @@ android:layout_width="48dp" android:layout_height="48dp" android:layout_marginEnd="24dp" + android:contentDescription="@string/action_view_profile" android:foregroundGravity="center_vertical" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -26,8 +27,8 @@ android:layout_height="24dp" android:contentDescription="@null" android:importantForAccessibility="no" - android:visibility="gone" android:src="@drawable/bot_badge" + android:visibility="gone" app:layout_constraintBottom_toBottomOf="@id/account_avatar" app:layout_constraintEnd_toEndOf="@id/account_avatar" tools:src="#000" diff --git a/app/src/main/res/layout/item_blocked_user.xml b/app/src/main/res/layout/item_blocked_user.xml index d99513b5..6b8600bb 100644 --- a/app/src/main/res/layout/item_blocked_user.xml +++ b/app/src/main/res/layout/item_blocked_user.xml @@ -1,21 +1,62 @@ - + android:paddingStart="16dp" + android:paddingEnd="16dp"> + android:contentDescription="@string/action_view_profile" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + tools:src="@drawable/avatar_default" /> + + + + + + - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_follow_request.xml b/app/src/main/res/layout/item_follow_request.xml index e31ec6cf..c0c8df97 100644 --- a/app/src/main/res/layout/item_follow_request.xml +++ b/app/src/main/res/layout/item_follow_request.xml @@ -35,6 +35,15 @@ app:layout_constraintTop_toBottomOf="@id/notificationTextView" tools:src="@drawable/avatar_default" /> + + + diff --git a/app/src/main/res/layout/item_muted_user.xml b/app/src/main/res/layout/item_muted_user.xml index ef8c83dc..915c28e3 100644 --- a/app/src/main/res/layout/item_muted_user.xml +++ b/app/src/main/res/layout/item_muted_user.xml @@ -19,11 +19,20 @@ app:layout_constraintTop_toTopOf="parent" tools:src="@drawable/avatar_default" /> + + + app:layout_constraintTop_toBottomOf="@id/muted_user_username" + app:switchPadding="4dp" /> diff --git a/app/src/test/java/com/keylesspalace/tusky/MainActivityTest.kt b/app/src/test/java/com/keylesspalace/tusky/MainActivityTest.kt index 8174aecb..09927d20 100644 --- a/app/src/test/java/com/keylesspalace/tusky/MainActivityTest.kt +++ b/app/src/test/java/com/keylesspalace/tusky/MainActivityTest.kt @@ -10,6 +10,7 @@ import androidx.viewpager2.widget.ViewPager2 import androidx.work.testing.WorkManagerTestInitHelper import at.connyduck.calladapter.networkresult.NetworkResult import com.keylesspalace.tusky.appstore.EventHub +import com.keylesspalace.tusky.components.accountlist.AccountListActivity import com.keylesspalace.tusky.components.notifications.NotificationHelper import com.keylesspalace.tusky.db.AccountEntity import com.keylesspalace.tusky.entity.Account