diff --git a/.gitignore b/.gitignore
index 84744a835..56cee6345 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@
/.idea/deploymentTargetDropDown.xml
/.idea/androidTestResultsUserPreferences.xml
/.idea/render.experimental.xml
+/.idea/inspectionProfiles/
.DS_Store
/build
/captures
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
deleted file mode 100644
index 38963f65d..000000000
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt
index 1bba104b8..947b80e8c 100644
--- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseBottomSheet.kt
@@ -9,13 +9,13 @@ import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams
import androidx.core.view.updateLayoutParams
import androidx.viewbinding.ViewBinding
-import com.google.android.material.R as materialR
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.dialog.AppBottomSheetDialog
import org.koitharu.kotatsu.utils.ext.displayCompat
+import com.google.android.material.R as materialR
abstract class BaseBottomSheet : BottomSheetDialogFragment() {
@@ -27,6 +27,9 @@ abstract class BaseBottomSheet : BottomSheetDialogFragment() {
protected val behavior: BottomSheetBehavior<*>?
get() = (dialog as? BottomSheetDialog)?.behavior
+ val isExpanded: Boolean
+ get() = behavior?.state == BottomSheetBehavior.STATE_EXPANDED
+
final override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt
index 561ebbb36..65887cbc3 100644
--- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsMenuProvider.kt
@@ -42,7 +42,7 @@ class DetailsMenuProvider(
menu.findItem(R.id.action_delete).isVisible = manga?.source == MangaSource.LOCAL
menu.findItem(R.id.action_browser).isVisible = manga?.source != MangaSource.LOCAL
menu.findItem(R.id.action_shortcut).isVisible = ShortcutManagerCompat.isRequestPinShortcutSupported(activity)
- menu.findItem(R.id.action_shiki_track).isVisible = viewModel.isScrobblingAvailable
+ menu.findItem(R.id.action_scrobbling).isVisible = viewModel.isScrobblingAvailable
menu.findItem(R.id.action_favourite).setIcon(
if (viewModel.favouriteCategories.value == true) R.drawable.ic_heart else R.drawable.ic_heart_outline,
)
@@ -60,11 +60,13 @@ class DetailsMenuProvider(
}
}
}
+
R.id.action_favourite -> {
viewModel.manga.value?.let {
FavouriteCategoriesBottomSheet.show(activity.supportFragmentManager, it)
}
}
+
R.id.action_delete -> {
val title = viewModel.manga.value?.title.orEmpty()
MaterialAlertDialogBuilder(activity)
@@ -76,6 +78,7 @@ class DetailsMenuProvider(
.setNegativeButton(android.R.string.cancel, null)
.show()
}
+
R.id.action_save -> {
viewModel.manga.value?.let {
val chaptersCount = it.chapters?.size ?: 0
@@ -87,21 +90,25 @@ class DetailsMenuProvider(
}
}
}
+
R.id.action_browser -> {
viewModel.manga.value?.let {
activity.startActivity(BrowserActivity.newIntent(activity, it.publicUrl, it.title))
}
}
+
R.id.action_related -> {
viewModel.manga.value?.let {
activity.startActivity(MultiSearchActivity.newIntent(activity, it.title))
}
}
- R.id.action_shiki_track -> {
+
+ R.id.action_scrobbling -> {
viewModel.manga.value?.let {
- ScrobblingSelectorBottomSheet.show(activity.supportFragmentManager, it)
+ ScrobblingSelectorBottomSheet.show(activity.supportFragmentManager, it, null)
}
}
+
R.id.action_shortcut -> {
viewModel.manga.value?.let {
activity.lifecycleScope.launch {
@@ -112,6 +119,7 @@ class DetailsMenuProvider(
}
}
}
+
else -> return false
}
return true
diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt
index d53e12f7a..e7c98d27e 100644
--- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsViewModel.kt
@@ -256,29 +256,24 @@ class DetailsViewModel @AssistedInject constructor(
}
}
- fun updateScrobbling(rating: Float, status: ScrobblingStatus?) {
- for (info in scrobblingInfo.value ?: return) {
- val scrobbler = scrobblers.first { it.scrobblerService == info.scrobbler }
- if (!scrobbler.isAvailable) continue
- launchJob(Dispatchers.Default) {
- scrobbler.updateScrobblingInfo(
- mangaId = delegate.mangaId,
- rating = rating,
- status = status,
- comment = null,
- )
- }
+ fun updateScrobbling(index: Int, rating: Float, status: ScrobblingStatus?) {
+ val scrobbler = getScrobbler(index) ?: return
+ launchJob(Dispatchers.Default) {
+ scrobbler.updateScrobblingInfo(
+ mangaId = delegate.mangaId,
+ rating = rating,
+ status = status,
+ comment = null,
+ )
}
}
- fun unregisterScrobbling() {
- for (scrobbler in scrobblers) {
- if (!scrobbler.isAvailable) continue
- launchJob(Dispatchers.Default) {
- scrobbler.unregisterScrobbling(
- mangaId = delegate.mangaId,
- )
- }
+ fun unregisterScrobbling(index: Int) {
+ val scrobbler = getScrobbler(index) ?: return
+ launchJob(Dispatchers.Default) {
+ scrobbler.unregisterScrobbling(
+ mangaId = delegate.mangaId,
+ )
}
}
@@ -315,6 +310,19 @@ class DetailsViewModel @AssistedInject constructor(
return spannable.trim()
}
+ private fun getScrobbler(index: Int): Scrobbler? {
+ val info = scrobblingInfo.value?.getOrNull(index)
+ val scrobbler = if (info != null) {
+ scrobblers.find { it.scrobblerService == info.scrobbler && it.isAvailable }
+ } else {
+ null
+ }
+ if (scrobbler == null) {
+ errorEvent.call(IllegalStateException("Scrobbler [$index] is not available"))
+ }
+ return scrobbler
+ }
+
@AssistedFactory
interface Factory {
diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt
index f5f8510e5..39fd5fd45 100644
--- a/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/scrobbling/ScrobblingInfoBottomSheet.kt
@@ -15,9 +15,7 @@ import androidx.core.net.toUri
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.activityViewModels
import coil.ImageLoader
-import coil.request.ImageRequest
import dagger.hilt.android.AndroidEntryPoint
-import javax.inject.Inject
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseBottomSheet
import org.koitharu.kotatsu.databinding.SheetScrobblingBinding
@@ -26,7 +24,12 @@ import org.koitharu.kotatsu.image.ui.ImageActivity
import org.koitharu.kotatsu.scrobbling.domain.model.ScrobblingInfo
import org.koitharu.kotatsu.scrobbling.domain.model.ScrobblingStatus
import org.koitharu.kotatsu.scrobbling.ui.selector.ScrobblingSelectorBottomSheet
-import org.koitharu.kotatsu.utils.ext.*
+import org.koitharu.kotatsu.utils.ext.enqueueWith
+import org.koitharu.kotatsu.utils.ext.getDisplayMessage
+import org.koitharu.kotatsu.utils.ext.newImageRequest
+import org.koitharu.kotatsu.utils.ext.scaleUpActivityOptionsOf
+import org.koitharu.kotatsu.utils.ext.withArgs
+import javax.inject.Inject
@AndroidEntryPoint
class ScrobblingInfoBottomSheet :
@@ -41,6 +44,7 @@ class ScrobblingInfoBottomSheet :
@Inject
lateinit var coil: ImageLoader
+
private var menu: PopupMenu? = null
override fun onCreate(savedInstanceState: Bundle?) {
@@ -78,6 +82,7 @@ class ScrobblingInfoBottomSheet :
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
viewModel.updateScrobbling(
+ index = scrobblerIndex,
rating = binding.ratingBar.rating / binding.ratingBar.numStars,
status = enumValues().getOrNull(position),
)
@@ -88,6 +93,7 @@ class ScrobblingInfoBottomSheet :
override fun onRatingChanged(ratingBar: RatingBar, rating: Float, fromUser: Boolean) {
if (fromUser) {
viewModel.updateScrobbling(
+ index = scrobblerIndex,
rating = rating / ratingBar.numStars,
status = enumValues().getOrNull(binding.spinnerStatus.selectedItemPosition),
)
@@ -115,15 +121,15 @@ class ScrobblingInfoBottomSheet :
binding.ratingBar.rating = scrobbling.rating * binding.ratingBar.numStars
binding.textViewDescription.text = scrobbling.description
binding.spinnerStatus.setSelection(scrobbling.status?.ordinal ?: -1)
- ImageRequest.Builder(context ?: return)
- .target(binding.imageViewCover)
- .data(scrobbling.coverUrl)
- .crossfade(context)
- .lifecycle(viewLifecycleOwner)
- .placeholder(R.drawable.ic_placeholder)
- .fallback(R.drawable.ic_placeholder)
- .error(R.drawable.ic_error_placeholder)
- .enqueueWith(coil)
+ binding.imageViewLogo.contentDescription = getString(scrobbling.scrobbler.titleResId)
+ binding.imageViewLogo.setImageResource(scrobbling.scrobbler.iconResId)
+ binding.imageViewCover.newImageRequest(scrobbling.coverUrl)?.apply {
+ lifecycle(viewLifecycleOwner)
+ placeholder(R.drawable.ic_placeholder)
+ fallback(R.drawable.ic_placeholder)
+ error(R.drawable.ic_error_placeholder)
+ enqueueWith(coil)
+ }
}
override fun onMenuItemClick(item: MenuItem): Boolean {
@@ -135,13 +141,16 @@ class ScrobblingInfoBottomSheet :
Intent.createChooser(intent, getString(R.string.open_in_browser)),
)
}
+
R.id.action_unregister -> {
- viewModel.unregisterScrobbling()
+ viewModel.unregisterScrobbling(scrobblerIndex)
dismiss()
}
+
R.id.action_edit -> {
val manga = viewModel.manga.value ?: return false
- ScrobblingSelectorBottomSheet.show(parentFragmentManager, manga)
+ val scrobblerService = viewModel.scrobblingInfo.value?.getOrNull(scrobblerIndex)?.scrobbler
+ ScrobblingSelectorBottomSheet.show(parentFragmentManager, manga, scrobblerService)
dismiss()
}
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorBottomSheet.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorBottomSheet.kt
index dcdfafcf8..a8eeb49e0 100644
--- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorBottomSheet.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorBottomSheet.kt
@@ -8,13 +8,12 @@ import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
-import android.widget.AdapterView
-import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.appcompat.widget.SearchView
import androidx.core.view.isVisible
import androidx.fragment.app.FragmentManager
import coil.ImageLoader
+import com.google.android.material.tabs.TabLayout
import dagger.hilt.android.AndroidEntryPoint
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.domain.MangaIntent
@@ -23,11 +22,14 @@ import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
import org.koitharu.kotatsu.base.ui.list.PaginationScrollListener
import org.koitharu.kotatsu.core.model.parcelable.ParcelableManga
import org.koitharu.kotatsu.databinding.SheetScrobblingSelectorBinding
+import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.scrobbling.domain.model.ScrobblerManga
+import org.koitharu.kotatsu.scrobbling.domain.model.ScrobblerService
import org.koitharu.kotatsu.scrobbling.ui.selector.adapter.ShikiMangaSelectionDecoration
import org.koitharu.kotatsu.scrobbling.ui.selector.adapter.ShikimoriSelectorAdapter
import org.koitharu.kotatsu.utils.ext.assistedViewModels
+import org.koitharu.kotatsu.utils.ext.firstVisibleItemPosition
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.requireParcelable
import org.koitharu.kotatsu.utils.ext.withArgs
@@ -42,7 +44,8 @@ class ScrobblingSelectorBottomSheet :
MenuItem.OnActionExpandListener,
SearchView.OnQueryTextListener,
DialogInterface.OnKeyListener,
- AdapterView.OnItemSelectedListener {
+ TabLayout.OnTabSelectedListener,
+ ListStateHolderListener {
@Inject
lateinit var viewModelFactory: ScrobblingSelectorViewModel.Factory
@@ -68,7 +71,7 @@ class ScrobblingSelectorBottomSheet :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
- val listAdapter = ShikimoriSelectorAdapter(viewLifecycleOwner, coil, this)
+ val listAdapter = ShikimoriSelectorAdapter(viewLifecycleOwner, coil, this, this)
val decoration = ShikiMangaSelectionDecoration(view.context)
with(binding.recyclerView) {
adapter = listAdapter
@@ -77,7 +80,7 @@ class ScrobblingSelectorBottomSheet :
}
binding.buttonDone.setOnClickListener(this)
initOptionsMenu()
- initSpinner()
+ initTabs()
viewModel.content.observe(viewLifecycleOwner) { listAdapter.items = it }
viewModel.selectedItemId.observe(viewLifecycleOwner) {
@@ -103,6 +106,12 @@ class ScrobblingSelectorBottomSheet :
viewModel.selectedItemId.value = item.id
}
+ override fun onRetryClick(error: Throwable) = Unit
+
+ override fun onEmptyActionClick() {
+ openSearch()
+ }
+
override fun onScrolledToEnd() {
viewModel.loadList(append = true)
}
@@ -143,11 +152,23 @@ class ScrobblingSelectorBottomSheet :
return false
}
- override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
- viewModel.setScrobblerIndex(position)
+ override fun onTabSelected(tab: TabLayout.Tab) {
+ viewModel.setScrobblerIndex(tab.position)
}
- override fun onNothingSelected(parent: AdapterView<*>?) = Unit
+ override fun onTabUnselected(tab: TabLayout.Tab?) = Unit
+
+ override fun onTabReselected(tab: TabLayout.Tab?) {
+ if (!isExpanded) {
+ setExpanded(isExpanded = true, isLocked = behavior?.isDraggable == false)
+ }
+ binding.recyclerView.firstVisibleItemPosition = 0
+ }
+
+ private fun openSearch() {
+ val menuItem = binding.headerBar.menu.findItem(R.id.action_search) ?: return
+ menuItem.expandActionView()
+ }
private fun onError(e: Throwable) {
Toast.makeText(requireContext(), e.getDisplayMessage(resources), Toast.LENGTH_LONG).show()
@@ -166,32 +187,41 @@ class ScrobblingSelectorBottomSheet :
searchView.queryHint = searchMenuItem.title
}
- private fun initSpinner() {
+ private fun initTabs() {
val entries = viewModel.availableScrobblers
+ val tabs = binding.tabs
if (entries.size <= 1) {
- binding.spinnerScrobblers.isVisible = false
+ tabs.isVisible = false
return
}
- val adapter = ArrayAdapter(
- requireContext(),
- android.R.layout.simple_spinner_item,
- entries.map { getString(it.scrobblerService.titleResId) },
- )
- adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
- binding.spinnerScrobblers.adapter = adapter
- viewModel.selectedScrobblerIndex.observe(viewLifecycleOwner) {
- binding.spinnerScrobblers.setSelection(it)
+ val selectedId = arguments?.getInt(ARG_SCROBBLER, -1) ?: -1
+ tabs.removeAllTabs()
+ tabs.clearOnTabSelectedListeners()
+ tabs.addOnTabSelectedListener(this)
+ for (entry in entries) {
+ val tab = tabs.newTab()
+ tab.tag = entry.scrobblerService
+ tab.setIcon(entry.scrobblerService.iconResId)
+ tab.setText(entry.scrobblerService.titleResId)
+ tabs.addTab(tab)
+ if (entry.scrobblerService.id == selectedId) {
+ tab.select()
+ }
}
- binding.spinnerScrobblers.onItemSelectedListener = this
+ tabs.isVisible = true
}
companion object {
private const val TAG = "ScrobblingSelectorBottomSheet"
+ private const val ARG_SCROBBLER = "scrobbler"
- fun show(fm: FragmentManager, manga: Manga) =
- ScrobblingSelectorBottomSheet().withArgs(1) {
+ fun show(fm: FragmentManager, manga: Manga, scrobblerService: ScrobblerService?) =
+ ScrobblingSelectorBottomSheet().withArgs(2) {
putParcelable(MangaIntent.KEY_MANGA, ParcelableManga(manga, withChapters = false))
+ if (scrobblerService != null) {
+ putInt(ARG_SCROBBLER, scrobblerService.id)
+ }
}.show(fm, TAG)
}
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorViewModel.kt
index a9509e2b7..cb926248f 100644
--- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/ScrobblingSelectorViewModel.kt
@@ -12,7 +12,9 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
+import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseViewModel
+import org.koitharu.kotatsu.list.ui.model.EmptyHint
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.list.ui.model.LoadingFooter
import org.koitharu.kotatsu.list.ui.model.LoadingState
@@ -46,7 +48,7 @@ class ScrobblingSelectorViewModel @AssistedInject constructor(
hasNextPage,
) { list, isHasNextPage ->
when {
- list.isEmpty() -> listOf()
+ list.isEmpty() -> listOf(emptyResultsHint())
isHasNextPage -> list + LoadingFooter
else -> list
}
@@ -125,6 +127,13 @@ class ScrobblingSelectorViewModel @AssistedInject constructor(
}
}
+ private fun emptyResultsHint() = EmptyHint(
+ icon = R.drawable.ic_empty_history,
+ textPrimary = R.string.nothing_found,
+ textSecondary = R.string.text_search_holder_secondary,
+ actionStringRes = R.string.search,
+ )
+
@AssistedFactory
interface Factory {
diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ShikimoriMangaAD.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ScrobblingMangaAD.kt
similarity index 98%
rename from app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ShikimoriMangaAD.kt
rename to app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ScrobblingMangaAD.kt
index 8ce317320..73723229a 100644
--- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ShikimoriMangaAD.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ScrobblingMangaAD.kt
@@ -13,7 +13,7 @@ import org.koitharu.kotatsu.utils.ext.enqueueWith
import org.koitharu.kotatsu.utils.ext.newImageRequest
import org.koitharu.kotatsu.utils.ext.textAndVisible
-fun shikimoriMangaAD(
+fun scrobblingMangaAD(
lifecycleOwner: LifecycleOwner,
coil: ImageLoader,
clickListener: OnListItemClickListener,
diff --git a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ShikimoriSelectorAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ShikimoriSelectorAdapter.kt
index 90c6af56b..656ae82de 100644
--- a/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ShikimoriSelectorAdapter.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/scrobbling/ui/selector/adapter/ShikimoriSelectorAdapter.kt
@@ -4,23 +4,27 @@ import androidx.lifecycle.LifecycleOwner
import androidx.recyclerview.widget.DiffUtil
import coil.ImageLoader
import com.hannesdorfmann.adapterdelegates4.AsyncListDifferDelegationAdapter
-import kotlin.jvm.internal.Intrinsics
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
+import org.koitharu.kotatsu.list.ui.adapter.ListStateHolderListener
+import org.koitharu.kotatsu.list.ui.adapter.emptyHintAD
import org.koitharu.kotatsu.list.ui.adapter.loadingFooterAD
import org.koitharu.kotatsu.list.ui.adapter.loadingStateAD
import org.koitharu.kotatsu.list.ui.model.ListModel
import org.koitharu.kotatsu.scrobbling.domain.model.ScrobblerManga
+import kotlin.jvm.internal.Intrinsics
class ShikimoriSelectorAdapter(
lifecycleOwner: LifecycleOwner,
coil: ImageLoader,
clickListener: OnListItemClickListener,
+ stateHolderListener: ListStateHolderListener,
) : AsyncListDifferDelegationAdapter(DiffCallback()) {
init {
delegatesManager.addDelegate(loadingStateAD())
- .addDelegate(shikimoriMangaAD(lifecycleOwner, coil, clickListener))
+ .addDelegate(scrobblingMangaAD(lifecycleOwner, coil, clickListener))
.addDelegate(loadingFooterAD())
+ .addDelegate(emptyHintAD(stateHolderListener))
}
private class DiffCallback : DiffUtil.ItemCallback() {
@@ -37,4 +41,4 @@ class ShikimoriSelectorAdapter(
return Intrinsics.areEqual(oldItem, newItem)
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt
index 53371ec18..6237b5cbd 100644
--- a/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/settings/HistorySettingsFragment.kt
@@ -217,7 +217,8 @@ class HistorySettingsFragment : BasePreferenceFragment(R.string.history_and_cach
viewLifecycleScope.launch {
pref.summary = withContext(Dispatchers.Default) {
runCatching {
- repository.loadUser().nickname
+ val user = repository.loadUser()
+ getString(R.string.logged_in_as, user.nickname)
}.getOrElse {
it.printStackTraceDebug()
it.getDisplayMessage(resources)
diff --git a/app/src/main/res/drawable/ic_anilist.xml b/app/src/main/res/drawable/ic_anilist.xml
index e9fa65813..13cecb8a2 100644
--- a/app/src/main/res/drawable/ic_anilist.xml
+++ b/app/src/main/res/drawable/ic_anilist.xml
@@ -1,10 +1,11 @@
-
-
+
+
diff --git a/app/src/main/res/layout/sheet_scrobbling.xml b/app/src/main/res/layout/sheet_scrobbling.xml
index ecb30f7c8..3cfaaf4fd 100644
--- a/app/src/main/res/layout/sheet_scrobbling.xml
+++ b/app/src/main/res/layout/sheet_scrobbling.xml
@@ -36,6 +36,17 @@
tools:background="@sample/covers[9]"
tools:ignore="ContentDescription,UnusedAttribute" />
+
+
-
+ android:visibility="gone"
+ app:tabGravity="start"
+ tools:visibility="visible" />
diff --git a/app/src/main/res/menu/opt_details.xml b/app/src/main/res/menu/opt_details.xml
index 7f5d3445f..5aa52c579 100644
--- a/app/src/main/res/menu/opt_details.xml
+++ b/app/src/main/res/menu/opt_details.xml
@@ -32,7 +32,7 @@
app:showAsAction="never" />