3488 improve profile list (#3507)

Fixes #3488 

Working with lists from a profile page and in the normal "lists view"
from the drawer now use the same fragment view code.

(also) RFC regarding joining different list lists


![grafik](https://user-images.githubusercontent.com/1618905/229463168-397bd943-82d8-4e05-a8bf-9fcf22f6c1f9.png)
This commit is contained in:
UlrichKu 2024-01-03 21:17:03 +01:00 committed by GitHub
commit 0698333665
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
37 changed files with 250 additions and 380 deletions

View file

@ -1,4 +1,4 @@
/* Copyright 2017 Andrew Dawson
/* Copyright Tusky contributors
*
* This file is a part of Tusky.
*
@ -23,9 +23,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageButton
import android.widget.PopupMenu
import android.widget.TextView
import androidx.activity.viewModels
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog
@ -35,14 +33,14 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.color.MaterialColors
import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.databinding.ActivityListsBinding
import com.keylesspalace.tusky.databinding.DialogListBinding
import com.keylesspalace.tusky.databinding.ItemListBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding
@ -54,18 +52,12 @@ import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.ERROR_OTHER
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.INITIAL
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADED
import com.keylesspalace.tusky.viewmodel.ListsViewModel.LoadingState.LOADING
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
import com.mikepenz.iconics.utils.colorInt
import com.mikepenz.iconics.utils.sizeDp
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import kotlinx.coroutines.launch
import javax.inject.Inject
/**
* Created by charlag on 1/4/18.
*/
// TODO use the ListSelectionFragment (and/or its adapter or binding) here; but keep the LoadingState from here (?)
class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
@ -214,9 +206,9 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
).show()
}
private fun onListSelected(listId: String, listTitle: String) {
private fun onListSelected(list: MastoList) {
startActivityWithSlideInAnimation(
StatusListActivity.newListIntent(this, listId, listTitle)
StatusListActivity.newListIntent(this, list.id, list.title)
)
}
@ -255,42 +247,28 @@ class ListsActivity : BaseActivity(), Injectable, HasAndroidInjector {
}
private inner class ListsAdapter :
ListAdapter<MastoList, ListsAdapter.ListViewHolder>(ListsDiffer) {
ListAdapter<MastoList, BindingHolder<ItemListBinding>>(ListsDiffer) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder {
return LayoutInflater.from(parent.context).inflate(R.layout.item_list, parent, false)
.let(this::ListViewHolder)
.apply {
val iconColor = MaterialColors.getColor(nameTextView, android.R.attr.textColorTertiary)
val context = nameTextView.context
val icon = IconicsDrawable(context, GoogleMaterial.Icon.gmd_list).apply { sizeDp = 20; colorInt = iconColor }
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BindingHolder<ItemListBinding> {
return BindingHolder(ItemListBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
nameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null)
override fun onBindViewHolder(holder: BindingHolder<ItemListBinding>, position: Int) {
val item = getItem(position)
holder.binding.listName.text = item.title
holder.binding.moreButton.apply {
visible(true)
setOnClickListener {
onMore(item, holder.binding.moreButton)
}
}
override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
holder.nameTextView.text = getItem(position).title
}
private inner class ListViewHolder(view: View) :
RecyclerView.ViewHolder(view),
View.OnClickListener {
val nameTextView: TextView = view.findViewById(R.id.list_name_textview)
val moreButton: ImageButton = view.findViewById(R.id.editListButton)
init {
view.setOnClickListener(this)
moreButton.setOnClickListener(this)
}
override fun onClick(v: View) {
if (v == itemView) {
val list = getItem(bindingAdapterPosition)
onListSelected(list.id, list.title)
} else {
onMore(getItem(bindingAdapterPosition), v)
}
holder.itemView.setOnClickListener {
onListSelected(item)
}
}
}

View file

@ -15,18 +15,10 @@
package com.keylesspalace.tusky
import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.util.Log
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.FrameLayout
import android.widget.LinearLayout
import android.widget.ProgressBar
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatEditText
@ -38,34 +30,29 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.transition.TransitionManager
import at.connyduck.calladapter.networkresult.fold
import at.connyduck.sparkbutton.helpers.Utils
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform
import com.keylesspalace.tusky.adapter.ItemInteractionListener
import com.keylesspalace.tusky.adapter.TabAdapter
import com.keylesspalace.tusky.appstore.EventHub
import com.keylesspalace.tusky.appstore.MainTabsChangedEvent
import com.keylesspalace.tusky.components.account.list.ListSelectionFragment
import com.keylesspalace.tusky.databinding.ActivityTabPreferenceBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.network.MastodonApi
import com.keylesspalace.tusky.util.getDimension
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.unsafeLazy
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible
import kotlinx.coroutines.CoroutineStart
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.regex.Pattern
import javax.inject.Inject
class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListener {
class TabPreferenceActivity : BaseActivity(), Injectable, HasAndroidInjector, ItemInteractionListener, ListSelectionFragment.ListSelectionListener {
@Inject
lateinit var mastodonApi: MastodonApi
@ -73,6 +60,9 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
@Inject
lateinit var eventHub: EventHub
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Any>
private val binding by viewBinding(ActivityTabPreferenceBinding::inflate)
private lateinit var currentTabs: MutableList<TabData>
@ -267,81 +257,24 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
editText.requestFocus()
}
private var listSelectDialog: ListSelectionFragment? = null
private fun showSelectListDialog() {
val adapter = object : ArrayAdapter<MastoList>(this, android.R.layout.simple_list_item_1) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view = super.getView(position, convertView, parent)
getItem(position)?.let { item -> (view as TextView).text = item.title }
return view
}
}
listSelectDialog = ListSelectionFragment.newInstance(null)
listSelectDialog?.show(supportFragmentManager, null)
val statusLayout = LinearLayout(this)
statusLayout.gravity = Gravity.CENTER
val progress = ProgressBar(this)
val preferredPadding = getDimension(this, androidx.appcompat.R.attr.dialogPreferredPadding)
progress.setPadding(preferredPadding, 0, preferredPadding, 0)
progress.visible(false)
val noListsText = TextView(this)
noListsText.setPadding(preferredPadding, 0, preferredPadding, 0)
noListsText.text = getText(R.string.select_list_empty)
noListsText.visible(false)
statusLayout.addView(progress)
statusLayout.addView(noListsText)
val dialogBuilder = AlertDialog.Builder(this)
.setTitle(R.string.select_list_title)
.setNeutralButton(R.string.select_list_manage) { _, _ ->
val listIntent = Intent(applicationContext, ListsActivity::class.java)
startActivity(listIntent)
}
.setNegativeButton(android.R.string.cancel, null)
.setView(statusLayout)
.setAdapter(adapter) { _, position ->
adapter.getItem(position)?.let { item ->
val newTab = createTabDataFromId(LIST, listOf(item.id, item.title))
currentTabs.add(newTab)
currentTabsAdapter.notifyItemInserted(currentTabs.size - 1)
updateAvailableTabs()
saveTabs()
}
}
val showProgressBarJob = getProgressBarJob(progress, 500)
showProgressBarJob.start()
val dialog = dialogBuilder.show()
lifecycleScope.launch {
mastodonApi.getLists().fold(
{ lists ->
showProgressBarJob.cancel()
adapter.addAll(lists)
if (lists.isEmpty()) {
noListsText.show()
}
},
{ throwable ->
dialog.hide()
Log.e("TabPreferenceActivity", "failed to load lists", throwable)
Snackbar.make(binding.root, R.string.error_list_load, Snackbar.LENGTH_LONG).show()
}
)
}
return
}
private fun getProgressBarJob(progressView: View, delayMs: Long) = this.lifecycleScope.launch(
start = CoroutineStart.LAZY
) {
try {
delay(delayMs)
progressView.show()
awaitCancellation()
} finally {
progressView.hide()
}
override fun onListSelected(list: MastoList) {
listSelectDialog?.dismiss()
listSelectDialog = null
val newTab = createTabDataFromId(LIST, listOf(list.id, list.title))
currentTabs.add(newTab)
currentTabsAdapter.notifyItemInserted(currentTabs.size - 1)
updateAvailableTabs()
saveTabs()
}
private fun validateHashtag(input: CharSequence?): Boolean {
@ -419,6 +352,8 @@ class TabPreferenceActivity : BaseActivity(), Injectable, ItemInteractionListene
}
}
override fun androidInjector() = dispatchingAndroidInjector
companion object {
private const val MIN_TAB_COUNT = 2
}

View file

@ -66,7 +66,7 @@ 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.account.list.ListSelectionFragment
import com.keylesspalace.tusky.components.accountlist.AccountListActivity
import com.keylesspalace.tusky.components.compose.ComposeActivity
import com.keylesspalace.tusky.components.report.ReportActivity
@ -991,7 +991,7 @@ class AccountActivity : BottomSheetActivity(), ActionButtonActivity, MenuProvide
return true
}
R.id.action_add_or_remove_from_list -> {
ListsForAccountFragment.newInstance(viewModel.accountId).show(supportFragmentManager, null)
ListSelectionFragment.newInstance(viewModel.accountId).show(supportFragmentManager, null)
return true
}
R.id.action_mute_domain -> {

View file

@ -1,4 +1,4 @@
/* Copyright 2022 kyori19
/* Copyright Tusky Contributors
*
* This file is a part of Tusky.
*
@ -16,79 +16,99 @@
package com.keylesspalace.tusky.components.account.list
import android.app.Dialog
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.ListAdapter
import com.google.android.material.snackbar.Snackbar
import com.keylesspalace.tusky.ListsActivity
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.databinding.FragmentListsForAccountBinding
import com.keylesspalace.tusky.databinding.ItemAddOrRemoveFromListBinding
import com.keylesspalace.tusky.databinding.FragmentListsListBinding
import com.keylesspalace.tusky.databinding.ItemListBinding
import com.keylesspalace.tusky.di.Injectable
import com.keylesspalace.tusky.di.ViewModelFactory
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.util.BindingHolder
import com.keylesspalace.tusky.util.hide
import com.keylesspalace.tusky.util.show
import com.keylesspalace.tusky.util.viewBinding
import com.keylesspalace.tusky.util.visible
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject
class ListsForAccountFragment : DialogFragment(), Injectable {
class ListSelectionFragment : DialogFragment(), Injectable {
interface ListSelectionListener {
fun onListSelected(list: MastoList)
}
@Inject
lateinit var viewModelFactory: ViewModelFactory
private val viewModel: ListsForAccountViewModel by viewModels { viewModelFactory }
private val binding by viewBinding(FragmentListsForAccountBinding::bind)
private var _binding: FragmentListsListBinding? = null
// This property is only valid between onCreateDialog and onDestroyView
private val binding get() = _binding!!
private val adapter = Adapter()
private var selectListener: ListSelectionListener? = null
private var accountId: String? = null
override fun onAttach(context: Context) {
super.onAttach(context)
selectListener = context as? ListSelectionListener
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NORMAL, R.style.TuskyDialogFragmentStyle)
viewModel.setup(requireArguments().getString(ARG_ACCOUNT_ID)!!)
accountId = requireArguments().getString(ARG_ACCOUNT_ID)
}
override fun onStart() {
super.onStart()
dialog?.apply {
window?.setLayout(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
)
}
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val context = requireContext()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_lists_for_account, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
binding.listsView.layoutManager = LinearLayoutManager(view.context)
_binding = FragmentListsListBinding.inflate(layoutInflater)
binding.listsView.adapter = adapter
viewLifecycleOwner.lifecycleScope.launch {
val dialogBuilder = AlertDialog.Builder(context)
.setView(binding.root)
.setTitle(R.string.select_list_title)
.setNeutralButton(R.string.select_list_manage) { _, _ ->
val listIntent = Intent(context, ListsActivity::class.java)
startActivity(listIntent)
}
.setNegativeButton(if (accountId != null) R.string.button_done else android.R.string.cancel, null)
val dialog = dialogBuilder.create()
val showProgressBarJob = getProgressBarJob(binding.progressBar, 500)
showProgressBarJob.start()
// TODO change this to a (single) LoadState like elsewhere?
lifecycleScope.launch {
viewModel.states.collectLatest { states ->
binding.progressBar.hide()
showProgressBarJob.cancel()
if (states.isEmpty()) {
binding.messageView.show()
binding.messageView.setup(R.drawable.elephant_friend_empty, R.string.no_lists) {
load()
}
binding.messageView.setup(R.drawable.elephant_friend_empty, R.string.no_lists)
} else {
binding.listsView.show()
adapter.submitList(states)
@ -96,9 +116,11 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
}
viewLifecycleOwner.lifecycleScope.launch {
lifecycleScope.launch {
viewModel.loadError.collectLatest { error ->
Log.e(TAG, "failed to load lists", error)
binding.progressBar.hide()
showProgressBarJob.cancel()
binding.listsView.hide()
binding.messageView.apply {
show()
@ -107,20 +129,20 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
}
viewLifecycleOwner.lifecycleScope.launch {
lifecycleScope.launch {
viewModel.actionError.collectLatest { error ->
when (error.type) {
ActionError.Type.ADD -> {
Snackbar.make(binding.root, R.string.failed_to_add_to_list, Snackbar.LENGTH_LONG)
.setAction(R.string.action_retry) {
viewModel.addAccountToList(error.listId)
viewModel.addAccountToList(accountId!!, error.listId)
}
.show()
}
ActionError.Type.REMOVE -> {
Snackbar.make(binding.root, R.string.failed_to_remove_from_list, Snackbar.LENGTH_LONG)
.setAction(R.string.action_retry) {
viewModel.removeAccountFromList(error.listId)
viewModel.removeAccountFromList(accountId!!, error.listId)
}
.show()
}
@ -128,18 +150,35 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
}
binding.doneButton.setOnClickListener {
dismiss()
lifecycleScope.launch {
load()
}
load()
return dialog
}
private fun getProgressBarJob(progressView: View, delayMs: Long) = this.lifecycleScope.launch(
start = CoroutineStart.LAZY
) {
try {
delay(delayMs)
progressView.show()
awaitCancellation()
} finally {
progressView.hide()
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun load() {
binding.progressBar.show()
binding.listsView.hide()
binding.messageView.hide()
viewModel.load()
viewModel.load(accountId)
}
private object Differ : DiffUtil.ItemCallback<AccountListState>() {
@ -159,42 +198,55 @@ class ListsForAccountFragment : DialogFragment(), Injectable {
}
inner class Adapter :
ListAdapter<AccountListState, BindingHolder<ItemAddOrRemoveFromListBinding>>(Differ) {
ListAdapter<AccountListState, BindingHolder<ItemListBinding>>(Differ) {
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): BindingHolder<ItemAddOrRemoveFromListBinding> {
val binding =
ItemAddOrRemoveFromListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return BindingHolder(binding)
): BindingHolder<ItemListBinding> {
return BindingHolder(ItemListBinding.inflate(LayoutInflater.from(parent.context), parent, false))
}
override fun onBindViewHolder(holder: BindingHolder<ItemAddOrRemoveFromListBinding>, position: Int) {
override fun onBindViewHolder(holder: BindingHolder<ItemListBinding>, position: Int) {
val item = getItem(position)
holder.binding.listNameView.text = item.list.title
holder.binding.addButton.apply {
visible(!item.includesAccount)
setOnClickListener {
viewModel.addAccountToList(item.list.id)
holder.binding.listName.text = item.list.title
accountId?.let { accountId ->
holder.binding.addButton.apply {
visible(!item.includesAccount)
setOnClickListener {
viewModel.addAccountToList(accountId, item.list.id)
}
}
holder.binding.removeButton.apply {
visible(item.includesAccount)
setOnClickListener {
viewModel.removeAccountFromList(accountId, item.list.id)
}
}
}
holder.binding.removeButton.apply {
visible(item.includesAccount)
setOnClickListener {
viewModel.removeAccountFromList(item.list.id)
holder.itemView.setOnClickListener {
selectListener?.onListSelected(item.list)
accountId?.let { accountId ->
if (item.includesAccount) {
viewModel.removeAccountFromList(accountId, item.list.id)
} else {
viewModel.addAccountToList(accountId, item.list.id)
}
}
}
}
}
companion object {
private const val TAG = "ListsListFragment"
private const val ARG_ACCOUNT_ID = "accountId"
fun newInstance(accountId: String): ListsForAccountFragment {
fun newInstance(accountId: String?): ListSelectionFragment {
val args = Bundle().apply {
putString(ARG_ACCOUNT_ID, accountId)
}
return ListsForAccountFragment().apply { arguments = args }
return ListSelectionFragment().apply { arguments = args }
}
}
}

View file

@ -25,8 +25,6 @@ import at.connyduck.calladapter.networkresult.runCatching
import com.keylesspalace.tusky.entity.MastoList
import com.keylesspalace.tusky.network.MastodonApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.first
@ -54,8 +52,6 @@ class ListsForAccountViewModel @Inject constructor(
private val mastodonApi: MastodonApi
) : ViewModel() {
private lateinit var accountId: String
private val _states = MutableSharedFlow<List<AccountListState>>(1)
val states: SharedFlow<List<AccountListState>> = _states
@ -65,24 +61,21 @@ class ListsForAccountViewModel @Inject constructor(
private val _actionError = MutableSharedFlow<ActionError>(1)
val actionError: SharedFlow<ActionError> = _actionError
fun setup(accountId: String) {
this.accountId = accountId
}
fun load() {
fun load(accountId: String?) {
_loadError.resetReplayCache()
viewModelScope.launch {
runCatching {
val (all, includes) = listOf(
async { mastodonApi.getLists() },
async { mastodonApi.getListsIncludesAccount(accountId) }
).awaitAll()
val all = mastodonApi.getLists().getOrThrow()
var includes: List<MastoList> = emptyList()
if (accountId != null) {
includes = mastodonApi.getListsIncludesAccount(accountId).getOrThrow()
}
_states.emit(
all.getOrThrow().map { list ->
all.map { listState ->
AccountListState(
list = list,
includesAccount = includes.getOrThrow().any { it.id == list.id }
list = listState,
includesAccount = includes.any { it.id == listState.id }
)
}
)
@ -93,7 +86,9 @@ class ListsForAccountViewModel @Inject constructor(
}
}
fun addAccountToList(listId: String) {
// TODO there is no "progress" visible for these
fun addAccountToList(accountId: String, listId: String) {
_actionError.resetReplayCache()
viewModelScope.launch {
mastodonApi.addAccountToList(listId, listOf(accountId))
@ -114,7 +109,7 @@ class ListsForAccountViewModel @Inject constructor(
}
}
fun removeAccountFromList(listId: String) {
fun removeAccountFromList(accountId: String, listId: String) {
_actionError.resetReplayCache()
viewModelScope.launch {
mastodonApi.deleteAccountFromList(listId, listOf(accountId))

View file

@ -100,7 +100,7 @@ abstract class ActivitiesModule {
@ContributesAndroidInjector
abstract fun contributesLicenseActivity(): LicenseActivity
@ContributesAndroidInjector
@ContributesAndroidInjector(modules = [FragmentBuildersModule::class])
abstract fun contributesTabPreferenceActivity(): TabPreferenceActivity
@ContributesAndroidInjector

View file

@ -16,7 +16,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.list.ListSelectionFragment
import com.keylesspalace.tusky.components.account.media.AccountMediaFragment
import com.keylesspalace.tusky.components.accountlist.AccountListFragment
import com.keylesspalace.tusky.components.conversation.ConversationsFragment
@ -97,7 +97,7 @@ abstract class FragmentBuildersModule {
abstract fun preferencesFragment(): PreferencesFragment
@ContributesAndroidInjector
abstract fun listsForAccountFragment(): ListsForAccountFragment
abstract fun listsForAccountFragment(): ListSelectionFragment
@ContributesAndroidInjector
abstract fun trendingTagsFragment(): TrendingTagsFragment