Random manga dice
This commit is contained in:
@@ -2,9 +2,13 @@ package org.koitharu.kotatsu.explore
|
|||||||
|
|
||||||
import org.koin.androidx.viewmodel.dsl.viewModel
|
import org.koin.androidx.viewmodel.dsl.viewModel
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||||
import org.koitharu.kotatsu.explore.ui.ExploreViewModel
|
import org.koitharu.kotatsu.explore.ui.ExploreViewModel
|
||||||
|
|
||||||
val exploreModule
|
val exploreModule
|
||||||
get() = module {
|
get() = module {
|
||||||
viewModel { ExploreViewModel(get()) }
|
|
||||||
|
factory { ExploreRepository(get(), get()) }
|
||||||
|
|
||||||
|
viewModel { ExploreViewModel(get(), get()) }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package org.koitharu.kotatsu.explore.domain
|
||||||
|
|
||||||
|
import org.koitharu.kotatsu.core.parser.MangaRepository
|
||||||
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
|
import org.koitharu.kotatsu.history.domain.HistoryRepository
|
||||||
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
|
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||||
|
|
||||||
|
class ExploreRepository(
|
||||||
|
private val settings: AppSettings,
|
||||||
|
private val historyRepository: HistoryRepository,
|
||||||
|
) {
|
||||||
|
|
||||||
|
suspend fun findRandomManga(tagsLimit: Int): Manga {
|
||||||
|
val blacklistTagRegex = settings.getSuggestionsTagsBlacklistRegex()
|
||||||
|
val allTags = historyRepository.getPopularTags(tagsLimit).filterNot {
|
||||||
|
blacklistTagRegex?.containsMatchIn(it.title) ?: false
|
||||||
|
}
|
||||||
|
val tag = allTags.randomOrNull()
|
||||||
|
val source = checkNotNull(tag?.source ?: settings.getMangaSources(includeHidden = false).randomOrNull()) {
|
||||||
|
"No sources found"
|
||||||
|
}
|
||||||
|
val repo = MangaRepository(source)
|
||||||
|
val list = repo.getList(
|
||||||
|
offset = 0,
|
||||||
|
sortOrder = if (SortOrder.UPDATED in repo.sortOrders) SortOrder.UPDATED else null,
|
||||||
|
tags = setOfNotNull(tag),
|
||||||
|
).shuffled()
|
||||||
|
for (item in list) {
|
||||||
|
if (settings.isSuggestionsExcludeNsfw && item.isNsfw) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (blacklistTagRegex != null && item.tags.any { x -> blacklistTagRegex.containsMatchIn(x.title) }) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
return list.random()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import org.koin.android.ext.android.get
|
import org.koin.android.ext.android.get
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
@@ -15,14 +16,18 @@ import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
|||||||
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
import org.koitharu.kotatsu.base.ui.util.RecyclerViewOwner
|
||||||
import org.koitharu.kotatsu.bookmarks.ui.BookmarksActivity
|
import org.koitharu.kotatsu.bookmarks.ui.BookmarksActivity
|
||||||
import org.koitharu.kotatsu.databinding.FragmentExploreBinding
|
import org.koitharu.kotatsu.databinding.FragmentExploreBinding
|
||||||
|
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||||
import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter
|
import org.koitharu.kotatsu.explore.ui.adapter.ExploreAdapter
|
||||||
import org.koitharu.kotatsu.explore.ui.adapter.ExploreListEventListener
|
import org.koitharu.kotatsu.explore.ui.adapter.ExploreListEventListener
|
||||||
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
||||||
|
import org.koitharu.kotatsu.favourites.ui.categories.CategoriesActivity
|
||||||
import org.koitharu.kotatsu.history.ui.HistoryActivity
|
import org.koitharu.kotatsu.history.ui.HistoryActivity
|
||||||
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
import org.koitharu.kotatsu.search.ui.MangaListActivity
|
||||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||||
import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity
|
import org.koitharu.kotatsu.suggestions.ui.SuggestionsActivity
|
||||||
|
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||||
|
|
||||||
class ExploreFragment : BaseFragment<FragmentExploreBinding>(),
|
class ExploreFragment : BaseFragment<FragmentExploreBinding>(),
|
||||||
RecyclerViewOwner,
|
RecyclerViewOwner,
|
||||||
@@ -52,6 +57,8 @@ class ExploreFragment : BaseFragment<FragmentExploreBinding>(),
|
|||||||
viewModel.content.observe(viewLifecycleOwner) {
|
viewModel.content.observe(viewLifecycleOwner) {
|
||||||
exploreAdapter?.items = it
|
exploreAdapter?.items = it
|
||||||
}
|
}
|
||||||
|
viewModel.onError.observe(viewLifecycleOwner, ::onError)
|
||||||
|
viewModel.onOpenManga.observe(viewLifecycleOwner, ::onOpenManga)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
@@ -81,6 +88,11 @@ class ExploreFragment : BaseFragment<FragmentExploreBinding>(),
|
|||||||
R.id.button_local -> MangaListActivity.newIntent(v.context, MangaSource.LOCAL)
|
R.id.button_local -> MangaListActivity.newIntent(v.context, MangaSource.LOCAL)
|
||||||
R.id.button_bookmarks -> BookmarksActivity.newIntent(v.context)
|
R.id.button_bookmarks -> BookmarksActivity.newIntent(v.context)
|
||||||
R.id.button_suggestions -> SuggestionsActivity.newIntent(v.context)
|
R.id.button_suggestions -> SuggestionsActivity.newIntent(v.context)
|
||||||
|
R.id.button_favourites -> CategoriesActivity.newIntent(v.context)
|
||||||
|
R.id.button_random -> {
|
||||||
|
viewModel.openRandom()
|
||||||
|
return
|
||||||
|
}
|
||||||
else -> return
|
else -> return
|
||||||
}
|
}
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
@@ -95,6 +107,19 @@ class ExploreFragment : BaseFragment<FragmentExploreBinding>(),
|
|||||||
|
|
||||||
override fun onEmptyActionClick() = onManageClick(requireView())
|
override fun onEmptyActionClick() = onManageClick(requireView())
|
||||||
|
|
||||||
|
private fun onError(e: Throwable) {
|
||||||
|
Snackbar.make(
|
||||||
|
binding.recyclerView,
|
||||||
|
e.getDisplayMessage(resources),
|
||||||
|
Snackbar.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onOpenManga(manga: Manga) {
|
||||||
|
val intent = DetailsActivity.newIntent(context ?: return, manga)
|
||||||
|
startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
fun newInstance() = ExploreFragment()
|
fun newInstance() = ExploreFragment()
|
||||||
|
|||||||
@@ -1,24 +1,43 @@
|
|||||||
package org.koitharu.kotatsu.explore.ui
|
package org.koitharu.kotatsu.explore.ui
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.asFlow
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.flow.filter
|
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
import kotlinx.coroutines.flow.onStart
|
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
import org.koitharu.kotatsu.base.ui.BaseViewModel
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
|
import org.koitharu.kotatsu.explore.domain.ExploreRepository
|
||||||
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
import org.koitharu.kotatsu.explore.ui.model.ExploreItem
|
||||||
|
import org.koitharu.kotatsu.parsers.model.Manga
|
||||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||||
|
import org.koitharu.kotatsu.utils.SingleLiveEvent
|
||||||
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
|
||||||
|
|
||||||
class ExploreViewModel(
|
class ExploreViewModel(
|
||||||
private val settings: AppSettings,
|
private val settings: AppSettings,
|
||||||
|
private val exploreRepository: ExploreRepository,
|
||||||
) : BaseViewModel() {
|
) : BaseViewModel() {
|
||||||
|
|
||||||
val content: LiveData<List<ExploreItem>> = settings.observe()
|
val onOpenManga = SingleLiveEvent<Manga>()
|
||||||
|
|
||||||
|
val content: LiveData<List<ExploreItem>> = isLoading.asFlow().flatMapLatest { loading ->
|
||||||
|
if (loading) {
|
||||||
|
flowOf(listOf(ExploreItem.Loading))
|
||||||
|
} else {
|
||||||
|
createContentFlow()
|
||||||
|
}
|
||||||
|
}.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, listOf(ExploreItem.Loading))
|
||||||
|
|
||||||
|
fun openRandom() {
|
||||||
|
launchLoadingJob(Dispatchers.Default) {
|
||||||
|
val manga = exploreRepository.findRandomManga(tagsLimit = 8)
|
||||||
|
onOpenManga.postCall(manga)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createContentFlow() = settings.observe()
|
||||||
.filter {
|
.filter {
|
||||||
it == AppSettings.KEY_SOURCES_HIDDEN ||
|
it == AppSettings.KEY_SOURCES_HIDDEN ||
|
||||||
it == AppSettings.KEY_SOURCES_ORDER ||
|
it == AppSettings.KEY_SOURCES_ORDER ||
|
||||||
@@ -28,7 +47,6 @@ class ExploreViewModel(
|
|||||||
.map { settings.getMangaSources(includeHidden = false) }
|
.map { settings.getMangaSources(includeHidden = false) }
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.map { buildList(it) }
|
.map { buildList(it) }
|
||||||
.asLiveDataDistinct(viewModelScope.coroutineContext + Dispatchers.Default, emptyList())
|
|
||||||
|
|
||||||
private fun buildList(sources: List<MangaSource>): List<ExploreItem> {
|
private fun buildList(sources: List<MangaSource>): List<ExploreItem> {
|
||||||
val result = ArrayList<ExploreItem>(sources.size + 3)
|
val result = ArrayList<ExploreItem>(sources.size + 3)
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ class ExploreAdapter(
|
|||||||
exploreSourcesHeaderAD(listener),
|
exploreSourcesHeaderAD(listener),
|
||||||
exploreSourceItemAD(coil, clickListener, lifecycleOwner),
|
exploreSourceItemAD(coil, clickListener, lifecycleOwner),
|
||||||
exploreEmptyHintListAD(listener),
|
exploreEmptyHintListAD(listener),
|
||||||
|
exploreLoadingAD(),
|
||||||
)
|
)
|
||||||
@@ -6,7 +6,9 @@ import androidx.lifecycle.LifecycleOwner
|
|||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.request.Disposable
|
import coil.request.Disposable
|
||||||
import coil.request.ImageRequest
|
import coil.request.ImageRequest
|
||||||
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegate
|
||||||
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter
|
import org.koitharu.kotatsu.base.ui.list.AdapterDelegateClickListenerAdapter
|
||||||
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.base.ui.list.OnListItemClickListener
|
||||||
import org.koitharu.kotatsu.databinding.ItemEmptyCardBinding
|
import org.koitharu.kotatsu.databinding.ItemEmptyCardBinding
|
||||||
@@ -29,6 +31,8 @@ fun exploreButtonsAD(
|
|||||||
binding.buttonHistory.setOnClickListener(clickListener)
|
binding.buttonHistory.setOnClickListener(clickListener)
|
||||||
binding.buttonLocal.setOnClickListener(clickListener)
|
binding.buttonLocal.setOnClickListener(clickListener)
|
||||||
binding.buttonSuggestions.setOnClickListener(clickListener)
|
binding.buttonSuggestions.setOnClickListener(clickListener)
|
||||||
|
binding.buttonFavourites.setOnClickListener(clickListener)
|
||||||
|
binding.buttonRandom.setOnClickListener(clickListener)
|
||||||
|
|
||||||
bind {
|
bind {
|
||||||
binding.buttonSuggestions.isVisible = item.isSuggestionsEnabled
|
binding.buttonSuggestions.isVisible = item.isSuggestionsEnabled
|
||||||
@@ -101,4 +105,6 @@ fun exploreEmptyHintListAD(
|
|||||||
binding.textSecondary.setTextAndVisible(item.textSecondary)
|
binding.textSecondary.setTextAndVisible(item.textSecondary)
|
||||||
binding.buttonRetry.setTextAndVisible(item.actionStringRes)
|
binding.buttonRetry.setTextAndVisible(item.actionStringRes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun exploreLoadingAD() = adapterDelegate<ExploreItem.Loading, ExploreItem>(R.layout.item_loading_state) {}
|
||||||
@@ -9,6 +9,8 @@ class ExploreDiffCallback : DiffUtil.ItemCallback<ExploreItem>() {
|
|||||||
return when {
|
return when {
|
||||||
oldItem.javaClass != newItem.javaClass -> false
|
oldItem.javaClass != newItem.javaClass -> false
|
||||||
oldItem is ExploreItem.Buttons && newItem is ExploreItem.Buttons -> true
|
oldItem is ExploreItem.Buttons && newItem is ExploreItem.Buttons -> true
|
||||||
|
oldItem is ExploreItem.Loading && newItem is ExploreItem.Loading -> true
|
||||||
|
oldItem is ExploreItem.EmptyHint && newItem is ExploreItem.EmptyHint -> true
|
||||||
oldItem is ExploreItem.Source && newItem is ExploreItem.Source -> {
|
oldItem is ExploreItem.Source && newItem is ExploreItem.Source -> {
|
||||||
oldItem.source == newItem.source
|
oldItem.source == newItem.source
|
||||||
}
|
}
|
||||||
@@ -22,5 +24,4 @@ class ExploreDiffCallback : DiffUtil.ItemCallback<ExploreItem>() {
|
|||||||
override fun areContentsTheSame(oldItem: ExploreItem, newItem: ExploreItem): Boolean {
|
override fun areContentsTheSame(oldItem: ExploreItem, newItem: ExploreItem): Boolean {
|
||||||
return oldItem == newItem
|
return oldItem == newItem
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -82,4 +82,6 @@ sealed interface ExploreItem : ListModel {
|
|||||||
@StringRes textSecondary: Int,
|
@StringRes textSecondary: Int,
|
||||||
@StringRes actionStringRes: Int,
|
@StringRes actionStringRes: Int,
|
||||||
) : EmptyState(icon, textPrimary, textSecondary, actionStringRes), ExploreItem
|
) : EmptyState(icon, textPrimary, textSecondary, actionStringRes), ExploreItem
|
||||||
|
|
||||||
|
object Loading : ExploreItem
|
||||||
}
|
}
|
||||||
12
app/src/main/res/drawable/ic_dice.xml
Normal file
12
app/src/main/res/drawable/ic_dice.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?attr/colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#000"
|
||||||
|
android:pathData="M19 5V19H5V5H19M19 3H5C3.9 3 3 3.9 3 5V19C3 20.1 3.9 21 5 21H19C20.1 21 21 20.1 21 19V5C21 3.9 20.1 3 19 3M7.5 6C6.7 6 6 6.7 6 7.5S6.7 9 7.5 9 9 8.3 9 7.5 8.3 6 7.5 6M16.5 15C15.7 15 15 15.7 15 16.5C15 17.3 15.7 18 16.5 18C17.3 18 18 17.3 18 16.5C18 15.7 17.3 15 16.5 15M16.5 6C15.7 6 15 6.7 15 7.5S15.7 9 16.5 9C17.3 9 18 8.3 18 7.5S17.3 6 16.5 6M12 10.5C11.2 10.5 10.5 11.2 10.5 12S11.2 13.5 12 13.5 13.5 12.8 13.5 12 12.8 10.5 12 10.5M7.5 15C6.7 15 6 15.7 6 16.5C6 17.3 6.7 18 7.5 18S9 17.3 9 16.5C9 15.7 8.3 15 7.5 15Z" />
|
||||||
|
</vector>
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:padding="4dp"
|
|
||||||
android:weightSum="4">
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/button_history"
|
|
||||||
style="@style/Widget.Kotatsu.ExploreButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="4dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/history"
|
|
||||||
app:icon="@drawable/ic_history" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/button_local"
|
|
||||||
style="@style/Widget.Kotatsu.ExploreButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="4dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/local_storage"
|
|
||||||
app:icon="@drawable/ic_storage" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/button_suggestions"
|
|
||||||
style="@style/Widget.Kotatsu.ExploreButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="4dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/suggestions"
|
|
||||||
app:icon="@drawable/ic_suggestion" />
|
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
|
||||||
android:id="@+id/button_bookmarks"
|
|
||||||
style="@style/Widget.Kotatsu.ExploreButton"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginHorizontal="4dp"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="@string/bookmarks"
|
|
||||||
app:icon="@drawable/ic_bookmark" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -15,6 +15,14 @@
|
|||||||
android:text="@string/history"
|
android:text="@string/history"
|
||||||
app:icon="@drawable/ic_history" />
|
app:icon="@drawable/ic_history" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/button_favourites"
|
||||||
|
style="@style/Widget.Kotatsu.ExploreButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/favourites"
|
||||||
|
app:icon="@drawable/ic_heart_outline" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_suggestions"
|
android:id="@+id/button_suggestions"
|
||||||
style="@style/Widget.Kotatsu.ExploreButton"
|
style="@style/Widget.Kotatsu.ExploreButton"
|
||||||
@@ -39,13 +47,21 @@
|
|||||||
android:text="@string/bookmarks"
|
android:text="@string/bookmarks"
|
||||||
app:icon="@drawable/ic_bookmark" />
|
app:icon="@drawable/ic_bookmark" />
|
||||||
|
|
||||||
|
<com.google.android.material.button.MaterialButton
|
||||||
|
android:id="@+id/button_random"
|
||||||
|
style="@style/Widget.Kotatsu.ExploreButton"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/random"
|
||||||
|
app:icon="@drawable/ic_dice" />
|
||||||
|
|
||||||
<androidx.constraintlayout.helper.widget.Flow
|
<androidx.constraintlayout.helper.widget.Flow
|
||||||
android:id="@+id/flow"
|
android:id="@+id/flow"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:constraint_referenced_ids="button_history,button_local,button_suggestions,button_bookmarks"
|
app:constraint_referenced_ids="button_history,button_favourites,button_local,button_bookmarks,button_suggestions,button_random"
|
||||||
app:flow_horizontalGap="12dp"
|
app:flow_horizontalGap="12dp"
|
||||||
app:flow_maxElementsWrap="2"
|
app:flow_maxElementsWrap="@integer/explore_buttons_columns"
|
||||||
app:flow_verticalGap="8dp"
|
app:flow_verticalGap="8dp"
|
||||||
app:flow_wrapMode="aligned"
|
app:flow_wrapMode="aligned"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|||||||
4
app/src/main/res/values-w600dp/integers.xml
Normal file
4
app/src/main/res/values-w600dp/integers.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<integer name="explore_buttons_columns">3</integer>
|
||||||
|
</resources>
|
||||||
@@ -2,4 +2,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<integer name="manga_badge_max_character_count">3</integer>
|
<integer name="manga_badge_max_character_count">3</integer>
|
||||||
|
<integer name="explore_buttons_columns">2</integer>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -329,4 +329,5 @@
|
|||||||
<string name="bookmarks_removed">Bookmarks removed</string>
|
<string name="bookmarks_removed">Bookmarks removed</string>
|
||||||
<string name="no_manga_sources">No manga sources</string>
|
<string name="no_manga_sources">No manga sources</string>
|
||||||
<string name="no_manga_sources_text">Enable manga sources to read manga online</string>
|
<string name="no_manga_sources_text">Enable manga sources to read manga online</string>
|
||||||
|
<string name="random">Random</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user